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/05/12 17:26:40 UTC

cvs commit: jakarta-tomcat/src/share/org/apache/tomcat/session StandardManager.java

costin      00/05/12 08:26:40

  Modified:    src/share/org/apache/tomcat/context DefaultCMSetter.java
               src/share/org/apache/tomcat/core Context.java
                        RequestImpl.java SessionManager.java
               src/share/org/apache/tomcat/request SessionInterceptor.java
               src/share/org/apache/tomcat/session StandardManager.java
  Log:
  - moved the code that sets the session manager from DefaultCM setter to sessionInterceptor.
  All session-related stuff is in one place.
  
  - Propagate distributable from web.xml to the SessionManager.
  
  - renamed createSession to getNewSession. SessionManager should use a pool and recycle.
    Added released() notification - when the serlvet is done with a session object.
  
  - remove setContext() and all dependencies between SessionManager and tomcat ( the reverse
  is false - tomcat depends on SM ). That means SessionManager can be implemented on top of
  other packages that have no common architecture with tocmat.
  
  -  addes start/stop to SessionManager, SessionInterceptor will manage the communication
  and lifecycle of SM, in sync with the associated Context
  
  - re-aranged the code in StandardManager, removed un-used methods. It still need some work,
  but it's better.
  
  Revision  Changes    Path
  1.33      +0 -7      jakarta-tomcat/src/share/org/apache/tomcat/context/DefaultCMSetter.java
  
  Index: DefaultCMSetter.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/context/DefaultCMSetter.java,v
  retrieving revision 1.32
  retrieving revision 1.33
  diff -u -r1.32 -r1.33
  --- DefaultCMSetter.java	2000/05/12 06:15:22	1.32
  +++ DefaultCMSetter.java	2000/05/12 15:26:38	1.33
  @@ -159,13 +159,6 @@
   	ctx.setAttribute(Constants.ATTRIB_WORKDIR , ctx.getWorkDir());
   
   	// Set default session manager if none set
  -	if( ctx.getSessionManager() == null ) {
  -	    SessionManager sm=new org.apache.tomcat.session.StandardManager();
  -	    sm.setContext(ctx);
  -	    ctx.setSessionManager(sm);
  -	}
  -	//  Alternative: org.apache.tomcat.session.ServerSessionManager.getManager();
  -
   	ServletWrapper authWrapper=new ServletWrapper();
   	authWrapper.setContext( ctx );
   	authWrapper.setServletName( "tomcat.authServlet");
  
  
  
  1.86      +4 -0      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.85
  retrieving revision 1.86
  diff -u -r1.85 -r1.86
  --- Context.java	2000/05/09 17:56:11	1.85
  +++ Context.java	2000/05/12 15:26:39	1.86
  @@ -394,6 +394,9 @@
   
       public void setDistributable(boolean isDistributable) {
           this.isDistributable = isDistributable;
  +	if(null != sessionManager) {
  +	    sessionManager.setDistributable( isDistributable );
  +	}
       }
   
   
  @@ -623,6 +626,7 @@
       	sessionManager= manager;
           if(null != sessionManager) {
               sessionManager.setSessionTimeOut(sessionTimeOut);
  +	    sessionManager.setDistributable( isDistributable );
           }
       }
   
  
  
  
  1.35      +4 -4      jakarta-tomcat/src/share/org/apache/tomcat/core/RequestImpl.java
  
  Index: RequestImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/RequestImpl.java,v
  retrieving revision 1.34
  retrieving revision 1.35
  diff -u -r1.34 -r1.35
  --- RequestImpl.java	2000/05/12 06:15:23	1.34
  +++ RequestImpl.java	2000/05/12 15:26:39	1.35
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/RequestImpl.java,v 1.34 2000/05/12 06:15:23 costin Exp $
  - * $Revision: 1.34 $
  - * $Date: 2000/05/12 06:15:23 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/RequestImpl.java,v 1.35 2000/05/12 15:26:39 costin Exp $
  + * $Revision: 1.35 $
  + * $Date: 2000/05/12 15:26:39 $
    *
    * ====================================================================
    *
  @@ -441,7 +441,7 @@
   	    return null;
   
   	// no session exists, create flag
  -	serverSession =sM.createSession( );
  +	serverSession =sM.getNewSession( );
   	reqSessionId = serverSession.getId();
   
   	// XXX XXX will be changed - post-request Interceptors
  
  
  
  1.5       +52 -17    jakarta-tomcat/src/share/org/apache/tomcat/core/SessionManager.java
  
  Index: SessionManager.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/SessionManager.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- SessionManager.java	2000/05/12 06:15:23	1.4
  +++ SessionManager.java	2000/05/12 15:26:39	1.5
  @@ -74,29 +74,30 @@
    */
   public interface SessionManager {
   
  -    public void setContext( Context ctx );
  +    /* XXX The manager should try to reuse the session objects and avoid
  +     * allocating. The session can be "released" by Manager via timeout
  +     * or invalidate. 
  +     *
  +     * This is not easy right now - the session may expire while the servlet
  +     * is running in extreme cases - like very long transactions - and we may
  +     * end up with another user's session.
  +     *
  +     *  The fix will be to check if the id is still the same on each operation
  +     * on facade, or to maintain a useCount. We provide release if the manager
  +     * wants this.
  +     */
       
       /**
  -     * Construct and return a new session object, based on the default
  +     * Return a new session object, based on the default
        * settings specified by this Manager's properties.  The session
        * id will be assigned by this method, and available via the getId()
        * method of the returned session.  If a new session cannot be created
        * for any reason, return <code>null</code>.
        *
  -     * @param ctx The session will be created for the specified context
        * @exception IllegalStateException if a new session cannot be
        *  instantiated for any reason
  -     */
  -    public HttpSession createSession();
  -
  -
  -    /** Will mark the session lastAccess time.
  -     *  Will be called for each request that has a valid sessionId
  -     *
        */
  -    public void accessed(HttpSession s);
  -    //  we can pass only Request, as it contains both, but it's better to
  -    // show explicitely what this method uses.
  +    public HttpSession getNewSession();
   
   
       /**
  @@ -114,19 +115,53 @@
       public HttpSession findSession(String id);
   
   
  -    /** Used by context when stoped, need to remove all sessions used by that context
  +    /** Will mark the session lastAccess time.
  +     *  Will be called for each request that has a valid sessionId
  +     *   and a session.
  +     *
  +     *  Tomcat guarantees the session is the one created by the manager
  +     * and not null.
        */
  -    public void removeSessions();
  -
  +    public void access(HttpSession s);
  +    
       /**
  +     *  Will be called when the servlet that used this session is out.
  +     *  A session shouldn't timeout while a servlet is still executing.
  +     *
  +     *  Tomcat guarantees the session is the one created by the manager
  +     * and not null.
  +     */
  +    public void release(HttpSession s);
  +    
  +    /* -------------------- Manager attributes - from web.xml -------------------- */
  +    /* The manager will be initialized in server.xml via setters ( or whatever mechanism
  +       it supports ), but it has to take web.xml informations from the context
  +    */
  +      
  +    /**
        * Used by context to configure the session manager's inactivity timeout.
        *
        * The SessionManager may have some default session time out, the
        * Context on the other hand has it's timeout set by the deployment
  -     * descriptor (web.xml). This method lets the Context conforgure the
  +     * descriptor (web.xml). This method lets the Context configure the
        * session manager according to this value.
        *
        * @param minutes The session inactivity timeout in minutes.
        */
       public void setSessionTimeOut(int minutes);
  +
  +    /** Pass the distributable info from Web.xml
  +     */
  +    public void setDistributable(boolean b);
  +
  +    // -------------------- Control manager livecycle
  +
  +    /** Start managing the sessions. Called after everything is set up to allow
  +     *  the manager to allocate the resources it needs
  +     */
  +    public void start();
  +
  +    /** Release all resources. Called when the context was stoped.
  +     */
  +    public void stop();
   }
  
  
  
  1.19      +33 -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.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- SessionInterceptor.java	2000/05/12 06:15:23	1.18
  +++ SessionInterceptor.java	2000/05/12 15:26:39	1.19
  @@ -196,7 +196,7 @@
   	    SessionManager sM = ctx.getSessionManager();    
   	    HttpSession sess= sM.findSession( sessionId );
   	    if(null != sess) {
  -		sM.accessed( sess );
  +		sM.access( sess );
   		request.setRequestedSessionId(sessionId);
   		request.setSession( sess );
   		if( debug>0 ) cm.log(" Final session id " + sessionId );
  @@ -205,8 +205,17 @@
   	}
   	return null;
       }
  -  
   
  +    public int postService(  Request rrequest, Response response ) {
  +	Context ctx=rrequest.getContext();
  +	if( ctx==null ) return 0;
  +	SessionManager sm=ctx.getSessionManager();
  +	HttpSession sess=rrequest.getSession(false);
  +	if( sess == null ) return 0;
  +	sm.release( sess );
  +	return 0;
  +    }
  +
       public int beforeBody( Request rrequest, Response response ) {
       	String reqSessionId = response.getSessionId();
   	if( debug>0 ) cm.log("Before Body " + reqSessionId );
  @@ -245,15 +254,35 @@
       	return 0;
       }
   
  +    /** Init session management stuff for this context
  +     */
  +    public void contextInit(Context ctx) throws TomcatException {
  +	// Defaults !!
  +	if( ctx.getSessionManager() == null ) {
  +	    SessionManager sm=new org.apache.tomcat.session.StandardManager();
  +	    ctx.setSessionManager(sm);
  +	}
   
  +	SessionManager sm=ctx.getSessionManager();
  +	try {
  +	    sm.start();
  +	} catch(IllegalStateException ex ) {
  +	    throw new TomcatException( ex );
  +	}
  +    }
  +    
       /** Notification of context shutdown
        */
       public void contextShutdown( Context ctx )
   	throws TomcatException
       {
   	if( ctx.getDebug() > 0 ) ctx.log("Removing sessions from " + ctx );
  -	ctx.getSessionManager().removeSessions();
  +	SessionManager sm=ctx.getSessionManager();
  +	try {
  +	    sm.stop();
  +	} catch(IllegalStateException ex ) {
  +	    throw new TomcatException( ex );
  +	}
       }
  -
   
   }
  
  
  
  1.6       +113 -282  jakarta-tomcat/src/share/org/apache/tomcat/session/StandardManager.java
  
  Index: StandardManager.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/session/StandardManager.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- StandardManager.java	2000/05/12 06:15:24	1.5
  +++ StandardManager.java	2000/05/12 15:26:40	1.6
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/session/StandardManager.java,v 1.5 2000/05/12 06:15:24 costin Exp $
  - * $Revision: 1.5 $
  - * $Date: 2000/05/12 06:15:24 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/session/StandardManager.java,v 1.6 2000/05/12 15:26:40 costin Exp $
  + * $Revision: 1.6 $
  + * $Date: 2000/05/12 15:26:40 $
    *
    * ====================================================================
    *
  @@ -103,27 +103,11 @@
    * </ul>
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.5 $ $Date: 2000/05/12 06:15:24 $
  + * @author costin@eng.sun.com
  + * @version $Revision: 1.6 $ $Date: 2000/05/12 15:26:40 $
    */
  -
   public final class StandardManager implements Runnable, SessionManager {
  -    public StandardManager() {
  -	try {
  -	    start();
  -	} catch( Exception ex ) {
  -	}
  -    }
  -
       // ----------------------------------------------------- Instance Variables
  -
  -    Context ctx;
  -
  -    /**
  -     * The Container with which this Manager is associated.
  -     */
  -    protected Container container;
  -
  -
       /**
        * The distributable flag for Sessions created by this Manager.  If this
        * flag is set to <code>true</code>, any user attributes added to a
  @@ -131,72 +115,68 @@
        */
       protected boolean distributable;
   
  -
  -    /**
  -     * The descriptive information string for this implementation.
  -     */
  -    private static final String info = "ManagerBase/1.0";
  -
  -
       /**
        * The default maximum inactive interval for Sessions created by
        * this Manager.
        */
       protected int maxInactiveInterval = 60;
   
  -
       /**
        * The set of previously recycled Sessions for this Manager.
        */
       protected Vector recycled = new Vector();
   
  -
       /**
        * The set of currently active Sessions for this Manager, keyed by
        * session identifier.
        */
       protected Hashtable sessions = new Hashtable();
  -
  -
  -    // ------------------------------------------------------------- Properties
   
  -    public void setContext( Context ctx ) {
  -	this.ctx=ctx;
  -    }
  +    /**
  +     * The interval (in seconds) between checks for expired sessions.
  +     */
  +    private int checkInterval = 60;
   
       /**
  -     * Return the Container with which this Manager is associated.
  +     * The maximum number of active Sessions allowed, or -1 for no limit.
        */
  -    public Container getContainer() {
  +    protected int maxActiveSessions = -1;
   
  -	return (this.container);
  +    /**
  +     * The string manager for this package.
  +     */
  +    private static StringManager sm =
  +        StringManager.getManager("org.apache.tomcat.session");
   
  -    }
  +    /**
  +     * The background thread.
  +     */
  +    private Thread thread = null;
   
  +    /**
  +     * The background thread completion semaphore.
  +     */
  +    private boolean threadDone = false;
   
       /**
  -     * Set the Container with which this Manager is associated.
  -     *
  -     * @param container The newly associated Container
  +     * Name to register for the background thread.
        */
  -    public void setContainer(Container container) {
  +    private String threadName = "StandardManager";
   
  -	this.container = container;
  +    // ------------------------------------------------------------- Constructor
   
  +    public StandardManager() {
       }
   
  -
  +    // ------------------------------------------------------------- Properties
       /**
        * Return the distributable flag for the sessions supported by
        * this Manager.
        */
       public boolean getDistributable() {
  -
   	return (this.distributable);
  -
       }
   
  -
       /**
        * Set the distributable flag for the sessions supported by this
        * Manager.  If this flag is set, all user data objects added to
  @@ -205,35 +185,17 @@
        * @param distributable The new distributable flag
        */
       public void setDistributable(boolean distributable) {
  -
   	this.distributable = distributable;
  -
  -    }
  -
  -
  -    /**
  -     * Return descriptive information about this Manager implementation and
  -     * the corresponding version number, in the format
  -     * <code>&lt;description&gt;/&lt;version&gt;</code>.
  -     */
  -    public String getInfo() {
  -
  -	return (this.info);
  -
       }
   
  -
       /**
        * Return the default maximum inactive interval (in seconds)
        * for Sessions created by this Manager.
        */
       public int getMaxInactiveInterval() {
  -
   	return (this.maxInactiveInterval);
  -
       }
   
  -
       /**
        * Set the default maximum inactive interval (in seconds)
        * for Sessions created by this Manager.
  @@ -241,67 +203,10 @@
        * @param interval The new default value
        */
       public void setMaxInactiveInterval(int interval) {
  -
   	this.maxInactiveInterval = interval;
  -
       }
   
  -
  -    // --------------------------------------------------------- Public Methods
  -
       /**
  -     * Mark the specified session's last accessed time.  This should be
  -     * called for each request by a RequestInterceptor.
  -     *
  -     * @param session The session to be marked
  -     */
  -    public void accessed( HttpSession session ) {
  -	if( session == null) return;
  -	if (session instanceof StandardSession)
  -	    ((StandardSession) session).access();
  -    }
  -
  -
  -    /**
  -     * Return the active Session, associated with this Manager, with the
  -     * specified session id (if any); otherwise return <code>null</code>.
  -     *
  -     * @param id The session id for the session to be returned
  -     *
  -     * @exception ClassNotFoundException if a deserialization error occurs
  -     *  while processing this request
  -     * @exception IllegalStateException if a new session cannot be
  -     *  instantiated for any reason
  -     * @exception IOException if an input/output error occurs while
  -     *  processing this request
  -     */
  -    public HttpSession findSession(String id) {
  -	
  -	if (id == null)
  -	    return (null);
  -	return ((HttpSession) sessions.get(id));
  -    }
  -
  -    /**
  -     * Remove all sessions because our associated Context is being shut down.
  -     *
  -     * @param ctx The context that is being shut down
  -     */
  -    public void removeSessions() {
  -
  -	// XXX XXX a manager may be shared by multiple
  -	// contexts, we just want to remove the sessions of ctx!
  -	// The manager will still run after that ( i.e. keep database
  -	// connection open
  -	try {
  -	    stop();
  -	} catch (TomcatException e) {
  -	    throw new IllegalStateException("" + e);
  -	}
  -
  -    }
  -
  -    /**
        * Used by context to configure the session manager's inactivity timeout.
        *
        * The SessionManager may have some default session time out, the
  @@ -318,161 +223,30 @@
           }
       }
   
  -    
  -    /**
  -     * Return the set of active Sessions associated with this Manager.
  -     * If this Manager has no active Sessions, a zero-length array is returned.
  -     */
  -    public HttpSession[] findSessions() {
  -
  -	synchronized (sessions) {
  -	    Vector keys = new Vector();
  -	    Enumeration ids = sessions.keys();
  -	    while (ids.hasMoreElements()) {
  -		String id = (String) ids.nextElement();
  -		keys.addElement(id);
  -	    }
  -	    HttpSession results[] = new HttpSession[keys.size()];
  -	    for (int i = 0; i < results.length; i++) {
  -		String key = (String) keys.elementAt(i);
  -		results[i] = (HttpSession) sessions.get(key);
  -	    }
  -	    return (results);
  -	}
  -
  -    }
  -
  -
  -    // -------------------------------------------------------- Package Methods
  -
  -
       /**
  -     * Add this Session to the set of active Sessions for this Manager.
  -     *
  -     * @param session Session to be added
  -     */
  -    void add(StandardSession session) {
  -
  -	sessions.put(session.getId(), session);
  -
  -    }
  -
  -
  -    /**
  -     * Add this Session to the recycle collection for this Manager.
  -     *
  -     * @param session Session to be recycled
  -     */
  -    void recycle(StandardSession session) {
  -
  -	recycled.addElement(session);
  -
  -    }
  -
  -
  -    /**
  -     * Remove this Session from the active Sessions for this Manager.
  -     *
  -     * @param session Session to be removed
  -     */
  -    void remove(StandardSession session) {
  -
  -	sessions.remove(session.getId());
  -
  -    }
  -
  -
  -
  -    // ----------------------------------------------------- Instance Variables
  -
  -
  -    /**
  -     * The interval (in seconds) between checks for expired sessions.
  -     */
  -    private int checkInterval = 60;
  -
  -
  -    /**
  -     * Has this component been configured yet?
  -     */
  -    private boolean configured = false;
  -
  -
  -
  -    /**
  -     * The maximum number of active Sessions allowed, or -1 for no limit.
  -     */
  -    protected int maxActiveSessions = -1;
  -
  -
  -    /**
  -     * The string manager for this package.
  -     */
  -    private StringManager sm =
  -        StringManager.getManager("org.apache.tomcat.session");
  -
  -
  -    /**
  -     * Has this component been started yet?
  -     */
  -    private boolean started = false;
  -
  -
  -    /**
  -     * The background thread.
  -     */
  -    private Thread thread = null;
  -
  -
  -    /**
  -     * The background thread completion semaphore.
  -     */
  -    private boolean threadDone = false;
  -
  -
  -    /**
  -     * Name to register for the background thread.
  -     */
  -    private String threadName = "StandardManager";
  -
  -
  -    // ------------------------------------------------------------- Properties
  -
  -
  -    /**
        * Return the check interval (in seconds) for this Manager.
        */
       public int getCheckInterval() {
  -
   	return (this.checkInterval);
  -
       }
   
  -
       /**
        * Set the check interval (in seconds) for this Manager.
        *
        * @param checkInterval The new check interval
        */
       public void setCheckInterval(int checkInterval) {
  -
   	this.checkInterval = checkInterval;
  -
       }
   
  -
  -
       /**
        * Return the maximum number of active Sessions allowed, or -1 for
        * no limit.
        */
       public int getMaxActiveSessions() {
  -
   	return (this.maxActiveSessions);
  -
       }
   
  -
       /**
        * Set the maximum number of actives Sessions allowed, or -1 for
        * no limit.
  @@ -480,14 +254,65 @@
        * @param max The new maximum number of sessions
        */
       public void setMaxActiveSessions(int max) {
  -
   	this.maxActiveSessions = max;
  +    }
   
  +    // --------------------------------------------------------- Public Methods
  +
  +    /**
  +     * Mark the specified session's last accessed time.  This should be
  +     * called for each request by a RequestInterceptor.
  +     *
  +     * @param session The session to be marked
  +     */
  +    public void access( HttpSession session ) {
  +	((StandardSession) session).access();
       }
   
  +    /** Notify that the servlet that acccessed the session is done
  +     */
  +    public void release( HttpSession session ) {
  +    }
   
  -    // --------------------------------------------------------- Public Methods
  +    /**
  +     * Return the active Session, associated with this Manager, with the
  +     * specified session id (if any); otherwise return <code>null</code>.
  +     *
  +     * @param id The session id for the session to be returned
  +     *
  +     * @exception ClassNotFoundException if a deserialization error occurs
  +     *  while processing this request
  +     * @exception IllegalStateException if a new session cannot be
  +     *  instantiated for any reason
  +     * @exception IOException if an input/output error occurs while
  +     *  processing this request
  +     */
  +    public HttpSession findSession(String id) {
  +	if (id == null)
  +	    return (null);
  +	return ((HttpSession) sessions.get(id));
  +    }
   
  +    /**
  +     * Return the set of active Sessions associated with this Manager.
  +     * If this Manager has no active Sessions, a zero-length array is returned.
  +     */
  +    public HttpSession[] findSessions() {
  +	synchronized (sessions) {
  +	    Vector keys = new Vector();
  +	    Enumeration ids = sessions.keys();
  +	    while (ids.hasMoreElements()) {
  +		String id = (String) ids.nextElement();
  +		keys.addElement(id);
  +	    }
  +	    HttpSession results[] = new HttpSession[keys.size()];
  +	    for (int i = 0; i < results.length; i++) {
  +		String key = (String) keys.elementAt(i);
  +		results[i] = (HttpSession) sessions.get(key);
  +	    }
  +	    return (results);
  +	}
  +    }
   
       /**
        * Construct and return a new session object, based on the default
  @@ -499,7 +324,7 @@
        * @exception IllegalStateException if a new session cannot be
        *  instantiated for any reason
        */
  -    public HttpSession createSession() {
  +    public HttpSession getNewSession() {
   
   	if ((maxActiveSessions >= 0) &&
   	  (sessions.size() >= maxActiveSessions))
  @@ -538,23 +363,10 @@
        *  configured (if required for this component)
        * @exception IllegalStateException if this component has already been
        *  started
  -     * @exception TomcatException if this component detects a fatal error
  -     *  that prevents this component from being used
        */
  -    public void start() throws TomcatException {
  -
  -	// Validate and update our current component state
  -	if (!configured)
  -	    throw new TomcatException
  -		(sm.getString("standardManager.notConfigured"));
  -	if (started)
  -	    throw new TomcatException
  -		(sm.getString("standardManager.alreadyStarted"));
  -	started = true;
  -
  +    public void start() {
   	// Start the background reaper thread
   	threadStart();
  -
       }
   
   
  @@ -566,17 +378,8 @@
        * @exception IllegalStateException if this component has not been started
        * @exception IllegalStateException if this component has already
        *  been stopped
  -     * @exception TomcatException if this component detects a fatal error
  -     *  that needs to be reported
        */
  -    public void stop() throws TomcatException {
  -
  -	// Validate and update our current component state
  -	if (!started)
  -	    throw new TomcatException
  -		(sm.getString("standardManager.notStarted"));
  -	started = false;
  -
  +    public void stop() {
   	// Stop the background reaper thread
   	threadStop();
   
  @@ -589,6 +392,34 @@
   	    session.expire();
   	}
   
  +    }
  +    // -------------------------------------------------------- Package Methods
  +
  +    /**
  +     * Add this Session to the set of active Sessions for this Manager.
  +     *
  +     * @param session Session to be added
  +     */
  +    void add(StandardSession session) {
  +	sessions.put(session.getId(), session);
  +    }
  +
  +    /**
  +     * Add this Session to the recycle collection for this Manager.
  +     *
  +     * @param session Session to be recycled
  +     */
  +    void recycle(StandardSession session) {
  +	recycled.addElement(session);
  +    }
  +
  +    /**
  +     * Remove this Session from the active Sessions for this Manager.
  +     *
  +     * @param session Session to be removed
  +     */
  +    void remove(StandardSession session) {
  +	sessions.remove(session.getId());
       }