costin      00/12/31 16:17:24

  Modified:    .        changes3.3
               src/facade22/org/apache/tomcat/facade
                        HttpServletRequestFacade.java
                        HttpSessionFacade.java Servlet22Interceptor.java
               src/share/org/apache/tomcat/context LoaderInterceptor11.java
                        LoaderInterceptor12.java
               src/share/org/apache/tomcat/core BaseInterceptor.java
                        Container.java ContextManager.java Request.java
               src/share/org/apache/tomcat/modules/session SessionId.java
                        SimpleSessionStore.java
               src/share/org/apache/tomcat/request
                        CredentialsInterceptor.java ReloadInterceptor.java
               src/share/org/apache/tomcat/util ObjectSerializer.java
               src/share/org/apache/tomcat/util/hooks Hooks.java
               src/share/org/apache/tomcat/util/http Parameters.java
  Added:       src/share/org/apache/tomcat/core ServerSession.java
  Removed:     src/share/org/apache/tomcat/session ServerSession.java
                        ServerSessionManager.java
  Log:
  Finish ( I hope ) refactoring of session management.
  
  - ServerSession moved to core. It's no longer final - session manager modules
  can extend and replace the functionality.
  
  - added few more properties ( for symetry with other classes in core):
  notes, context, state, facade.
  
  - Replaced the "newSessionRequest" hook with 2 other hooks: findSession
  and sessionState. This allow modules to control most aspects of session
  processing.
  
  - Servlet22Interceptor now corectly handles servlet-specific aspects of
  session management - binding events, etc. That happens for both
  expired sessions and reloading.
  
  - Small improvement in reloading: we'll set a context note with the old
  class loader, and on session reloading we replace only the objects loaded
  with the old loader. That means an object that is loaded with the main
  class loader ( like DatabaseConnection ) will be valid after reload.
  ( should this be optional ? )
  
  - SessionId will now verify if the session is valid for both cookies and
  URL rewriting ( used to be only for cookies ). It'll also call "touch" -
  SimpleSessionManager will deal only with the 2 session hooks, no more
  intervention in the mapping hooks.
  
  - The ServerManager is now part of SimpleSessionStore. A session
  plugin is formed from a session manager and a tomcat 3.3 interceptor.
  
  Another small change: if the module implements "registerHooks", it'll
  be allowed to register the hooks itself, instead of using the automated
  code in Hooks. That means it can insert itself in front, end or after
  another module ( apache 2.0 style ) - by default the modules are inserted
  automatically at the end.
  
  Revision  Changes    Path
  1.5       +5 -0      jakarta-tomcat/changes3.3
  
  Index: changes3.3
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/changes3.3,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- changes3.3        2000/12/27 19:52:49     1.4
  +++ changes3.3        2001/01/01 00:17:22     1.5
  @@ -1,5 +1,10 @@
   -------------------- CORE --------------------
   
  +- reloading: objects loaded with the parent class loader will not be touched.
  +( faster, fewer problems with non-serializable objects )
  +
  +- better session plugability
  +
   - improved authentication - a bit of performance and more flexibility
    (CredentialInterceptor)
   
  
  
  
  1.16      +0 -1      
jakarta-tomcat/src/facade22/org/apache/tomcat/facade/HttpServletRequestFacade.java
  
  Index: HttpServletRequestFacade.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/facade22/org/apache/tomcat/facade/HttpServletRequestFacade.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- HttpServletRequestFacade.java     2000/12/30 07:54:10     1.15
  +++ HttpServletRequestFacade.java     2001/01/01 00:17:22     1.16
  @@ -64,7 +64,6 @@
   import org.apache.tomcat.util.http.*;
   import org.apache.tomcat.core.*;
   import org.apache.tomcat.facade.*;
  -import org.apache.tomcat.session.*;
   import java.io.*;
   import java.net.*;
   import java.security.*;
  
  
  
  1.6       +3 -2      
jakarta-tomcat/src/facade22/org/apache/tomcat/facade/HttpSessionFacade.java
  
  Index: HttpSessionFacade.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/facade22/org/apache/tomcat/facade/HttpSessionFacade.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- HttpSessionFacade.java    2000/12/01 19:59:21     1.5
  +++ HttpSessionFacade.java    2001/01/01 00:17:22     1.6
  @@ -61,7 +61,6 @@
   package org.apache.tomcat.facade;
   
   import org.apache.tomcat.core.*;
  -import org.apache.tomcat.session.*;
   import org.apache.tomcat.util.StringManager;
   import java.io.*;
   import java.net.*;
  @@ -102,6 +101,7 @@
        */
       void setRealSession(ServerSession s) {
        realSession=s;
  +     realSession.setFacade( this );
        }
   
       /** Package-level method - accessible only by core
  @@ -180,7 +180,8 @@
       public void setAttribute(String name, Object value) {
        checkValid();
   
  -     ServerSessionManager ssm=realSession.getSessionManager();
  +     //      ServerSessionManager ssm=(ServerSessionManager)
  +     //          realSession.getManager();
        // Original code - it's up to session manager to decide
        // what it can handle. 
        //      if (ssm.isDistributable() &&
  
  
  
  1.10      +36 -0     
jakarta-tomcat/src/facade22/org/apache/tomcat/facade/Servlet22Interceptor.java
  
  Index: Servlet22Interceptor.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/facade22/org/apache/tomcat/facade/Servlet22Interceptor.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- Servlet22Interceptor.java 2000/12/14 07:10:56     1.9
  +++ Servlet22Interceptor.java 2001/01/01 00:17:22     1.10
  @@ -157,6 +157,42 @@
        }
            
       }
  +
  +
  +    /** Call the Servlet22 callbacks when session expires.
  +     */
  +    public int sessionState( Request req, ServerSession sess, int newState)
  +    {
  +     if( newState==ServerSession.STATE_SUSPEND ||
  +         newState==ServerSession.STATE_EXPIRED )   {
  +         
  +         // generate "unbould" events when the session is suspended or
  +         // expired
  +         Vector removed=new Vector();
  +         Enumeration e = sess.getAttributeNames();
  +         // announce all values with listener that we'll remove them
  +         while( e.hasMoreElements() )   {
  +             String key = (String) e.nextElement();
  +             Object value = sess.getAttribute(key);
  +
  +             HttpSession httpSess=(HttpSession)sess.getFacade();
  +             
  +             if( value instanceof  HttpSessionBindingListener) {
  +                 ((HttpSessionBindingListener) value).valueUnbound
  +                     (new HttpSessionBindingEvent(httpSess , key));
  +                 removed.addElement( key );
  +             }
  +         }
  +         // remove
  +         e=removed.elements();
  +         while( e.hasMoreElements() ) {
  +             String key = (String) e.nextElement();
  +             sess.removeAttribute( key );
  +         }
  +     } 
  +     return 0;
  +    }
  +
       
       public int postRequest(Request rreq, Response rres ) {
        //if( rreq.getContext() != ctx ) return; // throw
  
  
  
  1.8       +4 -0      
jakarta-tomcat/src/share/org/apache/tomcat/context/LoaderInterceptor11.java
  
  Index: LoaderInterceptor11.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/context/LoaderInterceptor11.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- LoaderInterceptor11.java  2000/09/30 04:43:28     1.7
  +++ LoaderInterceptor11.java  2001/01/01 00:17:22     1.8
  @@ -149,6 +149,10 @@
   
        DependManager dm=new DependManager();
        context.setDependManager( dm );
  +     ClassLoader oldLoader=context.getClassLoader();
  +     int oldLoaderNote=cm.getNoteId( ContextManager.CONTAINER_NOTE,
  +                                     "oldLoader");
  +     context.getContainer().setNote( oldLoaderNote, oldLoader);
        
        // XXX Customize this - based on context prefs,
        // select the right parent - it may be CM.getParentLoader()
  
  
  
  1.6       +5 -0      
jakarta-tomcat/src/share/org/apache/tomcat/context/LoaderInterceptor12.java
  
  Index: LoaderInterceptor12.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/context/LoaderInterceptor12.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- LoaderInterceptor12.java  2000/09/30 04:43:28     1.5
  +++ LoaderInterceptor12.java  2001/01/01 00:17:22     1.6
  @@ -156,6 +156,11 @@
        ContextManager cm = context.getContextManager();
        URL urls[]=context.getClassPath();
   
  +     ClassLoader oldLoader=context.getClassLoader();
  +     int oldLoaderNote=cm.getNoteId( ContextManager.CONTAINER_NOTE,
  +                                     "oldLoader");
  +     context.getContainer().setNote( oldLoaderNote, oldLoader);
  +
        DependManager dm=new DependManager();
        context.setDependManager( dm );
   
  
  
  
  1.36      +54 -8     
jakarta-tomcat/src/share/org/apache/tomcat/core/BaseInterceptor.java
  
  Index: BaseInterceptor.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/BaseInterceptor.java,v
  retrieving revision 1.35
  retrieving revision 1.36
  diff -u -r1.35 -r1.36
  --- BaseInterceptor.java      2000/12/29 20:31:26     1.35
  +++ BaseInterceptor.java      2001/01/01 00:17:23     1.36
  @@ -61,6 +61,7 @@
   package org.apache.tomcat.core;
   
   import org.apache.tomcat.util.log.*;
  +import org.apache.tomcat.util.hooks.*;
   
   /** Implement "Chain of Responsiblity" pattern ( == hooks ).
    *
  @@ -165,15 +166,53 @@
        return 0;
       }
   
  -    /** New Session notification - called when the servlet
  -     asks for a new session. You can do all kind of stuff with
  -     this notification - the most important is create a session
  -     object. This will be the base for controling the
  -     session allocation.
  -    */
  -    public int newSessionRequest( Request request, Response response) {
  +//     /** New Session notification - called when the servlet
  +//   asks for a new session. You can do all kind of stuff with
  +//   this notification - the most important is create a session
  +//   object. This will be the base for controling the
  +//   session allocation.
  +//     */
  +//     public int newSessionRequest( Request request, Response response) {
  +//   return 0;
  +//     }
  +
  +    /** The hook for session managers. It'll be called to
  +     *  find or create a ServerSession object associated with a request.
  +     *
  +     *  There are 2 components of tomcat's session management - finding 
  +     *  the session ID, typically done during mapping ( either in tomcat
  +     *  or by a load balancer or web server ) and the actual storage
  +     *  manager ( including expiration, persistence, events, etc ).
  +     *
  +     *  This hook allow to plug different session managers. The mapping
  +     *  hooks ( combined with native code in the server/load balancer )
  +     *  are used to determine the session id and do low-level operations.
  +     *
  +     *  The hook will be called from the mapping hook whenever a session
  +     *  is detected ( create==false ) - the manager can update the timers.
  +     *  It will also be called if the user requests a new session, and
  +     *  none is created.
  +     *
  +     *  XXX should we return a status code and let the manager call
  +     *  req.setSession() ? Returning ServerSession seems more flexible,
  +     *  ( but different from the rest of the hooks )
  +     * @param reqSessionId if null the manager will generate the id
  +     */
  +    public ServerSession findSession( Request req,
  +                                   String reqSessionId, boolean create) {
  +     return null;
  +    }
  +
  +    /** Hook for session state changes.
  +     *  Will be called every time a session change it's state.
  +     *  A session module will announce all changes - like STATE_NEW when
  +     *  the session is created, STATE_EXPIRED when the session is expired,
  +     *  STATE_INVALID when the session is invalidated.
  +     */
  +    public int sessionState( Request req, ServerSession sess, int newState) {
        return 0;
       }
  +
       
       /** Called before the output buffer is commited.
        */
  @@ -367,6 +406,13 @@
       {
       }
   
  +    /** Notify that the context state changed
  +     */
  +    public void contextState( Context ctx, int newState )
  +     throws TomcatException
  +    {
  +    }
  +    
       /** Reload notification - called whenever a reload is done.
        This can be used to serialize sessions, log the event,
        remove any resource that was class-loader dependent.
  @@ -522,7 +568,7 @@
        *  a mechanism similar with Apache2.0 and further extensibility
        *  without interface changes.
        */
  -    public int registerHooks() {
  +    public int registerHooks(Hooks h) {
        return DECLINED;
       }
   
  
  
  
  1.44      +15 -9     jakarta-tomcat/src/share/org/apache/tomcat/core/Container.java
  
  Index: Container.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/Container.java,v
  retrieving revision 1.43
  retrieving revision 1.44
  diff -u -r1.43 -r1.44
  --- Container.java    2000/12/29 20:31:27     1.43
  +++ Container.java    2001/01/01 00:17:23     1.44
  @@ -380,13 +380,14 @@
       public static final int H_authorize=3;
       public static final int H_preService=4;
       public static final int H_beforeBody=5;
  -    public static final int H_newSessionRequest=6;
  -    public static final int H_beforeCommit=7;
  -    public static final int H_afterBody=8;
  -    public static final int H_postService=9;
  -    public static final int H_postRequest=10;
  -    public static final int H_handleError=11;
  -    public static final int H_engineInit=12;
  +    public static final int H_findSession=6;
  +    public static final int H_sessionState=7;
  +    public static final int H_beforeCommit=8;
  +    public static final int H_afterBody=9;
  +    public static final int H_postService=10;
  +    public static final int H_postRequest=11;
  +    public static final int H_handleError=12;
  +    public static final int H_engineInit=13;
       public static final int H_COUNT=14;
   
       Hooks hooks=new Hooks();
  @@ -400,7 +401,8 @@
        hooks.registerHook( "authorize", H_authorize );
        hooks.registerHook( "preService", H_preService );
        hooks.registerHook( "beforeBody", H_beforeBody );
  -     hooks.registerHook( "newSessionRequest", H_newSessionRequest );
  +     hooks.registerHook( "findSession", H_findSession );
  +     hooks.registerHook( "sessionState", H_sessionState );
        hooks.registerHook( "beforeCommit", H_beforeCommit );
        hooks.registerHook( "afterBody", H_afterBody );
        hooks.registerHook( "postService", H_postService );
  @@ -419,7 +421,11 @@
       public void addInterceptor( BaseInterceptor bi ) {
        bi.setContext( getContext() );
   
  -     hooks.addModule( bi );
  +     if( Hooks.hasHook( bi, "registerHooks" ) ) {
  +         bi.registerHooks( hooks );
  +     } else {
  +         hooks.addModule( bi );
  +     }
        hooksCache=null;
        allHooksCache=null;
       }
  
  
  
  1.163     +3 -2      
jakarta-tomcat/src/share/org/apache/tomcat/core/ContextManager.java
  
  Index: ContextManager.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/ContextManager.java,v
  retrieving revision 1.162
  retrieving revision 1.163
  diff -u -r1.162 -r1.163
  --- ContextManager.java       2000/12/29 20:31:27     1.162
  +++ ContextManager.java       2001/01/01 00:17:23     1.163
  @@ -865,18 +865,19 @@
       /** Note id counters. Synchronized access is not necesarily needed
        *  ( the initialization is in one thread ), but anyway we do it
        */
  -    public static final int NOTE_COUNT=5;
  +    public static final int NOTE_COUNT=8;
       private  int noteId[]=new int[NOTE_COUNT];
   
       /** Maximum number of notes supported
        */
       public static final int MAX_NOTES=32;
  -    public static final int RESERVED=3;
  +    public static final int RESERVED=5;
   
       public static final int SERVER_NOTE=0;
       public static final int CONTAINER_NOTE=1;
       public static final int REQUEST_NOTE=2;
       public static final int HANDLER_NOTE=3;
  +    public static final int SESSION_NOTE=4;
       
       public static final int REQ_RE_NOTE=0;
   
  
  
  
  1.86      +11 -16    jakarta-tomcat/src/share/org/apache/tomcat/core/Request.java
  
  Index: Request.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/Request.java,v
  retrieving revision 1.85
  retrieving revision 1.86
  diff -u -r1.85 -r1.86
  --- Request.java      2000/12/30 07:54:12     1.85
  +++ Request.java      2001/01/01 00:17:23     1.86
  @@ -69,8 +69,6 @@
   
   import org.apache.tomcat.util.http.*;
   
  -import org.apache.tomcat.session.ServerSession;
  -
   import java.security.Principal;
   import java.io.IOException;
   import java.util.Enumeration;
  @@ -527,27 +525,24 @@
   
       
       public ServerSession getSession(boolean create) {
  +     if (serverSession!=null && !serverSession.isValid())
  +         serverSession=null;
   
  +     if( ! create || serverSession!=null )
  +         return serverSession;
   
  -     if( serverSession!=null ) {
  -             /// XXX a forwarded request whose session was invalidated
  -            if (!serverSession.getTimeStamp().isValid() && create){
  -                 serverSession.getSessionManager().removeSession( serverSession );
  -                 serverSession=null;
  -            } else
  -                // if not null, it is validated by the session module
  -             return serverSession;
  -     }
  +     // create && serverSession==null
   
  -     if( ! create ) return null;
  -        
        BaseInterceptor reqI[]= getContainer().
  -         getInterceptors(Container.H_newSessionRequest);
  +         getInterceptors(Container.H_findSession);
   
        for( int i=0; i< reqI.length; i++ ) {
  -         reqI[i].newSessionRequest( this, response );
  +         serverSession=reqI[i].findSession( this, null, create );
  +         if( serverSession!=null ) break;
        }
  -
  +     if( serverSession!= null ) {
  +         setSessionId( serverSession.getId().toString());
  +     }
        return serverSession;
       }
   
  
  
  
  1.3       +134 -125  
jakarta-tomcat/src/share/org/apache/tomcat/core/ServerSession.java
  
  
  
  
  1.8       +87 -50    
jakarta-tomcat/src/share/org/apache/tomcat/modules/session/SessionId.java
  
  Index: SessionId.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/modules/session/SessionId.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- SessionId.java    2000/12/30 08:26:48     1.7
  +++ SessionId.java    2001/01/01 00:17:23     1.8
  @@ -62,8 +62,6 @@
   import org.apache.tomcat.core.*;
   import org.apache.tomcat.util.*;
   import org.apache.tomcat.util.http.*;
  -import org.apache.tomcat.session.ServerSessionManager;
  -import org.apache.tomcat.session.ServerSession;
   import java.io.*;
   import java.net.*;
   import java.util.*;
  @@ -73,12 +71,15 @@
    * session rewriting.
    * 
    * Will process the request and determine the session Id, and set it
  - * in the Request. It doesn't marks the session as accessed.
  + * in the Request. It doesn't marks the session as accessed, and it
  + * doesn't retrieve or set the HttpSession - the storage and management
  + * of sessions is implemented in a separate module. 
    *
    * This interceptor doesn't deal with any of the Session internals -
    * it just works with the sessionID. A pluggable session manager 
    *  ( or user-space manager !) will deal with marking the session
  - * as accessed or setting the session implementation.
  + * as accessed or setting the session implementation and maintaining
  + * lifecycles.
    *
    * This implementation only handles Cookies and URL rewriting sessions,
    * please extend or add new interceptors for other methods.
  @@ -90,27 +91,24 @@
    */
   public class SessionId extends  BaseInterceptor
   {
  -    private int manager_note;
  -    
       // GS, separates the session id from the jvm route
       static final char SESSIONID_ROUTE_SEP = '.';
       ContextManager cm;
       boolean noCookies=false;
  +    boolean cookiesFirst=true;
       
       public SessionId() {
       }
   
  -    public void setNoCookies(boolean noCookies) {
  -        this.noCookies = noCookies;
  +    public void setCookiesFirst( boolean b ) {
  +     cookiesFirst=b;
       }
   
  -    public void engineInit( ContextManager cm ) throws TomcatException {
  -     // set-up a per/container note for StandardManager
  -     // the standard manager is used to verify the session ID.
  -     manager_note = cm.getNoteId( ContextManager.CONTAINER_NOTE,
  -                                  "tomcat.standardManager");
  +    public void setNoCookies(boolean noCookies) {
  +        this.noCookies = noCookies;
       }
   
  +    
       /** Extract the session id from the request.
        * SessionInterceptor will have to be called _before_ mapper,
        * to avoid coding session stuff inside the mapper.
  @@ -125,7 +123,12 @@
            return 0;
        }
   
  -     // fix URL rewriting
  +     // quick test: if no extra path, no url rewriting.
  +     if( request.requestURI().indexOf( ';' ) < 0 )
  +         return 0;
  +     
  +     // In case URI rewriting is used, extract the uri and fix
  +     // the request.
        String sig=";jsessionid=";
        int foundAt=-1;
        String uri=request.requestURI().toString();
  @@ -133,9 +136,6 @@
        
        if ((foundAt=uri.indexOf(sig))!=-1){
            sessionId=uri.substring(foundAt+sig.length());
  -         // FIX [EMAIL PROTECTED]: reloading 
  -         //      sessionId = fixSessionId( request, sessionId );
  -         
            // rewrite URL, do I need to do anything more?
            request.requestURI().setString(uri.substring(0, foundAt));
   
  @@ -147,8 +147,14 @@
        return 0;
       }
   
  -    /** This happens after context map, so we know the context.
  -     *  We can probably do it later too.
  +    /**
  +     *  Extract and set the session id and ServerSession.
  +     *  We know the Context - and all local interceptors can be used
  +     *  ( like session managers that are set per context ).
  +     *
  +     *  This module knows about URI and cookies. It will validate the
  +     *  session id ( and set it only if valid ), and "touch" the 
  +     *  session.
        */
       public int requestMap(Request request ) {
        String sessionId = null;
  @@ -159,9 +165,19 @@
            return 0;
        }
   
  -
        int count=request.getCookies().getCookieCount();
   
  +     ServerSession sess=null;
  +
  +     if( ! cookiesFirst  ) {
  +         // try the information from URL rewriting
  +         sessionId= request.getRequestedSessionId();
  +         sess=processSession( request, sessionId,
  +                           request.getSessionIdSource() );
  +         if( sess!=null )
  +             return 0;
  +     }
  +     
        // Give priority to cookies. I don't know if that's part
        // of the spec - XXX
        for( int i=0; i<count; i++ ) {
  @@ -171,28 +187,68 @@
                sessionId = cookie.getValue().toString();
                if (debug > 0) log("Found session id cookie " +
                                   sessionId);
  -             // 3.2 - load balancing fix
  -             // sessionId = fixSessionId( request, sessionId );
                // 3.2 - PF ( [EMAIL PROTECTED] ): check the session id from
                // cookies for validity
  -
  -             ServerSessionManager sM = getManager( ctx );
  -             ServerSession sess = sM.findSession(sessionId);
  +             sess=processSession( request, sessionId,
  +                               Request.SESSIONID_FROM_COOKIE );
                if (sess != null) {
  -                 request.setRequestedSessionId( sessionId );
  -                 request.setSessionIdSource(Request.SESSIONID_FROM_COOKIE );
  -                 // since we verified this sessionID, we can also set
  -                 // it and adjust the session
  -                 request.setSession( sess );
  -                 request.setSessionId( sessionId );
                    break;
                }
            }
        }
   
  +     if( sess==null ) {
  +         // try the information from URL rewriting
  +         sessionId= request.getRequestedSessionId();
  +         sess=processSession( request, sessionId,
  +                           request.getSessionIdSource() );
  +         if( sess!=null )
  +             return 0;
  +     }
  +
        return 0;
       }
   
  +
  +    /** Find the session, set session id, source, mark it as accessed.
  +     */
  +    private ServerSession processSession(Request request,
  +                          String sessionId, String source )
  +    {
  +     BaseInterceptor reqI[]= request.getContainer().
  +         getInterceptors(Container.H_findSession);
  +     
  +     ServerSession sess=null;
  +     for( int i=0; i< reqI.length; i++ ) {
  +         sess=reqI[i].findSession( request,
  +                                   sessionId,  false );
  +         if( sess!=null ) break;
  +     }
  +
  +     if (sess != null) {
  +         request.setRequestedSessionId( sessionId );
  +         request.setSessionIdSource( source );
  +         // since we verified this sessionID, we can also set
  +         // it and adjust the session
  +         request.setSession( sess );
  +         request.setSessionId( sessionId );
  +         
  +         sess.touch( System.currentTimeMillis() );
  +
  +         // if the session was NEW ( never accessed - change it's state )
  +         if( sess.getState() == ServerSession.STATE_NEW ) {
  +             reqI= request.getContainer().
  +                 getInterceptors(Container.H_sessionState);
  +             for( int i=0; i< reqI.length; i++ ) {
  +                 reqI[i].sessionState( request,
  +                                       sess,  ServerSession.STATE_ACCESSED);
  +             }
  +             sess.setState( ServerSession.STATE_ACCESSED);
  +         }
  +     }
  +     return sess;
  +    }
  +    
   //     /** Fix the session id. If the session is not valid return null.
   //      *  It will also clean up the session from load-balancing strings.
   //      * @return sessionId, or null if not valid
  @@ -242,19 +298,6 @@
   //             }
   //  //     }
   
  -     // we know reqSessionId doesn't need quoting ( we generate it )
  -//   StringBuffer buf = new StringBuffer();
  -//   buf.append( "JSESSIONID=" ).append( reqSessionId );
  -//   buf.append( ";Version=1" );
  -//   buf.append( ";Path=" );
  -//   ServerCookie.maybeQuote( 1 , buf, sessionPath ); // XXX ugly 
  -//   buf.append( ";Discard" );
  -//   // discard results from:        cookie.setMaxAge(-1);
  -     
  -     
  -//   response.addHeader( "Set-Cookie2",
  -//                       buf.toString() ); // XXX XXX garbage generator
  -
        // We'll use a Netscape cookie for sessions - it's
        // the only one supported by all browsers
        StringBuffer buf = new StringBuffer();
  @@ -265,11 +308,5 @@
        
        return 0;
       }
  -
  -    // -------------------- Internal methods --------------------
  -    private ServerSessionManager getManager( Context ctx ) {
  -     return (ServerSessionManager)ctx.getContainer().getNote(manager_note);
  -    }
  -
   
   }
  
  
  
  1.6       +253 -94   
jakarta-tomcat/src/share/org/apache/tomcat/modules/session/SimpleSessionStore.java
  
  Index: SimpleSessionStore.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/modules/session/SimpleSessionStore.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- SimpleSessionStore.java   2000/12/26 23:26:15     1.5
  +++ SimpleSessionStore.java   2001/01/01 00:17:23     1.6
  @@ -59,14 +59,14 @@
   package org.apache.tomcat.modules.session;
   
   import java.io.*;
  -import java.util.Enumeration;
  -import java.util.Hashtable;
  -import java.util.Vector;
   import java.util.Random;
   import org.apache.tomcat.util.*;
   import org.apache.tomcat.util.threads.*;
   import org.apache.tomcat.core.*;
  -import org.apache.tomcat.session.*;
  +import java.util.*;
  +import org.apache.tomcat.util.collections.SimplePool;
  +import org.apache.tomcat.util.log.*;
  +//import org.apache.tomcat.session.*;
   
   
   /**
  @@ -133,111 +133,93 @@
        manager_note = cm.getNoteId( ContextManager.CONTAINER_NOTE,
                                     "tomcat.standardManager");
       }
  -
  -    /**
  -     *  StandardManager will set the HttpSession if one is found.
  -     */
  -    public int requestMap(Request request ) {
  -     String sessionId = null;
  -     Context ctx=request.getContext();
  -     if( ctx==null ) {
  -         log( "Configuration error in StandardSessionInterceptor " +
  -              " - no context " + request );
  -         return 0;
  -     }
  -
  -     // "access" it and set HttpSession if valid
  -     sessionId=request.getRequestedSessionId();
  -
  -     if (sessionId != null && sessionId.length()!=0) {
  -         // GS, We are in a problem here, we may actually get
  -         // multiple Session cookies (one for the root
  -         // context and one for the real context... or old session
  -         // cookie. We must check for validity in the current context.
  -         ServerSessionManager sM = getManager( ctx );    
  -         ServerSession sess= request.getSession( false );
  -
  -         // if not set already, try to find it using the session id
  -         if( sess==null )
  -             sess=sM.findSession( sessionId );
  -
  -         // 3.2 - Hans fix ( use the session id from URL ) - it's
  -         // part of the current code
  -
  -         // 3.2 - PF ( [EMAIL PROTECTED] ): fix moved to SessionId.
  -         // ( check if the ID is valid before setting it, do that
  -         //  for cookies since we can have multiple cookies, some
  -         //  from old sessions )
  -
  -         if(null != sess) {
  -             // touch it 
  -             sess.getTimeStamp().touch( System.currentTimeMillis() );
  -
  -             //log("Session found " + sessionId );
  -             // set it only if nobody else did !
  -             if( null == request.getSession( false ) ) {
  -                 request.setSession( sess );
  -                 // XXX use MessageBytes!
  -                 request.setSessionId( sessionId );
  -                 //log("Session set " + sessionId );
  -             }
  -         }
  -         return 0;
  -     }
  -     return 0;
  -    }
       
  -    public void reload( Request req, Context ctx ) {
  +    public void reload( Request req, Context ctx ) throws TomcatException {
        ClassLoader newLoader = ctx.getClassLoader();
  -     ServerSessionManager sM = getManager( ctx );    
  +     SimpleSessionManager sM = getManager( ctx );    
   
        // remove all non-serializable objects from session
        Enumeration sessionEnum=sM.getSessions().keys();
        while( sessionEnum.hasMoreElements() ) {
            ServerSession session = (ServerSession)sessionEnum.nextElement();
  +
  +         // Move it to SUSPEND state
  +         BaseInterceptor reqI[]= req.getContainer().
  +             getInterceptors(Container.H_sessionState);
  +         for( int i=0; i< reqI.length; i++ ) {
  +             // during suspend hook the servlet callbacks will be called
  +             // - typically from the ServletInterceptor
  +             reqI[i].sessionState( req,
  +                                   session,  ServerSession.STATE_SUSPEND);
  +         }
  +         session.setState( ServerSession.STATE_SUSPEND );
  +         
  +         int oldLoaderNote=cm.getNoteId( ContextManager.CONTAINER_NOTE,
  +                                         "oldLoader");
  +         ClassLoader oldLoader=(ClassLoader)ctx.getContainer().
  +             getNote(oldLoaderNote);
  +
  +         Hashtable newSession=new Hashtable();
            Enumeration e = session.getAttributeNames();
            while( e.hasMoreElements() )   {
                String key = (String) e.nextElement();
                Object value = session.getAttribute(key);
  -             // XXX XXX We don't have to change loader for objects loaded
  -             // by the parent loader ?
  -             if (! ( value instanceof Serializable)) {
  -                 session.removeAttribute( key );
  -                 // XXX notification!!
  -             }
  +
  +             if( value.getClass().getClassLoader() != oldLoader ) {
  +                 // it's loaded by the parent loader, no need to reload
  +                 newSession.put( key, value );
  +             } else if ( value instanceof Serializable ) {
  +                 Object newValue =
  +                     ObjectSerializer.doSerialization( newLoader,
  +                                                       value);
  +                 newSession.put( key, newValue );
  +             } 
            }
  -     }
  +
  +         // Move it to RESTORE state
  +         reqI= req.getContainer().
  +             getInterceptors(Container.H_sessionState);
  +         for( int i=0; i< reqI.length; i++ ) {
  +             // during suspend hook the servlet callbacks will be called
  +             // - typically from the ServletInterceptor
  +             reqI[i].sessionState( req,
  +                                   session,  ServerSession.STATE_RESTORED);
  +         }
  +         session.setState( ServerSession.STATE_RESTORED );
   
  -     // XXX We should change the loader for each object, and
  -     // avoid accessing object's internals
  -     // XXX PipeStream !?!
  -     Hashtable orig= sM.getSessions();
  -     Object newS = ObjectSerializer.doSerialization( newLoader, orig);
  -     sM.setSessions( (Hashtable)newS );
  -     
  -     // Update the request session id
  -     String reqId=req.getRequestedSessionId();
  -     ServerSession sS=sM.findSession( reqId );
  -     if ( sS != null) {
  -         req.setSession(sS);
  -         req.setSessionId( reqId );
  +         /* now put back all attributs */
  +         e=newSession.keys();
  +         while(e.hasMoreElements() ) {
  +             String key = (String) e.nextElement();
  +             Object value=newSession.get(key );
  +             session.setAttribute( key, value );
  +         }
        }
  +
  +     
       }
  -    
  -    public int newSessionRequest( Request request, Response response) {
  +
  +    /** The session store hook
  +     */
  +    public ServerSession findSession( Request request,
  +                                   String sessionId, boolean create)
  +    {
        Context ctx=request.getContext();
  -     if( ctx==null ) return 0;
  +     if( ctx==null ) return null;
  +     SimpleSessionManager sM = getManager( ctx );    
        
  -     ServerSessionManager sM = getManager( ctx );    
  +     ServerSession sess=sM.findSession( sessionId );
  +     if( sess!= null ) return sess;
   
  -     if( request.getSession( false ) != null )
  -         return 0; // somebody already set the session
  +     if( ! create ) return null; // not found, don't create
   
  +     // create new session
        // Fix from Shai Fultheim: load balancing needs jvmRoute
        ServerSession newS=sM.getNewSession(request.getJvmRoute());
  -     request.setSession( newS );
  -     request.setSessionId( newS.getId().toString());
  -     return 0;
  +     if( newS==null ) return null;
  +     newS.setContext( ctx );
  +     
  +     return newS;
       }
   
       //--------------------  Tomcat context events --------------------
  @@ -247,10 +229,10 @@
        */
       public void contextInit(Context ctx) throws TomcatException {
        // Defaults !!
  -     ServerSessionManager sm= getManager( ctx );
  +     SimpleSessionManager sm= getManager( ctx );
        
        if( sm == null ) {
  -         sm=new ServerSessionManager();
  +         sm=new SimpleSessionManager();
            ctx.getContainer().setNote( manager_note, sm );
            if( randomClassName==null )
                setRandomClass("java.security.SecureRandom" );
  @@ -265,7 +247,8 @@
        expirer.setExpireCallback( new Expirer.ExpireCallback() {
                public void expired(TimeStamp o ) {
                    ServerSession sses=(ServerSession)o.getParent();
  -                 ServerSessionManager ssm=sses.getSessionManager();
  +                 SimpleSessionManager ssm=(SimpleSessionManager)
  +                     sses.getManager();
                    ssm.removeSession( sses );
                }
            });
  @@ -281,14 +264,14 @@
        throws TomcatException
       {
        if( debug > 0 ) ctx.log("Removing sessions from " + ctx );
  -     ServerSessionManager sm=getManager(ctx);
  +     SimpleSessionManager sm=getManager(ctx);
        sm.getExpirer().stop();
        sm.removeAllSessions();
       }
   
       // -------------------- Internal methods --------------------
  -    private ServerSessionManager getManager( Context ctx ) {
  -     return (ServerSessionManager)ctx.getContainer().getNote(manager_note);
  +    private SimpleSessionManager getManager( Context ctx ) {
  +     return (SimpleSessionManager)ctx.getContainer().getNote(manager_note);
       }
   
       private Random createRandomClass( String s ) {
  @@ -307,4 +290,180 @@
        return randomSource;
       }
       
  +}
  +
  +/**
  + * The actual "simple" manager
  + * 
  + */
  +class SimpleSessionManager  
  +{
  +    protected Log loghelper = new Log("tc_log", this);
  +    
  +    /** The set of previously recycled Sessions for this Manager.
  +     */
  +    protected SimplePool recycled = new SimplePool();
  +
  +    /**
  +     * The set of currently active Sessions for this Manager, keyed by
  +     * session identifier.
  +     */
  +    protected Hashtable sessions = new Hashtable();
  +
  +    protected Expirer expirer;
  +    /**
  +     * The interval (in seconds) between checks for expired sessions.
  +     */
  +    private int checkInterval = 60;
  +
  +    /**
  +     * The maximum number of active Sessions allowed, or -1 for no limit.
  +     */
  +    protected int maxActiveSessions = -1;
  +
  +    long maxInactiveInterval;
  +    
  +    protected Reaper reaper;
  +    Random randomSource=null;
  +    
  +    public SimpleSessionManager() {
  +    }
  +
  +    public void setExpirer( Expirer ex ) {
  +     expirer = ex;
  +    }
  +
  +    public Expirer getExpirer() {
  +     return expirer;
  +    }
  +
  +    public void setRandomSource( Random r ) {
  +     randomSource=r;
  +    }
  +
  +    // ------------------------------------------------------------- Properties
  +
  +    public int getMaxActiveSessions() {
  +     return maxActiveSessions;
  +    }
  +
  +    public void setMaxActiveSessions(int max) {
  +     maxActiveSessions = max;
  +    }
  +
  +    // --------------------------------------------------------- Public Methods
  +
  +    public void setMaxInactiveInterval( long l ) {
  +     maxInactiveInterval=l;
  +    }
  +    
  +    /**
  +     * Return the default maximum inactive interval (in miliseconds)
  +     * for Sessions created by this Manager. We use miliseconds
  +     * because that's how the time is expressed, avoid /1000
  +     * in the common code
  +     */
  +    public long getMaxInactiveInterval() {
  +     return maxInactiveInterval;
  +    }
  +
  +
  +    public Hashtable getSessions() {
  +     return sessions;
  +    }
  +    
  +    public void setSessions(Hashtable s) {
  +     sessions=s;
  +    }
  +
  +    public ServerSession findSession(String id) {
  +     if (id == null) return null;
  +     return (ServerSession)sessions.get(id);
  +    }
  +
  +    /**
  +     * Remove this Session from the active Sessions for this Manager.
  +     *
  +     * @param session Session to be removed
  +     */
  +    public void removeSession(ServerSession session) {
  +     sessions.remove(session.getId().toString());
  +     recycled.put(session);
  +     // announce the state change
  +     BaseInterceptor reqI[]=session.getContext().getContainer().
  +         getInterceptors(Container.H_sessionState);
  +     for( int i=0; i< reqI.length; i++ ) {
  +         // during suspend hook the servlet callbacks will be called
  +         // - typically from the ServletInterceptor
  +         reqI[i].sessionState( null,
  +                               session,  ServerSession.STATE_EXPIRED);
  +     }
  +     session.setState( ServerSession.STATE_EXPIRED );
  +     
  +     session.removeAllAttributes();
  +     expirer.removeManagedObject( session.getTimeStamp());
  +     session.setValid(false);
  +     
  +    }
  +
  +    public ServerSession getNewSession() {
  +     return getNewSession( null ) ;
  +    }
  +    
  +    public ServerSession getNewSession(String jsIdent) {
  +     if ((maxActiveSessions >= 0) &&
  +         (sessions.size() >= maxActiveSessions)) {
  +         loghelper.log( "Too many sessions " + maxActiveSessions );
  +         return null;
  +     }
  +
  +     // Recycle or create a Session instance
  +     ServerSession session = (ServerSession)recycled.get();
  +     if (session == null) {
  +         session = new ServerSession();
  +         session.setManager( this );
  +         recycled.put( session );
  +     }
  +     
  +     // XXX can return MessageBytes !!!
  +
  +
  +     String newId= SessionIdGenerator.getIdentifier(randomSource, jsIdent);
  +
  +     // What if the newId belongs to an existing session ?
  +     // This shouldn't happen ( maybe we can try again ? )
  +     ServerSession oldS=findSession( newId );
  +     if( oldS!=null) {
  +         // that's what the original code did
  +         removeSession( oldS );
  +     }
  +
  +     // Initialize the properties of the new session and return it
  +     session.getId().setString( newId );
  +
  +     TimeStamp ts=session.getTimeStamp();
  +     ts.setNew(true);
  +     ts.setValid(true);
  +
  +     ts.setCreationTime(System.currentTimeMillis());
  +     ts.setMaxInactiveInterval(getMaxInactiveInterval());
  +     session.getTimeStamp().setParent( session );
  +
  +     //      System.out.println("New session: " + newId );
  +     sessions.put( newId, session );
  +     expirer.addManagedObject( session.getTimeStamp());
  +     return (session);
  +    }
  +
  +    public void removeAllSessions() {
  +     Enumeration ids = sessions.keys();
  +     while (ids.hasMoreElements()) {
  +         String id = (String) ids.nextElement();
  +         ServerSession session = (ServerSession) sessions.get(id);
  +         if (!session.getTimeStamp().isValid())
  +             continue;
  +         removeSession( session );
  +     }
  +    }
  +
   }
  
  
  
  1.2       +1 -1      
jakarta-tomcat/src/share/org/apache/tomcat/request/CredentialsInterceptor.java
  
  Index: CredentialsInterceptor.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/request/CredentialsInterceptor.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- CredentialsInterceptor.java       2000/12/27 19:52:52     1.1
  +++ CredentialsInterceptor.java       2001/01/01 00:17:23     1.2
  @@ -60,7 +60,7 @@
   
   import org.apache.tomcat.core.*;
   import org.apache.tomcat.util.*;
  -import org.apache.tomcat.session.ServerSession;
  +//import org.apache.tomcat.session.ServerSession;
   import org.apache.tomcat.util.xml.*;
   import java.io.*;
   import java.net.*;
  
  
  
  1.11      +5 -1      
jakarta-tomcat/src/share/org/apache/tomcat/request/ReloadInterceptor.java
  
  Index: ReloadInterceptor.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/request/ReloadInterceptor.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- ReloadInterceptor.java    2000/12/26 23:35:35     1.10
  +++ ReloadInterceptor.java    2001/01/01 00:17:24     1.11
  @@ -182,12 +182,16 @@
                // the right actions
   
   
  -             if( debug>0 ) log( "Reloading hooks for context " + ctx.toString());
  +             if( debug>0 ) log( "Reloading hooks for context " +
  +                                ctx.toString());
   
                // Call reload hook in context manager
                BaseInterceptor cI[]=ctx.getContainer().getInterceptors();
                for( int i=0; i< cI.length; i++ ) {
                    cI[i].reload(  request, ctx );
  +                 int oldLoaderNote=cm.getNoteId
  +                     ( ContextManager.CONTAINER_NOTE, "oldLoader");
  +                 ctx.getContainer().setNote( oldLoaderNote, null);
                }
            }
        } catch( TomcatException ex) {
  
  
  
  1.2       +5 -1      
jakarta-tomcat/src/share/org/apache/tomcat/util/ObjectSerializer.java
  
  Index: ObjectSerializer.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/ObjectSerializer.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ObjectSerializer.java     2000/11/22 00:21:25     1.1
  +++ ObjectSerializer.java     2001/01/01 00:17:24     1.2
  @@ -66,7 +66,11 @@
   
   /**
    * Helper for object reloading. Will change the classloader of a
  - * serializable object.
  + * serializable object. 
  + *
  + * The object must be serializable - the caller should do special
  + * actions for all non-serializable objects ( like using their
  + *  specific protocol ).
    * 
    * Old comment: ( code works now for any object, not only HttpSession )
    *
  
  
  
  1.3       +8 -0      jakarta-tomcat/src/share/org/apache/tomcat/util/hooks/Hooks.java
  
  Index: Hooks.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/hooks/Hooks.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- Hooks.java        2000/12/28 07:14:45     1.2
  +++ Hooks.java        2001/01/01 00:17:24     1.3
  @@ -108,6 +108,13 @@
        hooks=new Object[hookCount][];
       }
   
  +    /** Allow direct access to hooks. You must call resetCache()
  +     if you change the hooks
  +    */
  +    public Vector getHooksVector( int type ) {
  +     return hooksV[type];
  +    }
  +    
       public int registerHook( String name ) {
        for( int i=0; i<hookNames.length; i++ ) {
            if( hookNames[i]==null ) {
  @@ -140,6 +147,7 @@
        *  ( not inherited - explicitely defined there )
        */
       public void addModule( Object bi ) {
  +     // the module wants to register the hooks itself
        for( int i=0; i< hookNames.length ; i++ ) {
            if( hookNames[i]==null ) continue;
            if( hasHook( bi, hookNames[i] )) {
  
  
  
  1.6       +1 -1      
jakarta-tomcat/src/share/org/apache/tomcat/util/http/Parameters.java
  
  Index: Parameters.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/http/Parameters.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- Parameters.java   2000/12/30 07:54:18     1.5
  +++ Parameters.java   2001/01/01 00:17:24     1.6
  @@ -279,7 +279,7 @@
       /** Decode a URL-encoded string. Inefficient.
        */
       private static String unUrlDecode(String data) {
  -     System.out.println("DECODING : " +data );
  +     //      System.out.println("DECODING : " +data );
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < data.length(); i++) {
            char c = data.charAt(i);
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, email: [EMAIL PROTECTED]

Reply via email to