/* Wotonomy: OpenStep design patterns for pure Java applications. Copyright (C) 2003 Intersect Software Corp. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, see http://www.gnu.org */ package net.wotonomy.web; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamClass; import jakarta.servlet.http.HttpSession; /** * An implementation of WOSessionStore that stores WOSessions inside of * HttpSessions, to take advantage of the servlet containers built-in * distribution capabilities. * * @author michael@mpowers.net * @author $Author: cgruber $ * @version $Revision: 905 $ */ public class WOServletSessionStore extends WOSessionStore { private static final String ServletSessionKey = "WOServletSessionStoreKey"; /** * This implementation currently does nothing and returns null, as we rely on * the servlet container to dispose of the HttpSession which contains our * WOSession. */ @Override public WOSession removeSessionWithID(String sessionID) { return null; } /** * Returns the WOSession for the specified ID from the store. The sessionID * parameter is ignored, and the session is removed from the store until * saveSessionForContext is called. */ @Override public WOSession restoreSessionWithID(String sessionID, WORequest aRequest) { WOSession result = null; HttpSession servletSession = aRequest.servletRequest().getSession(); if (servletSession != null) { try { result = (WOSession) servletSession.getAttribute(ServletSessionKey); if (result != null) { // if the servlet's class loader has changed, we need to reload if (result.getClass().getClassLoader() != WOApplication.application().getClass().getClassLoader()) { throw new ClassCastException(result.getClass().toString()); } } } catch (ClassCastException exc) { // we're having an issue with the container's class loader: // try serializing and deserializing to see if it is reloaded correctly try { ByteArrayOutputStream bytes = new ByteArrayOutputStream(); ObjectOutputStream output = new ObjectOutputStream(bytes); Object o = servletSession.getAttribute(ServletSessionKey); output.writeObject(o); output.flush(); output.close(); System.out.println( "WOServletSessionStore: reloaded session with size: " + bytes.toByteArray().length); ObjectInputStream input = new CustomObjectInputStream(new ByteArrayInputStream(bytes.toByteArray()), WOApplication.application().getClass().getClassLoader()); o = input.readObject(); input.close(); // try it again result = (WOSession) o; } catch (Exception e) { e.printStackTrace(); // give up: remove the attribute and allow a new session servletSession.removeAttribute(ServletSessionKey); } } if (result != null) { servletSession.removeAttribute(ServletSessionKey); } } // System.out.println( "restoreSessionWithID: " + sessionID + " : " + result ); return result; } /** * Places the context's session into the store. */ @Override public void saveSessionForContext(WOContext context) { // System.out.println( "saveSessionForContext: " + context + " : " + // context.session() ); context.request().servletRequest().getSession(true).setAttribute(ServletSessionKey, context.session()); } /** * Needed to specify a class loader which may be different that the one used to * load the ObjectInputStream class. */ private static class CustomObjectInputStream extends ObjectInputStream { ClassLoader loader; public CustomObjectInputStream(InputStream anInputStream, ClassLoader aClassLoader) throws java.io.IOException, java.io.StreamCorruptedException { super(anInputStream); loader = aClassLoader; } @Override protected Class resolveClass(ObjectStreamClass v) throws IOException, ClassNotFoundException { return loader.loadClass(v.getName()); } } } /* * $Log$ Revision 1.2 2006/02/19 01:44:02 cgruber Add xmlrpc files Remove jclark * and replace with dom4j and javax.xml.sax stuff Re-work dependencies and * imports so it all compiles. * * Revision 1.1 2006/02/16 13:22:22 cgruber Check in all sources in * eclipse-friendly maven-enabled packages. * * Revision 1.7 2003/01/22 23:00:32 mpowers Now keeping the most recent page * around. * * Revision 1.6 2003/01/21 17:53:16 mpowers Now handling reloading when wotonomy * is on the system class path. * * Revision 1.5 2003/01/15 19:50:49 mpowers Fixed issues with WOSession and * Serializable. Can now persist sessions between classloaders (hot swap of * class impls). * * Revision 1.3 2003/01/14 16:05:19 mpowers Removed extraneous printlns. * * Revision 1.2 2003/01/13 22:25:07 mpowers Request-response cycle is working * with session and page persistence. * * Revision 1.1 2003/01/07 20:48:24 mpowers Implemented WOSessionStore and * WOServletSessionStore. * * */