Source Code Cross Referenced for PersistentManagerBase.java in  » Web-Server » Rimfaxe-Web-Server » org » apache » catalina » session » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Server » Rimfaxe Web Server » org.apache.catalina.session 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/session/PersistentManagerBase.java,v 1.8 2002/06/09 02:19:43 remm Exp $
0003:         * $Revision: 1.8 $
0004:         * $Date: 2002/06/09 02:19:43 $
0005:         *
0006:         * ====================================================================
0007:         *
0008:         * The Apache Software License, Version 1.1
0009:         *
0010:         * Copyright (c) 1999 The Apache Software Foundation.  All rights
0011:         * reserved.
0012:         *
0013:         * Redistribution and use in source and binary forms, with or without
0014:         * modification, are permitted provided that the following conditions
0015:         * are met:
0016:         *
0017:         * 1. Redistributions of source code must retain the above copyright
0018:         *    notice, this list of conditions and the following disclaimer.
0019:         *
0020:         * 2. Redistributions in binary form must reproduce the above copyright
0021:         *    notice, this list of conditions and the following disclaimer in
0022:         *    the documentation and/or other materials provided with the
0023:         *    distribution.
0024:         *
0025:         * 3. The end-user documentation included with the redistribution, if
0026:         *    any, must include the following acknowlegement:
0027:         *       "This product includes software developed by the
0028:         *        Apache Software Foundation (http://www.apache.org/)."
0029:         *    Alternately, this acknowlegement may appear in the software itself,
0030:         *    if and wherever such third-party acknowlegements normally appear.
0031:         *
0032:         * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
0033:         *    Foundation" must not be used to endorse or promote products derived
0034:         *    from this software without prior written permission. For written
0035:         *    permission, please contact apache@apache.org.
0036:         *
0037:         * 5. Products derived from this software may not be called "Apache"
0038:         *    nor may "Apache" appear in their names without prior written
0039:         *    permission of the Apache Group.
0040:         *
0041:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0042:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0043:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0044:         * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0045:         * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0046:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0047:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0048:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0049:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0050:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0051:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0052:         * SUCH DAMAGE.
0053:         * ====================================================================
0054:         *
0055:         * This software consists of voluntary contributions made by many
0056:         * individuals on behalf of the Apache Software Foundation.  For more
0057:         * information on the Apache Software Foundation, please see
0058:         * <http://www.apache.org/>.
0059:         *
0060:         * [Additional notices, if required by prior licensing conditions]
0061:         *
0062:         */
0063:
0064:        package org.apache.catalina.session;
0065:
0066:        import java.beans.PropertyChangeEvent;
0067:        import java.beans.PropertyChangeListener;
0068:        import java.beans.PropertyChangeSupport;
0069:        import java.io.BufferedInputStream;
0070:        import java.io.BufferedOutputStream;
0071:        import java.io.File;
0072:        import java.io.FileInputStream;
0073:        import java.io.FileNotFoundException;
0074:        import java.io.FileOutputStream;
0075:        import java.io.InputStream;
0076:        import java.io.IOException;
0077:        import java.io.ObjectInputStream;
0078:        import java.io.ObjectOutputStream;
0079:        import java.io.ObjectStreamClass;
0080:        import java.util.ArrayList;
0081:        import java.util.Iterator;
0082:        import javax.servlet.ServletContext;
0083:        import org.apache.catalina.Container;
0084:        import org.apache.catalina.Context;
0085:        import org.apache.catalina.Globals;
0086:        import org.apache.catalina.Lifecycle;
0087:        import org.apache.catalina.LifecycleEvent;
0088:        import org.apache.catalina.LifecycleException;
0089:        import org.apache.catalina.LifecycleListener;
0090:        import org.apache.catalina.Loader;
0091:        import org.apache.catalina.Manager;
0092:        import org.apache.catalina.Session;
0093:        import org.apache.catalina.Store;
0094:        import org.apache.catalina.util.LifecycleSupport;
0095:
0096:        /**
0097:         * Extends the <b>ManagerBase</b> class to implement most of the
0098:         * functionality required by a Manager which supports any kind of
0099:         * persistence, even if onlyfor  restarts.
0100:         * <p>
0101:         * <b>IMPLEMENTATION NOTE</b>:  Correct behavior of session storing and
0102:         * reloading depends upon external calls to the <code>start()</code> and
0103:         * <code>stop()</code> methods of this class at the correct times.
0104:         *
0105:         * @author Craig R. McClanahan
0106:         * @version $Revision: 1.8 $ $Date: 2002/06/09 02:19:43 $
0107:         */
0108:
0109:        public abstract class PersistentManagerBase extends ManagerBase
0110:                implements  Lifecycle, PropertyChangeListener, Runnable {
0111:
0112:            // ----------------------------------------------------- Instance Variables
0113:
0114:            /**
0115:             * The interval (in seconds) between checks for expired sessions.
0116:             */
0117:            private int checkInterval = 60;
0118:
0119:            /**
0120:             * The descriptive information about this implementation.
0121:             */
0122:            private static final String info = "PersistentManagerBase/1.0";
0123:
0124:            /**
0125:             * The lifecycle event support for this component.
0126:             */
0127:            protected LifecycleSupport lifecycle = new LifecycleSupport(this );
0128:
0129:            /**
0130:             * The maximum number of active Sessions allowed, or -1 for no limit.
0131:             */
0132:            private int maxActiveSessions = -1;
0133:
0134:            /**
0135:             * The descriptive name of this Manager implementation (for logging).
0136:             */
0137:            protected static String name = "PersistentManagerBase";
0138:
0139:            /**
0140:             * Has this component been started yet?
0141:             */
0142:            private boolean started = false;
0143:
0144:            /**
0145:             * The background thread.
0146:             */
0147:            private Thread thread = null;
0148:
0149:            /**
0150:             * The background thread completion semaphore.
0151:             */
0152:            protected boolean threadDone = false;
0153:
0154:            /**
0155:             * Name to register for the background thread.
0156:             */
0157:            private String threadName = "PersistentManagerBase";
0158:
0159:            /**
0160:             * Store object which will manage the Session store.
0161:             */
0162:            private Store store = null;
0163:
0164:            /**
0165:             * Whether to save and reload sessions when the Manager <code>unload</code>
0166:             * and <code>load</code> methods are called.
0167:             */
0168:            private boolean saveOnRestart = true;
0169:
0170:            /**
0171:             * How long a session must be idle before it should be backed up.
0172:             * -1 means sessions won't be backed up.
0173:             */
0174:            private int maxIdleBackup = -1;
0175:
0176:            /**
0177:             * Minimum time a session must be idle before it is swapped to disk.
0178:             * This overrides maxActiveSessions, to prevent thrashing if there are lots
0179:             * of active sessions. Setting to -1 means it's ignored.
0180:             */
0181:            private int minIdleSwap = -1;
0182:
0183:            /**
0184:             * The maximum time a session may be idle before it should be swapped
0185:             * to file just on general principle. Setting this to -1 means sessions
0186:             * should not be forced out.
0187:             */
0188:            private int maxIdleSwap = -1;
0189:
0190:            // ------------------------------------------------------------- Properties
0191:
0192:            /**
0193:             * Return the check interval (in seconds) for this Manager.
0194:             */
0195:            public int getCheckInterval() {
0196:
0197:                return (this .checkInterval);
0198:
0199:            }
0200:
0201:            /**
0202:             * Set the check interval (in seconds) for this Manager.
0203:             *
0204:             * @param checkInterval The new check interval
0205:             */
0206:            public void setCheckInterval(int checkInterval) {
0207:
0208:                int oldCheckInterval = this .checkInterval;
0209:                this .checkInterval = checkInterval;
0210:                support.firePropertyChange("checkInterval", new Integer(
0211:                        oldCheckInterval), new Integer(this .checkInterval));
0212:
0213:            }
0214:
0215:            /**
0216:             * Indicates how many seconds old a session can get, after its last
0217:             * use in a request, before it should be backed up to the store. -1
0218:             * means sessions are not backed up.
0219:             */
0220:            public int getMaxIdleBackup() {
0221:
0222:                return maxIdleBackup;
0223:
0224:            }
0225:
0226:            /**
0227:             * Sets the option to back sessions up to the Store after they
0228:             * are used in a request. Sessions remain available in memory
0229:             * after being backed up, so they are not passivated as they are
0230:             * when swapped out. The value set indicates how old a session
0231:             * may get (since its last use) before it must be backed up: -1
0232:             * means sessions are not backed up.
0233:             * <p>
0234:             * Note that this is not a hard limit: sessions are checked
0235:             * against this age limit periodically according to <b>checkInterval</b>.
0236:             * This value should be considered to indicate when a session is
0237:             * ripe for backing up.
0238:             * <p>
0239:             * So it is possible that a session may be idle for maxIdleBackup +
0240:             * checkInterval seconds, plus the time it takes to handle other
0241:             * session expiration, swapping, etc. tasks.
0242:             *
0243:             * @param backup The number of seconds after their last accessed
0244:             * time when they should be written to the Store.
0245:             */
0246:            public void setMaxIdleBackup(int backup) {
0247:
0248:                if (backup == this .maxIdleBackup)
0249:                    return;
0250:                int oldBackup = this .maxIdleBackup;
0251:                this .maxIdleBackup = backup;
0252:                support.firePropertyChange("maxIdleBackup", new Integer(
0253:                        oldBackup), new Integer(this .maxIdleBackup));
0254:
0255:            }
0256:
0257:            /**
0258:             * The time in seconds after which a session should be swapped out of
0259:             * memory to disk.
0260:             */
0261:            public int getMaxIdleSwap() {
0262:
0263:                return maxIdleSwap;
0264:
0265:            }
0266:
0267:            /**
0268:             * Sets the time in seconds after which a session should be swapped out of
0269:             * memory to disk.
0270:             */
0271:            public void setMaxIdleSwap(int max) {
0272:
0273:                if (max == this .maxIdleSwap)
0274:                    return;
0275:                int oldMaxIdleSwap = this .maxIdleSwap;
0276:                this .maxIdleSwap = max;
0277:                support.firePropertyChange("maxIdleSwap", new Integer(
0278:                        oldMaxIdleSwap), new Integer(this .maxIdleSwap));
0279:
0280:            }
0281:
0282:            /**
0283:             * The minimum time in seconds that a session must be idle before
0284:             * it can be swapped out of memory, or -1 if it can be swapped out
0285:             * at any time.
0286:             */
0287:            public int getMinIdleSwap() {
0288:
0289:                return minIdleSwap;
0290:
0291:            }
0292:
0293:            /**
0294:             * Sets the minimum time in seconds that a session must be idle before
0295:             * it can be swapped out of memory due to maxActiveSession. Set it to -1
0296:             * if it can be swapped out at any time.
0297:             */
0298:            public void setMinIdleSwap(int min) {
0299:
0300:                if (this .minIdleSwap == min)
0301:                    return;
0302:                int oldMinIdleSwap = this .minIdleSwap;
0303:                this .minIdleSwap = min;
0304:                support.firePropertyChange("minIdleSwap", new Integer(
0305:                        oldMinIdleSwap), new Integer(this .minIdleSwap));
0306:
0307:            }
0308:
0309:            /**
0310:             * Set the Container with which this Manager has been associated.  If
0311:             * it is a Context (the usual case), listen for changes to the session
0312:             * timeout property.
0313:             *
0314:             * @param container The associated Container
0315:             */
0316:            public void setContainer(Container container) {
0317:
0318:                // De-register from the old Container (if any)
0319:                if ((this .container != null)
0320:                        && (this .container instanceof  Context))
0321:                    ((Context) this .container)
0322:                            .removePropertyChangeListener(this );
0323:
0324:                // Default processing provided by our superclass
0325:                super .setContainer(container);
0326:
0327:                // Register with the new Container (if any)
0328:                if ((this .container != null)
0329:                        && (this .container instanceof  Context)) {
0330:                    setMaxInactiveInterval(((Context) this .container)
0331:                            .getSessionTimeout() * 60);
0332:                    ((Context) this .container).addPropertyChangeListener(this );
0333:                }
0334:
0335:            }
0336:
0337:            /**
0338:             * Return descriptive information about this Manager implementation and
0339:             * the corresponding version number, in the format
0340:             * <code>&lt;description&gt;/&lt;version&gt;</code>.
0341:             */
0342:            public String getInfo() {
0343:
0344:                return (this .info);
0345:
0346:            }
0347:
0348:            /**
0349:             * Return the maximum number of active Sessions allowed, or -1 for
0350:             * no limit.
0351:             */
0352:            public int getMaxActiveSessions() {
0353:
0354:                return (this .maxActiveSessions);
0355:
0356:            }
0357:
0358:            /**
0359:             * Set the maximum number of actives Sessions allowed, or -1 for
0360:             * no limit.
0361:             *
0362:             * @param max The new maximum number of sessions
0363:             */
0364:            public void setMaxActiveSessions(int max) {
0365:
0366:                int oldMaxActiveSessions = this .maxActiveSessions;
0367:                this .maxActiveSessions = max;
0368:                support.firePropertyChange("maxActiveSessions", new Integer(
0369:                        oldMaxActiveSessions), new Integer(
0370:                        this .maxActiveSessions));
0371:
0372:            }
0373:
0374:            /**
0375:             * Return the descriptive short name of this Manager implementation.
0376:             */
0377:            public String getName() {
0378:
0379:                return (name);
0380:
0381:            }
0382:
0383:            /**
0384:             * Get the started status.
0385:             */
0386:            protected boolean isStarted() {
0387:
0388:                return started;
0389:
0390:            }
0391:
0392:            /**
0393:             * Set the started flag
0394:             */
0395:            protected void setStarted(boolean started) {
0396:
0397:                this .started = started;
0398:
0399:            }
0400:
0401:            /**
0402:             * Set the Store object which will manage persistent Session
0403:             * storage for this Manager.
0404:             *
0405:             * @param store the associated Store
0406:             */
0407:            public void setStore(Store store) {
0408:
0409:                this .store = store;
0410:                store.setManager(this );
0411:
0412:            }
0413:
0414:            /**
0415:             * Return the Store object which manages persistent Session
0416:             * storage for this Manager.
0417:             */
0418:            public Store getStore() {
0419:
0420:                return (this .store);
0421:
0422:            }
0423:
0424:            /**
0425:             * Indicates whether sessions are saved when the Manager is shut down
0426:             * properly. This requires the unload() method to be called.
0427:             */
0428:            public boolean getSaveOnRestart() {
0429:
0430:                return saveOnRestart;
0431:
0432:            }
0433:
0434:            /**
0435:             * Set the option to save sessions to the Store when the Manager is
0436:             * shut down, then loaded when the Manager starts again. If set to
0437:             * false, any sessions found in the Store may still be picked up when
0438:             * the Manager is started again.
0439:             *
0440:             * @param save true if sessions should be saved on restart, false if
0441:             *     they should be ignored.
0442:             */
0443:            public void setSaveOnRestart(boolean saveOnRestart) {
0444:
0445:                if (saveOnRestart == this .saveOnRestart)
0446:                    return;
0447:
0448:                boolean oldSaveOnRestart = this .saveOnRestart;
0449:                this .saveOnRestart = saveOnRestart;
0450:                support.firePropertyChange("saveOnRestart", new Boolean(
0451:                        oldSaveOnRestart), new Boolean(this .saveOnRestart));
0452:
0453:            }
0454:
0455:            // --------------------------------------------------------- Public Methods
0456:
0457:            /**
0458:             * Clear all sessions from the Store.
0459:             */
0460:            public void clearStore() {
0461:
0462:                if (store == null)
0463:                    return;
0464:
0465:                try {
0466:                    store.clear();
0467:                } catch (IOException e) {
0468:                    log("Exception clearing the Store: " + e);
0469:                    e.printStackTrace();
0470:                }
0471:
0472:            }
0473:
0474:            /**
0475:             * Called by the background thread after active sessions have
0476:             * been checked for expiration, to allow sessions to be
0477:             * swapped out, backed up, etc.
0478:             */
0479:            public void processPersistenceChecks() {
0480:
0481:                processMaxIdleSwaps();
0482:                processMaxActiveSwaps();
0483:                processMaxIdleBackups();
0484:
0485:            }
0486:
0487:            /**
0488:             * Return a new session object as long as the number of active
0489:             * sessions does not exceed <b>maxActiveSessions</b>. If there
0490:             * aren't too many active sessions, or if there is no limit,
0491:             * a session is created or retrieved from the recycled pool.
0492:             *
0493:             * @exception IllegalStateException if a new session cannot be
0494:             *  instantiated for any reason
0495:             */
0496:            public Session createSession() {
0497:
0498:                if ((maxActiveSessions >= 0)
0499:                        && (sessions.size() >= maxActiveSessions))
0500:                    throw new IllegalStateException(sm
0501:                            .getString("standardManager.createSession.ise"));
0502:
0503:                return (super .createSession());
0504:
0505:            }
0506:
0507:            /**
0508:             * Return the active Session, associated with this Manager, with the
0509:             * specified session id (if any); otherwise return <code>null</code>.
0510:             * This method checks the persistence store if persistence is enabled,
0511:             * otherwise just uses the functionality from ManagerBase.
0512:             *
0513:             * @param id The session id for the session to be returned
0514:             *
0515:             * @exception IllegalStateException if a new session cannot be
0516:             *  instantiated for any reason
0517:             * @exception IOException if an input/output error occurs while
0518:             *  processing this request
0519:             */
0520:            public Session findSession(String id) throws IOException {
0521:
0522:                Session session = super .findSession(id);
0523:                if (session != null)
0524:                    return (session);
0525:
0526:                // See if the Session is in the Store
0527:                session = swapIn(id);
0528:                return (session);
0529:
0530:            }
0531:
0532:            /**
0533:             * Load all sessions found in the persistence mechanism, assuming
0534:             * they are marked as valid and have not passed their expiration
0535:             * limit. If persistence is not supported, this method returns
0536:             * without doing anything.
0537:             * <p>
0538:             * Note that by default, this method is not called by the MiddleManager
0539:             * class. In order to use it, a subclass must specifically call it,
0540:             * for example in the start() and/or processPersistenceChecks() methods.
0541:             */
0542:            public void load() {
0543:
0544:                // Initialize our internal data structures
0545:                recycled.clear();
0546:                sessions.clear();
0547:
0548:                if (store == null)
0549:                    return;
0550:
0551:                String[] ids = null;
0552:                try {
0553:                    ids = store.keys();
0554:                } catch (IOException e) {
0555:                    log("Can't load sessions from store, " + e.getMessage(), e);
0556:                    return;
0557:                }
0558:
0559:                int n = ids.length;
0560:                if (n == 0)
0561:                    return;
0562:
0563:                if (debug >= 1)
0564:                    log(sm.getString("persistentManager.loading", String
0565:                            .valueOf(n)));
0566:
0567:                for (int i = 0; i < n; i++)
0568:                    try {
0569:                        swapIn(ids[i]);
0570:                    } catch (IOException e) {
0571:                        log(
0572:                                "Failed load session from store, "
0573:                                        + e.getMessage(), e);
0574:                    }
0575:
0576:            }
0577:
0578:            /**
0579:             * Remove this Session from the active Sessions for this Manager,
0580:             * and from the Store.
0581:             *
0582:             * @param session Session to be removed
0583:             */
0584:            public void remove(Session session) {
0585:
0586:                super .remove(session);
0587:
0588:                if (store != null)
0589:                    try {
0590:                        store.remove(session.getId());
0591:                    } catch (IOException e) {
0592:                        log("Exception removing session  " + e.getMessage());
0593:                        e.printStackTrace();
0594:                    }
0595:
0596:            }
0597:
0598:            /**
0599:             * Save all currently active sessions in the appropriate persistence
0600:             * mechanism, if any.  If persistence is not supported, this method
0601:             * returns without doing anything.
0602:             * <p>
0603:             * Note that by default, this method is not called by the MiddleManager
0604:             * class. In order to use it, a subclass must specifically call it,
0605:             * for example in the stop() and/or processPersistenceChecks() methods.
0606:             */
0607:            public void unload() {
0608:
0609:                if (store == null)
0610:                    return;
0611:
0612:                Session sessions[] = findSessions();
0613:                int n = sessions.length;
0614:                if (n == 0)
0615:                    return;
0616:
0617:                if (debug >= 1)
0618:                    log(sm.getString("persistentManager.unloading", String
0619:                            .valueOf(n)));
0620:
0621:                for (int i = 0; i < n; i++)
0622:                    try {
0623:                        swapOut(sessions[i]);
0624:                    } catch (IOException e) {
0625:                        ; // This is logged in writeSession()
0626:                    }
0627:
0628:            }
0629:
0630:            // ------------------------------------------------------ Protected Methods
0631:
0632:            /**
0633:             * Look for a session in the Store and, if found, restore
0634:             * it in the Manager's list of active sessions if appropriate.
0635:             * The session will be removed from the Store after swapping
0636:             * in, but will not be added to the active session list if it
0637:             * is invalid or past its expiration.
0638:             */
0639:            protected Session swapIn(String id) throws IOException {
0640:
0641:                if (store == null)
0642:                    return null;
0643:
0644:                Session session = null;
0645:                try {
0646:                    session = store.load(id);
0647:                } catch (ClassNotFoundException e) {
0648:                    log(sm.getString("persistentManager.deserializeError", id,
0649:                            e));
0650:                    throw new IllegalStateException(sm.getString(
0651:                            "persistentManager.deserializeError", id, e));
0652:                }
0653:
0654:                if (session == null)
0655:                    return (null);
0656:
0657:                if (!session.isValid()
0658:                        || isSessionStale(session, System.currentTimeMillis())) {
0659:                    log("session swapped in is invalid or expired");
0660:                    session.expire();
0661:                    store.remove(id);
0662:                    return (null);
0663:                }
0664:
0665:                if (debug > 2)
0666:                    log(sm.getString("persistentManager.swapIn", id));
0667:
0668:                session.setManager(this );
0669:                add(session);
0670:                ((StandardSession) session).activate();
0671:
0672:                return (session);
0673:
0674:            }
0675:
0676:            /**
0677:             * Remove the session from the Manager's list of active
0678:             * sessions and write it out to the Store. If the session
0679:             * is past its expiration or invalid, this method does
0680:             * nothing.
0681:             *
0682:             * @param session The Session to write out.
0683:             */
0684:            protected void swapOut(Session session) throws IOException {
0685:
0686:                if (store == null || !session.isValid()
0687:                        || isSessionStale(session, System.currentTimeMillis()))
0688:                    return;
0689:
0690:                ((StandardSession) session).passivate();
0691:                writeSession(session);
0692:                super .remove(session);
0693:                session.recycle();
0694:
0695:            }
0696:
0697:            /**
0698:             * Write the provided session to the Store without modifying
0699:             * the copy in memory or triggering passivation events. Does
0700:             * nothing if the session is invalid or past its expiration.
0701:             */
0702:            protected void writeSession(Session session) throws IOException {
0703:
0704:                if (store == null || !session.isValid()
0705:                        || isSessionStale(session, System.currentTimeMillis()))
0706:                    return;
0707:
0708:                try {
0709:                    store.save(session);
0710:                } catch (IOException e) {
0711:                    log(sm.getString("persistentManager.serializeError",
0712:                            session.getId(), e));
0713:                    throw e;
0714:                }
0715:
0716:            }
0717:
0718:            // ------------------------------------------------------ Lifecycle Methods
0719:
0720:            /**
0721:             * Add a lifecycle event listener to this component.
0722:             *
0723:             * @param listener The listener to add
0724:             */
0725:            public void addLifecycleListener(LifecycleListener listener) {
0726:
0727:                lifecycle.addLifecycleListener(listener);
0728:
0729:            }
0730:
0731:            /**
0732:             * Get the lifecycle listeners associated with this lifecycle. If this 
0733:             * Lifecycle has no listeners registered, a zero-length array is returned.
0734:             */
0735:            public LifecycleListener[] findLifecycleListeners() {
0736:
0737:                return lifecycle.findLifecycleListeners();
0738:
0739:            }
0740:
0741:            /**
0742:             * Remove a lifecycle event listener from this component.
0743:             *
0744:             * @param listener The listener to remove
0745:             */
0746:            public void removeLifecycleListener(LifecycleListener listener) {
0747:
0748:                lifecycle.removeLifecycleListener(listener);
0749:
0750:            }
0751:
0752:            /**
0753:             * Prepare for the beginning of active use of the public methods of this
0754:             * component.  This method should be called after <code>configure()</code>,
0755:             * and before any of the public methods of the component are utilized.
0756:             *
0757:             * @exception LifecycleException if this component detects a fatal error
0758:             *  that prevents this component from being used
0759:             */
0760:            public void start() throws LifecycleException {
0761:
0762:                if (debug >= 1)
0763:                    log("Starting");
0764:
0765:                // Validate and update our current component state
0766:                if (started)
0767:                    throw new LifecycleException(sm
0768:                            .getString("standardManager.alreadyStarted"));
0769:                lifecycle.fireLifecycleEvent(START_EVENT, null);
0770:                started = true;
0771:
0772:                // Force initialization of the random number generator
0773:                if (debug >= 1)
0774:                    log("Force random number initialization starting");
0775:                String dummy = generateSessionId();
0776:                if (debug >= 1)
0777:                    log("Force random number initialization completed");
0778:
0779:                if (store == null)
0780:                    log("No Store configured, persistence disabled");
0781:                else if (store instanceof  Lifecycle)
0782:                    ((Lifecycle) store).start();
0783:
0784:                // Start the background reaper thread
0785:                threadStart();
0786:
0787:            }
0788:
0789:            /**
0790:             * Gracefully terminate the active use of the public methods of this
0791:             * component.  This method should be the last one called on a given
0792:             * instance of this component.
0793:             *
0794:             * @exception LifecycleException if this component detects a fatal error
0795:             *  that needs to be reported
0796:             */
0797:            public void stop() throws LifecycleException {
0798:
0799:                if (debug >= 1)
0800:                    log("Stopping");
0801:
0802:                // Validate and update our current component state
0803:                if (!isStarted())
0804:                    throw new LifecycleException(sm
0805:                            .getString("standardManager.notStarted"));
0806:                lifecycle.fireLifecycleEvent(STOP_EVENT, null);
0807:                setStarted(false);
0808:
0809:                // Stop the background reaper thread
0810:                threadStop();
0811:
0812:                if (getStore() != null && saveOnRestart) {
0813:                    unload();
0814:                } else {
0815:                    // Expire all active sessions
0816:                    Session sessions[] = findSessions();
0817:                    for (int i = 0; i < sessions.length; i++) {
0818:                        StandardSession session = (StandardSession) sessions[i];
0819:                        if (!session.isValid())
0820:                            continue;
0821:                        session.expire();
0822:                    }
0823:                }
0824:
0825:                if (getStore() != null && getStore() instanceof  Lifecycle)
0826:                    ((Lifecycle) getStore()).stop();
0827:
0828:                // Require a new random number generator if we are restarted
0829:                this .random = null;
0830:
0831:            }
0832:
0833:            // ----------------------------------------- PropertyChangeListener Methods
0834:
0835:            /**
0836:             * Process property change events from our associated Context.
0837:             *
0838:             * @param event The property change event that has occurred
0839:             */
0840:            public void propertyChange(PropertyChangeEvent event) {
0841:
0842:                // Validate the source of this event
0843:                if (!(event.getSource() instanceof  Context))
0844:                    return;
0845:                Context context = (Context) event.getSource();
0846:
0847:                // Process a relevant property change
0848:                if (event.getPropertyName().equals("sessionTimeout")) {
0849:                    try {
0850:                        setMaxInactiveInterval(((Integer) event.getNewValue())
0851:                                .intValue() * 60);
0852:                    } catch (NumberFormatException e) {
0853:                        log(sm.getString("standardManager.sessionTimeout",
0854:                                event.getNewValue().toString()));
0855:                    }
0856:                }
0857:
0858:            }
0859:
0860:            // -------------------------------------------------------- Private Methods
0861:
0862:            /**
0863:             * Indicate whether the session has been idle for longer
0864:             * than its expiration date as of the supplied time.
0865:             *
0866:             * FIXME: Probably belongs in the Session class.
0867:             */
0868:            protected boolean isSessionStale(Session session, long timeNow) {
0869:
0870:                int maxInactiveInterval = session.getMaxInactiveInterval();
0871:                if (maxInactiveInterval >= 0) {
0872:                    int timeIdle = // Truncate, do not round up
0873:                    (int) ((timeNow - session.getLastAccessedTime()) / 1000L);
0874:                    if (timeIdle >= maxInactiveInterval)
0875:                        return true;
0876:                }
0877:
0878:                return false;
0879:
0880:            }
0881:
0882:            /**
0883:             * Invalidate all sessions that have expired.
0884:             */
0885:            protected void processExpires() {
0886:
0887:                if (!started)
0888:                    return;
0889:
0890:                long timeNow = System.currentTimeMillis();
0891:                Session sessions[] = findSessions();
0892:
0893:                for (int i = 0; i < sessions.length; i++) {
0894:                    StandardSession session = (StandardSession) sessions[i];
0895:                    if (!session.isValid())
0896:                        continue;
0897:                    if (isSessionStale(session, timeNow))
0898:                        session.expire();
0899:                }
0900:
0901:            }
0902:
0903:            /**
0904:             * Swap idle sessions out to Store if they are idle too long.
0905:             */
0906:            protected void processMaxIdleSwaps() {
0907:
0908:                if (!isStarted() || maxIdleSwap < 0)
0909:                    return;
0910:
0911:                Session sessions[] = findSessions();
0912:                long timeNow = System.currentTimeMillis();
0913:
0914:                // Swap out all sessions idle longer than maxIdleSwap
0915:                // FIXME: What's preventing us from mangling a session during
0916:                // a request?
0917:                if (maxIdleSwap >= 0) {
0918:                    for (int i = 0; i < sessions.length; i++) {
0919:                        StandardSession session = (StandardSession) sessions[i];
0920:                        if (!session.isValid())
0921:                            continue;
0922:                        int timeIdle = // Truncate, do not round up
0923:                        (int) ((timeNow - session.getLastAccessedTime()) / 1000L);
0924:                        if (timeIdle > maxIdleSwap && timeIdle > minIdleSwap) {
0925:                            if (debug > 1)
0926:                                log(sm.getString(
0927:                                        "persistentManager.swapMaxIdle",
0928:                                        session.getId(), new Integer(timeIdle)));
0929:                            try {
0930:                                swapOut(session);
0931:                            } catch (IOException e) {
0932:                                ; // This is logged in writeSession()
0933:                            }
0934:                        }
0935:                    }
0936:                }
0937:
0938:            }
0939:
0940:            /**
0941:             * Swap idle sessions out to Store if too many are active
0942:             */
0943:            protected void processMaxActiveSwaps() {
0944:
0945:                if (!isStarted() || getMaxActiveSessions() < 0)
0946:                    return;
0947:
0948:                Session sessions[] = findSessions();
0949:
0950:                // FIXME: Smarter algorithm (LRU)
0951:                if (getMaxActiveSessions() >= sessions.length)
0952:                    return;
0953:
0954:                if (debug > 0)
0955:                    log(sm.getString("persistentManager.tooManyActive",
0956:                            new Integer(sessions.length)));
0957:
0958:                int toswap = sessions.length - getMaxActiveSessions();
0959:                long timeNow = System.currentTimeMillis();
0960:
0961:                for (int i = 0; i < sessions.length && toswap > 0; i++) {
0962:                    int timeIdle = // Truncate, do not round up
0963:                    (int) ((timeNow - sessions[i].getLastAccessedTime()) / 1000L);
0964:                    if (timeIdle > minIdleSwap) {
0965:                        if (debug > 1)
0966:                            log(sm.getString(
0967:                                    "persistentManager.swapTooManyActive",
0968:                                    sessions[i].getId(), new Integer(timeIdle)));
0969:                        try {
0970:                            swapOut(sessions[i]);
0971:                        } catch (IOException e) {
0972:                            ; // This is logged in writeSession()
0973:                        }
0974:                        toswap--;
0975:                    }
0976:                }
0977:
0978:            }
0979:
0980:            /**
0981:             * Back up idle sessions.
0982:             */
0983:            protected void processMaxIdleBackups() {
0984:
0985:                if (!isStarted() || maxIdleBackup < 0)
0986:                    return;
0987:
0988:                Session sessions[] = findSessions();
0989:                long timeNow = System.currentTimeMillis();
0990:
0991:                // Back up all sessions idle longer than maxIdleBackup
0992:                if (maxIdleBackup >= 0) {
0993:                    for (int i = 0; i < sessions.length; i++) {
0994:                        StandardSession session = (StandardSession) sessions[i];
0995:                        if (!session.isValid())
0996:                            continue;
0997:                        int timeIdle = // Truncate, do not round up
0998:                        (int) ((timeNow - session.getLastAccessedTime()) / 1000L);
0999:                        if (timeIdle > maxIdleBackup) {
1000:                            if (debug > 1)
1001:                                log(sm.getString(
1002:                                        "persistentManager.backupMaxIdle",
1003:                                        session.getId(), new Integer(timeIdle)));
1004:
1005:                            try {
1006:                                writeSession(session);
1007:                            } catch (IOException e) {
1008:                                ; // This is logged in writeSession()
1009:                            }
1010:                        }
1011:                    }
1012:                }
1013:
1014:            }
1015:
1016:            /**
1017:             * Sleep for the duration specified by the <code>checkInterval</code>
1018:             * property.
1019:             */
1020:            protected void threadSleep() {
1021:
1022:                try {
1023:                    Thread.sleep(checkInterval * 1000L);
1024:                } catch (InterruptedException e) {
1025:                    ;
1026:                }
1027:
1028:            }
1029:
1030:            /**
1031:             * Start the background thread that will periodically check for
1032:             * session timeouts.
1033:             */
1034:            protected void threadStart() {
1035:
1036:                if (thread != null)
1037:                    return;
1038:
1039:                threadDone = false;
1040:                threadName = "StandardManager[" + container.getName() + "]";
1041:                thread = new Thread(this , threadName);
1042:                thread.setDaemon(true);
1043:                thread.start();
1044:
1045:            }
1046:
1047:            /**
1048:             * Stop the background thread that is periodically checking for
1049:             * session timeouts.
1050:             */
1051:            protected void threadStop() {
1052:
1053:                if (thread == null)
1054:                    return;
1055:
1056:                threadDone = true;
1057:                thread.interrupt();
1058:                try {
1059:                    thread.join();
1060:                } catch (InterruptedException e) {
1061:                    ;
1062:                }
1063:
1064:                thread = null;
1065:
1066:            }
1067:
1068:            // ------------------------------------------------------ Background Thread
1069:
1070:            /**
1071:             * The background thread that checks for session timeouts and shutdown.
1072:             */
1073:            public void run() {
1074:
1075:                // Loop until the termination semaphore is set
1076:                while (!threadDone) {
1077:                    threadSleep();
1078:                    processExpires();
1079:                    processPersistenceChecks();
1080:                }
1081:
1082:            }
1083:
1084:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.