/* 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 javax.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. */ 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. */ 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. */ 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; } 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. * * */