001: /*
002: * Enhydra Java Application Server Project
003: *
004: * The contents of this file are subject to the Enhydra Public License
005: * Version 1.1 (the "License"); you may not use this file except in
006: * compliance with the License. You may obtain a copy of the License on
007: * the Enhydra web site ( http://www.enhydra.org/ ).
008: *
009: * Software distributed under the License is distributed on an "AS IS"
010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
011: * the License for the specific terms governing rights and limitations
012: * under the License.
013: *
014: * The Initial Developer of the Enhydra Application Server is Lutris
015: * Technologies, Inc. The Enhydra Application Server and portions created
016: * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
017: * All Rights Reserved.
018: *
019: * Contributor(s):
020: *
021: * $Id: StandardAppUtil.java,v 1.4 2007-10-19 10:05:39 sinisa Exp $
022: */
023:
024: package com.lutris.appserver.server;
025:
026: import java.net.InetAddress;
027: import java.net.MalformedURLException;
028: import java.net.URL;
029: import java.net.UnknownHostException;
030: import java.util.StringTokenizer;
031:
032: import javax.servlet.ServletRequest;
033: import javax.servlet.http.Cookie;
034: import javax.servlet.http.HttpServletRequest;
035:
036: import com.lutris.appserver.server.httpPresentation.HttpPresentationComms;
037: import com.lutris.appserver.server.httpPresentation.HttpPresentationException;
038: import com.lutris.appserver.server.session.Session;
039: import com.lutris.appserver.server.session.SessionException;
040: import com.lutris.appserver.server.session.SessionManager;
041:
042: /**
043: * Static methods used by <CODE>StandardApplication</CODE>. These mostly are
044: * used to manage sessions.
045: *
046: * @version $Revision: 1.4 $
047: * @author Mark Diekhans
048: * @author Richard Kunze <kunze@opus5.de>
049: */
050: public class StandardAppUtil {
051:
052: /*
053: * Constant used for encoding the session in a url rewrite.
054: */
055: public static final String ENHYDRA_SESSION_ID_URL = "jsessionid";
056:
057: public static final String ENHYDRA_SESSION_ID_COOKIE = "JSESSIONID";
058:
059: /**
060: * Prevent instantiation.
061: */
062: private StandardAppUtil() {
063: }
064:
065: /**
066: * Get internet peer address.
067: *
068: * @param comms
069: * The presentations manager comms object with all
070: * request/response information in it.
071: * @return The peer address.
072: * @exception ApplicationException
073: * If address can't be obtained.
074: */
075: // FIXME: no longer needed, but might make a nice general util function.
076: public static InetAddress[] getPeerAddress(
077: HttpPresentationComms comms) throws ApplicationException {
078:
079: InetAddress[] peer = new InetAddress[1];
080: String remoteHost;
081: try {
082: remoteHost = comms.request.getRemoteHost();
083: } catch (HttpPresentationException except) {
084: throw new ApplicationException(except);
085: }
086: if (remoteHost == null) {
087: throw new ApplicationException(
088: "Can't find remote host for request.");
089: }
090: if (remoteHost != null) {
091: try {
092: peer[0] = InetAddress.getByName(remoteHost);
093: } catch (UnknownHostException except) {
094: throw new ApplicationException(
095: "Can't find remote address for \"" + remoteHost
096: + "\"", except);
097: }
098: }
099: return peer;
100: }
101:
102: /**
103: * Search for a session cookie with the specified application name.
104: *
105: * @param applicationName
106: * Application name that is saved in the cookie.
107: * @param cookies
108: * Array of cookies for the current request.
109: * @return The session key decoded from the cookie, or null if the session
110: * was not found.
111: * @deprecated
112: */
113: private static String findSessionKey(String applicationName,
114: Cookie[] cookies) {
115: return findSessionKey(cookies);
116: }
117:
118: /**
119: * Search for a session cookie with the name jsessionid.
120: *
121: * @param applicationName
122: * Application name that is saved in the cookie.
123: * @param cookies
124: * Array of cookies for the current request.
125: * @return The session key decoded from the cookie, or null if the session
126: * was not found.
127: * @deprecated
128: */
129: private static String findSessionKey(Cookie[] cookies) {
130: if (cookies == null) {
131: return null;
132: }
133: for (int i = 0; i < cookies.length; i++) {
134: if (cookies[i].getName().equalsIgnoreCase(
135: ENHYDRA_SESSION_ID_COOKIE)) {
136: return cookies[i].getValue();
137: }
138: }
139: return null;
140: }
141:
142: /**
143: * Encode a URL with a session identifier.
144: *
145: * @param url
146: * The url to encode.
147: * @param id
148: * The session identifier to encode with the url.
149: */
150: public static String encodeUrl(String url, String id) {
151: String pre = url;
152: String post = "";
153: int pos;
154: // Need to put the parameters before a local anchor
155: if ((pos = url.indexOf('?')) != -1
156: || (pos = url.indexOf('#')) != -1) {
157: pre = url.substring(0, pos);
158: post = url.substring(pos);
159: }
160: return pre + ';' + ENHYDRA_SESSION_ID_URL + '=' + id + post;
161: }
162:
163: /**
164: * Determine if a URL references a presentation object. Used for URL
165: * rewriting to test if a session ID should be appended to a given URL.
166: * Takes the cheap way out at the moment in that it simply returns true iff
167: * (if and only if, for the non-mathematicians :-) the URL contains the
168: * character sequence <code>.po</code>. <br>
169: * TODO: Implement a better check A safety check has been added by Petr
170: * Stehlik on 2002/11/05 First, it strips a query and fragment parts of the
171: * URL, since both the query and the fragment may contain ".po" that
172: * confuses the original algorithm. <br>
173: * Example: <code>http://www.server.org/path/file.html?query=page.po</code>
174: * <br>
175: * The function now correctly returns false for the URL above.
176: *
177: * @param url
178: * The url to check
179: * @return True if the URL points to a PO, false otherwise
180: */
181: public static boolean pointsToPO(String url) {
182: // int idx = url.indexOf(".po");
183: // first, strip any query and fragment
184: int idx = url.indexOf('?'); // is there a query?
185: if (idx == -1) {
186: idx = url.indexOf('#'); // or is there a fragment?
187: }
188: if (idx > 0) {
189: url = url.substring(0, idx); // strip them!
190: }
191:
192: // now check for the ".po" (should be at the end of the URL)
193: idx = url.indexOf(".po");
194: if (idx == -1) {
195: return false;
196: }
197: if (idx == url.length() - 3) {
198: return true;
199: }
200: /*
201: * switch (url.charAt(idx+3)) { case '?': case '#': return true; case
202: * '/': // A bit more difficult: Need to decide if it's in the // the
203: * server or URI part of the URL. try { URL u = new URL(url); int i =
204: * u.getFile().indexOf(".po"); return (i != -1); } catch
205: * (MalformedURLException e) { // url doesn't contain a schema and/or
206: * server // part, so it must be relative. OK, found a PO. return true; }
207: * default: return false;
208: */
209: // if it's not at the end of the URL then decide if it's in the URI
210: if (url.charAt(idx + 3) == '/') {
211: // A bit more difficult: Need to decide if it's in the
212: // the server or URI part of the URL.
213: try {
214: URL u = new URL(url);
215: int i = u.getFile().indexOf(".po");
216: return (i != -1);
217: } catch (MalformedURLException e) {
218: // url doesn't contain a schema and/or server
219: // part, so it must be relative. OK, found a PO.
220: return true;
221: }
222: }
223: return false;
224: }
225:
226: /**
227: * Determine if a session exists for this request. Does not validate that a
228: * session is logged in.
229: *
230: * @param comms
231: * The presentations manager comms object with all
232: * request/response information in it.
233: * @return The session object or null if a session cookie or matching
234: * session is not found.
235: * @exception ApplicationException
236: * If address can't be obtained.
237: */
238: public static Session getRequestSession(HttpPresentationComms comms)
239: throws ApplicationException {
240: Session s = null;
241: String sessionKey = null;
242: Cookie[] cookies;
243: SessionManager sessionManager = (SessionManager) comms.application
244: .getSessionManager();
245:
246: try {
247: if (!sessionManager.getEncodeUrlState().equalsIgnoreCase(
248: SessionManager.ENCODE_URL_ALWAYS)) {
249: cookies = comms.request.getCookies();
250: sessionKey = findSessionKey(ENHYDRA_SESSION_ID_COOKIE,
251: cookies);
252: if (sessionKey != null) {
253: // These are set so that application programmers
254: // can determine the state of session cookies if not
255: // using automatic url encoding
256: comms.request.setRequestedSessionIdFromCookie(true);
257: comms.request.setRequestedSessionIdFromUrl(false);
258: comms.response.setSessionIdCookieRequired(true);
259: comms.response.setSessionIdEncodeUrlRequired(false);
260: }
261: }
262:
263: if (!sessionManager.getEncodeUrlState().equalsIgnoreCase(
264: SessionManager.ENCODE_URL_NEVER)
265: && sessionKey == null) {
266:
267: //
268: // This needs to be redone.
269: //
270: // if (comms.request.getHttpServletRequest() instanceof
271: // EnhydraRequest ) {
272: // EnhydraRequest er = (EnhydraRequest)
273: // comms.request.getHttpServletRequest();
274: // }
275:
276: // Check if sessionKey is encoded as a parameter in the path
277: // info (the form is http://localhost/foo.po;jsessionid=XYZ
278: HttpServletRequest servletRequest = comms.request
279: .getHttpServletRequest();
280: sessionKey = servletRequest.getRequestedSessionId();
281: if (sessionKey != null) {
282: if (servletRequest.isRequestedSessionIdFromURL()) {
283: comms.request
284: .setRequestedSessionIdFromUrl(true);
285: comms.request
286: .setRequestedSessionIdFromCookie(false);
287: comms.response
288: .setSessionIdEncodeUrlRequired(true);
289: comms.response
290: .setSessionIdCookieRequired(false);
291: }
292:
293: } else {
294: String pathInfo = comms.request.getPathInfo();
295: StringTokenizer tokens = new StringTokenizer(
296: pathInfo, "/\\;=", false);
297: while (tokens.hasMoreTokens()) {
298: String param = tokens.nextToken();
299: if (param
300: .equalsIgnoreCase(ENHYDRA_SESSION_ID_URL)) {
301: sessionKey = tokens.nextToken();
302: break;
303: }
304: }
305:
306: if (sessionKey != null) {
307: // These are set so that application programmers
308: // can determine the state of session cookies if not
309: // using automatic url encoding
310: comms.request
311: .setRequestedSessionIdFromUrl(true);
312: comms.request
313: .setRequestedSessionIdFromCookie(false);
314: comms.response
315: .setSessionIdEncodeUrlRequired(true);
316: comms.response
317: .setSessionIdCookieRequired(false);
318: }
319: }
320: }
321: } catch (HttpPresentationException except2) {
322: throw new ApplicationException(except2);
323: }
324: if (sessionKey == null) {
325: return null;
326: }
327:
328: try {
329: s = comms.application.getSessionManager().getSession(
330: Thread.currentThread(),
331: // sessionKey);
332: sessionKey, comms);
333: } catch (SessionException e) {
334: throw new ApplicationException(e);
335: }
336:
337: if (s != null
338: && !sessionManager.getEncodeUrlState()
339: .equalsIgnoreCase(
340: SessionManager.ENCODE_URL_NEVER)) {
341: comms.response.setSessionKey(s.getSessionKey());
342: comms.response.setSessionManager(comms.application
343: .getSessionManager());
344:
345: comms.session = s;
346: }
347: return s;
348: }
349:
350: /**
351: * This is a rarely used utility function. Give a raw ServletRequest, the
352: * session cookie used to look up the session object that would be used with
353: * the request if it were passed into the Enhydra framework. Returns null if
354: * no cookie or session is found; a new session will not be created.
355: * Currently this is only used to support the debugger.
356: *
357: * @param request
358: * The raw request.
359: * @param application
360: * The application that will be servicing the request.
361: * @return The session object that would be used if the request were passed
362: * into the Enhydra framework, or null if not found (no new session
363: * will be created).
364: */
365: public static Session getRequestSession(ServletRequest request,
366: Application application) throws ApplicationException {
367: if (application == null) {
368: return null;
369: }
370: Cookie[] cookies;
371: Session s;
372: HttpServletRequest req;
373: try {
374: req = (HttpServletRequest) request;
375: } catch (ClassCastException e) {
376: return null;
377: }
378: cookies = req.getCookies();
379: String sessionKey = findSessionKey(cookies);
380: if (sessionKey == null) {
381: return null;
382: }
383: SessionManager sm = application.getSessionManager();
384: if (sm == null) {
385: return null;
386: }
387: try {
388: s = sm.getSession(Thread.currentThread(), sessionKey);
389: } catch (SessionException e) {
390: throw new ApplicationException(e);
391: }
392: return s;
393: }
394:
395: /**
396: * Associate a new <CODE>StandardSession<CODE> to a client cookie.
397: *
398: * @param comms
399: * The presentations manager comms object with all
400: * request/response information in it.
401: * @exception ApplicationException
402: * If address can't be obtained.
403: */
404: public static void bindSessionToClient(HttpPresentationComms comms)
405: throws ApplicationException {
406:
407: Session session = (Session) comms.session;
408:
409: SessionManager sessionManager = (SessionManager) session
410: .getSessionManager();
411: /*if(sessionManager == null)
412: sessionManager = (SessionManager) comms.application.getSessionManager();*/
413:
414: if (!sessionManager.getEncodeUrlState().equalsIgnoreCase(
415: SessionManager.ENCODE_URL_ALWAYS)) {
416: try {
417: Cookie cookie = new Cookie(ENHYDRA_SESSION_ID_COOKIE,
418: session.getSessionKey());
419:
420: String cookiePath = "/";
421: if (!sessionManager.getEmptySessionPath()) {
422: cookiePath = comms.request.getApplicationPath();
423: if (cookiePath != null) {
424: cookiePath.trim();
425: if (cookiePath.endsWith("/")
426: && cookiePath.length() > 1) {
427: cookiePath = cookiePath.substring(0,
428: cookiePath.length() - 1);
429: }
430: }
431: }
432: cookie.setPath(cookiePath);
433:
434: // Do not set the domain (PJ).
435: /*
436: * String serverName = comms.request.getServerName(); int first =
437: * serverName.indexOf('.'); int last =
438: * serverName.lastIndexOf('.'); if ((first > -1) && (last > -1) &&
439: * (first != last)) {
440: * cookie.setDomain(serverName.substring(first)); }
441: */
442: comms.response.addCookie(cookie);
443: } catch (HttpPresentationException except) {
444: throw new ApplicationException(except);
445: }
446: }
447: if (!sessionManager.getEncodeUrlState().equalsIgnoreCase(
448: SessionManager.ENCODE_URL_NEVER)) {
449: comms.response.setSessionKey(comms.session.getSessionKey());
450: comms.response.setSessionManager(comms.application
451: .getSessionManager());
452: }
453: }
454: }
|