001: /******************************************************************************
002: * ResponderConnection.java
003: * ****************************************************************************/package org.openlaszlo.servlets.responders;
004:
005: import java.io.*;
006: import java.util.*;
007: import java.net.*;
008: import javax.servlet.*;
009: import javax.servlet.http.*;
010: import org.openlaszlo.auth.*;
011: import org.openlaszlo.compiler.*;
012: import org.openlaszlo.connection.*;
013: import org.openlaszlo.utils.*;
014: import org.apache.log4j.*;
015:
016: public abstract class ResponderConnection extends ResponderCompile {
017: private static final String DEFAULT_AUTHENTICATOR = "org.openlaszlo.auth.HTTPAuthentication";
018: private static final String ANONYMOUS_AUTHENTICATOR = "org.openlaszlo.auth.NullAuthentication";
019:
020: private static String mDefaultAuthClass = null;
021:
022: private static String mDefaultUserName = null;
023: private static Properties mLPSProperties = null;
024: private static String mCMOption = "check";
025: private static boolean mIsInitialized = false;
026: private static Logger mLogger = Logger
027: .getLogger(ResponderConnection.class);
028:
029: private static Hashtable mAuthenticators = new Hashtable();
030:
031: protected abstract void respondImpl(HttpServletRequest req,
032: HttpServletResponse res, Application app, int serial,
033: String username) throws IOException;
034:
035: synchronized public void init(String reqName, ServletConfig config,
036: Properties prop) throws ServletException, IOException {
037: super .init(reqName, config, prop);
038:
039: if (!mIsInitialized) {
040:
041: HTTPConnection.init(prop);
042: mLPSProperties = prop;
043: mDefaultUserName = prop.getProperty(
044: "connection.none-authenticator.username",
045: NullAuthentication.DEFAULT_USERNAME);
046: mDefaultAuthClass = prop.getProperty(
047: "connection.default.authenticator",
048: DEFAULT_AUTHENTICATOR);
049: mCMOption = prop.getProperty("compMgrDependencyOption",
050: "check");
051:
052: mIsInitialized = true;
053: }
054: }
055:
056: protected final void respondImpl(String fileName,
057: HttpServletRequest req, HttpServletResponse res)
058: throws IOException {
059: try {
060: String path = req.getServletPath();
061: String info = null;
062:
063: Application app = getConnectedApplication(fileName, req);
064: if (app == null) {
065: info = "application does not allow persistent connection calls";
066: respondWithErrorSWF(res, info);
067: return;
068: }
069:
070: // Session is valid if a username is returned
071: String username = mDefaultUserName;
072: Authentication authenticator = app.getAuthenticator();
073:
074: // Kludge: skip authentication if lzt=connectionlogin.
075: String lzt = req.getParameter("lzt");
076: if (!lzt.equals("connectionlogin") && authenticator != null) {
077: username = authenticator.getUsername(req, res,
078: getAuthParam(req));
079: if (username == null) {
080: respondWithErrorSWF(res, "invalid user or session");
081: return;
082: }
083: }
084:
085: // s: serial number of request; this number needs to be echoed
086: // back for successful response as an attribute of the resultset
087: // tag. See xml response in respondWithStatusSWF() for more
088: // information.
089: int serial = 0;
090: try {
091: String serialStr = req.getParameter("s");
092: if (serialStr != null) {
093: serial = Integer.parseInt(serialStr);
094: }
095: } catch (NumberFormatException e) {
096: respondWithErrorSWF(res,
097: /* (non-Javadoc)
098: * @i18n.test
099: * @org-mes="'s' is not a number"
100: */
101: org.openlaszlo.i18n.LaszloMessages.getMessage(
102: ResponderConnection.class.getName(),
103: "051018-113"));
104: return;
105: }
106:
107: respondImpl(req, res, app, serial, username);
108:
109: } catch (AuthenticationException e) {
110:
111: respondWithExceptionSWF(res, e);
112:
113: }
114: }
115:
116: synchronized private Application getConnectedApplication(
117: String filename, HttpServletRequest req)
118: throws IOException, AuthenticationException {
119: mLogger.debug("checkConnection(filename,req)");
120:
121: if (filename.endsWith(".lzo")) {
122: filename = filename.substring(0, filename.length() - 1)
123: + "x";
124: }
125:
126: Application app = null;
127: String path = req.getServletPath();
128:
129: app = Application.getApplication(path, false);
130: if (app != null && mCMOption.equals("never"))
131: return app;
132:
133: // FIXME: [2003-11-03 pkang] should have another object that connection and
134: // connectionlogin inherit from. This is the safer option for now.
135: String lzt = req.getParameter("lzt");
136: if (!lzt.equals("connect") && !lzt.equals("connectionlogin"))
137: return app;
138:
139: Canvas canvas = getCanvas(filename, req);
140: if (canvas.isConnected()) {
141:
142: app = Application.getApplication(path);
143:
144: // Fetching lmt should be low impact, since the file should already
145: // be cached.
146: long lmt = getLastModified(filename, req);
147: if (lmt != app.getLastModifiedTime()) {
148:
149: String authClass = canvas.getAuthenticator();
150: Authentication authenticator;
151: try {
152: authenticator = (authClass == null ? getAuthenticator(mDefaultAuthClass)
153: : getAuthenticator(authClass));
154: } catch (ClassNotFoundException e) {
155: if (app != null)
156: Application.removeApplication(app);
157: throw new AuthenticationException(
158: "ClassNotFoundException: " + e.getMessage());
159: } catch (InstantiationException e) {
160: if (app != null)
161: Application.removeApplication(app);
162: throw new AuthenticationException(
163: "InstantiationException: " + e.getMessage());
164: } catch (IllegalAccessException e) {
165: if (app != null)
166: Application.removeApplication(app);
167: throw new AuthenticationException(
168: "IllegalAccessException: " + e.getMessage());
169: }
170:
171: long heartbeat = canvas.getHeartbeat();
172: boolean sendUserDisconnect = canvas
173: .doSendUserDisconnect();
174:
175: String grName = canvas.getGroup();
176: if (grName == null)
177: grName = path;
178: ConnectionGroup group = ConnectionGroup
179: .getGroup(grName);
180:
181: app.setAgents(canvas.getAgents());
182:
183: app.setConnectionGroup(group);
184: app.setAuthenticator(authenticator);
185: app.setHeartbeat(heartbeat);
186: app.setLastModifiedTime(lmt);
187: app.setSendUserDisconnect(sendUserDisconnect);
188:
189: mLogger.debug(
190: /* (non-Javadoc)
191: * @i18n.test
192: * @org-mes="connected app settings " + "- authenticator: " + p[0] + ", senduserdisconnect: " + p[1] + ", heartbeat: " + p[2] + ", lmt: " + p[3]
193: */
194: org.openlaszlo.i18n.LaszloMessages.getMessage(
195: ResponderConnection.class.getName(),
196: "051018-200", new Object[] { authenticator,
197: new Boolean(sendUserDisconnect),
198: new Long(heartbeat), new Long(lmt) }));
199: }
200:
201: } else if (app != null) {
202:
203: Application.removeApplication(app);
204:
205: mLogger.debug(
206: /* (non-Javadoc)
207: * @i18n.test
208: * @org-mes="Removed " + p[0] + " as a connected application"
209: */
210: org.openlaszlo.i18n.LaszloMessages.getMessage(
211: ResponderConnection.class.getName(), "051018-213",
212: new Object[] { path }));
213: }
214:
215: return app;
216: }
217:
218: protected HashMap getAuthParam(HttpServletRequest req) {
219: HashMap map = new HashMap();
220: String authParam = req.getParameter("authparam");
221: if (authParam != null) {
222: authParam = URLDecoder.decode(authParam);
223: String[] params = StringUtils.split(authParam, "&");
224: for (int i = 0; i < params.length; i++) {
225: String[] kv = StringUtils.split(params[i], "=");
226: if (kv.length == 2) {
227: map.put(kv[0], kv[1]);
228: }
229: }
230: }
231:
232: if (mLogger.isDebugEnabled()) {
233: Iterator iter = map.keySet().iterator();
234: while (iter.hasNext()) {
235: String k = (String) iter.next();
236: mLogger.debug(k + ": " + map.get(k));
237: }
238: }
239:
240: return map;
241: }
242:
243: synchronized private Authentication getAuthenticator(
244: String className) throws AuthenticationException,
245: InstantiationException, IllegalAccessException,
246: ClassNotFoundException {
247: if (className.equals("anonymous"))
248: className = ANONYMOUS_AUTHENTICATOR;
249:
250: Authentication auth = (Authentication) mAuthenticators
251: .get(className);
252: if (auth == null) {
253: auth = (Authentication) Class.forName(className)
254: .newInstance();
255: auth.init(mLPSProperties);
256: mAuthenticators.put(className, auth);
257: }
258: return auth;
259: }
260:
261: public final int getMimeType() {
262: return MIME_TYPE_SWF;
263: }
264: }
|