You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by co...@locus.apache.org on 2000/01/07 22:11:41 UTC

cvs commit: jakarta-tomcat/src/share/org/apache/tomcat/session ApplicationSession.java Constants.java LocalStrings.properties Reaper.java ServerSession.java ServerSessionManager.java

costin      00/01/07 13:11:41

  Modified:    src/share/org/apache/tomcat/core Context.java
                        LocalStrings.properties Request.java
               src/share/org/apache/tomcat/request SessionInterceptor.java
  Added:       src/share/org/apache/tomcat/core SessionManager.java
               src/share/org/apache/tomcat/session ApplicationSession.java
                        Constants.java LocalStrings.properties Reaper.java
                        ServerSession.java ServerSessionManager.java
  Removed:     src/share/org/apache/tomcat/core ApplicationSession.java
                        Reaper.java ServerSession.java
                        ServerSessionManager.java
  Log:
  - Session move out of core.
  - added sessionManager interface, it's the only dependency between
  core and a session manager.
  
  It still passes the tests, but don't count on it.
  
  Revision  Changes    Path
  1.14      +15 -3     jakarta-tomcat/src/share/org/apache/tomcat/core/Context.java
  
  Index: Context.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/Context.java,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- Context.java	2000/01/07 19:14:10	1.13
  +++ Context.java	2000/01/07 21:11:37	1.14
  @@ -94,8 +94,8 @@
       private ClassLoader classLoader = null;
       private String classPath = ""; // classpath used by the classloader.
       //private Hashtable sessions = new Hashtable();
  -    private ServerSessionManager sessionManager =
  -	ServerSessionManager.getManager();
  +    // XXX XXX XXX hardcoded ! 
  +    private SessionManager sessionManager;
       private ServletContextFacade contextFacade;
       private Hashtable initializationParameters = new Hashtable();
       private Hashtable attributes = new Hashtable();
  @@ -488,6 +488,18 @@
           }
       }
   
  +    public SessionManager getSessionManager() {
  +	if( sessionManager==null ) {
  +	    // default - will change when a better one exists
  +	    sessionManager = org.apache.tomcat.session.ServerSessionManager.getManager();
  +	}
  +	return sessionManager;
  +    }
  +
  +    public void setSessionManager( SessionManager manager ) {
  +	sessionManager= manager;
  +    }
  +    
       public void shutdown() {
   	// shut down container
   
  @@ -495,7 +507,7 @@
   
   	// shut down any sessions
   
  -	sessionManager.removeApplicationSessions(this);
  +	getSessionManager().removeSessions(this);
   
   	if (! isWorkDirPersistent) {
               clearDir(workDir);
  
  
  
  1.4       +1 -6      jakarta-tomcat/src/share/org/apache/tomcat/core/LocalStrings.properties
  
  Index: LocalStrings.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/LocalStrings.properties,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- LocalStrings.properties	1999/12/30 02:44:58	1.3
  +++ LocalStrings.properties	2000/01/07 21:11:37	1.4
  @@ -1,4 +1,4 @@
  -# $Id: LocalStrings.properties,v 1.3 1999/12/30 02:44:58 craigmcc Exp $
  +# $Id: LocalStrings.properties,v 1.4 2000/01/07 21:11:37 costin Exp $
   #
   
   # Localized strings for package org.apache.tomcat.core
  @@ -35,16 +35,11 @@
   resfac.getoutstream.ise=Writer already obtained for this request.
   resfac.getwriter.ise=OutputStream already obtained for this request.
   
  -applicationSession.session.ise=invalid session state
  -applicationSession.value.iae=null value
  -
   hsrf.encodeRedirect.iae=urls must be absolute
   hsrf.redirect.iae=specified url redirect is null
   hsrf.dispatcher.iae=Request dispatcher paths can't be null: {0}
   
   rdi.forward.ise=Cannot forward as OutputStream or Writer has already been obtained
  -
  -serverSession.value.iae=null value
   
   serverReponse.outputStream.ise=getWriter() has already been called
   serverResponse.ise.writer.ise=getOutputStream() has already been called
  
  
  
  1.13      +5 -5      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.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- Request.java	2000/01/07 19:14:11	1.12
  +++ Request.java	2000/01/07 21:11:37	1.13
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/Request.java,v 1.12 2000/01/07 19:14:11 costin Exp $
  - * $Revision: 1.12 $
  - * $Date: 2000/01/07 19:14:11 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/Request.java,v 1.13 2000/01/07 21:11:37 costin Exp $
  + * $Revision: 1.13 $
  + * $Date: 2000/01/07 21:11:37 $
    *
    * ====================================================================
    *
  @@ -400,8 +400,8 @@
   // 		    ServerSessionManager.getManager()
   // 		    .getServerSession(this, response, create);
   // 		serverSession.accessed();
  -		serverSession =ServerSessionManager.getManager()
  - 		    .getSession(this, response, create);
  +		SessionManager sM=getContext().getSessionManager();
  +		serverSession =sM.getSession(this, response, create);
    		
   	    }
   	}
  
  
  
  1.1                  jakarta-tomcat/src/share/org/apache/tomcat/core/SessionManager.java
  
  Index: SessionManager.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  
  package org.apache.tomcat.core;
  
  import org.apache.tomcat.util.*;
  import java.io.*;
  import java.net.*;
  import java.util.*;
  import javax.servlet.http.*;
  
  /**
   * 
   * @author costin@dnt.ro
   */
  public interface SessionManager {
  
      /**
       * Called by Request.getSession() to create/get a new session object.
       * May also be called by RequestInterceptors to find the session that
       * needs to be marked as accessed
       */
      public HttpSession getSession(Request request, Response response,boolean create);
  
      /** Will mark the session lastAccess time.
       *  Will be called for each request by a SessionInterceptor
       */
      public void accessed(HttpSession session);
  
      /** Used by context when stoped, need to remove all sessions used by that context
       */
      public void removeSessions( Context ctx );
  }
  
  
  
  1.2       +3 -4      jakarta-tomcat/src/share/org/apache/tomcat/request/SessionInterceptor.java
  
  Index: SessionInterceptor.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/request/SessionInterceptor.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- SessionInterceptor.java	2000/01/07 19:14:15	1.1
  +++ SessionInterceptor.java	2000/01/07 21:11:40	1.2
  @@ -73,21 +73,20 @@
    */
   public class SessionInterceptor implements RequestInterceptor {
       
  -    private ServerSessionManager sessionManager = ServerSessionManager.getManager();
  -
       public SessionInterceptor() {
       }
   	
       public int handleRequest(Request request ) {
   	// look for session id -- cookies only right now
   
  -	HttpSession session= sessionManager.getSession(request, request.getResponse(), false);
  +	SessionManager sM=request.getContext().getSessionManager();
  +	HttpSession session= sM.getSession(request, request.getResponse(), false);
   
   	// ServerSession session =
   	// 	    sessionManager.getServerSession(request, request.getResponse(), false);
   
   	if (session != null) {
  -	    sessionManager.accessed( session );
  +	    sM.accessed( session );
   	}
   
   	request.setSession(session);  // may be null
  
  
  
  1.1                  jakarta-tomcat/src/share/org/apache/tomcat/session/ApplicationSession.java
  
  Index: ApplicationSession.java
  ===================================================================
  /*
   * ====================================================================
   * 
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  
  package org.apache.tomcat.session;
  
  import org.apache.tomcat.core.*;
  import org.apache.tomcat.util.StringManager;
  import java.io.*;
  import java.net.*;
  import java.util.*;
  import javax.servlet.*;
  import javax.servlet.http.*;
  
  /**
   * Core implementation of an application level session
   *
   * @author James Duncan Davidson [duncan@eng.sun.com]
   * @author Jason Hunter [jch@eng.sun.com]
   * @author James Todd [gonzo@eng.sun.com]
   */
  
  public class ApplicationSession implements HttpSession {
  
      private StringManager sm =
          StringManager.getManager(Constants.Package);
      private Hashtable values = new Hashtable();
      private String id;
      private ServerSession serverSession;
      private Context context;
      private long creationTime = System.currentTimeMillis();;
      private long thisAccessTime = creationTime;
      private long lastAccessed = creationTime;
      private int inactiveInterval = -1;
      private boolean valid = true;
  
      ApplicationSession(String id, ServerSession serverSession,
          Context context) {
          this.serverSession = serverSession;
  	this.context = context;
          this.id = id;
  
  	this.inactiveInterval = context.getSessionTimeOut();
  
          if (this.inactiveInterval != -1) {
              this.inactiveInterval *= 60;
          }
      }
  
      ServerSession getServerSession() {
  	return serverSession;
      }
  
      /**
       * Called by context when request comes in so that accesses and
       * inactivities can be dealt with accordingly.
       */
  
      void accessed() {
          // set last accessed to thisAccessTime as it will be left over
  	// from the previous access
  	lastAccessed = thisAccessTime;
  	thisAccessTime = System.currentTimeMillis();
  
  	validate();
      }
  
      void validate() {
  	// if we have an inactive interval, check to see if we've exceeded it
  	if (inactiveInterval != -1) {
  	    int thisInterval =
  		(int)(System.currentTimeMillis() - lastAccessed) / 1000;
  
  	    if (thisInterval > inactiveInterval) {
  		invalidate();
  	    }
  	}
      }
      
      // HTTP SESSION IMPLEMENTATION METHODS
      
      public String getId() {
  	if (valid) {
  	    return id;
  	} else {
  	    String msg = sm.getString("applicationSession.session.ise");
  
  	    throw new IllegalStateException(msg);
  	}
      }
  
      public long getCreationTime() {
  	if (valid) {
  	    return creationTime;
  	} else {
  	    String msg = sm.getString("applicationSession.session.ise");
  
  	    throw new IllegalStateException(msg);
  	}
      }
      
      /**
       *
       * @deprecated
       */
  
      public HttpSessionContext getSessionContext() {
  	return new SessionContextImpl();
      }
      
      public long getLastAccessedTime() {
  	if (valid) {
  	    return lastAccessed;
  	} else {
  	    String msg = sm.getString("applicationSession.session.ise");
  
  	    throw new IllegalStateException(msg);
  	}
      }
  
      public void invalidate() {
  	serverSession.removeApplicationSession(context);
  
  	// remove everything in the session
  
  	Enumeration enum = values.keys();
  	while (enum.hasMoreElements()) {
  	    String name = (String)enum.nextElement();
  	    removeValue(name);
  	}
  
  	valid = false;
      }
  
      public boolean isNew() {
  	if (! valid) {
  	    String msg = sm.getString("applicationSession.session.ise");
  
  	    throw new IllegalStateException(msg);
  	}
  
  	if (thisAccessTime == creationTime) {
  	    return true;
  	} else {
  	    return false;
  	}
      }
      
      /**
       * @deprecated
       */
  
      public void putValue(String name, Object value) {
  	setAttribute(name, value);
      }
  
      public void setAttribute(String name, Object value) {
          if (! valid) {
  	    String msg = sm.getString("applicationSession.session.ise");
  
  	    throw new IllegalStateException(msg);
  	}
  
  	if (name == null) {
  	    String msg = sm.getString("applicationSession.value.iae");
  
  	    throw new IllegalArgumentException(msg);
  	}
  
  	removeValue(name);  // remove any existing binding
  
  	if (value != null && value instanceof HttpSessionBindingListener) {
  	    HttpSessionBindingEvent e =
                  new HttpSessionBindingEvent(this, name);
  
  	    ((HttpSessionBindingListener)value).valueBound(e);
  	}
  
  	values.put(name, value);
      }
  
      /**
       * @deprecated
       */
      public Object getValue(String name) {
  	return getAttribute(name);
      }
  
      public Object getAttribute(String name) {
  	if (! valid) {
  	    String msg = sm.getString("applicationSession.session.ise");
  
  	    throw new IllegalStateException(msg);
  	}
  
  	if (name == null) {
  	    String msg = sm.getString("applicationSession.value.iae");
  
  	    throw new IllegalArgumentException(msg);
  	}
  
  	return values.get(name);
      }
  
      /**
       * @deprecated
       */
      public String[] getValueNames() {
  	Enumeration e = getAttributeNames();
  	Vector names = new Vector();
  
  	while (e.hasMoreElements()) {
  	    names.addElement(e.nextElement());
  	}
  
  	String[] valueNames = new String[names.size()];
  
  	names.copyInto(valueNames);
  
  	return valueNames;
  	
      }
  
      public Enumeration getAttributeNames() {
  	if (! valid) {
  	    String msg = sm.getString("applicationSession.session.ise");
  
  	    throw new IllegalStateException(msg);
  	}
  
  	Hashtable valuesClone = (Hashtable)values.clone();
  
  	return (Enumeration)valuesClone.keys();
      }
  
      /**
       * @deprecated
       */
  
      public void removeValue(String name) {
  	removeAttribute(name);
      }
  
      public void removeAttribute(String name) {
  	if (! valid) {
  	    String msg = sm.getString("applicationSession.session.ise");
  
  	    throw new IllegalStateException(msg);
  	}
  
  	if (name == null) {
  	    String msg = sm.getString("applicationSession.value.iae");
  
  	    throw new IllegalArgumentException(msg);
  	}
  
  	Object o = values.get(name);
  
  	if (o instanceof HttpSessionBindingListener) {
  	    HttpSessionBindingEvent e =
                  new HttpSessionBindingEvent(this,name);
  
  	    ((HttpSessionBindingListener)o).valueUnbound(e);
  	}
  
  	values.remove(name);
      }
  
      public void setMaxInactiveInterval(int interval) {
  	if (! valid) {
  	    String msg = sm.getString("applicationSession.session.ise");
  
  	    throw new IllegalStateException(msg);
  	}
  
  	inactiveInterval = interval;
      }
  
      public int getMaxInactiveInterval() {
  	if (! valid) {
  	    String msg = sm.getString("applicationSession.session.ise");
  
  	    throw new IllegalStateException(msg);
  	}
  
  	return inactiveInterval;
      }
  }
  
  
  
  1.1                  jakarta-tomcat/src/share/org/apache/tomcat/session/Constants.java
  
  Index: Constants.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  
  package org.apache.tomcat.session;
  
  /**
   *
   * @author James Todd [gonzo@eng.sun.com]
   */
  
  public class Constants {
  
      public static final String Package = "org.apache.tomcat.session";
  
      public static final String SESSION_COOKIE_NAME = "JSESSIONID";
  }
  
  
  
  1.1                  jakarta-tomcat/src/share/org/apache/tomcat/session/LocalStrings.properties
  
  Index: LocalStrings.properties
  ===================================================================
  applicationSession.session.ise=invalid session state
  applicationSession.value.iae=null value
  serverSession.value.iae=null value
  
  
  
  1.1                  jakarta-tomcat/src/share/org/apache/tomcat/session/Reaper.java
  
  Index: Reaper.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  
  package org.apache.tomcat.session;
  
  import org.apache.tomcat.core.*;
  import org.apache.tomcat.util.*;
  
  /**
   * The reaper is a background thread with which ticks every minute
   * and calls registered objects to allow reaping of old session
   * data.
   * 
   * @author James Duncan Davidson [duncan@eng.sun.com]
   */
  
  public class Reaper extends Thread {
  
      private static Reaper reaper;
      
      static {
  	reaper = new Reaper();
      }
      
      static Reaper getReaper() {
  	return reaper;
      }
  
      private int interval = 1000 * 60; //ms    
      private ServerSessionManager serverSessionMgr;
      
      private Reaper() {
  	this.setDaemon(true);
      }
      
      void setServerSessionManager(ServerSessionManager serverSessionMgr) {
  	this.serverSessionMgr = serverSessionMgr;
      }
      
      public void run() {
  
  	// XXX
  	// eventually, to be nice, this should know when everything
  	// goes down so that it's not continuing to tick in the background
  
  	while (true) {
  	    try {
  		this.sleep(interval);
  	    } catch (InterruptedException ie) {
  		// sometimes will happen
  	    }
  
  	    if (serverSessionMgr != null) {
  		serverSessionMgr.reap();
  	    }
  	}
      }
  }
  
  
  
  1.1                  jakarta-tomcat/src/share/org/apache/tomcat/session/ServerSession.java
  
  Index: ServerSession.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  
  package org.apache.tomcat.session;
  
  import org.apache.tomcat.core.*;
  import org.apache.tomcat.util.StringManager;
  import java.io.*;
  import java.net.*;
  import java.util.*;
  import javax.servlet.*;
  import javax.servlet.http.*;
  
  /**
   * Core implementation of a server session
   *
   * @author James Duncan Davidson [duncan@eng.sun.com]
   * @author James Todd [gonzo@eng.sun.com]
   */
  
  public class ServerSession {
  
      private StringManager sm =
          StringManager.getManager(Constants.Package);
      private Hashtable values = new Hashtable();
      private Hashtable appSessions = new Hashtable();
      private String id;
      private long creationTime = System.currentTimeMillis();;
      private long thisAccessTime = creationTime;
      private long lastAccessed = creationTime;
      private int inactiveInterval = -1;
      
      ServerSession(String id) {
  	this.id = id;
      }
  
      public String getId() {
  	return id;
      }
  
      public long getCreationTime() {
  	return creationTime;
      }
  
      public long getLastAccessedTime() {
  	return lastAccessed;
      }
      
      public ApplicationSession getApplicationSession(Context context,
          boolean create) {
  	ApplicationSession appSession =
  	    (ApplicationSession)appSessions.get(context);
  
  	if (appSession == null && create) {
  
  	    // XXX
  	    // sync to ensure valid?
  	    
  	    appSession = new ApplicationSession(id, this, context);
  	    appSessions.put(context, appSession);
  	}
  
  	// XXX
  	// make sure that we haven't gone over the end of our
  	// inactive interval -- if so, invalidate and create
  	// a new appSession
  	
  	return appSession;
      }
      
      void removeApplicationSession(Context context) {
  	appSessions.remove(context);
      }
  
      /**
       * Called by context when request comes in so that accesses and
       * inactivities can be dealt with accordingly.
       */
  
      void accessed() {
          // set last accessed to thisAccessTime as it will be left over
  	// from the previous access
  
  	lastAccessed = thisAccessTime;
  	thisAccessTime = System.currentTimeMillis();
  	
      }
  
      void validate() {
  	// if we have an inactive interval, check to see if
          // we've exceeded it
  
  	if (inactiveInterval != -1) {
  	    int thisInterval =
  		(int)(System.currentTimeMillis() - lastAccessed) / 1000;
  
  	    if (thisInterval > inactiveInterval) {
  		invalidate();
  
  		ServerSessionManager ssm =
                      ServerSessionManager.getManager();
  
  		ssm.removeSession(this);
  	    }
  	}
      }
  
      synchronized void invalidate() {
  	Enumeration enum = appSessions.keys();
  
  	while (enum.hasMoreElements()) {
  	    Object key = enum.nextElement();
  	    ApplicationSession appSession =
  		(ApplicationSession)appSessions.get(key);
  
  	    appSession.invalidate();
  	}
      }
      
      public void putValue(String name, Object value) {
  	if (name == null) {
              String msg = sm.getString("serverSession.value.iae");
  
  	    throw new IllegalArgumentException(msg);
  	}
  
  	removeValue(name);  // remove any existing binding
  	values.put(name, value);
      }
  
      public Object getValue(String name) {
  	if (name == null) {
              String msg = sm.getString("serverSession.value.iae");
  
  	    throw new IllegalArgumentException(msg);
  	}
  
  	return values.get(name);
      }
  
      public Enumeration getValueNames() {
  	return values.keys();
      }
  
      public void removeValue(String name) {
  	values.remove(name);
      }
  
      public void setMaxInactiveInterval(int interval) {
  	inactiveInterval = interval;
      }
  
      public int getMaxInactiveInterval() {
  	return inactiveInterval;
      }    
  
      // XXX
      // sync'd for safty -- no other thread should be getting something
      // from this while we are reaping. This isn't the most optimal
      // solution for this, but we'll determine something else later.
      
      synchronized void reap() {
  	Enumeration enum = appSessions.keys();
  
  	while (enum.hasMoreElements()) {
  	    Object key = enum.nextElement();
  	    ApplicationSession appSession =
  		(ApplicationSession)appSessions.get(key);
  
  	    appSession.validate();
  	}
      }
  }
  
  
  
  1.1                  jakarta-tomcat/src/share/org/apache/tomcat/session/ServerSessionManager.java
  
  Index: ServerSessionManager.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  
  package org.apache.tomcat.session;
  
  import org.apache.tomcat.util.*;
  import org.apache.tomcat.core.*;
  import java.io.*;
  import java.net.*;
  import java.util.*;
  import javax.servlet.http.*;
  
  /**
   * 
   * @author James Duncan Davidson [duncan@eng.sun.com]
   * @author Jason Hunter [jch@eng.sun.com]
   * @author James Todd [gonzo@eng.sun.com]
   */
  
  public class ServerSessionManager implements SessionManager {
  
      private StringManager sm =
          StringManager.getManager(Constants.Package);
      private static ServerSessionManager manager; // = new ServerSessionManager();
  
      static {
  	manager = new ServerSessionManager();
      }
      
      public static ServerSessionManager getManager() {
  	return manager;
      }
  
      private Hashtable sessions = new Hashtable();
      private Reaper reaper;
      
      private ServerSessionManager() {
  	reaper = Reaper.getReaper();
  	reaper.setServerSessionManager(this);
  	reaper.start();
      }
  
      /** Called from Request.getSession to create a new session 
       */
      public HttpSession getSession(Request request, Response response,
          boolean create) {
  	ServerSession sSession=getServerSession( request, response, create);
  	if( sSession!=null ) sSession.accessed();
  	if( sSession ==null) return null;
  	
  	return sSession.getApplicationSession(request.getContext(), create);
      }
  
      public void accessed( HttpSession session ) {
  	ApplicationSession apS=(ApplicationSession)session;
  	ServerSession servS=apS.getServerSession();
  	servS.accessed();
  	apS.accessed();
  	
      }
      
      ServerSession getServerSession(Request request, Response response,
          boolean create) {
  	// Look for session id -- cookies only right now
  
  	String sessionId = null;
  	ServerSession session = null;
  
  	// XXX need to check if request.getRequestdSessionId() returns something,
  	// since the connector might have set it.
  	
  	//	Enumeration enum = request.getCookies().elements();
  	Cookie cookies[]=request.getCookies(); // assert !=null
  	
  	//while (enum.hasMoreElements()) {
  	for( int i=0; i<cookies.length; i++ ) {
  	    Cookie cookie = cookies[i]; // (Cookie)enum.nextElement();
  
  	    if (cookie.getName().equals(
                  Constants.SESSION_COOKIE_NAME)) {
  		sessionId = cookie.getValue();
  
  		if (sessionId != null) {
  		    request.setRequestedSessionId(sessionId);
  		    session = (ServerSession)sessions.get(sessionId);
  		}
  	    }
  	}
  
  	if (session == null && create) {
  	    if (sessionId == null) {
  		sessionId = SessionIdGenerator.generateId();
  		Cookie cookie = new Cookie(
                      Constants.SESSION_COOKIE_NAME, sessionId);
  
  		cookie.setMaxAge(-1);
  		cookie.setPath("/");
  		cookie.setVersion(1);
  
  		response.addSystemCookie(cookie);
  	    }
  
  	    session = new ServerSession(sessionId);
  	    sessions.put(sessionId, session);
  	}
  
  	return session;
      }
  
      // XXX
      // sync'd for safty -- no other thread should be getting something
      // from this while we are reaping. This isn't the most optimal
      // solution for this, but we'll determine something else later.
      
      synchronized void reap() {
  	Enumeration enum = sessions.keys();
  
  	while (enum.hasMoreElements()) {
  	    Object key = enum.nextElement();
  	    ServerSession session = (ServerSession)sessions.get(key);
  
  	    session.reap();
  	    session.validate();
  	}
      }
  
      synchronized void removeSession(ServerSession session) {
  	String id = session.getId();
  
  	session.invalidate();
  	sessions.remove(id);
      }
  
      public void removeSessions(Context context) {
  	Enumeration enum = sessions.keys();
  
  	while (enum.hasMoreElements()) {
  	    Object key = enum.nextElement();
  	    ServerSession session = (ServerSession)sessions.get(key);
  	    ApplicationSession appSession =
  		session.getApplicationSession(context, false);
  
  	    if (appSession != null) {
  		appSession.invalidate();
  	    }
  	}
      }
  }