📄 blasterhttpproxyservlet.java
字号:
/*------------------------------------------------------------------------------Name: BlasterHttpProxyServlet.javaProject: xmlBlaster.orgCopyright: xmlBlaster.org, see xmlBlaster-LICENSE file------------------------------------------------------------------------------*/package org.xmlBlaster.protocol.http;import java.util.logging.LogRecord;import java.util.logging.Logger;import java.util.logging.Level;import org.xmlBlaster.util.Global;import org.xmlBlaster.util.XmlBlasterException;import org.xmlBlaster.util.def.ErrorCode;import org.xmlBlaster.client.I_XmlBlasterAccess;import org.xmlBlaster.client.qos.ConnectQos;import org.xmlBlaster.client.qos.PublishReturnQos;import org.xmlBlaster.client.qos.SubscribeReturnQos;import org.xmlBlaster.util.MsgUnit;import org.xmlBlaster.util.def.MethodName;import org.xmlBlaster.client.key.SubscribeKey;import org.xmlBlaster.client.key.UnSubscribeKey;import org.xmlBlaster.client.key.EraseKey;import java.io.*;import java.util.*;import javax.servlet.*;import javax.servlet.http.*;/** * This servlet doesn't leave the doGet() method after an invocation * keeping a permanent http connection. * <p /> * With the doGet() method you may login/logout to xmlBlaster, and * receive your instant callbacks.<br /> * With the doPost() you can invoke publish/subscribe etc.<br /> * <p /> * The logging output is redirected to the normal servlet log file. * If you use Apache/Jserv, look into /var/log/httpd/jserv.log * <p /> * Invoke for testing:<br /> * http://localhost/xmlBlaster/BlasterHttpProxyServlet?ActionType=login&xmlBlaster.loginName=martin&xmlBlaster.passwd=secret * @author Marcel Ruff xmlBlaster@marcelruff.info */public class BlasterHttpProxyServlet extends HttpServlet implements org.xmlBlaster.util.log.I_LogListener{ private static final long serialVersionUID = 1L; private static boolean propertyRead = false; private final String header = "<html><meta http-equiv='no-cache'><meta http-equiv='Cache-Control' content='no-cache'><meta http-equiv='expires' content='Wed, 26 Feb 1997 08:21:57 GMT'>"; private Global glob = null; private static Logger log = Logger.getLogger(BlasterHttpProxyServlet.class.getName()); public final static String ENCODING = "UTF-8"; /** * This method is invoked only once when the servlet is startet. * @param conf init parameter of the servlet */ public void init(ServletConfig conf) throws ServletException { super.init(conf); if (!propertyRead) { propertyRead = true; // Add the web.xml parameters to our environment settings: Enumeration enumer = conf.getInitParameterNames(); int count = 0; while(enumer.hasMoreElements()) { if (enumer.nextElement() == null) continue; count++; } String[] args = new String[2*count]; count = 0; enumer = conf.getInitParameterNames(); while(enumer.hasMoreElements()) { String name = (String)enumer.nextElement(); if (name == null) continue; if (!name.startsWith("-")) args[count++] = "-" + name; else args[count++] = name; args[count++] = conf.getInitParameter(name); //Global.instance().getLog(null).info("", "Reading web.xml property " + args[count-2] + "=" + args[count-1]); } glob = new Global(); int ret = glob.init(args); if (ret != 0) { // init problems } } // Redirect xmlBlaster logs to servlet log file (see method log() below) // Use xmlBlaster/demo/http/WEB-INF/web.xml to configure logging. // To redirect your Logging output into the servlet logfile (jserv.log), // outcomment this line: //log.addLogableDevice(this); log.fine("Initialize ..."); initSystemProperties(conf); // Using JacORB and Suns XML parser as a default ... } /** * GET request from the browser, usually to do an initial login. * <p /> * Used for login and for keeping a permanent http connection. * <br /> * The sessionId from the login is delivered back to the browser, * and will be used for all following calls to this and other servlets. * <br /> * It is important that this login servlet generates the sessionId * and no other servlet generates one - so call other servlets *after* * successful login. * <p /> * Example:<br /> * <code>index.html?ActionType=login&xmlBlaster.loginName=karl&xmlBlaster.passwd=secret</code> */ public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { if (log.isLoggable(Level.FINER)) log.finer("Entering doGet() ... " + Global.getMemoryStatistic()); res.setContentType("text/html"); String ME = "BlasterHttpProxyServlet-" + req.getRemoteAddr(); String actionType = Util.getParameter(req, "ActionType", ""); if (actionType == null) { String str = "Please call servlet with some ActionType"; log.severe(str); htmlOutput(str, res); return; } HttpSession session = req.getSession(true); if (actionType.equals("login")) { boolean invalidate = Util.getParameter(req, "xmlBlaster.invalidate", true); if (invalidate == true) { log.info("Entering servlet doGet(), forcing a new sessionId"); session.invalidate(); // force a new sessionId } session = req.getSession(true); } String sessionId = session.getId(); ME += "-" + sessionId; if (log.isLoggable(Level.FINE)) log.fine("Entering servlet doGet() ..."); if (sessionId == null) { PrintWriter out = res.getWriter(); out.println(HttpPushHandler.alert("Sorry, your sessionId is invalid")); return; } try { //------------------ Login ------------------------------------------------- if (actionType.equals("login") || actionType.equals("connect")) { ConnectQos connectQos; if (actionType.equals("connect")) { String qos = Util.getParameter(req, "xmlBlaster.connectQos", null); if (qos == null || qos.length() < 1) throw new XmlBlasterException(glob, ErrorCode.USER_CONFIGURATION, ME, "Missing connect QoS. Pass xmlBlaster.connectQos='<qos> ... </qos>' with your URL in your POST in a hidden form field or in your cookie."); connectQos = new ConnectQos(glob, glob.getConnectQosFactory().readObject(qos)); } else { String loginName = Util.getParameter(req, "xmlBlaster.loginName", null); // "Joe"; if (loginName == null || loginName.length() < 1) throw new XmlBlasterException(glob, ErrorCode.USER_CONFIGURATION, ME, "Missing login name. Pass xmlBlaster.loginName=xy with your URL or in your cookie."); String passwd = Util.getParameter(req, "xmlBlaster.passwd", null); // "secret"; if (passwd == null || passwd.length() < 1) throw new XmlBlasterException(glob, ErrorCode.USER_CONFIGURATION, ME, "Missing passwd"); connectQos = new ConnectQos(glob, loginName, passwd); } ME = "BlasterHttpProxyServlet-" + req.getRemoteAddr() + "-" + connectQos.getSessionName().getLoginName() + "-" + sessionId; I_XmlBlasterAccess xmlBlasterAccess = glob.getXmlBlasterAccess(); HttpPushHandler pushHandler = new HttpPushHandler(req, res, sessionId, connectQos.getSessionName().getRelativeName(), xmlBlasterAccess); xmlBlasterAccess.connect(connectQos, pushHandler); if (!session.isNew()) { pushHandler.startPing(); } else { log.info("Login action, browser has not yet joined this sessionId (cookie), so first pings pong may return an invalid sessionId"); pushHandler.startPing(); // This is too early here, we need to start the ping thread later? } BlasterHttpProxy.addHttpPushHandler( sessionId, pushHandler ); // Don't fall out of doGet() to keep the HTTP connection open log.info("Waiting forever, permanent HTTP connection from " + req.getRemoteHost() + "/" + req.getRemoteAddr() + ", sessionName=" + connectQos.getSessionName().getRelativeName() + " sessionId=" + sessionId + "', protocol='" + req.getProtocol() + "', agent='" + req.getHeader("User-Agent") + "', referer='" + req.getHeader("Referer") + "'."); if (log.isLoggable(Level.FINE)) log.fine("user='" + req.getRemoteUser() + "', serverPort='" + req.getServerPort() + "', query='" + req.getQueryString() + "', pathInfo='" + req.getPathInfo() + "', pathTranslated='" + req.getPathTranslated() + "', servletPath='" + req.getServletPath() + "', documentRoot='" + getServletConfig().getServletContext().getRealPath("/") + "', accept='" + req.getHeader("Accept") + "', referer='" + req.getHeader("Referer") + "', authorization='" + req.getHeader("Authorization") + "'."); pushHandler.setBrowserIsReady( true ); pushHandler.ping("loginSucceeded"); while (!pushHandler.closed()) { try { Thread.sleep(10000L); } catch (InterruptedException i) { log.severe("Error in Thread handling, don't know what to do: "+i.toString()); pushHandler.cleanup(); break; } } pushHandler = null; log.info("Persistent HTTP connection lost, leaving doGet() ...."); /* System.out.println("Currently consumed threads:"); System.out.println("==========================="); ThreadLister.listAllThreads(System.out); */ } //------------------ first request from applet -------------------------- else if(actionType.equals("dummyToCreateASessionId")) { // I_XmlBlasterAccessRaw.CREATE_SESSIONID_NAME log.info("doGet: dummyToCreateASessionId"); PrintWriter out = res.getWriter(); out.println(header+"<body text='white' bgcolor='white'>Empty response for your ActionType='dummyToCreateASessionId' " + System.currentTimeMillis() + "</body></html>"); return; } //------------------ ready, browser processed last message -------------------------- // The HttpPushHandler adds javascript 'parent.browserReady();' which // is invoked after the browser is ready. else if(actionType.equals("browserReady")) { try { HttpPushHandler pushHandler = BlasterHttpProxy.getHttpPushHandler(sessionId); if (log.isLoggable(Level.FINE)) log.fine("Received 'browserReady'"); pushHandler.setBrowserIsReady( true ); // Otherwise the browser (controlFrame) complains 'document contained no data' PrintWriter out = res.getWriter(); out.println(header+"<body text='white' bgcolor='white'>Empty response for your ActionType='browserReady' " + System.currentTimeMillis() + "</body></html>"); return; } catch (XmlBlasterException e) { log.severe("Caught XmlBlaster Exception for actionType '" + actionType + "': " + e.getMessage()); return; } } //------------------ answer of a ping ----------------------------------------------- // The HttpPushHandler adds javascript 'parent.ping();' which // pings the browser to hold the http connection. // The browser responses with 'pong', to allow the servlet to // detect if the browser is alive. // Locally this works fine, but over the internet the second or third pong from the browser // was never reaching this servlet. Adding some dynamic content/URL helped a bit, // but after some ten pongs, the following pongs where lost. // The browserReady request hasn't got this problem, why?? // So we do a pong on browserReady as well, which solved the problem (see HttpPushHandler.java) else if(actionType.equals("pong")) { try { HttpPushHandler pushHandler = BlasterHttpProxy.getHttpPushHandler(sessionId); pushHandler.pong(); // state is only for debugging and to avoid internet proxies to discard this content (since it has not changed) if (log.isLoggable(Level.FINE)) log.fine("Received pong '" + Util.getParameter(req, "state", "noState") + "'"); // Otherwise the browser (controlFrame) complains 'document contained no data' PrintWriter out = res.getWriter(); out.println(header+"<body text='white' bgcolor='white'>Empty response for your ActionType='pong' " + Util.getParameter(req, "state", "noState") + " " + System.currentTimeMillis() + "</body></html>"); return; } catch (XmlBlasterException e) { log.severe("Caught XmlBlaster Exception for actionType '" + actionType + "': " + e.getMessage()); return; } } else if (MethodName.PUBLISH.toString().equalsIgnoreCase(actionType)) { // "publish" doPost(req, res); } else if (MethodName.SUBSCRIBE.toString().equalsIgnoreCase(actionType)) { // "subscribe" doPost(req, res); } else if (MethodName.UNSUBSCRIBE.toString().equalsIgnoreCase(actionType)) { // "unSubscribe" doPost(req, res); } else if (MethodName.GET.toString().equalsIgnoreCase(actionType)) { // "get" doPost(req, res); } else if (MethodName.ERASE.toString().equalsIgnoreCase(actionType)) { // "erase" doPost(req, res); } else if (MethodName.PING.toString().equalsIgnoreCase(actionType)) { // "ping" doPost(req, res); } //------------------ logout --------------------------------------------------------- else if (actionType.equals("logout")) { log.info("Logout arrived ..."); try { HttpPushHandler pc = BlasterHttpProxy.getHttpPushHandler(sessionId); pc.cleanup(); } catch(XmlBlasterException e) { log.severe(e.toString()); } // Otherwise the browser (controlFrame) complains 'document contained no data' PrintWriter out = res.getWriter(); out.println(header+" <body text='white' bgcolor='white'><script language='JavaScript' type='text/javascript'>top.close()</script></body></html>"); } else { String text = "Unknown ActionType '" + actionType + "', request for permanent http connection ignored"; throw new XmlBlasterException(glob, ErrorCode.USER_CONFIGURATION, ME, text); } } catch (XmlBlasterException e) { log.severe("Caught XmlBlaster Exception: " + e.getMessage()); String codedText = Global.encode( e.getMessage(), ENCODING );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -