FileDocCategorySizeDatePackage
PersistentManagerBase.javaAPI DocGlassfish v2 API45216Mon Sep 03 22:32:22 BST 2007org.apache.catalina.session

PersistentManagerBase

public abstract class PersistentManagerBase extends ManagerBase implements PropertyChangeListener, org.apache.catalina.Lifecycle
Extends the ManagerBase class to implement most of the functionality required by a Manager which supports any kind of persistence, even if onlyfor restarts.

IMPLEMENTATION NOTE: Correct behavior of session storing and reloading depends upon external calls to the start() and stop() methods of this class at the correct times.

author
Craig R. McClanahan
author
Jean-Francois Arcand
version
$Revision: 1.16.6.1 $ $Date: 2007/09/04 05:32:22 $

Fields Summary
private static final com.sun.org.apache.commons.logging.Log
log
private static final String
info
The descriptive information about this implementation.
protected org.apache.catalina.util.LifecycleSupport
lifecycle
The lifecycle event support for this component.
private int
maxActiveSessions
The maximum number of active Sessions allowed, or -1 for no limit.
protected static final String
name
The descriptive name of this Manager implementation (for logging).
private boolean
started
Has this component been started yet?
private org.apache.catalina.Store
store
Store object which will manage the Session store.
private boolean
saveOnRestart
Whether to save and reload sessions when the Manager unload and load methods are called.
private int
maxIdleBackup
How long a session must be idle before it should be backed up. -1 means sessions won't be backed up.
private int
minIdleSwap
Minimum time a session must be idle before it is swapped to disk. This overrides maxActiveSessions, to prevent thrashing if there are lots of active sessions. Setting to -1 means it's ignored.
private int
maxIdleSwap
The maximum time a session may be idle before it should be swapped to file just on general principle. Setting this to -1 means sessions should not be forced out.
private int
rejectedSessions
Number of sessions that were not created because the maximum allowed number of sessions was active
protected ConcurrentHashMap
invalidatedSessions
The set of invalidated Sessions for this Manager, keyed by session identifier.
private long
rememberInvalidatedSessionIdMilliSecs
Constructors Summary
Methods Summary
public voidaddLifecycleListener(org.apache.catalina.LifecycleListener listener)
Add a lifecycle event listener to this component.

param
listener The listener to add


        lifecycle.addLifecycleListener(listener);

    
public voidaddToInvalidatedSessions(java.lang.String sessionId)
Add this Session id to the set of invalidated Session ids for this Manager.

param
sessionId session id to be added

        invalidatedSessions.put(sessionId,
                                Long.valueOf(System.currentTimeMillis()));
    
public voidbackgroundProcess()
Perform the background processes for this Manager

    // END SJSAS 6406580


    // ------------------------------------------------------------- Properties

                
       
        this.processExpires();
        this.processPersistenceChecks();
        // START SJSAS 6406580
        this.processInvalidatedSessions();
        // END SJSAS 6406580
        if ((this.getStore() != null)
            && (this.getStore() instanceof StoreBase)) {
            ((StoreBase) this.getStore()).processExpires();
        }
    
public voidclearStore()
Clear all sessions from the Store.


        if (store == null)
            return;

        try {     
            if (SecurityUtil.isPackageProtectionEnabled()){
                try{
                    AccessController.doPrivileged(new PrivilegedStoreClear());
                }catch(PrivilegedActionException ex){
                    Exception exception = ex.getException();
                    log.error("Exception clearing the Store: " + exception);
                    exception.printStackTrace();                        
                }
            } else {
                store.clear();
            }
        } catch (IOException e) {
            log.error("Exception clearing the Store: " + e);
            e.printStackTrace();
        }

    
public org.apache.catalina.SessioncreateSession()
Return a new session object as long as the number of active sessions does not exceed maxActiveSessions. If there aren't too many active sessions, or if there is no limit, a session is created or retrieved from the recycled pool.

exception
IllegalStateException if a new session cannot be instantiated for any reason


        if ((maxActiveSessions >= 0) &&
          (sessions.size() >= maxActiveSessions))
            throw new IllegalStateException
                (sm.getString("standardManager.createSession.ise"));

        return (super.createSession());

    
private org.apache.catalina.SessiondoSwapIn(java.lang.String id, java.lang.String version)
Look for a session in the Store and, if found, restore it in the Manager's list of active sessions if appropriate. The session will be removed from the Store after swapping in, but will not be added to the active session list if it is invalid or past its expiration.


        if (store == null)
            return null;
        
        Session session = null;
        try {
            if (SecurityUtil.isPackageProtectionEnabled()){
                try{
                    session = (Session) AccessController.doPrivileged(new PrivilegedStoreLoad(id));
                }catch(PrivilegedActionException ex){
                    Exception exception = ex.getException();
                    log.error("Exception in the Store during swapIn: " + exception);
                    if (exception instanceof IOException){
                        throw (IOException)exception;
                    } else if (exception instanceof ClassNotFoundException) {
                        throw (ClassNotFoundException)exception;
                    }
                }
            } else {
		if (version != null) {
                     session = ((StoreBase) store).load(id, version);
                } else {
                     session = store.load(id);
                }
            }   
        } catch (ClassNotFoundException e) {
            log.error(sm.getString("persistentManager.deserializeError", id, e));
            throw new IllegalStateException
                (sm.getString("persistentManager.deserializeError", id, e));
        }

        if (session == null)
            return (null);

        if (!session.isValid()) {
            log.error("session swapped in is invalid or expired");
            //6406580 START
            /* - these lines are calling remove on store redundantly
            session.expire();
            removeSession(id);
             */
            //6406580 END            
            return (null);
        }

        if(log.isDebugEnabled())
            log.debug(sm.getString("persistentManager.swapIn", id));

        session.setManager(this);
        // make sure the listeners know about it.
        ((StandardSession)session).tellNew();
        add(session);
        ((StandardSession)session).activate();

        return (session);

    
public org.apache.catalina.LifecycleListener[]findLifecycleListeners()
Get the lifecycle listeners associated with this lifecycle. If this Lifecycle has no listeners registered, a zero-length array is returned.


        return lifecycle.findLifecycleListeners();

    
public org.apache.catalina.SessionfindSession(java.lang.String id)
Return the active Session, associated with this Manager, with the specified session id (if any); otherwise return null. This method checks the persistence store if persistence is enabled, otherwise just uses the functionality from ManagerBase.

param
id The session id for the session to be returned
exception
IllegalStateException if a new session cannot be instantiated for any reason
exception
IOException if an input/output error occurs while processing this request

        
        //6406580 START
        if(!this.isSessionIdValid(id)) {
            return null;
        }
        //6406580 END        

        Session session = super.findSession(id);
        if (session != null)
            return (session);

        // See if the Session is in the Store
        session = swapIn(id);
        return (session);

    
public org.apache.catalina.SessionfindSession(java.lang.String id, boolean removeCachedCopy)
Return the active Session, associated with this Manager, with the specified session id (if any); otherwise return null. This method first removes the cached copy if removeCachedCopy = true. Then this method checks the persistence store if persistence is enabled, otherwise just uses the functionality from ManagerBase.

param
id The session id for the session to be returned
param
removeCachedCopy
exception
IllegalStateException if a new session cannot be instantiated for any reason
exception
IOException if an input/output error occurs while processing this request


        Session theSession = super.findSession(id);
        if (theSession != null) {
            if(removeCachedCopy) {
                //remove from manager cache
                removeSuper(theSession);
                //remove from store cache if it exists
                if ((this.getStore() != null)
                    && (this.getStore() instanceof StoreBase)) {                
                    ((StoreBase) this.getStore()).removeFromStoreCache(id);
                }
                theSession = null;
            } else {
                return (theSession);
            }
        } 
        //now do full findSession
        theSession = findSession(id);   
        return theSession;

    
public java.lang.StringgetInfo()
Return descriptive information about this Manager implementation and the corresponding version number, in the format <description>/<version>.


        return (this.info);

    
public intgetMaxActiveSessions()
Return the maximum number of active Sessions allowed, or -1 for no limit.


        return (this.maxActiveSessions);

    
public intgetMaxIdleBackup()
Indicates how many seconds old a session can get, after its last use in a request, before it should be backed up to the store. -1 means sessions are not backed up.


        return maxIdleBackup;

    
public intgetMaxIdleSwap()
The time in seconds after which a session should be swapped out of memory to disk.


        return maxIdleSwap;

    
public intgetMinIdleSwap()
The minimum time in seconds that a session must be idle before it can be swapped out of memory, or -1 if it can be swapped out at any time.


        return minIdleSwap;

    
public java.lang.StringgetMonitorAttributeValues()

        //FIXME if desired for monitoring 'file'
        return "";
    
public java.lang.StringgetName()
Return the descriptive short name of this Manager implementation.


        return (name);

    
public intgetRejectedSessions()
Gets the number of sessions that were not created because the maximum number of active sessions was reached.

return
Number of rejected sessions

        return rejectedSessions;
    
public booleangetSaveOnRestart()
Indicates whether sessions are saved when the Manager is shut down properly. This requires the unload() method to be called.


        return saveOnRestart;

    
public org.apache.catalina.StoregetStore()
Return the Store object which manages persistent Session storage for this Manager.


        return (this.store);

    
public booleanisLoaded(java.lang.String id)
Return true, if the session id is loaded in memory otherwise false is returned

param
id The session id for the session to be searched for
exception
IOException if an input/output error occurs while processing this request

        try {
            if ( super.findSession(id) != null )
                return true;
        } catch (IOException e) {
            log.error("checking isLoaded for id, " + id + ", "+e.getMessage(), e);
        }
        return false;
    
public booleanisSessionIdValid(java.lang.String sessionId)

return
true if the given session id is not contained in the map of invalidated session ids, false otherwise

       
        return (!invalidatedSessions.containsKey(sessionId));
    
protected booleanisStarted()
Get the started status.


        return started;

    
public voidload()
Load all sessions found in the persistence mechanism, assuming they are marked as valid and have not passed their expiration limit. If persistence is not supported, this method returns without doing anything.

Note that by default, this method is not called by the MiddleManager class. In order to use it, a subclass must specifically call it, for example in the start() and/or processPersistenceChecks() methods.


        // Initialize our internal data structures
        sessions.clear();

        if (store == null)
            return;

        String[] ids = null;
        try {
            if (SecurityUtil.isPackageProtectionEnabled()){
                try{
                    ids = (String[])AccessController.doPrivileged(new PrivilegedStoreKeys());
                }catch(PrivilegedActionException ex){
                    Exception exception = ex.getException();
                    log.error("Exception in the Store during load: " + exception);
                    exception.printStackTrace();                        
                }
            } else {
                ids = store.keys();
            }
        } catch (IOException e) {
            log.error("Can't load sessions from store, " + e.getMessage(), e);
            return;
        }

        int n = ids.length;
        if (n == 0)
            return;

        if (log.isDebugEnabled())
            log.debug(sm.getString("persistentManager.loading", String.valueOf(n)));

        for (int i = 0; i < n; i++)
            try {
                swapIn(ids[i]);
            } catch (IOException e) {
                log.error("Failed load session from store, " + e.getMessage(), e);
            }

    
protected voidprocessExpires()
Invalidate all sessions that have expired. Hercules: modified method


        if (!started)
            return;

        long timeNow = System.currentTimeMillis();
        Session sessions[] = findSessions();

        for (int i = 0; i < sessions.length; i++) {
            StandardSession session = (StandardSession) sessions[i];            
            /* START CR 6363689
            if (!session.isValid()) {
            */
            // START CR 6363689
            if(!session.getIsValid() || session.hasExpired()) {
            // END CR 6363689            
                if(session.lockBackground()) { 
                    try {
                        session.expire();
                    } finally {
                        session.unlockBackground();
                    }
                }                                
	    }            
        }
    
protected voidprocessInvalidatedSessions()
Purges those session ids from the map of invalidated session ids whose time has come up


        if (!started) {
            return;
        }

        long timeNow = System.currentTimeMillis();
        Iterator<String> iter = invalidatedSessions.keySet().iterator();
        while (iter.hasNext()) {
            String id = iter.next();
            Long timeAdded = invalidatedSessions.get(id);
            if ((timeAdded == null)
                    || (timeNow - timeAdded.longValue() >
                                    rememberInvalidatedSessionIdMilliSecs)) {
                removeFromInvalidatedSessions(id);
            }
        }
    
protected voidprocessMaxActiveSwaps()
Swap idle sessions out to Store if too many are active Hercules: modified method

        
        if (!isStarted() || getMaxActiveSessions() < 0)
            return;

        Session sessions[] = findSessions();

        // FIXME: Smarter algorithm (LRU)
        if (getMaxActiveSessions() >= sessions.length)
            return;

        if(log.isDebugEnabled())
            log.debug(sm.getString
                ("persistentManager.tooManyActive",
                 Integer.valueOf(sessions.length)));        

        int toswap = sessions.length - getMaxActiveSessions();
        long timeNow = System.currentTimeMillis();

        for (int i = 0; i < sessions.length && toswap > 0; i++) {
            int timeIdle = // Truncate, do not round up
                (int) ((timeNow - sessions[i].getLastAccessedTime()) / 1000L);
            if (timeIdle > minIdleSwap) {
                StandardSession session = (StandardSession) sessions[i];
                //skip the session if it cannot be locked
                if(session.lockBackground()) {
                    if(log.isDebugEnabled())
                        log.debug(sm.getString
                            ("persistentManager.swapTooManyActive",
                            sessions[i].getIdInternal(),
                            Integer.valueOf(timeIdle)));                    
                    try {
                        swapOut(sessions[i]);
                    } catch (java.util.ConcurrentModificationException e1) {
                        ;   // This is logged in writeSession()                           
                    } catch (IOException e) {
                        ;   // This is logged in writeSession()
                    } catch (Exception e) {
                        ;   // This is logged in writeSession()                        
                    } finally {
                        session.unlockBackground();
                    }
                    toswap--;
                }
            }
        }

    
protected voidprocessMaxIdleBackups()
Back up idle sessions. Hercules: modified method

        
        if (!isStarted() || maxIdleBackup < 0)
            return;

        Session sessions[] = findSessions();
        long timeNow = System.currentTimeMillis();

        // Back up all sessions idle longer than maxIdleBackup
        if (maxIdleBackup >= 0) {
            for (int i = 0; i < sessions.length; i++) {
                StandardSession session = (StandardSession) sessions[i];
                if (!session.isValid())
                    continue;                
                int timeIdle = // Truncate, do not round up
                    (int) ((timeNow - session.getLastAccessedTime()) / 1000L);
                if (timeIdle > maxIdleBackup) { 
                    //if session cannot be background locked then skip it
                    if (session.lockBackground()) {                         
                        if (log.isDebugEnabled())
                            log.debug(sm.getString
                                ("persistentManager.backupMaxIdle",
                                session.getIdInternal(),
                                Integer.valueOf(timeIdle))); 
                        try {
                            writeSession(session);
                        } catch (java.util.ConcurrentModificationException e1) {
                            ;   // This is logged in writeSession()                            
                        } catch (IOException e) {
                            ;   // This is logged in writeSession()
                        } catch (Exception e) {
                            ;   // This is logged in writeSession()                                
                        } finally {
                            session.unlockBackground();
                        }
                    }
                }
            }
        }

    
protected voidprocessMaxIdleSwaps()
Swap idle sessions out to Store if they are idle too long.


        if (!isStarted() || maxIdleSwap < 0)
            return;

        Session sessions[] = findSessions();
        long timeNow = System.currentTimeMillis();

        // Swap out all sessions idle longer than maxIdleSwap
        // FIXME: What's preventing us from mangling a session during
        // a request?
        if (maxIdleSwap >= 0) {
            for (int i = 0; i < sessions.length; i++) {
                StandardSession session = (StandardSession) sessions[i];
                if (!session.isValid())
                    continue;
                int timeIdle = // Truncate, do not round up
                    (int) ((timeNow - session.getLastAccessedTime()) / 1000L);
                if (timeIdle > maxIdleSwap && timeIdle > minIdleSwap) {
                    if (log.isDebugEnabled())
                        log.debug(sm.getString
                            ("persistentManager.swapMaxIdle",
                             session.getIdInternal(),
                             Integer.valueOf(timeIdle)));
                    try {
                        swapOut(session);
                    } catch (IOException e) {
                        ;   // This is logged in writeSession()
                    }
                }
            }
        }

    
public voidprocessPersistenceChecks()
Called by the background thread after active sessions have been checked for expiration, to allow sessions to be swapped out, backed up, etc.


            processMaxIdleSwaps();
            processMaxActiveSwaps();
            processMaxIdleBackups();

    
public voidpropertyChange(java.beans.PropertyChangeEvent event)
Process property change events from our associated Context.

param
event The property change event that has occurred


        // Validate the source of this event
        if (!(event.getSource() instanceof Context))
            return;
        Context context = (Context) event.getSource();

        // Process a relevant property change
        if (event.getPropertyName().equals("sessionTimeout")) {
            try {
                setMaxInactiveIntervalSeconds
                    ( ((Integer) event.getNewValue()).intValue()*60 );
            } catch (NumberFormatException e) {
                log.error(sm.getString("standardManager.sessionTimeout",
                                 event.getNewValue().toString()));
            }
        }

    
public voidrelease()

        super.release();
        clearStore();
    
public voidremove(org.apache.catalina.Session session)
Remove this Session from the active Sessions for this Manager, and from the Store.

param
session Session to be removed

        remove(session, true);
    
public voidremove(org.apache.catalina.Session session, boolean persistentRemove)
Remove this Session from the active Sessions for this Manager, and from the Store.

param
session Session to be removed
param
boolean persistentRemove - do we remove persistent session too


        super.remove (session);

        if (persistentRemove && store != null){
            removeSession(session.getIdInternal());
        }
    
public voidremoveFromInvalidatedSessions(java.lang.String sessionId)
Removes the given session id from the map of invalidated session ids.

param
sessionId The session id to remove

       
        invalidatedSessions.remove(sessionId);
    
public voidremoveLifecycleListener(org.apache.catalina.LifecycleListener listener)
Remove a lifecycle event listener from this component.

param
listener The listener to remove


        lifecycle.removeLifecycleListener(listener);

    
private voidremoveSession(java.lang.String id)
Remove this Session from the active Sessions for this Manager, and from the Store.

param
is Session's id to be removed

        try {
            if (SecurityUtil.isPackageProtectionEnabled()){
                try{
                    AccessController.doPrivileged(new PrivilegedStoreRemove(id));
                }catch(PrivilegedActionException ex){
                    Exception exception = ex.getException();
                    log.error("Exception in the Store during removeSession: " + exception);
                    exception.printStackTrace();                        
                }
            } else {
                 store.remove(id);
            }               
        } catch (IOException e) {
            log.error("Exception removing session  " + e.getMessage());
            e.printStackTrace();
        }        
    
public voidremoveSuper(org.apache.catalina.Session session)
Remove this Session from the active Sessions for this Manager, but not from the Store. (Used by the PersistentValve)

param
session Session to be removed

        super.remove (session);
    
public voidsetContainer(org.apache.catalina.Container container)
Set the Container with which this Manager has been associated. If it is a Context (the usual case), listen for changes to the session timeout property.

param
container The associated Container


        // De-register from the old Container (if any)
        if ((this.container != null) && (this.container instanceof Context))
            ((Context) this.container).removePropertyChangeListener(this);

        // Default processing provided by our superclass
        super.setContainer(container);

        // Register with the new Container (if any)
        if ((this.container != null) && (this.container instanceof Context)) {
            setMaxInactiveIntervalSeconds
                ( ((Context) this.container).getSessionTimeout()*60 );
            ((Context) this.container).addPropertyChangeListener(this);
        }

        // START SJSAS 6406580
        if (container instanceof StandardContext) {
            // Determine for how long we're going to remember invalidated
            // session ids
            StandardContext ctx = (StandardContext) container;
            int frequency = ctx.getManagerChecksFrequency();
            int reapIntervalSeconds = ctx.getBackgroundProcessorDelay();
            rememberInvalidatedSessionIdMilliSecs
                = frequency * reapIntervalSeconds * 1000L * 2;
            if (rememberInvalidatedSessionIdMilliSecs <= 0) {
                rememberInvalidatedSessionIdMilliSecs = 60000L;
            }
        }
        // END SJSAS 6406580
    
public voidsetMaxActiveSessions(int max)
Set the maximum number of actives Sessions allowed, or -1 for no limit.

param
max The new maximum number of sessions


        int oldMaxActiveSessions = this.maxActiveSessions;
        this.maxActiveSessions = max;
        support.firePropertyChange("maxActiveSessions",
                                   Integer.valueOf(oldMaxActiveSessions),
                                   Integer.valueOf(this.maxActiveSessions));

    
public voidsetMaxIdleBackup(int backup)
Sets the option to back sessions up to the Store after they are used in a request. Sessions remain available in memory after being backed up, so they are not passivated as they are when swapped out. The value set indicates how old a session may get (since its last use) before it must be backed up: -1 means sessions are not backed up.

Note that this is not a hard limit: sessions are checked against this age limit periodically according to checkInterval. This value should be considered to indicate when a session is ripe for backing up.

So it is possible that a session may be idle for maxIdleBackup + checkInterval seconds, plus the time it takes to handle other session expiration, swapping, etc. tasks.

param
backup The number of seconds after their last accessed time when they should be written to the Store.


        if (backup == this.maxIdleBackup)
            return;
        int oldBackup = this.maxIdleBackup;
        this.maxIdleBackup = backup;
        support.firePropertyChange("maxIdleBackup",
                                   Integer.valueOf(oldBackup),
                                   Integer.valueOf(this.maxIdleBackup));

    
public voidsetMaxIdleSwap(int max)
Sets the time in seconds after which a session should be swapped out of memory to disk.


        if (max == this.maxIdleSwap)
            return;
        int oldMaxIdleSwap = this.maxIdleSwap;
        this.maxIdleSwap = max;
        support.firePropertyChange("maxIdleSwap",
                                   Integer.valueOf(oldMaxIdleSwap),
                                   Integer.valueOf(this.maxIdleSwap));

    
public voidsetMinIdleSwap(int min)
Sets the minimum time in seconds that a session must be idle before it can be swapped out of memory due to maxActiveSession. Set it to -1 if it can be swapped out at any time.


        if (this.minIdleSwap == min)
            return;
        int oldMinIdleSwap = this.minIdleSwap;
        this.minIdleSwap = min;
        support.firePropertyChange("minIdleSwap",
                                   Integer.valueOf(oldMinIdleSwap),
                                   Integer.valueOf(this.minIdleSwap));

    
public voidsetRejectedSessions(int rejectedSessions)
Sets the number of sessions that were not created because the maximum number of active sessions was reached.

param
rejectedSessions Number of rejected sessions

        this.rejectedSessions = rejectedSessions;
    
public voidsetSaveOnRestart(boolean saveOnRestart)
Set the option to save sessions to the Store when the Manager is shut down, then loaded when the Manager starts again. If set to false, any sessions found in the Store may still be picked up when the Manager is started again.

param
save true if sessions should be saved on restart, false if they should be ignored.


        if (saveOnRestart == this.saveOnRestart)
            return;

        boolean oldSaveOnRestart = this.saveOnRestart;
        this.saveOnRestart = saveOnRestart;
        support.firePropertyChange("saveOnRestart",
                                   Boolean.valueOf(oldSaveOnRestart),
                                   Boolean.valueOf(this.saveOnRestart));

    
protected voidsetStarted(boolean started)
Set the started flag


        this.started = started;

    
public voidsetStore(org.apache.catalina.Store store)
Set the Store object which will manage persistent Session storage for this Manager.

param
store the associated Store

        this.store = store;
        store.setManager(this);

    
public voidstart()
Prepare for the beginning of active use of the public methods of this component. This method should be called after configure(), and before any of the public methods of the component are utilized.

exception
LifecycleException if this component detects a fatal error that prevents this component from being used


        // Validate and update our current component state
        if (started) {
            log.info(sm.getString("standardManager.alreadyStarted"));
            return;
        }
        if( ! initialized )
            init();
        
        lifecycle.fireLifecycleEvent(START_EVENT, null);
        started = true;

        // Force initialization of the random number generator
        if (log.isTraceEnabled())
            log.trace("Force random number initialization starting");
        String dummy = generateSessionId();
        if (log.isTraceEnabled())
            log.trace("Force random number initialization completed");

        if (store == null)
            log.error("No Store configured, persistence disabled");
        else if (store instanceof Lifecycle)
            ((Lifecycle)store).start();

    
public voidstop()
Gracefully terminate the active use of the public methods of this component. This method should be the last one called on a given instance of this component.

exception
LifecycleException if this component detects a fatal error that needs to be reported


        if (log.isDebugEnabled())
            log.debug("Stopping");

        // Validate and update our current component state
        if (!isStarted()) {
            log.info(sm.getString("standardManager.notStarted"));
            return;
        }
        
        lifecycle.fireLifecycleEvent(STOP_EVENT, null);
        setStarted(false);

        if (getStore() != null && saveOnRestart) {
            unload();
        } else {
            // Expire all active sessions
            Session sessions[] = findSessions();
            for (int i = 0; i < sessions.length; i++) {
                StandardSession session = (StandardSession) sessions[i];
                if (!session.isValid())
                    continue;
                session.expire();
            }
        }

        if (getStore() != null && getStore() instanceof Lifecycle)
            ((Lifecycle)getStore()).stop();

        // Require a new random number generator if we are restarted
        this.random = null;

        if( initialized )
            destroy();

    
protected org.apache.catalina.SessionsuperFindSession(java.lang.String id)
used by subclasses of PersistentManagerBase Hercules: added method

        return super.findSession(id);
    
protected org.apache.catalina.SessionswapIn(java.lang.String id)
Look for a session in the Store and, if found, restore it in the Manager's list of active sessions if appropriate. The session will be removed from the Store after swapping in, but will not be added to the active session list if it is invalid or past its expiration.

        return swapIn(id, null);
    
protected org.apache.catalina.SessionswapIn(java.lang.String id, java.lang.String version)
Look for a session in the Store and, if found, restore it in the Manager's list of active sessions if appropriate. The session will be removed from the Store after swapping in, but will not be added to the active session list if it is invalid or past its expiration.

param
id The session id
param
version The requested session version


        ClassLoader webappCl = null;
        ClassLoader curCl = null;

        if (getContainer() != null
                    && getContainer().getLoader() != null) {
            webappCl = getContainer().getLoader().getClassLoader();
            curCl = Thread.currentThread().getContextClassLoader();
        }

        Session sess = null;

        if (webappCl != null && curCl != webappCl) {
            try {
                Thread.currentThread().setContextClassLoader(webappCl);
                sess = doSwapIn(id, version);
            } finally {
                Thread.currentThread().setContextClassLoader(curCl);
            }
        } else {
            sess = doSwapIn(id, version);
        }

        return sess;
    
protected voidswapOut(org.apache.catalina.Session session)
Remove the session from the Manager's list of active sessions and write it out to the Store. If the session is past its expiration or invalid, this method does nothing.

param
session The Session to write out.


        if (store == null || !session.isValid()) {
            return;
        }

        ((StandardSession)session).passivate();
        writeSession(session);
        super.remove(session);
        session.recycle();

    
public voidunload()
Save all currently active sessions in the appropriate persistence mechanism, if any. If persistence is not supported, this method returns without doing anything.

Note that by default, this method is not called by the MiddleManager class. In order to use it, a subclass must specifically call it, for example in the stop() and/or processPersistenceChecks() methods.


        if (store == null)
            return;

        Session sessions[] = findSessions();
        int n = sessions.length;
        if (n == 0)
            return;

        if (log.isDebugEnabled())
            log.debug(sm.getString("persistentManager.unloading",
                             String.valueOf(n)));

        for (int i = 0; i < n; i++)
            try {
                swapOut(sessions[i]);
            } catch (IOException e) {
                ;   // This is logged in writeSession()
            }

    
protected voidwriteSession(org.apache.catalina.Session session)
Write the provided session to the Store without modifying the copy in memory or triggering passivation events. Does nothing if the session is invalid or past its expiration.


        if (store == null || !session.isValid()) {
            return;
        }

        try {
            if (SecurityUtil.isPackageProtectionEnabled()){
                try{
                    AccessController.doPrivileged(new PrivilegedStoreSave(session));
                }catch(PrivilegedActionException ex){
                    Exception exception = ex.getException();
                    log.error("Exception in the Store during writeSession: " + exception);
                    exception.printStackTrace();                        
                }
            } else {
                 store.save(session);
            }   
        } catch (IOException e) {
            log.error(sm.getString
                ("persistentManager.serializeError", session.getIdInternal(), e));
            throw e;
        }