KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > catalina > session > PersistentManagerBase


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18
19 package org.apache.catalina.session;
20
21 import java.beans.PropertyChangeEvent JavaDoc;
22 import java.beans.PropertyChangeListener JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.security.AccessController JavaDoc;
25 import java.security.PrivilegedActionException JavaDoc;
26 import java.security.PrivilegedExceptionAction JavaDoc;
27 import org.apache.catalina.Container;
28 import org.apache.catalina.Context;
29 import org.apache.catalina.Lifecycle;
30 import org.apache.catalina.LifecycleException;
31 import org.apache.catalina.LifecycleListener;
32 import org.apache.catalina.Session;
33 import org.apache.catalina.Store;
34 import org.apache.catalina.util.LifecycleSupport;
35
36 import org.apache.catalina.security.SecurityUtil;
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39 /**
40  * Extends the <b>ManagerBase</b> class to implement most of the
41  * functionality required by a Manager which supports any kind of
42  * persistence, even if onlyfor restarts.
43  * <p>
44  * <b>IMPLEMENTATION NOTE</b>: Correct behavior of session storing and
45  * reloading depends upon external calls to the <code>start()</code> and
46  * <code>stop()</code> methods of this class at the correct times.
47  *
48  * @author Craig R. McClanahan
49  * @author Jean-Francois Arcand
50  * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
51  */

52
53 public abstract class PersistentManagerBase
54     extends ManagerBase
55     implements Lifecycle, PropertyChangeListener JavaDoc {
56
57     private static Log log = LogFactory.getLog(PersistentManagerBase.class);
58
59     // ---------------------------------------------------- Security Classes
60

61     private class PrivilegedStoreClear
62         implements PrivilegedExceptionAction JavaDoc {
63
64         PrivilegedStoreClear() {
65         }
66
67         public Object JavaDoc run() throws Exception JavaDoc{
68            store.clear();
69            return null;
70         }
71     }
72      
73     private class PrivilegedStoreRemove
74         implements PrivilegedExceptionAction JavaDoc {
75
76         private String JavaDoc id;
77             
78         PrivilegedStoreRemove(String JavaDoc id) {
79             this.id = id;
80         }
81
82         public Object JavaDoc run() throws Exception JavaDoc{
83            store.remove(id);
84            return null;
85         }
86     }
87      
88     private class PrivilegedStoreLoad
89         implements PrivilegedExceptionAction JavaDoc {
90
91         private String JavaDoc id;
92             
93         PrivilegedStoreLoad(String JavaDoc id) {
94             this.id = id;
95         }
96
97         public Object JavaDoc run() throws Exception JavaDoc{
98            return store.load(id);
99         }
100     }
101           
102     private class PrivilegedStoreSave
103         implements PrivilegedExceptionAction JavaDoc {
104
105         private Session session;
106             
107         PrivilegedStoreSave(Session session) {
108             this.session = session;
109         }
110
111         public Object JavaDoc run() throws Exception JavaDoc{
112            store.save(session);
113            return null;
114         }
115     }
116      
117     private class PrivilegedStoreKeys
118         implements PrivilegedExceptionAction JavaDoc {
119
120         PrivilegedStoreKeys() {
121         }
122
123         public Object JavaDoc run() throws Exception JavaDoc{
124            return store.keys();
125         }
126     }
127
128     // ----------------------------------------------------- Instance Variables
129

130
131     /**
132      * The descriptive information about this implementation.
133      */

134     private static final String JavaDoc info = "PersistentManagerBase/1.1";
135
136
137     /**
138      * The lifecycle event support for this component.
139      */

140     protected LifecycleSupport lifecycle = new LifecycleSupport(this);
141
142
143     /**
144      * The maximum number of active Sessions allowed, or -1 for no limit.
145      */

146     protected int maxActiveSessions = -1;
147
148
149     /**
150      * The descriptive name of this Manager implementation (for logging).
151      */

152     private static String JavaDoc name = "PersistentManagerBase";
153
154
155     /**
156      * Has this component been started yet?
157      */

158     protected boolean started = false;
159
160
161     /**
162      * Store object which will manage the Session store.
163      */

164     protected Store store = null;
165
166
167     /**
168      * Whether to save and reload sessions when the Manager <code>unload</code>
169      * and <code>load</code> methods are called.
170      */

171     protected boolean saveOnRestart = true;
172
173
174     /**
175      * How long a session must be idle before it should be backed up.
176      * -1 means sessions won't be backed up.
177      */

178     protected int maxIdleBackup = -1;
179
180
181     /**
182      * Minimum time a session must be idle before it is swapped to disk.
183      * This overrides maxActiveSessions, to prevent thrashing if there are lots
184      * of active sessions. Setting to -1 means it's ignored.
185      */

186     protected int minIdleSwap = -1;
187
188     /**
189      * The maximum time a session may be idle before it should be swapped
190      * to file just on general principle. Setting this to -1 means sessions
191      * should not be forced out.
192      */

193     protected int maxIdleSwap = -1;
194
195
196     /**
197      * Number of session creations that failed due to maxActiveSessions.
198      */

199     protected int rejectedSessions = 0;
200
201
202     /**
203      * Processing time during session expiration and passivation.
204      */

205     protected long processingTime = 0;
206
207
208     // ------------------------------------------------------------- Properties
209

210     
211   
212
213
214     /**
215      * Indicates how many seconds old a session can get, after its last use in a
216      * request, before it should be backed up to the store. -1 means sessions
217      * are not backed up.
218      */

219     public int getMaxIdleBackup() {
220
221         return maxIdleBackup;
222
223     }
224
225
226     /**
227      * Sets the option to back sessions up to the Store after they
228      * are used in a request. Sessions remain available in memory
229      * after being backed up, so they are not passivated as they are
230      * when swapped out. The value set indicates how old a session
231      * may get (since its last use) before it must be backed up: -1
232      * means sessions are not backed up.
233      * <p>
234      * Note that this is not a hard limit: sessions are checked
235      * against this age limit periodically according to <b>processExpiresFrequency</b>.
236      * This value should be considered to indicate when a session is
237      * ripe for backing up.
238      * <p>
239      * So it is possible that a session may be idle for maxIdleBackup +
240      * processExpiresFrequency * engine.backgroundProcessorDelay seconds, plus the time it takes to handle other
241      * session expiration, swapping, etc. tasks.
242      *
243      * @param backup The number of seconds after their last accessed
244      * time when they should be written to the Store.
245      */

246     public void setMaxIdleBackup (int backup) {
247
248         if (backup == this.maxIdleBackup)
249             return;
250         int oldBackup = this.maxIdleBackup;
251         this.maxIdleBackup = backup;
252         support.firePropertyChange("maxIdleBackup",
253                                    new Integer JavaDoc(oldBackup),
254                                    new Integer JavaDoc(this.maxIdleBackup));
255
256     }
257
258
259     /**
260      * The time in seconds after which a session should be swapped out of
261      * memory to disk.
262      */

263     public int getMaxIdleSwap() {
264
265         return maxIdleSwap;
266
267     }
268
269
270     /**
271      * Sets the time in seconds after which a session should be swapped out of
272      * memory to disk.
273      */

274     public void setMaxIdleSwap(int max) {
275
276         if (max == this.maxIdleSwap)
277             return;
278         int oldMaxIdleSwap = this.maxIdleSwap;
279         this.maxIdleSwap = max;
280         support.firePropertyChange("maxIdleSwap",
281                                    new Integer JavaDoc(oldMaxIdleSwap),
282                                    new Integer JavaDoc(this.maxIdleSwap));
283
284     }
285
286
287     /**
288      * The minimum time in seconds that a session must be idle before
289      * it can be swapped out of memory, or -1 if it can be swapped out
290      * at any time.
291      */

292     public int getMinIdleSwap() {
293
294         return minIdleSwap;
295
296     }
297
298
299     /**
300      * Sets the minimum time in seconds that a session must be idle before
301      * it can be swapped out of memory due to maxActiveSession. Set it to -1
302      * if it can be swapped out at any time.
303      */

304     public void setMinIdleSwap(int min) {
305
306         if (this.minIdleSwap == min)
307             return;
308         int oldMinIdleSwap = this.minIdleSwap;
309         this.minIdleSwap = min;
310         support.firePropertyChange("minIdleSwap",
311                                    new Integer JavaDoc(oldMinIdleSwap),
312                                    new Integer JavaDoc(this.minIdleSwap));
313
314     }
315
316
317     /**
318      * Set the Container with which this Manager has been associated. If it is a
319      * Context (the usual case), listen for changes to the session timeout
320      * property.
321      *
322      * @param container
323      * The associated Container
324      */

325     public void setContainer(Container container) {
326
327         // De-register from the old Container (if any)
328
if ((this.container != null) && (this.container instanceof Context))
329             ((Context) this.container).removePropertyChangeListener(this);
330
331         // Default processing provided by our superclass
332
super.setContainer(container);
333
334         // Register with the new Container (if any)
335
if ((this.container != null) && (this.container instanceof Context)) {
336             setMaxInactiveInterval
337                 ( ((Context) this.container).getSessionTimeout()*60 );
338             ((Context) this.container).addPropertyChangeListener(this);
339         }
340
341     }
342
343
344     /**
345      * Return descriptive information about this Manager implementation and
346      * the corresponding version number, in the format
347      * <code>&lt;description&gt;/&lt;version&gt;</code>.
348      */

349     public String JavaDoc getInfo() {
350
351         return (info);
352
353     }
354
355
356     /**
357      * Return true, if the session id is loaded in memory
358      * otherwise false is returned
359      *
360      * @param id The session id for the session to be searched for
361      */

362     public boolean isLoaded( String JavaDoc id ){
363         try {
364             if ( super.findSession(id) != null )
365                 return true;
366         } catch (IOException JavaDoc e) {
367             log.error("checking isLoaded for id, " + id + ", "+e.getMessage(), e);
368         }
369         return false;
370     }
371
372
373     /**
374      * Return the maximum number of active Sessions allowed, or -1 for
375      * no limit.
376      */

377     public int getMaxActiveSessions() {
378
379         return (this.maxActiveSessions);
380
381     }
382
383
384     /**
385      * Set the maximum number of actives Sessions allowed, or -1 for
386      * no limit.
387      *
388      * @param max The new maximum number of sessions
389      */

390     public void setMaxActiveSessions(int max) {
391
392         int oldMaxActiveSessions = this.maxActiveSessions;
393         this.maxActiveSessions = max;
394         support.firePropertyChange("maxActiveSessions",
395                                    new Integer JavaDoc(oldMaxActiveSessions),
396                                    new Integer JavaDoc(this.maxActiveSessions));
397
398     }
399
400
401     /**
402      * Number of session creations that failed due to maxActiveSessions.
403      *
404      * @return The count
405      */

406     public int getRejectedSessions() {
407         return rejectedSessions;
408     }
409
410     
411     public void setRejectedSessions(int rejectedSessions) {
412         this.rejectedSessions = rejectedSessions;
413     }
414
415     /**
416      * Return the descriptive short name of this Manager implementation.
417      */

418     public String JavaDoc getName() {
419
420         return (name);
421
422     }
423
424
425     /**
426      * Get the started status.
427      */

428     protected boolean isStarted() {
429
430         return started;
431
432     }
433
434
435     /**
436      * Set the started flag
437      */

438     protected void setStarted(boolean started) {
439
440         this.started = started;
441
442     }
443
444
445     /**
446      * Set the Store object which will manage persistent Session
447      * storage for this Manager.
448      *
449      * @param store the associated Store
450      */

451     public void setStore(Store store) {
452         this.store = store;
453         store.setManager(this);
454
455     }
456
457
458     /**
459      * Return the Store object which manages persistent Session
460      * storage for this Manager.
461      */

462     public Store getStore() {
463
464         return (this.store);
465
466     }
467
468
469
470     /**
471      * Indicates whether sessions are saved when the Manager is shut down
472      * properly. This requires the unload() method to be called.
473      */

474     public boolean getSaveOnRestart() {
475
476         return saveOnRestart;
477
478     }
479
480
481     /**
482      * Set the option to save sessions to the Store when the Manager is
483      * shut down, then loaded when the Manager starts again. If set to
484      * false, any sessions found in the Store may still be picked up when
485      * the Manager is started again.
486      *
487      * @param saveOnRestart true if sessions should be saved on restart, false if
488      * they should be ignored.
489      */

490     public void setSaveOnRestart(boolean saveOnRestart) {
491
492         if (saveOnRestart == this.saveOnRestart)
493             return;
494
495         boolean oldSaveOnRestart = this.saveOnRestart;
496         this.saveOnRestart = saveOnRestart;
497         support.firePropertyChange("saveOnRestart",
498                                    new Boolean JavaDoc(oldSaveOnRestart),
499                                    new Boolean JavaDoc(this.saveOnRestart));
500
501     }
502
503
504     // --------------------------------------------------------- Public Methods
505

506
507     /**
508      * Clear all sessions from the Store.
509      */

510     public void clearStore() {
511
512         if (store == null)
513             return;
514
515         try {
516             if (SecurityUtil.isPackageProtectionEnabled()){
517                 try{
518                     AccessController.doPrivileged(new PrivilegedStoreClear());
519                 }catch(PrivilegedActionException JavaDoc ex){
520                     Exception JavaDoc exception = ex.getException();
521                     log.error("Exception clearing the Store: " + exception);
522                     exception.printStackTrace();
523                 }
524             } else {
525                 store.clear();
526             }
527         } catch (IOException JavaDoc e) {
528             log.error("Exception clearing the Store: " + e);
529             e.printStackTrace();
530         }
531
532     }
533
534
535     /**
536      * Implements the Manager interface, direct call to processExpires and processPersistenceChecks
537      */

538     public void processExpires() {
539         
540         long timeNow = System.currentTimeMillis();
541         Session sessions[] = findSessions();
542         int expireHere = 0 ;
543         if(log.isDebugEnabled())
544              log.debug("Start expire sessions " + getName() + " at " + timeNow + " sessioncount " + sessions.length);
545         for (int i = 0; i < sessions.length; i++) {
546             if (!sessions[i].isValid()) {
547                 expiredSessions++;
548                 expireHere++;
549             }
550         }
551         processPersistenceChecks();
552         if ((getStore() != null) && (getStore() instanceof StoreBase)) {
553             ((StoreBase) getStore()).processExpires();
554         }
555         
556         long timeEnd = System.currentTimeMillis();
557         if(log.isDebugEnabled())
558              log.debug("End expire sessions " + getName() + " processingTime " + (timeEnd - timeNow) + " expired sessions: " + expireHere);
559         processingTime += (timeEnd - timeNow);
560         
561     }
562
563
564     /**
565      * Called by the background thread after active sessions have been checked
566      * for expiration, to allow sessions to be swapped out, backed up, etc.
567      */

568     public void processPersistenceChecks() {
569
570         processMaxIdleSwaps();
571         processMaxActiveSwaps();
572         processMaxIdleBackups();
573
574     }
575
576
577     /**
578      * Return the active Session, associated with this Manager, with the
579      * specified session id (if any); otherwise return <code>null</code>.
580      * This method checks the persistence store if persistence is enabled,
581      * otherwise just uses the functionality from ManagerBase.
582      *
583      * @param id The session id for the session to be returned
584      *
585      * @exception IllegalStateException if a new session cannot be
586      * instantiated for any reason
587      * @exception IOException if an input/output error occurs while
588      * processing this request
589      */

590     public Session findSession(String JavaDoc id) throws IOException JavaDoc {
591
592         Session session = super.findSession(id);
593         if (session != null)
594             return (session);
595
596         // See if the Session is in the Store
597
session = swapIn(id);
598         return (session);
599
600     }
601
602     /**
603      * Remove this Session from the active Sessions for this Manager,
604      * but not from the Store. (Used by the PersistentValve)
605      *
606      * @param session Session to be removed
607      */

608     public void removeSuper(Session session) {
609         super.remove (session);
610     }
611
612     /**
613      * Load all sessions found in the persistence mechanism, assuming
614      * they are marked as valid and have not passed their expiration
615      * limit. If persistence is not supported, this method returns
616      * without doing anything.
617      * <p>
618      * Note that by default, this method is not called by the MiddleManager
619      * class. In order to use it, a subclass must specifically call it,
620      * for example in the start() and/or processPersistenceChecks() methods.
621      */

622     public void load() {
623
624         // Initialize our internal data structures
625
sessions.clear();
626
627         if (store == null)
628             return;
629
630         String JavaDoc[] ids = null;
631         try {
632             if (SecurityUtil.isPackageProtectionEnabled()){
633                 try{
634                     ids = (String JavaDoc[])
635                         AccessController.doPrivileged(new PrivilegedStoreKeys());
636                 }catch(PrivilegedActionException JavaDoc ex){
637                     Exception JavaDoc exception = ex.getException();
638                     log.error("Exception in the Store during load: "
639                               + exception);
640                     exception.printStackTrace();
641                 }
642             } else {
643                 ids = store.keys();
644             }
645         } catch (IOException JavaDoc e) {
646             log.error("Can't load sessions from store, " + e.getMessage(), e);
647             return;
648         }
649
650         int n = ids.length;
651         if (n == 0)
652             return;
653
654         if (log.isDebugEnabled())
655             log.debug(sm.getString("persistentManager.loading", String.valueOf(n)));
656
657         for (int i = 0; i < n; i++)
658             try {
659                 swapIn(ids[i]);
660             } catch (IOException JavaDoc e) {
661                 log.error("Failed load session from store, " + e.getMessage(), e);
662             }
663
664     }
665
666
667     /**
668      * Remove this Session from the active Sessions for this Manager,
669      * and from the Store.
670      *
671      * @param session Session to be removed
672      */

673     public void remove(Session session) {
674
675         super.remove (session);
676
677         if (store != null){
678             removeSession(session.getIdInternal());
679         }
680     }
681
682     
683     /**
684      * Remove this Session from the active Sessions for this Manager,
685      * and from the Store.
686      *
687      * @param id Session's id to be removed
688      */

689     protected void removeSession(String JavaDoc id){
690         try {
691             if (SecurityUtil.isPackageProtectionEnabled()){
692                 try{
693                     AccessController.doPrivileged(new PrivilegedStoreRemove(id));
694                 }catch(PrivilegedActionException JavaDoc ex){
695                     Exception JavaDoc exception = ex.getException();
696                     log.error("Exception in the Store during removeSession: "
697                               + exception);
698                     exception.printStackTrace();
699                 }
700             } else {
701                  store.remove(id);
702             }
703         } catch (IOException JavaDoc e) {
704             log.error("Exception removing session " + e.getMessage());
705             e.printStackTrace();
706         }
707     }
708
709     /**
710      * Save all currently active sessions in the appropriate persistence
711      * mechanism, if any. If persistence is not supported, this method
712      * returns without doing anything.
713      * <p>
714      * Note that by default, this method is not called by the MiddleManager
715      * class. In order to use it, a subclass must specifically call it,
716      * for example in the stop() and/or processPersistenceChecks() methods.
717      */

718     public void unload() {
719
720         if (store == null)
721             return;
722
723         Session sessions[] = findSessions();
724         int n = sessions.length;
725         if (n == 0)
726             return;
727
728         if (log.isDebugEnabled())
729             log.debug(sm.getString("persistentManager.unloading",
730                              String.valueOf(n)));
731
732         for (int i = 0; i < n; i++)
733             try {
734                 swapOut(sessions[i]);
735             } catch (IOException JavaDoc e) {
736                 ; // This is logged in writeSession()
737
}
738
739     }
740
741
742     // ------------------------------------------------------ Protected Methods
743

744
745     /**
746      * Look for a session in the Store and, if found, restore
747      * it in the Manager's list of active sessions if appropriate.
748      * The session will be removed from the Store after swapping
749      * in, but will not be added to the active session list if it
750      * is invalid or past its expiration.
751      */

752     protected Session swapIn(String JavaDoc id) throws IOException JavaDoc {
753
754         if (store == null)
755             return null;
756
757         Session session = null;
758         try {
759             if (SecurityUtil.isPackageProtectionEnabled()){
760                 try{
761                     session = (Session)
762                       AccessController.doPrivileged(new PrivilegedStoreLoad(id));
763                 }catch(PrivilegedActionException JavaDoc ex){
764                     Exception JavaDoc exception = ex.getException();
765                     log.error("Exception in the Store during swapIn: "
766                               + exception);
767                     if (exception instanceof IOException JavaDoc){
768                         throw (IOException JavaDoc)exception;
769                     } else if (exception instanceof ClassNotFoundException JavaDoc) {
770                         throw (ClassNotFoundException JavaDoc)exception;
771                     }
772                 }
773             } else {
774                  session = store.load(id);
775             }
776         } catch (ClassNotFoundException JavaDoc e) {
777             log.error(sm.getString("persistentManager.deserializeError", id, e));
778             throw new IllegalStateException JavaDoc
779                 (sm.getString("persistentManager.deserializeError", id, e));
780         }
781
782         if (session == null)
783             return (null);
784
785         if (!session.isValid()) {
786             log.error("session swapped in is invalid or expired");
787             session.expire();
788             removeSession(id);
789             return (null);
790         }
791
792         if(log.isDebugEnabled())
793             log.debug(sm.getString("persistentManager.swapIn", id));
794
795         session.setManager(this);
796         // make sure the listeners know about it.
797
((StandardSession)session).tellNew();
798         add(session);
799         ((StandardSession)session).activate();
800         session.endAccess();
801
802         return (session);
803
804     }
805
806
807     /**
808      * Remove the session from the Manager's list of active
809      * sessions and write it out to the Store. If the session
810      * is past its expiration or invalid, this method does
811      * nothing.
812      *
813      * @param session The Session to write out.
814      */

815     protected void swapOut(Session session) throws IOException JavaDoc {
816
817         if (store == null || !session.isValid()) {
818             return;
819         }
820
821         ((StandardSession)session).passivate();
822         writeSession(session);
823         super.remove(session);
824         session.recycle();
825
826     }
827
828
829     /**
830      * Write the provided session to the Store without modifying
831      * the copy in memory or triggering passivation events. Does
832      * nothing if the session is invalid or past its expiration.
833      */

834     protected void writeSession(Session session) throws IOException JavaDoc {
835
836         if (store == null || !session.isValid()) {
837             return;
838         }
839
840         try {
841             if (SecurityUtil.isPackageProtectionEnabled()){
842                 try{
843                     AccessController.doPrivileged(new PrivilegedStoreSave(session));
844                 }catch(PrivilegedActionException JavaDoc ex){
845                     Exception JavaDoc exception = ex.getException();
846                     log.error("Exception in the Store during writeSession: "
847                               + exception);
848                     exception.printStackTrace();
849                 }
850             } else {
851                  store.save(session);
852             }
853         } catch (IOException JavaDoc e) {
854             log.error(sm.getString
855                 ("persistentManager.serializeError", session.getIdInternal(), e));
856             throw e;
857         }
858
859     }
860
861
862     // ------------------------------------------------------ Lifecycle Methods
863

864
865     /**
866      * Add a lifecycle event listener to this component.
867      *
868      * @param listener The listener to add
869      */

870     public void addLifecycleListener(LifecycleListener listener) {
871
872         lifecycle.addLifecycleListener(listener);
873
874     }
875
876
877     /**
878      * Get the lifecycle listeners associated with this lifecycle. If this
879      * Lifecycle has no listeners registered, a zero-length array is returned.
880      */

881     public LifecycleListener[] findLifecycleListeners() {
882
883         return lifecycle.findLifecycleListeners();
884
885     }
886
887
888     /**
889      * Remove a lifecycle event listener from this component.
890      *
891      * @param listener The listener to remove
892      */

893     public void removeLifecycleListener(LifecycleListener listener) {
894
895         lifecycle.removeLifecycleListener(listener);
896
897     }
898
899
900     /**
901      * Prepare for the beginning of active use of the public methods of this
902      * component. This method should be called after <code>configure()</code>,
903      * and before any of the public methods of the component are utilized.
904      *
905      * @exception LifecycleException if this component detects a fatal error
906      * that prevents this component from being used
907      */

908     public void start() throws LifecycleException {
909
910         // Validate and update our current component state
911
if (started) {
912             log.info(sm.getString("standardManager.alreadyStarted"));
913             return;
914         }
915         if( ! initialized )
916             init();
917         
918         lifecycle.fireLifecycleEvent(START_EVENT, null);
919         started = true;
920
921         // Force initialization of the random number generator
922
if (log.isDebugEnabled())
923             log.debug("Force random number initialization starting");
924         String JavaDoc dummy = generateSessionId();
925         if (log.isDebugEnabled())
926             log.debug("Force random number initialization completed");
927
928         if (store == null)
929             log.error("No Store configured, persistence disabled");
930         else if (store instanceof Lifecycle)
931             ((Lifecycle)store).start();
932
933     }
934
935
936     /**
937      * Gracefully terminate the active use of the public methods of this
938      * component. This method should be the last one called on a given
939      * instance of this component.
940      *
941      * @exception LifecycleException if this component detects a fatal error
942      * that needs to be reported
943      */

944    public void stop() throws LifecycleException {
945
946         if (log.isDebugEnabled())
947             log.debug("Stopping");
948
949         // Validate and update our current component state
950
if (!isStarted()) {
951             log.info(sm.getString("standardManager.notStarted"));
952             return;
953         }
954         
955         lifecycle.fireLifecycleEvent(STOP_EVENT, null);
956         setStarted(false);
957
958         if (getStore() != null && saveOnRestart) {
959             unload();
960         } else {
961             // Expire all active sessions
962
Session sessions[] = findSessions();
963             for (int i = 0; i < sessions.length; i++) {
964                 StandardSession session = (StandardSession) sessions[i];
965                 if (!session.isValid())
966                     continue;
967                 session.expire();
968             }
969         }
970
971         if (getStore() != null && getStore() instanceof Lifecycle)
972             ((Lifecycle)getStore()).stop();
973
974         // Require a new random number generator if we are restarted
975
this.random = null;
976
977         if( initialized )
978             destroy();
979
980     }
981
982
983     // ----------------------------------------- PropertyChangeListener Methods
984

985
986     /**
987      * Process property change events from our associated Context.
988      *
989      * @param event The property change event that has occurred
990      */

991     public void propertyChange(PropertyChangeEvent JavaDoc event) {
992
993         // Validate the source of this event
994
if (!(event.getSource() instanceof Context))
995             return;
996         Context context = (Context) event.getSource();
997
998         // Process a relevant property change
999
if (event.getPropertyName().equals("sessionTimeout")) {
1000            try {
1001                setMaxInactiveInterval
1002                    ( ((Integer JavaDoc) event.getNewValue()).intValue()*60 );
1003            } catch (NumberFormatException JavaDoc e) {
1004                log.error(sm.getString("standardManager.sessionTimeout",
1005                                 event.getNewValue().toString()));
1006            }
1007        }
1008
1009    }
1010
1011
1012    // ------------------------------------------------------ Protected Methods
1013

1014
1015    /**
1016     * Swap idle sessions out to Store if they are idle too long.
1017     */

1018    protected void processMaxIdleSwaps() {
1019
1020        if (!isStarted() || maxIdleSwap < 0)
1021            return;
1022
1023        Session sessions[] = findSessions();
1024        long timeNow = System.currentTimeMillis();
1025
1026        // Swap out all sessions idle longer than maxIdleSwap
1027
// FIXME: What's preventing us from mangling a session during
1028
// a request?
1029
if (maxIdleSwap >= 0) {
1030            for (int i = 0; i < sessions.length; i++) {
1031                StandardSession session = (StandardSession) sessions[i];
1032                if (!session.isValid())
1033                    continue;
1034                int timeIdle = // Truncate, do not round up
1035
(int) ((timeNow - session.getLastAccessedTime()) / 1000L);
1036                if (timeIdle > maxIdleSwap && timeIdle > minIdleSwap) {
1037                    if (log.isDebugEnabled())
1038                        log.debug(sm.getString
1039                            ("persistentManager.swapMaxIdle",
1040                             session.getIdInternal(), new Integer JavaDoc(timeIdle)));
1041                    try {
1042                        swapOut(session);
1043                    } catch (IOException JavaDoc e) {
1044                        ; // This is logged in writeSession()
1045
}
1046                }
1047            }
1048        }
1049
1050    }
1051
1052
1053    /**
1054     * Swap idle sessions out to Store if too many are active
1055     */

1056    protected void processMaxActiveSwaps() {
1057
1058        if (!isStarted() || getMaxActiveSessions() < 0)
1059            return;
1060
1061        Session sessions[] = findSessions();
1062
1063        // FIXME: Smarter algorithm (LRU)
1064
if (getMaxActiveSessions() >= sessions.length)
1065            return;
1066
1067        if(log.isDebugEnabled())
1068            log.debug(sm.getString
1069                ("persistentManager.tooManyActive",
1070                 new Integer JavaDoc(sessions.length)));
1071
1072        int toswap = sessions.length - getMaxActiveSessions();
1073        long timeNow = System.currentTimeMillis();
1074
1075        for (int i = 0; i < sessions.length && toswap > 0; i++) {
1076            int timeIdle = // Truncate, do not round up
1077
(int) ((timeNow - sessions[i].getLastAccessedTime()) / 1000L);
1078            if (timeIdle > minIdleSwap) {
1079                if(log.isDebugEnabled())
1080                    log.debug(sm.getString
1081                        ("persistentManager.swapTooManyActive",
1082                         sessions[i].getIdInternal(), new Integer JavaDoc(timeIdle)));
1083                try {
1084                    swapOut(sessions[i]);
1085                } catch (IOException JavaDoc e) {
1086                    ; // This is logged in writeSession()
1087
}
1088                toswap--;
1089            }
1090        }
1091
1092    }
1093
1094
1095    /**
1096     * Back up idle sessions.
1097     */

1098    protected void processMaxIdleBackups() {
1099
1100        if (!isStarted() || maxIdleBackup < 0)
1101            return;
1102
1103        Session sessions[] = findSessions();
1104        long timeNow = System.currentTimeMillis();
1105
1106        // Back up all sessions idle longer than maxIdleBackup
1107
if (maxIdleBackup >= 0) {
1108            for (int i = 0; i < sessions.length; i++) {
1109                StandardSession session = (StandardSession) sessions[i];
1110                if (!session.isValid())
1111                    continue;
1112                int timeIdle = // Truncate, do not round up
1113
(int) ((timeNow - session.getLastAccessedTime()) / 1000L);
1114                if (timeIdle > maxIdleBackup) {
1115                    if (log.isDebugEnabled())
1116                        log.debug(sm.getString
1117                            ("persistentManager.backupMaxIdle",
1118                            session.getIdInternal(), new Integer JavaDoc(timeIdle)));
1119
1120                    try {
1121                        writeSession(session);
1122                    } catch (IOException JavaDoc e) {
1123                        ; // This is logged in writeSession()
1124
}
1125                }
1126            }
1127        }
1128
1129    }
1130
1131}
1132
Popular Tags