⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 httppushhandler.java

📁 java开源的企业总线.xmlBlaster
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------------Name:      HttpPushHandler.javaProject:   xmlBlaster.orgCopyright: xmlBlaster.org, see xmlBlaster-LICENSE fileComment:   Handling callback over http------------------------------------------------------------------------------*/package org.xmlBlaster.protocol.http;import java.util.logging.Logger;import java.util.logging.Level;import org.xmlBlaster.util.ReplaceVariable;import org.xmlBlaster.util.Global;import org.xmlBlaster.client.I_XmlBlasterAccess;import org.xmlBlaster.client.I_Callback;import org.xmlBlaster.client.key.UpdateKey;import org.xmlBlaster.client.qos.UpdateQos;import java.io.*;import java.util.*;import javax.servlet.*;import javax.servlet.http.*;/** * This handles and hides the different http push modes when sending * data back to the browser through method update(). * <br /> * Push mode works with keeping a permanent http connection * <p /> * TODO: *   HTTP 1.1 specifies rfc2616 that the connection stays open as the *   default case. How must this code be changed? * <p /> * See Java Servlet Programming from Jason Hunter * @author Marcel Ruff xmlBlaster@marcelruff.info */public class HttpPushHandler implements I_Callback {   private String ME  = "HttpPushHandler";   private static Logger log = Logger.getLogger(HttpPushHandler.class.getName());   /**    * Ping the browser every 10 seconds.    * <br />    * You need to adjust ping() in persistenWindow/index.html as well,    * if you change the value here.    */   private final long PING_INTERVAL = 10000L;   private I_XmlBlasterAccess xmlBlasterAccess;   private I_Callback callbackInterceptor;   private HttpServletRequest req = null;   private HttpServletResponse res = null;   private String sessionId = null;   /** Current http connection state */   private boolean closed = false;   private ServletOutputStream outMulti;   private PrintWriter outPlain;   /** The header of the HTML page */   private String head;   /** The tail of the HTML page */   private String tail;   /** Check it the browser is ready to accept more messages */   private boolean browserIsReady = false;   /** handlesMultipart is true for netscape browser */   private boolean handlesMultipart = false;   /** Check browser and holds the http connection */   private HttpPingThread pingThread = null;   /** Queue to hold messages (class PushDataItem) until the browser is ready for them */   private Vector pushQueue = null;   private boolean firstPush = true;   /**    * Use this constructor if you are too lazy to pass a HTML header, a default will be used.    * @param req The request object    * @param res The response object    * @param sessionId The browser id    * @param loginName For loggin only    * @param xmlBlasterAccess Not yet logged in    */   public HttpPushHandler(HttpServletRequest req, HttpServletResponse res, String sessionId,                          String loginName, I_XmlBlasterAccess xmlBlasterAccess)                               throws ServletException, IOException   {      this.req = req;      this.res = res;      this.sessionId = sessionId;      this.xmlBlasterAccess = xmlBlasterAccess;      String browserId = req.getRemoteAddr() + "-" + loginName + "-" + sessionId;      this.ME  = "HttpPushHandler-" + browserId;      // Setting HTTP headers to prevent caching      /* !!! activate when migrating to servlet 2.2 !!!      res.addHeader("Expires", "Tue, 31 Dec 1997 23:59:59 GMT");      res.addHeader("Cache-Control", "no-cache");      res.addHeader("Pragma", "no-cache");      */      initialize(null, null);      pushQueue = new Vector();      setBrowserIsReady(true);      log.fine(ME + " Creating PingThread ...");      pingThread = new HttpPingThread(this, PING_INTERVAL, browserId);   }   public I_XmlBlasterAccess getXmlBlasterAccess() {      return this.xmlBlasterAccess;   }   /**    */   private void initialize(String head, String tail) throws IOException   {      if (log.isLoggable(Level.FINE)) log.fine("Creating HttpPushHandler ...");      this.head = head;      this.tail = tail;      this.handlesMultipart = doesHandleMultipart();      if (handlesMultipart)         this.outMulti =  res.getOutputStream();      else         this.outPlain =  res.getWriter();      log.fine("Initialize ...");      if (this.head == null) {         this.head = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">" +                                 "<HTML>\n" +          "<HEAD>\n" +          "   <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'>\n" +          "   <meta http-equiv='Pragma' content='no-cache'>\n" +          "   <meta http-equiv='Cache-Control' content='no-cache'>\n" +          "   <meta http-equiv='Expires' content='Tue, 31 Dec 1997 23:59:59 GMT'>\n" +          "   <TITLE>BlasterHttpProxy Connection</TITLE>\n" +          "</HEAD>\n" +          "<BODY>\n" +          "   <br>&nbsp;\n" +          "   <br>&nbsp;\n" +          "   <form ACTION=\"\" METHOD=\"POST\" TARGET=\"callback\">\n" +          "      <INPUT TYPE=\"HIDDEN\" NAME=\"NoName\" VALUE=\"NoValue\" />\n" +          "   </form>\n" +          "   <script language='JavaScript' type='text/javascript'>\n";      }      if (handlesMultipart) {         if (this.tail == null) {            this.tail  =   "</script>\n</BODY></HTML>";         }         res.setContentType("multipart/x-mixed-replace;boundary=End");         outMulti.println();         outMulti.println("--End");      }      else {         res.setContentType("text/html"); // bugfix, thanks to Just van den Broecke <just@justobjects.nl>      }   }   /**    * Don't forget to call this method when you want to close the connection.    */   public void shutdownBrowserConnection()   {      try {         setClosed(true);         setBrowserIsReady(false);         if (handlesMultipart) {            outMulti.close();         }         else {            outPlain.close();         }         pingThread.stopThread();         log.info("Closed push connection to browser");      }      catch(Exception e) {         log.severe("Error occurred while de-initializing the push handler :"+e.toString());      }   }   /**    * If you implement I_ProxyInterceptor and register it here,    * your update() implementation is called and may manipulate the    * received message from xmlBlaster before it is sent to the browser.    * @param interceptor Your optional implementation    */   public void setProxyInterceptor( I_Callback interceptor )   {      this.callbackInterceptor = interceptor;   }   /**    * Delegates the cleanup call to HttpPushHandler    */   public void cleanup() {      if (log.isLoggable(Level.FINER)) log.finer("Entering cleanup(" + sessionId + ") ...");      try {         if (this.sessionId != null) {            BlasterHttpProxy.cleanup(this.sessionId);         }         if (this.xmlBlasterAccess != null) {            this.xmlBlasterAccess.disconnect(null);            log.info("XmlBlaster connection removed");            this.xmlBlasterAccess = null;         }         this.callbackInterceptor = null;         shutdownBrowserConnection();      }      catch (Exception e) {         e.printStackTrace();         log.severe("Can't destroy http connection for sessionId=" + sessionId + ": " + e.toString());      }   }   public void startPing() throws ServletException, IOException   {      pingThread.start();      ping("refresh");   }   /**    * check's whether the HTTP connection is closed or not    */   public boolean closed()   {      return closed;   }   /**    */   public void setClosed(boolean closed)   {      if (log.isLoggable(Level.FINE)) log.fine("Setting closed from " + this.closed + " to " + closed);      this.closed = closed;   }   /**    * check's whether the browser is ready to accept more messages or not    * [if (parent.browserReady != null) parent.browserReady();].    *        This shows, that the browser had processed the whole message.    *        If the Browser implements this javascript function, it could send    *        a browserReady signal back to the  BlasterHttpProxyServlet.    *        This feature solves the problem, that the browser got messages too fast    *        and could not process all content of the message.    */   public final boolean isBrowserReady()   {      return browserIsReady;   }   /**    */   public void setBrowserIsReady(boolean ready)   {      if (closed()) { this.browserIsReady=false; return; }      this.browserIsReady = ready;      if (log.isLoggable(Level.FINE)) log.fine("Setting browserReady=" + browserIsReady);      pong(); // Use this as a browser alive as well, since some internet proxies seem to hold back my pongs      //send queue if browser is ready      if (browserIsReady) {         try {            pushToBrowser();         }         catch(Exception e) {            log.severe("sending push queue to browser failed. ["+e.toString()+"]");            shutdownBrowserConnection();         }      }   }   /**    * Determine if the browser can handle multipart pushs.    * Only Netscape returns true.    */   private boolean doesHandleMultipart() throws IOException   {      String browser = req.getHeader("User-Agent");      // netscape 4.74:                   "Mozilla/4.74 [de] (X11; U; Linux 2.2.16 i686)"      // opera 4.0b2 (Identify as Opera): "Mozilla/ (Linux; U) Opera 4.01  [en]"      boolean doesMulti = false;      if (browser == null)         doesMulti = false;      else if (browser.indexOf("Mozilla") != -1 &&               browser.indexOf("MSIE") == -1  &&               browser.indexOf("Opera") == -1)         doesMulti = true;   // Only real mozillas support multipart request      if (doesMulti)         log.info("Checking browser = " + browser + ". Assuming it supports 'multipart requests'");      else         log.info("Checking browser = " + browser + ". We won't use 'multipart requests'");      return doesMulti;   }   /**    * Updating data to the browser (callback/push mode).    * The data must be Javascript code    * @param str

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -