KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lutris > appserver > server > sessionEnhydra > StandardSessionManager


1 /*
2  * Enhydra Java Application Server Project
3  *
4  * The contents of this file are subject to the Enhydra Public License
5  * Version 1.1 (the "License"); you may not use this file except in
6  * compliance with the License. You may obtain a copy of the License on
7  * the Enhydra web site ( http://www.enhydra.org/ ).
8  *
9  * Software distributed under the License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
11  * the License for the specific terms governing rights and limitations
12  * under the License.
13  *
14  * The Initial Developer of the Enhydra Application Server is Lutris
15  * Technologies, Inc. The Enhydra Application Server and portions created
16  * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
17  * All Rights Reserved.
18  *
19  * Contributor(s):
20  *
21  * $Id: StandardSessionManager.java,v 1.8 2005/04/21 10:03:17 lola Exp $
22  */

23
24
25 package com.lutris.appserver.server.sessionEnhydra;
26
27 import java.lang.reflect.Constructor JavaDoc;
28 import java.util.Date JavaDoc;
29 import java.util.Enumeration JavaDoc;
30
31 import javax.servlet.http.HttpSession JavaDoc;
32 import javax.servlet.http.HttpSessionBindingEvent JavaDoc;
33 import javax.servlet.http.HttpSessionBindingListener JavaDoc;
34
35 import com.lutris.appserver.server.Application;
36 import com.lutris.appserver.server.Enhydra;
37 import com.lutris.appserver.server.httpPresentation.HttpPresentationComms;
38 import com.lutris.appserver.server.httpPresentation.HttpPresentationException;
39 import com.lutris.appserver.server.session.MemoryPersistence;
40 import com.lutris.appserver.server.session.Session;
41 import com.lutris.appserver.server.session.SessionException;
42 import com.lutris.appserver.server.session.SessionManager;
43 import com.lutris.appserver.server.sessionEnhydra.persistent.PersistentSessionHome;
44 import com.lutris.appserver.server.sessionEnhydra.persistent.PersistentSessionUserTable;
45 import com.lutris.appserver.server.user.User;
46 import com.lutris.logging.LogChannel;
47 import com.lutris.logging.Logger;
48 import com.lutris.util.Config;
49 import com.lutris.util.ConfigException;
50 import com.lutris.util.KeywordValueException;
51
52
53 /**
54  * This session manager maintains the mapping between session keys
55  * and sessions. It generates secure session keys that are safe to use
56  * as cookie values in web applications. It also manages the life
57  * of a session. If a session is not used (touched) for a preconfigured
58  * amount of time, then it is expired and removed from the session
59  * manager. The following parameters can be used to configure
60  * the session manager. They should be grouped together in a section,
61  * normally <code>SessionManager</code>, which is specified to
62  * the constructor.<p>
63  * <ul>
64  * <li><code>SessionLifetimeMax: {int}</code><p>
65  *
66  * The maximum number of minutes a session is valid. If this
67  * value us zero, then there is no lifetime limit.
68  * This parameter must be set in the configuration file.<p>
69  *
70  * <li><code>SessionIdleTimeMax: {int}</code><p>
71  *
72  * Maximum number of minutes a session may be idle before
73  * the session is expired (deleted). If this value
74  * is less than or equal to zero, then the session may
75  * be idle indefinitly.<p>
76  *
77  * <li><code>SessionNoUserIdleTimeMax: {int}</code><p>
78  *
79  * Maximum number of minutes a session that does not have a
80  * <CODE>User</CODE> object assocaited with it may be idle before
81  * the session is expired (deleted). If this value
82  * is less than or equal to zero, then the session may
83  * be idle indefinitly. Default is the same as <code>MaxIdleTime</code><p>
84  *
85  * <li><code>IdleScanInterval: {int}</code><p>
86  *
87  * How often, in seconds, the session manager tests if
88  * any sessions should be expired.
89  * This parameter must be greater than zero.<p>
90  *
91  * <li><code>RandomizerIntervals: {int [,int]...}</code><p>
92  *
93  * The set of varying intervals to use for adding user-generated entropy
94  * to the random number generator. It is a good idea to use several
95  * different prime numbers. These intervals are in seconds.<p>
96  *
97  * <li><code>SessionHome.Mode: {BASIC | PAGE_TO_DISK | PAGE_TO_DB | CUSTOM}</code><p>
98  *
99  * Indicates the mode (StandardSessionHome interface) that the standard
100  * session manager will use.
101  * In 'BASIC' mode the standard session manager uses the <code>BasicSessionHome</code>
102  * to manage sessions. In 'PAGE_TO_DISK' the standard session manager uses
103  * the <code>DiskPagedSessionHome</code> to manage sessions. In 'PAGE_TO_DB'
104  * the standard session manager used the <code>PersistentSessionHome</code>
105  * to manage sessions. In 'CUSTOM' the application specifies the classes
106  * that should be loaded and provide the <code>StandardSessionHome</code>
107  * implementation. If set to 'CUSTOM' then the settings
108  * <code>SessionHome.Class</code> and <code>SessionUserTable.Class</code>
109  * should be set.
110  *
111  * <li><code>SessionHome.Class: {String}</code><p>
112  *
113  * The class that implements the StandardSessionHome interface. This
114  * class is loaded by StandardSessionManager and used to managed
115  * the collection of sessions. If this option is not specified then
116  * BasicSessionHome is used. The SessionHome that is
117  * loaded by the session manager is expected to contain a consturctor
118  * that takes the following arguments:
119  * <code>SessionHome(StandardSessionManager mgr,
120  * com.lutris.util.Config config,
121  * ClassLoader loader)</code><p>
122  *
123  * <li><code>SessionUserTable.Class: {String}</code><p>
124  *
125  * The class that implements the StandardSessiondUserTable interface. This
126  * class is loaded by StandardSessionManager and used to managed
127  * the session to user relationships. If this option is not specified then
128  * BasicSessionUserTable is used. The SessionUserTable that is
129  * loaded by the session manager is expected to contain a consturctor
130  * that takes the following arguments:
131  * <code>SessionUserTable(com.lutris.util.Config config)</code><p>
132  *
133  * <li><code>MemoryPersistence: {true|false}</code><p>
134  *
135  * Indicate that should we keep sessions in memory when stop application
136  *
137  * </ul>
138  *
139  * @version $Revision: 1.8 $
140  * @author John Marco
141  * @author Shawn McMurdo
142  * @author Kyle Clark
143  * @author Mark Diekhans
144  * @see com.lutris.util.Config
145  * @see StandardSessionHome
146  * @see StandardSessionUserTable
147  * @see BasicSessionHome
148  * @see DiskPagedSessionHome
149  * @see com.lutris.appserver.server.sessionEnhydra.persistent.PersistentSessionHome
150  */

151 public class StandardSessionManager
152     implements SessionManager, StandardSessionIdleHandler {
153   /**
154    * Represents the current session management mode.
155    */

156   protected int mode;
157   /**
158    * Indicates that the session manager is using
159    * the basic session home interface to manage sessions.
160    * @see #getMode
161    * @see com.lutris.appserver.server.sessionEnhydra.BasicSessionHome
162    */

163   public static final int MODE_BASIC = 1;
164   /**
165    * Indicates that the session manager is using
166    * the page to disk home interface to manage sessions.
167    * @see #getMode
168    * @see com.lutris.appserver.server.sessionEnhydra.DiskPagedSessionHome
169    */

170   public static final int MODE_PAGE_TO_DISK = 2;
171   /**
172    * Indicates that the session manager is using
173    * the page to database home interface to manage sessions.
174    * @see #getMode
175    * @see com.lutris.appserver.server.sessionEnhydra.persistent.PersistentSessionHome
176    */

177   public static final int MODE_PAGE_TO_DB = 3;
178   /**
179    * Indicates that the session manager is using
180    * the custom home interface to manage sessions.
181    * @see #getMode
182    */

183   public static final int MODE_CUSTOM = 4;
184   /**
185    * Indicates that url encoding of session ids is never preformed.
186    * @see #getEncodeUrlState
187    **/

188   public static final String JavaDoc ENCODE_URL_NEVER = "Never";
189   /**
190    * Indicates that url encoding of session ids is always preformed.
191    * @see #getEncodeUrlState
192    **/

193   public static final String JavaDoc ENCODE_URL_ALWAYS = "Always";
194   /**
195    * Indicates that url encoding of session ids is preformed only when
196    * cookies are disabled on the client browser. This is automatically
197    * detected.
198    * @see #getEncodeUrlState
199    **/

200   public static final String JavaDoc ENCODE_URL_AUTO = "Auto";
201   public static final String JavaDoc ENCODE_RANDOM_YES = "Yes";
202   public static final String JavaDoc ENCODE_RANDOM_NO = "No";
203   /**
204    * Default maximum session life time, in seconds. Zero if there is no
205    * limit. A derived <CODE>SessionManager</CODE> may override this value
206    * to use the default expiration logic or override
207    * <CODE>isSessionExpired</CODE> to define custom expiration logic.
208    *
209    * @see lutris.session.StandardSessionManager#getMaxSessionLifeTime
210    */

211   protected static long defaultMaxSessionLifeTime = 0;
212   /**
213    * Default maximum session idle time, in seconds. A derived
214    * <CODE>SessionManager</CODE> may override this value to use the default
215    * expiration logic or override <CODE>isSessionExpired</CODE>
216    * to define custom expiration logic.
217    * A value less-than or equal to zero disables idle checking.
218    * Default value is 30 minutes.
219    *
220    * @see #getMaxSessionIdleTime
221    */

222   protected static long defaultMaxSessionIdleTime = 30*60;
223   /**
224    * Indicates url encoding status. Assumes that
225    * comms.response.writeHTML(HTMLDocument doc) is used to commit the
226    * response to the client. The default is to Auto.<br>
227    * <code>Never</code> indicates urls are never encoded with session keys.
228    * This indicates that session cookies have to be used or no session state
229    * can be maintained.<br>
230    * <code>Always</code> indicates that urls are always encoded with session
231    * keys. Session cookies are never used.<br>
232    * <code>Auto</code> indicates that session cookies will be if available.
233    * If not, urls will automatically be encoded.<br>
234    * @see #getEncodeUrlState
235    */

236   protected static String JavaDoc defaultEncodeUrlState = "Auto";
237   /**
238    * Default interval, in seconds, to scan for sessions to expire.
239    * A derived <CODE>SessionManager</CODE> may override this value.
240    * Default value is 30 seconds.
241    */

242   protected static long defaultIdleScanInterval = 30;
243   /**
244    * Default list of randomize key generator time intervals, in seconds.
245    * A list of prime numbers is recommended.
246    * A derived <CODE>SessionManager</CODE> may override this value.
247    */

248   protected static long[] defaultRandomizerIntervals = {
249     301, 1001, 5003
250   };
251   /**
252    * The name of the config variable for the max session lifetime.
253    */

254   public static final String JavaDoc CFG_LIFE = "SessionLifetimeMax";
255   /**
256    * The name of the config variable for the max session idle time.
257    */

258   public static final String JavaDoc CFG_IDLE = "SessionIdleTimeMax";
259   /**
260    * The name of the config variable for the url encoding state
261    */

262   public static final String JavaDoc CFG_ENCODE_URL_STATE = "SessionEncodeUrlState";
263   /**
264    * Url encoding for first page state (to force it or not)
265    * CFG_ENCODE_URL_STATE must not be set to NEVER for this parameter to take efect
266    */

267   public static final String JavaDoc CFG_ENCODE_FIRST_URL = "SessionEncodeFirstUrl";
268   /**
269    * The name of the config variable for the max idle time for sessions
270    * with no user.
271    */

272   public static final String JavaDoc CFG_NOUSER_IDLE = "SessionNoUserIdleTimeMax";
273   /**
274    * The name of the config variable for the interval between scans for
275    * idle sessions.
276    */

277   public static final String JavaDoc CFG_SCAN = "IdleScanInterval";
278   /**
279    * The name of the config variable for the interval between introduction
280    * of randomness to the session key generator.
281    */

282   public static final String JavaDoc CFG_RANDOM = "RandomizerIntervals";
283   /**
284    * The name of the config variable for the session home settings.
285    */

286   public static final String JavaDoc CFG_SESSION_HOME = "SessionHome";
287   /**
288    * The name of the config variable for the session home type.
289    */

290   public static final String JavaDoc CFG_SESSION_HOME_TYPE = "SessionHome.Mode";
291   /**
292    * Indicates that a sesson is still active.
293    *
294    * @see #sessionDeleted
295    */

296   public static final int SESSION_ACTIVE = 0;
297   /**
298    * Indicates that a sesson was deleted due to max time
299    * being exceeded.
300    *
301    * @see #sessionDeleted
302    */

303   public static final int SESSION_MAX_TIME = 1;
304   /**
305    * Indicates that a sesson was deleted due to idle time
306    * being exceeded.
307    *
308    * @see #sessionDeleted
309    */

310   public static final int SESSION_IDLE_EXPIRE = 2;
311   /**
312    * Indicates that a sesson was explictly deleted.
313    *
314    * @see #sessionDeleted
315    */

316   public static final int SESSION_EXPLICT_DELETE = 3;
317   /**
318    * Table of currently active user sessions is managed
319    * by the session home. Different implementations of
320    * StandardSessionHome can be loaded by this manager. A specific
321    * implementation can manage failover persistence, paging, etc.
322    */

323   // private StandardSessionHome sessionHome;
324
protected StandardSessionHome sessionHome;
325   /**
326    * Table of users objects. This table tracks the number of simultaneous
327    * sessions a user currently has active. Table entries are of type
328    * <CODE>Vector</CODE>, constaining Session objects, keyed by User
329    * object reference.
330    */

331   private StandardSessionUserTable sessionUserTable;
332   // The maximum number of sessions (highwater mark).
333
protected int maxSessions;
334   protected Date JavaDoc maxSessionsDate;
335   /**
336    * Object that generates random session keys. Manages a thread to
337    * for increase randomization.
338    *
339    * @see StandardSessionKeyGen
340    */

341   private StandardSessionKeyGen keyGenerator;
342   /**
343    * Maximum session life time, in seconds. Zero if there is no
344    * limit.
345    *
346    * @see lutris.session.StandardSessionManager#getMaxSessionLifeTime
347    */

348   private long maxSessionLifeTime;
349   /**
350    * Maximum session idle time, in seconds.
351    * A value less-than or equal to zero disables idle checking.
352    *
353    * @see #getMaxSessionIdleTime
354    */

355   protected long maxSessionIdleTime;
356   /**
357    * The url encoding state. Either <code>Never</code>
358    * <code>Always</code> <code>Auto</code>.
359    */

360   protected String JavaDoc encodeUrlState;
361   /**
362    * Url encoding for first page state (force it or not)
363    */

364   protected boolean encodeFirstUrl;
365   /**
366    * Background thread that keeps track of session idle time.
367    * Sessions that have been idle for more than a configurable time
368    * limit are terminated by this thread.
369    *
370    * @see StandardSessionIdleTimer
371    */

372   private StandardSessionIdleTimer idleTimer;
373   /**
374    * Maximum session idle time, in seconds for sessions
375    * that don't have a <CODE>User</CODE> object associated with them.
376    * A value less-than or equal to zero disables idle checking.
377    *
378    * @see #getMaxNoUserSessionIdleTime
379    */

380   protected long maxNoUserSessionIdleTime;
381   /**
382    * The time in seconds between scans for idle sessions to expire.
383    */

384   protected long scanInterval;
385   /**
386    * Log channel for debugging messages.
387    */

388     LogChannel logChannel = null;
389   /**
390    * The application using this session manager.
391    */

392   Application app = null;
393   /**
394    * The class loader used by this app/context.
395    */

396   ClassLoader JavaDoc classLoader;
397   /**
398    * The supported session home types.
399    */

400   private static final String JavaDoc BASIC = "BASIC";
401   private static final String JavaDoc PAGE_TO_DISK = "PAGE_TO_DISK";
402   private static final String JavaDoc PAGE_TO_DB = "PAGE_TO_DB";
403   private static final String JavaDoc CUSTOM = "CUSTOM";
404   /**
405    * The session home interface type being used.
406    */

407   String JavaDoc sessionHomeType = BASIC;
408   /** DACHA & TUFA
409    * variable which determine should we held sessions in memory during
410    * restart application
411    */

412   private boolean isMemoryPersistence = false;
413
414   /**
415    * Log configuration information.
416    */

417   private void logConfig () {
418       if (logChannel != null) {
419       logChannel.write(Logger.DEBUG,
420                "SessionManager." + CFG_LIFE + " = "
421                + maxSessionLifeTime + " sec");
422       logChannel.write(Logger.DEBUG,
423                "SessionManager." + CFG_IDLE + " = "
424                + maxSessionIdleTime + " sec");
425       logChannel.write(Logger.DEBUG,
426                "SessionManager." + CFG_NOUSER_IDLE + " = "
427                + maxNoUserSessionIdleTime + " sec");
428       logChannel.write(Logger.DEBUG,
429                "SessionManager." + CFG_SCAN + " = "
430                + scanInterval + " sec");
431       logChannel.write(Logger.DEBUG,
432                "SessionManager." + CFG_ENCODE_URL_STATE + " = "
433                + encodeUrlState);
434     logChannel.write(Logger.DEBUG,
435                "SessionManager." + CFG_ENCODE_FIRST_URL + " = "
436                + encodeFirstUrl);
437     }
438   }
439 public StandardSessionManager (){}
440   /**
441    * Creates a new <code>SessionManager</code> object.
442    * This constructor will first looks for the session manager
443    * configuration parameters that have the specified configuration
444    * prefix prepended to the standard session manager configuration
445    * option.<p>
446    *
447    * @param app the application associate with this session
448    * manager.
449    * @param config Object parsed from configuration file. This should be
450    * for the section constaining the session manager configuration.
451    * @param sessionMgrLogChannel If not <CODE>null</CODE>, channel to
452    * log debugging information to.
453    * @exception ConfigException signifies a problem in the
454    * configuration file.
455    * @exception SessionException
456    * if all classes (Home and UserTable) couldn't be loaded
457    * by the session manager.
458    */

459   public StandardSessionManager (Application application, Config config,
460                  LogChannel sessionMgrLogChannel)
461     throws ConfigException, SessionException {
462     //DACHA: first initialize app
463
app = application;
464     initManager(application.getClass().getClassLoader(),config,sessionMgrLogChannel);
465   }
466
467   public StandardSessionManager (ClassLoader JavaDoc classLoader, Config config,
468                  LogChannel sessionMgrLogChannel) throws ConfigException, SessionException {
469       initManager(classLoader,config,sessionMgrLogChannel);
470   }
471
472   private void initManager (ClassLoader JavaDoc classLoader, Config config,
473                 LogChannel sessionMgrLogChannel) throws ConfigException, SessionException {
474       this.classLoader = classLoader;
475       logChannel = sessionMgrLogChannel;
476     // High-water mark
477
maxSessions = 0;
478     maxSessionsDate = new Date JavaDoc();
479     /**DACHA & TUFA
480      *Config file specifies should we keep SessionManager in memory
481      *during restart application
482      */

483     if (config.containsKey("MemoryPersistence")) {
484       String JavaDoc mp = config.getString("MemoryPersistence");
485       if (mp.equals("true"))
486         isMemoryPersistence = true;
487     }
488     /*
489      * Config file specifies minutes, but the values are kept internally
490      * as seconds.
491      */

492     // Session lifetime
493
if (config.containsKey(CFG_LIFE)) {
494       maxSessionLifeTime = config.getLong(CFG_LIFE)*60;
495     }
496     else if (config.containsKey("Lifetime")) {
497       // backwards compatability
498
maxSessionLifeTime = config.getLong("Lifetime")*60;
499     }
500     else {
501       maxSessionLifeTime = defaultMaxSessionLifeTime;
502     }
503     // Idle time.
504
if (config.containsKey(CFG_IDLE)) {
505       maxSessionIdleTime = config.getLong(CFG_IDLE)*60;
506     }
507     else if (config.containsKey("MaxIdleTime")) {
508       // backwards compatability
509
maxSessionIdleTime = config.getLong("MaxIdleTime")*60;
510     }
511     else {
512       maxSessionIdleTime = defaultMaxSessionIdleTime;
513     }
514     // Url encoding state
515
if (config.containsKey(CFG_ENCODE_URL_STATE)) {
516       encodeUrlState = config.getString(CFG_ENCODE_URL_STATE);
517     }
518     else if (config.containsKey("EncodeUrlState")) {
519       // backwards compatability
520
encodeUrlState = config.getString("EncodeUrlState");
521     }
522     else {
523       encodeUrlState = defaultEncodeUrlState;
524     }
525     if (!encodeUrlState.equalsIgnoreCase(ENCODE_URL_NEVER) && !encodeUrlState.equalsIgnoreCase(ENCODE_URL_ALWAYS)
526         && !encodeUrlState.equalsIgnoreCase(ENCODE_URL_AUTO)) {
527       throw new ConfigException("EncodeUrlState must be one of the following: "
528           + ENCODE_URL_NEVER + ", " + ENCODE_URL_ALWAYS + ", or " + ENCODE_URL_AUTO
529           + ".");
530     }
531         
532     /**
533     * Url encoding for first page state (to force it or not)
534     * CFG_ENCODE_URL_STATE must not be set to NEVER for this parameter to take efect
535     */

536     if (config.containsKey(CFG_ENCODE_FIRST_URL)) {
537         encodeFirstUrl = config.getBoolean(CFG_ENCODE_FIRST_URL, false);
538     } else {
539         encodeFirstUrl = false;
540     }
541     
542     /**
543     * if CFG_ENCODE_URL_STATE is set to ALWAYS or NEVER
544     * ignore original and set adequate CFG_ENCODE_FIRST_URL
545     * parameter value
546     */

547     if (encodeUrlState.equalsIgnoreCase(ENCODE_URL_ALWAYS)){
548         encodeFirstUrl = true;
549     } else if (encodeUrlState.equalsIgnoreCase(ENCODE_URL_NEVER)) {
550         encodeFirstUrl = false;
551     }
552         
553     if (config.containsKey(CFG_NOUSER_IDLE)) {
554       maxNoUserSessionIdleTime = config.getLong(CFG_NOUSER_IDLE)*60;
555     }
556     else if (config.containsKey("MaxNoUserIdleTime")) {
557       // backwards compatability
558
maxNoUserSessionIdleTime = config.getLong("MaxNoUserIdleTime")*60;
559     }
560     else {
561       maxNoUserSessionIdleTime = maxSessionIdleTime;
562     }
563     scanInterval = defaultIdleScanInterval;
564     if (config.containsKey(CFG_SCAN)) {
565       scanInterval = config.getLong(CFG_SCAN);
566     }
567     else if (config.containsKey("IdleScanInterval")) {
568       // backwards compatability
569
scanInterval = config.getLong("IdleScanInterval");
570     }
571     if (scanInterval <= 0) {
572       throw new ConfigException("IdleScanInterval must be greater than zero.");
573     }
574     idleTimer = new StandardSessionIdleTimer(this, app, scanInterval);
575     if (config.containsKey(CFG_SESSION_HOME_TYPE)) {
576       sessionHomeType = config.getString(CFG_SESSION_HOME_TYPE);
577     }
578     if (!sessionHomeType.equalsIgnoreCase(BASIC) && !sessionHomeType.equalsIgnoreCase(PAGE_TO_DISK)
579         && !sessionHomeType.equalsIgnoreCase(PAGE_TO_DB) && !sessionHomeType.equalsIgnoreCase(CUSTOM)) {
580       throw new ConfigException("Invalid " + CFG_SESSION_HOME_TYPE + ": '"
581           + sessionHomeType + "'");
582     }
583     // Session Home
584
sessionHome = loadSessionHome(config);
585     // Session User Table
586
sessionUserTable = loadSessionUserTable(config);
587     // Random key generator.
588
long[] intervals = config.getLongs(CFG_RANDOM, defaultRandomizerIntervals);
589     if (intervals.length == 0) {
590       throw new ConfigException(CFG_RANDOM + " must contain some values.");
591     }
592     for (int i = 0; i < intervals.length; i++) {
593       if (intervals[i] <= 0) {
594         throw new ConfigException(CFG_RANDOM + " must contain positive integers.");
595       }
596     }
597     keyGenerator = new StandardSessionKeyGen(intervals);
598     // Start threads.
599
keyGenerator.start();
600     idleTimer.start();
601     logConfig();
602   }
603
604   /**
605    * Loads the StandardSessionHome used by this session manager.
606    *
607    * @param config
608    * This session manager's config section.
609    * @exception
610    * ConfigException if the configuration is invalid.
611    * @exception
612    * SessionException if the StandardSessionHome could not be loaded.
613    */

614   protected StandardSessionHome loadSessionHome (Config config) throws ConfigException,
615       SessionException {
616     try {
617       StandardSessionHome sessionHome = null;
618       Config homeConfig = null;
619       if (config.containsKey(CFG_SESSION_HOME)) {
620         homeConfig = (Config)config.getSection(CFG_SESSION_HOME);
621       }
622       else {
623         homeConfig = new Config();
624       }
625       if (sessionHomeType.equalsIgnoreCase(CUSTOM)) {
626         if (homeConfig.containsKey("Class")) {
627           String JavaDoc homeClassName = homeConfig.getString("Class");
628           try {
629             Class JavaDoc[] paramTypes = new Class JavaDoc[3];
630             Object JavaDoc[] args = new Object JavaDoc[3];
631             paramTypes[0] = Class.forName("com.lutris.appserver.server.sessionEnhydra.StandardSessionManager");
632             paramTypes[1] = Class.forName("com.lutris.util.Config");
633             paramTypes[2] = Class.forName("java.lang.ClassLoader");
634             args[0] = this;
635             args[1] = homeConfig;
636             args[2] = classLoader;
637             Constructor JavaDoc c = Class.forName(homeClassName).getConstructor(paramTypes);
638             sessionHome = (StandardSessionHome)c.newInstance(args);
639         if (logChannel != null) {
640         logChannel.write(Logger.DEBUG, "SessionMgr: "
641                  + "StandardSessionHome: " + homeClassName);
642             }
643           } catch (Exception JavaDoc e) {
644             throw new SessionException("Unable to load " + homeClassName,
645                 e);
646           }
647         }
648         mode = MODE_CUSTOM;
649       }
650       else if (sessionHomeType.equalsIgnoreCase(PAGE_TO_DISK)) {
651         sessionHome = new DiskPagedSessionHome(this, homeConfig, classLoader);
652         mode = MODE_PAGE_TO_DISK;
653       }
654       else if (sessionHomeType.equalsIgnoreCase(PAGE_TO_DB)) {
655         sessionHome = new PersistentSessionHome(this, homeConfig, classLoader);
656         mode = MODE_PAGE_TO_DB;
657       }
658       else {
659         sessionHome = new BasicSessionHome(this, homeConfig);
660         mode = MODE_BASIC;
661       }
662       if (logChannel != null) {
663       logChannel.write(Logger.DEBUG, "SessionMgr: "
664                + "StandardSessionHome: " + sessionHomeType + "\n");
665       }
666       return sessionHome;
667     } catch (KeywordValueException e) {
668       e.printStackTrace();
669       throw new ConfigException("SessionMgr: unable to load StandardSessionHome: "
670           + e);
671     }
672   }
673
674   /**
675    * Loads the StandardSessiondUserTable used by this session manager.
676    *
677    * @param config
678    * This session manager's config section.
679    * @exception
680    * ConfigException if the StandardSessionHome could not be loaded.
681    */

682   protected StandardSessionUserTable loadSessionUserTable (Config config) throws ConfigException,
683       SessionException {
684     try {
685       StandardSessionUserTable sessionUserTable = null;
686       Config userTableConfig = null;
687       if (config.containsKey("SessionUserTable")) {
688         userTableConfig = (Config)config.getSection("SessionUserTable");
689       }
690       else {
691         userTableConfig = new Config();
692       }
693       if (sessionHomeType.equalsIgnoreCase(CUSTOM)) {
694         String JavaDoc tableClassName = userTableConfig.getString("Class");
695         try {
696           Class JavaDoc[] paramTypes = new Class JavaDoc[1];
697           Object JavaDoc[] args = new Object JavaDoc[1];
698           paramTypes[0] = Class.forName("com.lutris.util.Config");
699           args[0] = userTableConfig;
700           Constructor JavaDoc c = Class.forName(tableClassName).getConstructor(paramTypes);
701           sessionUserTable = (StandardSessionUserTable)c.newInstance(args);
702       if (logChannel != null) {
703           logChannel.write(Logger.DEBUG, "SessionMgr: "
704                    + "StandardSessionUserTable: " + tableClassName);
705           }
706         } catch (NoSuchMethodException JavaDoc e) {
707           throw new SessionException("Unable to load " + tableClassName +
708               ": " + "Constructor not found.", e);
709         } catch (Exception JavaDoc e) {
710           throw new SessionException("Unable to create instance of " + tableClassName,
711               e);
712         }
713       }
714       else if (sessionHomeType.equalsIgnoreCase(PAGE_TO_DISK)) {
715         sessionUserTable = new PagedSessionUserTable(userTableConfig);
716       }
717       else if (sessionHomeType.equalsIgnoreCase(PAGE_TO_DB)) {
718         sessionUserTable = new PersistentSessionUserTable(userTableConfig);
719       }
720       else {
721         sessionUserTable = new BasicSessionUserTable(userTableConfig);
722       }
723       return sessionUserTable;
724     } catch (KeywordValueException e) {
725       throw new ConfigException("SessionMgr: unable to load StandardSessionUserTable: "
726           + e);
727     }
728   }
729
730   /**
731    * Shutdown this session manager, stopping threads that are
732    * associated with it.
733    */

734   public synchronized void shutdown () {
735     if (isMemoryPersistence)
736       MemoryPersistence.putSessionManager(app.getName(), this);
737     else {
738       if (keyGenerator != null) {
739         keyGenerator.shutdown();
740         keyGenerator = null;
741       }
742       if (idleTimer != null) {
743         idleTimer.shutdown();
744         idleTimer = null;
745       }
746       if (sessionHome != null) {
747         sessionHome.shutdown();
748         sessionHome = null;
749       }
750       if (sessionUserTable != null) {
751         sessionUserTable.shutdown();
752         sessionUserTable = null;
753       }
754     }
755   }
756
757   /**
758    * Allocate a new <CODE>StandardSession</CODE> object. This maybe
759    * overridden by derived session managers to allocated a
760    * <CODE>Session</CODE> object derived from <CODE>StandardSession</CODE>.
761    * This is called by <CODE>createSession</CODE>.
762    *
763    * @param sessionKey The session key to associate with the
764    * session.
765    * @return session The new <code>StandardSession</code> object.
766    * @see StandardSession
767    * @deprecated The instance of StandardSessionHome should be replaced
768    * instead of extending this method.
769    */

770   protected StandardSession newSession (String JavaDoc sessionKey) throws CreateSessionException,
771       SessionException {
772     return (StandardSession)sessionHome.createSession(sessionKey);
773   }
774
775   /**
776    * Create a new <CODE>Session</CODE> object and associate a unique random
777    * key. No <CODE>User</CODE> is initially associated with
778    * (<CODE>Session.getUser()</CODE> returns <CODE>null</CODE>/
779    *
780    * @return session The new <code>Session</code> object.
781    * @exception SessionException
782    * if the session cannot be created.
783    * @see Session
784    */

785   public Session JavaDoc createSession () throws SessionException {
786     return createSession("");
787   }
788
789   /**
790    * Create a new <CODE>Session</CODE> object and associate a unique random
791    * key. No <CODE>User</CODE> is initially associated with
792    * (<CODE>Session.getUser()</CODE> returns <CODE>null</CODE>/
793    *
794    * @param ipPortToken
795    * The base64 encoded IP and Port number to include in session key
796    * @return session The new <code>Session</code> object.
797    * @exception SessionException
798    * if the session cannot be created.
799    * @see Session
800    */

801   public Session JavaDoc createSession (String JavaDoc ipPortToken) throws SessionException {
802     StandardSession session = null;
803     String JavaDoc sessionKey = null;
804     /*
805      * Create a new key that does not already exist in
806      * the session table. The odds of this loop making more than
807      * one pass are astronomically small, but not zero.
808      */

809     do {
810       try {
811         sessionKey = keyGenerator.newSessionKey();
812         if (ipPortToken != null && ipPortToken.length() > 0) {
813                     sessionKey = sessionKey.substring(0,sessionKey.length()-2)+ipPortToken;
814         }
815         session = sessionHome.createSession(sessionKey);
816       } catch (DuplicateKeyException e) {
817         // TODO - log message?
818
session = null;
819       }
820     } while (session == null);
821     int currentSize = sessionHome.size();
822     if (currentSize > maxSessions) {
823       maxSessions = currentSize;
824       maxSessionsDate = new Date JavaDoc();
825     }
826     keyGenerator.incrementRandomCounter();
827     if (logChannel != null) {
828     logChannel.write(Logger.DEBUG, "SessionMgr: createSession: " + sessionKey);
829     }
830     return session;
831   }
832
833   public Session JavaDoc createSession (HttpPresentationComms comms) throws SessionException {
834     Session JavaDoc s = null;
835     String JavaDoc saTok = null;
836     try {
837       saTok = comms.request.getHeader(":aff:");
838     } catch (HttpPresentationException hpe) {
839       saTok = null;
840     }
841     if (saTok == null) {
842       s = createSession();
843     }
844     else {
845       s = createSession(saTok);
846       if (logChannel != null) {
847       logChannel.write(Logger.DEBUG,
848                "SessionKey created for EnhydraDirector");
849       }
850     }
851     return s;
852   }
853
854   /**
855    * Log a user being registered or unregistered.
856    */

857   private void logRegisterUser (Session JavaDoc session, String JavaDoc which) {
858       if (logChannel != null) {
859       String JavaDoc userName = null;
860       User user = session.getUser();
861       if (user != null) {
862           userName = user.getName();
863       }
864       logChannel.write(Logger.DEBUG, "SessionMgr: "
865                + which + ": " + session.getSessionKey() +
866                " user = \"" + userName + "\"");
867       }
868   }
869
870   /**
871    * Adds a session's user to the session-to-user table.
872    * This is called by the <CODE>Session</CODE> object to associate
873    * a session with a user.
874    *
875    * @param session The now logged-in <code>Session</code> instance to
876    * store in the session table.
877    * @see Session
878    * @see User
879    * @see #unregisterUser
880    * @exception SessionException
881    * if an error occurs.
882    */

883   protected synchronized void registerUser (Session JavaDoc session) throws SessionException {
884     sessionUserTable.add(session.getSessionKey(), session.getUser());
885     logRegisterUser(session, "registerUser");
886   }
887
888   /**
889    * Removes a session's user from the session-to-user table.
890    * This is called by the <CODE>Session</CODE> object to disassoicate
891    * a user from a session.
892    *
893    * @param session The now <code>Session</code> instance
894    * the user is being logged out from.
895    * @see Session
896    * @exception SessionException
897    * if an error occurs.
898    */

899   protected synchronized void unregisterUser (Session JavaDoc session) throws SessionException {
900     logRegisterUser(session, "unregisterUser");
901     sessionUserTable.remove(session.getSessionKey(), session.getUser());
902   }
903
904   /**
905    * Determine if a session should be expired based on the idle
906    * time. This method is designed to be overriden by derived classes that
907    * want to use different idle time checks.
908    *
909    * @param session Session to check.
910    * @return A reason code for the experation.
911    * One of <CODE>SESSION_MAX_TIME</CODE>,
912    * <CODE>SESSION_IDLE_EXPIRE</CODE>, or
913    * <CODE>SESSION_ACTIVE</CODE>, to indicate that the session
914    * is not expired.
915    *
916    * @see #sessionDeleted
917    * @see #maxSessionIdleTime
918    * @see #maxNoUserSessionIdleTime
919    */

920   protected int isSessionExpired (StandardSession session) {
921     long now = System.currentTimeMillis();
922     /*
923      * Has the session reached it's maximum age, regardless of user
924      * interaction? This is an optional feature.
925      */

926     long maxAge = session.getTimeExpires();
927     if ((maxAge > 0) && (now > maxAge)) {
928       return SESSION_MAX_TIME;
929     }
930     /*
931      * Has the session been idle too long? There are two thresholds,
932      * for whether or not a user is logged in.
933      * Both are optional features.
934      */

935     long idle = now - session.getTimeLastUsed();
936     long maxIdle;
937     if (session.getUser() != null) {
938       maxIdle = session.getMaxIdleTime();
939     }
940     else {
941       maxIdle = session.getMaxNoUserIdleTime();
942     }
943     if ((maxIdle > 0) && (idle > maxIdle)) {
944       return SESSION_IDLE_EXPIRE;
945     }
946     /*
947      * The session is ok.
948      */

949     return SESSION_ACTIVE;
950   }
951
952   /**
953    * Method called when a session is deleted.
954    * This method is designed to be overriden by derived classes that
955    * want need to take specific action, such as saving the sessions
956    * state.
957    * The default implementation of this method does nothing.
958    *
959    * @param session Session that is being delete.
960    * @param reason The reason the session was being deleted.
961    * One of <CODE>SESSION_MAX_TIME</CODE>,
962    * <CODE>SESSION_IDLE_EXPIRE</CODE>,
963    * <CODE>SESSION_EXPLICT_DELETE</CODE>.
964    * @see #isSessionExpired
965    */

966   protected void sessionDeleted (Session JavaDoc session, int reason) {
967   // Default implementation does nothing.
968
}
969
970   /**
971    * Does the actual work of deleting an entry from the session table.
972    *
973    * @param session The session to delete.
974    * @param reason The reason the session was being deleted.
975    * @exception SessionException
976    * If the session cannot be deleted.
977    */

978   private void doDeleteSession (StandardSession session, int reason) throws SessionException {
979     keyGenerator.incrementRandomCounter();
980     if (logChannel != null) {
981       String JavaDoc userName = null;
982       User user = session.getUser();
983       if (user != null) {
984         userName = user.getName();
985       }
986       String JavaDoc reasonMsg;
987       switch (reason) {
988         case SESSION_ACTIVE:
989           reasonMsg = "SESSION_ACTIVE";
990           break;
991         case SESSION_MAX_TIME:
992           reasonMsg = "SESSION_MAX_TIME";
993           break;
994         case SESSION_IDLE_EXPIRE:
995           reasonMsg = "SESSION_IDLE_EXPIRE";
996           break;
997         case SESSION_EXPLICT_DELETE:
998           reasonMsg = "SESSION_EXPLICT_DELETE";
999           break;
1000        default:
1001          reasonMsg = "bad reason code " + reason;
1002          break;
1003      }
1004      logChannel.write(Logger.DEBUG, "SessionMgr deleteSession: "
1005               + session.getSessionKey() + " user = \"" + userName
1006               + "\" reason = " + reasonMsg);
1007    }
1008    // add by K.Nakamura
1009
// Call valueUnbound on session attributes
1010
HttpSession JavaDoc hs = session.getHttpSession();
1011    for (Enumeration JavaDoc e = hs.getAttributeNames(); e.hasMoreElements();) {
1012      String JavaDoc key = (String JavaDoc)e.nextElement();
1013      Object JavaDoc value = hs.getAttribute(key);
1014      if (value instanceof HttpSessionBindingListener JavaDoc) {
1015        try {
1016          ((HttpSessionBindingListener JavaDoc)value).valueUnbound(new HttpSessionBindingEvent JavaDoc(hs,
1017              key));
1018        } catch (Exception JavaDoc ex) {
1019        // ignored
1020
}
1021      }
1022    }
1023    if (session.getUser() != null) {
1024      sessionUserTable.remove(session.getSessionKey(), session.getUser());
1025    }
1026    sessionHome.removeSession(session.getSessionKey());
1027  }
1028
1029  /**
1030   * Removes a session from the Session Table. This method is used
1031   * to log a user off the application. Note that
1032   * <CODE>sessionDeleted()</CODE> is called.
1033   *
1034   * @param session Session object to remove from table removed.
1035   * @exception SessionException
1036   * If the session cannot be deleted.
1037   */

1038  public synchronized void deleteSession (Session JavaDoc session) throws SessionException {
1039    sessionDeleted((StandardSession)session, SESSION_EXPLICT_DELETE);
1040    doDeleteSession((StandardSession)session, SESSION_EXPLICT_DELETE);
1041  }
1042
1043  /**
1044   * Removes a session from the Session Table. This method is used
1045   * to log a user off the application. Note that
1046   * <CODE>sessionDeleted()</CODE> is called.
1047   *
1048   * @param sessionKey A key corresponding to a user session to be
1049   * removed.
1050   * @exception SessionException
1051   * If the session cannot be deleted.
1052   */

1053  public synchronized void deleteSession (String JavaDoc sessionKey) throws SessionException {
1054    Session JavaDoc session = (Session JavaDoc)sessionHome.getSession(Thread.currentThread(), sessionKey);
1055    if (session != null) {
1056      deleteSession(session);
1057    }
1058  }
1059
1060  /**
1061   * Puts a session into the 'passive' state. A 'passive'
1062   * session may be made persistent.
1063   *
1064   * @param thread the thread currently associated with the session.
1065   * @param sessionKey the session key for the session
1066   * that will be made persistent.
1067   * @exception SessionException
1068   * If the session cannot be put into the passive state.
1069   */

1070  public void passivateSession (Thread JavaDoc thread, String JavaDoc sessionKey) throws SessionException {
1071    sessionHome.passivateSession(thread, sessionKey);
1072  }
1073
1074  /**
1075   * Scans session table to determine if any sessions need to be
1076   * expired.
1077   *
1078   * @exception SessionException
1079   * if an error occurs.
1080   */

1081  public void cleanUpIdleSessions () throws SessionException {
1082    Enumeration JavaDoc e = sessionHome.keys();
1083    StandardSession session;
1084    String JavaDoc sessionKey;
1085    debug(3, "checking for idle sessions... ");
1086    while (e.hasMoreElements()) {
1087      sessionKey = (String JavaDoc)e.nextElement();
1088      session = (StandardSession)sessionHome.getSession(Thread.currentThread(),
1089          sessionKey);
1090      if (session != null) {
1091        int stat = isSessionExpired(session);
1092        if (stat != SESSION_ACTIVE) {
1093        debug(3, "cleaning up idle session: " + sessionKey);
1094        sessionDeleted(session, stat);
1095        doDeleteSession(session, stat);
1096        } else {
1097        sessionHome.passivateSession(Thread.currentThread(), sessionKey);
1098        }
1099      }
1100    }
1101  }
1102
1103  /**
1104   * Returns whether the <code>Session</code> object associated with
1105   * the specified session key exists.
1106   *
1107   * @param sessionKey The String used to reference a
1108   * <code>Session</code> object.
1109   * @return If the key is associated with an active session, then
1110   * return true, otherwise return false.
1111   * @exception SessionException
1112   * If existence of the session cannot be tested.
1113   */

1114  public synchronized boolean sessionExists (String JavaDoc sessionKey) throws SessionException {
1115    if (sessionKey == null) {
1116      return false;
1117    }
1118    return sessionHome.containsKey(sessionKey);
1119  }
1120
1121  /**
1122   * Lookup the <code>Session</code> object associated with the
1123   * specified session key. <P>
1124   *
1125   * Each time a session is returned via this method, the session's
1126   * last used (referenced) time is updated to the current time.
1127   *
1128   * @param sessionKey The String used to reference a
1129   * <code>Session</code> object.
1130   * @return If the key is associated with an active session, then
1131   * the corresponding <code>Session</code> object is
1132   * returned. Otherwise <code>null</code> is returned.
1133   * @see Session
1134   * @see StandardSession#touch
1135   * @exception SessionException
1136   * If the session cannot be retrieved.
1137   */

1138  public synchronized Session JavaDoc getSession (String JavaDoc sessionKey) throws SessionException {
1139    keyGenerator.incrementRandomCounter();
1140    StandardSession session = (StandardSession)sessionHome.getSession(sessionKey);
1141    if (session != null) {
1142      session.touch();
1143    }
1144    else {
1145      sessionUserTable.remove(sessionKey);
1146    }
1147    return session;
1148  }
1149
1150  /**
1151   * Lookup the <code>Session</code> object associated with the
1152   * specified session key. <P>
1153   *
1154   * Each time a session is returned via this method, the session's
1155   * last used (referenced) time is updated to the current time.
1156   *
1157   * @param thread the thread to associate with the session.
1158   * @param sessionKey The String used to reference a
1159   * <code>Session</code> object.
1160   * @return If the key is associated with an active session, then
1161   * the corresponding <code>Session</code> object is
1162   * returned. Otherwise <code>null</code> is returned.
1163   * @see Session
1164   * @see StandardSession#touch
1165   * @exception SessionException
1166   * If the session cannot be retrieved.
1167   */

1168  public synchronized Session JavaDoc getSession (Thread JavaDoc thread, String JavaDoc sessionKey) throws SessionException {
1169    keyGenerator.incrementRandomCounter();
1170    StandardSession session = (StandardSession)sessionHome.getSession(thread,
1171        sessionKey);
1172    if (session != null) {
1173      session.touch();
1174    }
1175    else {
1176      sessionUserTable.remove(sessionKey);
1177    }
1178    return session;
1179  }
1180  
1181  /**
1182   * Support for director connector
1183   * Director connector sets header :affCR: , in that case we need to delete active session and create new one , with new ipPortToken
1184   */

1185public synchronized Session JavaDoc getSession (Thread JavaDoc thread, String JavaDoc sessionKey, HttpPresentationComms comms) throws SessionException {
1186
1187 Session JavaDoc session=getSession (thread, sessionKey);
1188
1189String JavaDoc saTokChangeRequest=null;
1190 /* try{
1191 saTokChangeRequest = comms.request.getHeader(":affCR:");
1192    } catch (HttpPresentationException hpe) {
1193      saTokChangeRequest=null;
1194    }
1195   */

1196   if(saTokChangeRequest!=null&&session!=null)
1197    {
1198     deleteSession(session);
1199     return null;
1200    }
1201   else
1202    {
1203    return session;
1204    }
1205}
1206  /**
1207   * Lookup the <code>Session</code> object associated with the
1208   * specified session key. <P>
1209   *
1210   * Each time a session is returned via this method, the session's
1211   * last used (referenced) time is NOT!!! updated to the current time.
1212   *
1213   * This method is for save reporting without change the last time used.
1214   *
1215   * @param thread the thread to associate with the session.
1216   * @param sessionKey The String used to reference a
1217   * <code>Session</code> object.
1218   * @return If the key is associated with an active session, then
1219   * the corresponding <code>Session</code> object is
1220   * returned. Otherwise <code>null</code> is returned.
1221   * @see Session
1222   * @see StandardSession#touch
1223   * @exception SessionException
1224   * If the session cannot be retrieved.
1225   * @author schubi@die-schubis.de
1226   */

1227  public synchronized Session JavaDoc getSaveSession (Thread JavaDoc thread, String JavaDoc sessionKey) throws SessionException {
1228    keyGenerator.incrementRandomCounter();
1229    StandardSession session = (StandardSession)sessionHome.getSession(thread,
1230        sessionKey);
1231    if (session != null) {
1232    // session.touch();
1233
}
1234    else {
1235      sessionUserTable.remove(sessionKey);
1236    }
1237    return session;
1238  }
1239
1240  /**
1241   * Get all of the active sessions.
1242   *
1243   * @return An enumeration of the active sessions.
1244   * @exception SessionException
1245   * If the sessions cannot be retrieved.
1246   */

1247  public synchronized Enumeration JavaDoc getSessionKeys () throws SessionException {
1248    return sessionHome.keys();
1249  }
1250
1251  /**
1252   * Lookup the keys for the active sessions for a user.
1253   * A given user may have multiple sessions associated
1254   * with it (using FTP as an example, the "anonymous" account).
1255   *
1256   * @param user The user to search for.
1257   * @return An enumeration containing the session keys of the
1258   * active sessions for the user.
1259   * @exception SessionException
1260   * If the sessions cannot be retrieved.
1261   */

1262  public synchronized Enumeration JavaDoc getSessionKeys (User user) throws SessionException {
1263    return sessionUserTable.getSessionKeys(user);
1264  }
1265
1266  /**
1267   * Gets the number of currently active sessions.
1268   *
1269   * @return The number of currently active sessions.
1270   * @exception SessionException
1271   * If the session cannot be calculated.
1272   */

1273  public int activeSessionCount () throws SessionException {
1274    return sessionHome.size();
1275  }
1276
1277  /**
1278   * Gets the number of session that are paged to persistent store.
1279   *
1280   * @return The number of currently paged sessions.
1281   * @exception SessionException
1282   * If the session cannot be calculated.
1283   */

1284  public int pagedSessionCount () throws SessionException {
1285    return sessionHome.pagedSize();
1286  }
1287
1288  /**
1289   * Returns the current mode for the session manager.
1290   *
1291   * @return the mode.
1292   * @exception SessionException
1293   * If the mode cannot be determined.
1294   * @see #MODE_BASIC
1295   * @see #MODE_PAGE_TO_DISK
1296   * @see #MODE_PAGE_TO_DB
1297   * @see #MODE_CUSTOM
1298   */

1299  public int getMode () throws SessionException {
1300    return mode;
1301  }
1302
1303  /**
1304   * Gets the maximum number of concurent sessions that existed
1305   * at any time since this object was created, or
1306   * <CODE>resetMaxSessionCount()</CODE> was called.
1307   * This is a historical highwater mark.
1308   *
1309   * @return The highwater mark for number of sessions, or -1.
1310   */

1311  public int maxSessionCount () {
1312    return maxSessions;
1313  }
1314
1315  /**
1316   * Gets the time when the maximum refered to by
1317   * <CODE>maxSessionCount()</CODE> occured.
1318   *
1319   * @return The Date of when the maximum number of sessions occured.
1320   */

1321  public Date JavaDoc maxSessionCountDate () {
1322    return maxSessionsDate;
1323  }
1324
1325  /**
1326   * Reset the maximum session count. See <CODE>maxSessionCount()</CODE>.
1327   * The highwater mark should be reset to the current number of sessions.
1328   *
1329   * @exception SessionException
1330   * if the max session count cannot be reset.
1331   */

1332  public void resetMaxSessionCount () throws SessionException {
1333    maxSessions = sessionHome.size();
1334    maxSessionsDate = new Date JavaDoc();
1335  }
1336
1337  /**
1338   * Returns the maximum session life time, in seconds.
1339   */

1340  public long getMaxSessionLifeTime () {
1341    return maxSessionLifeTime;
1342  }
1343
1344  /**
1345   * Sets the maximum session idle time, in seconds.
1346   */

1347  public void setMaxSessionIdleTime (long maxSessionIdleTime) {
1348    this.maxSessionIdleTime = maxSessionIdleTime;
1349  }
1350
1351  /**
1352   * Returns the maximum session idle time, in seconds.
1353   */

1354  public long getMaxSessionIdleTime () {
1355    return maxSessionIdleTime;
1356  }
1357
1358  /**
1359   * Returns the url encoding state. Either <code>Never</code>
1360   * <code>Always</code> <code>Auto</code>
1361   */

1362  public String JavaDoc getEncodeUrlState () {
1363    return encodeUrlState;
1364  }
1365  
1366  /**
1367   * Returns the url encoding rule for the first application page (true/false).
1368   *
1369   * CFG_ENCODE_URL_STATE must not be set to NEVER for this parameter to take efect
1370   */

1371  public boolean getEncodeFirstUrl() {
1372      return encodeFirstUrl;
1373  }
1374
1375  /**
1376   * Returns the maximum no-user session idle time, in seconds.
1377   */

1378  public long getMaxNoUserSessionIdleTime () {
1379    return maxNoUserSessionIdleTime;
1380  }
1381
1382    /**
1383     * Prints debug information under Logger.DEBUG.
1384     *
1385     * @param level the debug level.
1386     * @param msg the message to print.
1387     */

1388    protected void debug(int level, String JavaDoc msg) {
1389    int dbg = Logger.DEBUG;
1390    switch (level) {
1391    case 1:
1392        dbg = Logger.DEBUG1;
1393        break;
1394    case 2:
1395        dbg = Logger.DEBUG2;
1396        break;
1397    case 3:
1398        dbg = Logger.DEBUG3;
1399        break;
1400    case 4:
1401        dbg = Logger.DEBUG4;
1402        break;
1403    case 5:
1404         dbg = Logger.DEBUG5;
1405         break;
1406    case 6:
1407        dbg = Logger.DEBUG6;
1408        break;
1409    case 7:
1410        dbg = Logger.DEBUG7;
1411        break;
1412    case 8:
1413        dbg = Logger.DEBUG8;
1414        break;
1415    case 9:
1416        dbg = Logger.DEBUG9;
1417        break;
1418    default:
1419        dbg = Logger.DEBUG;
1420        break;
1421    }
1422    Enhydra.getLogChannel().write(dbg, "PersistentSessionHome("
1423                                      + Thread.currentThread().getName()
1424                                      + "): " + msg);
1425    }
1426}
1427
1428
1429
1430
Popular Tags