001: /******************************************************************************
002: * ResponderCONNECT.java
003: * ****************************************************************************/package org.openlaszlo.servlets.responders;
004:
005: import java.io.*;
006: import java.util.*;
007: import javax.servlet.*;
008: import javax.servlet.http.*;
009: import org.openlaszlo.connection.*;
010: import org.openlaszlo.server.*;
011: import org.openlaszlo.utils.*;
012: import org.openlaszlo.servlets.LoadCount;
013: import org.apache.log4j.*;
014:
015: public final class ResponderCONNECT extends ResponderConnection {
016: private static boolean mIsInitialized = false;
017: private static boolean mEmitConnectHeaders = false;
018:
019: private static int[] mSTAT_activeCount = new int[1];
020:
021: private static Logger mLogger = Logger
022: .getLogger(ResponderCONNECT.class);
023:
024: synchronized public void init(String reqName, ServletConfig config,
025: Properties prop) throws ServletException, IOException {
026: super .init(reqName, config, prop);
027: if (!mIsInitialized) {
028: mEmitConnectHeaders = prop.getProperty(
029: "emitConnectHeaders", "false").intern() == "true";
030: mIsInitialized = true;
031: }
032: }
033:
034: /**
035: * Get current number of active connections.
036: */
037: public static int getActiveCount() {
038: synchronized (mSTAT_activeCount) {
039: return mSTAT_activeCount[0];
040: }
041: }
042:
043: protected void respondImpl(HttpServletRequest req,
044: HttpServletResponse res, Application app, int serial,
045: String username) throws IOException {
046: mLogger.debug(
047: /* (non-Javadoc)
048: * @i18n.test
049: * @org-mes="respondImpl(username=" + p[0] + ")"
050: */
051: org.openlaszlo.i18n.LaszloMessages.getMessage(
052: ResponderCONNECT.class.getName(), "051018-62",
053: new Object[] { username }));
054:
055: // This case is annoying
056: String ua = req.getHeader(LZHttpUtils.USER_AGENT);
057: if (ua == null) {
058: respondWithErrorSWF(res,
059: /* (non-Javadoc)
060: * @i18n.test
061: * @org-mes="request has no user-agent header"
062: */
063: org.openlaszlo.i18n.LaszloMessages.getMessage(
064: ResponderCONNECT.class.getName(), "051018-74"));
065: mLogger.warn(
066: /* (non-Javadoc)
067: * @i18n.test
068: * @org-mes="request has no user-agent header"
069: */
070: org.openlaszlo.i18n.LaszloMessages.getMessage(
071: ResponderCONNECT.class.getName(), "051018-74"));
072: return;
073: }
074:
075: if (!LPS.configuration
076: .optionAllows("connection-user-agent", ua)) {
077: respondWithErrorSWF(res, "forbidden user-agent: " + ua);
078: mLogger.warn(
079: /* (non-Javadoc)
080: * @i18n.test
081: * @org-mes="forbidden user-agent: " + p[0]
082: */
083: org.openlaszlo.i18n.LaszloMessages.getMessage(
084: ResponderCONNECT.class.getName(), "051018-95",
085: new Object[] { ua }));
086: return;
087: }
088:
089: // ...create the connection...
090: HTTPConnection connection = null;
091: HTTPConnection prevConnection = app.getConnection(req
092: .getParameter("i"));
093:
094: // for reconnects!
095: String type = req.getParameter("type");
096: boolean isReconnect = (type != null && type.equals("r"));
097: boolean doConnect = true;
098: if (isReconnect) {
099: if (prevConnection != null) {
100: doConnect = false;
101: connection = new HTTPConnection(res, prevConnection);
102: } else {
103: // Log that reconnection request has lost previous session.
104: // This can happen if client takes longer than the reconnection
105: // request wait interval and tries to make a reconnect request.
106: mLogger
107: .warn(
108: /* (non-Javadoc)
109: * @i18n.test
110: * @org-mes="tried reconnecting but there was no previous connection"
111: */
112: org.openlaszlo.i18n.LaszloMessages.getMessage(
113: ResponderCONNECT.class.getName(),
114: "051018-122"));
115: }
116: }
117:
118: if (doConnect) {
119: // ...pad connection headers with empty bytes if MSIE...
120: String userAgent = req.getHeader("User-Agent");
121: boolean doPad = (userAgent != null && userAgent
122: .indexOf("MSIE") != -1);
123:
124: connection = new HTTPConnection(res, username,
125: mSWFVersionNum).setHeartbeatInterval(
126: app.getHeartbeat()).setEmitConnectHeaders(
127: mEmitConnectHeaders).setDoPad(doPad);
128: }
129:
130: synchronized (mSTAT_activeCount) {
131: // ...and finally register. Check to see if we had a previous
132: // connection. If so, disconnect it after we register the new one.
133: //
134: // Registering the new connection and disconnecting the old one *must*
135: // be an atomic operation.
136: app.register(connection);
137: if (prevConnection != null)
138: prevConnection.disconnect(true);
139:
140: ++mSTAT_activeCount[0];
141: }
142:
143: try {
144: // this call blocks until a new connection comes in or is
145: // disconnected
146: connection.connect();
147: } catch (IOException e) {
148: mLogger.debug("ioexception: " + e.getMessage());
149: } catch (Exception e) {
150: mLogger.debug("exception: " + e.getMessage());
151: } finally {
152: app.unregister(connection);
153: synchronized (mSTAT_activeCount) {
154: --mSTAT_activeCount[0];
155: }
156: }
157:
158: // Send disconnect message when it isn't reconnect
159: if (!connection.toBeReconnected() && app.doSendUserDisconnect()) {
160: String disconnectInfo = HTTPConnection
161: .getConnectionInfoXML("__LPSUSERDISCONNECT",
162: connection.getUsername());
163: ConnectionGroup group = app.getConnectionGroup();
164: group.sendMessage("*", disconnectInfo, "all", null);
165: }
166:
167: try {
168:
169: // Send a byte to flush out socket. The flash player keeps its
170: // socket open for a few seconds after disconnect unless we do
171: // this. See bug 1447 for more info.
172: byte[] buf = new byte[1];
173: buf[0] = (byte) 0; // sending a buch of end tags (code 0).
174:
175: ServletOutputStream out = res.getOutputStream();
176: out.write(buf);
177: out.close();
178:
179: } catch (IOException e) {
180: mLogger.debug(e.getMessage());
181: }
182: }
183: }
|