KickJava   Java API By Example, From Geeks To Geeks.

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


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

24
25 package com.lutris.appserver.server.sessionEnhydra;
26
27 import java.util.Enumeration JavaDoc;
28 import java.util.Hashtable JavaDoc;
29 import java.util.Vector JavaDoc;
30
31 import com.lutris.appserver.server.Enhydra;
32 import com.lutris.appserver.server.session.SessionException;
33 import com.lutris.logging.Logger;
34 import com.lutris.util.Config;
35 import com.lutris.util.ConfigException;
36
37 /**
38  * BasicSessionHome creates instances of BasicSession and
39  * manages the 'active'/'passive' state of those sessions.
40  * All sessions created by BasicSessionHome are held in
41  * memory.<p>
42  *
43  * The following parameters can be used to configure
44  * the BasicSessionHome. They should be grouped together in a section,
45  * normally <code>SessionManager.SessionHome</code>, which is specified to
46  * the constructor.<p>
47  *
48  * <ul>
49  * <li><code>MaxSessions: {int}</code><p>
50  * Specifies the maximum number of in use concurrent sessions. If this value
51  * is exceeded then CreateSession() will throw a CreateSessionException.
52  * -1 indicates unlimited session. If MaxSessions is not set
53  * in the application's configuration then MaxSessions defaults to
54  * unlimited sessions.<p>
55  * </ul>
56  *
57  * @see BasicSession
58  * @see StandardSession
59  * @see StandardSessionManager
60  * @version $Revision: 1.2 $
61  * @author Kyle Clark
62  */

63 public class BasicSessionHome implements StandardSessionHome {
64
65     /**
66      * The active cache holds sessions that are in the
67      * 'active' state.
68      */

69     private Hashtable JavaDoc activeCache = new Hashtable JavaDoc();
70
71     /**
72      * The active thread cache holds all the association
73      * between active sessions and the threads that have
74      * checked them out.
75      */

76     private Hashtable JavaDoc activeThreadCache = new Hashtable JavaDoc();
77
78     /**
79      * The active cache holds sessions that are in the
80      * 'active' state. There is a single mapping
81      * of keys to session objects: sessionKey -> session
82      */

83     private Hashtable JavaDoc passiveCache = new Hashtable JavaDoc();
84
85     /**
86      * Maximum number of allowed sessions.
87      */

88     private long maxSessions = -1;
89
90     /**
91      * Configuration keys.
92      */

93     private final String JavaDoc MAX_SESSIONS_KEY = "MaxSessions";
94     private final long UNDEFINED_MAX_SESSIONS = -1;
95
96     /**
97      * The session manager associated with the session home.
98      */

99     private StandardSessionManager sessionMgr;
100
101     /**
102      * @param sessionMgr
103      * The session manager associated with this session home.
104      * @param config
105      * Object parsed from configuration file. This should be
106      * for the section constaining the standard session home configuration.
107      * @exception ConfigException
108      * signifies a problem in the configuration file.
109      */

110     public BasicSessionHome(StandardSessionManager sessionMgr,
111                             Config config)
112         throws ConfigException {
113         this.sessionMgr = sessionMgr;
114         if (config.containsKey(MAX_SESSIONS_KEY)) {
115             maxSessions = config.getLong(MAX_SESSIONS_KEY);
116             debug(MAX_SESSIONS_KEY + " = " + maxSessions);
117         }
118         if (maxSessions <= 0) {
119             maxSessions = UNDEFINED_MAX_SESSIONS;
120         }
121     }
122
123     /**
124      * @param sessionMgr
125      * The session manager associated with this session home.
126      * @param config
127      * Object parsed from configuration file. This should be
128      * for the section constaining the standard session home configuration.
129      * @param loader
130      * The class load to use when load objects from persistent store.
131      * @exception ConfigException
132      * signifies a problem in the configuration file.
133      */

134     public BasicSessionHome(StandardSessionManager sessionMgr,
135                             Config config, ClassLoader JavaDoc loader)
136         throws ConfigException {
137         this(sessionMgr, config);
138     }
139
140     /**
141      * Creates and returns a new session instance. The
142      * session is bound to the specified session key. The
143      * session is also associated with the current thread
144      * and is considered in the 'active' state. The
145      * session remains in the 'active' state until the
146      * thread puts the session into the 'passive' state..
147      * Only this thread will be able to put the
148      * session into the 'passive' state.
149      *
150      * @param sessionKey the key to associate with the session.
151      * @return the newly created session.
152      * @exception CreateSessionException if the session cannot be
153      * created.
154      * @exception DuplicateKeyException if the session cannot
155      * be created because the key is already in use.
156      * @exception SessionException if an error occurs.
157      * @see #passivateSession
158      */

159     public synchronized StandardSession createSession(String JavaDoc sessionKey)
160         throws CreateSessionException, DuplicateKeyException, SessionException {
161         if (containsKey(sessionKey)) {
162             throw new DuplicateKeyException("Session key " +
163                                             sessionKey + " is already in use.");
164         }
165         if ((maxSessions != UNDEFINED_MAX_SESSIONS) &&
166             (maxSessions <= size())) {
167             cleanupNewSession();
168             if (maxSessions <= size()) {
169                 throw new CreateSessionException("Maximum session limit ("
170                                                  + maxSessions +
171                                                  ") has been reached.");
172             }
173         }
174         BasicSession session = new BasicSession(sessionMgr, sessionKey);
175         SessionThread activeKey = new SessionThread(Thread.currentThread(),
176                                                     sessionKey);
177         // keep track of # of threads that reference session
178
session.incrementRefCount();
179         activeCache.put(sessionKey, session);
180         activeThreadCache.put(activeKey, session);
181     debug(3, "create session: key = " + sessionKey);
182         return (StandardSession)session;
183     }
184
185     /**
186      * Returns the session bound to the session key.
187      * The session must already be in the 'active' state
188      * and associated with the current thread,
189      * otherwise null is returned.
190      *
191      * @param sessionKey
192      * the session key for the session. If the session
193      * doesn't exist or is not is not bound to the current
194      * thread then null is returned.
195      * @return
196      * the session.
197      * @exception SessionException
198      * if the session cannot be retrieved.
199      * @see #getSession(Thread, String)
200      */

201     public synchronized StandardSession getSession(String JavaDoc sessionKey)
202         throws SessionException {
203     debug(3, "get session: key = " + sessionKey);
204         SessionThread activeKey = new SessionThread(Thread.currentThread(),
205                                                     sessionKey);
206         return (BasicSession)activeThreadCache.get(activeKey);
207     }
208
209     /**
210      * Returns the session bound to the specified
211      * session key. The session is put into the 'active' state.
212      * The session is also associated with the specified thread.
213      * Only this thread will be able to put the session
214      * back into the 'passive' state once it is done with the
215      * session.
216      *
217      * @param thread the thread that should be associated with
218      * the session while it is in the active state. Only this
219      * thread can put the session back into the passive state.
220      * @param sessionKey
221      * the session key for the session that will be made
222      * 'active' and returned. If the session doesn't exist
223      * then null is returned.
224      * @return
225      * the session.
226      * @exception SessionException
227      * if the session cannot be retrieved.
228      * @see #passivateSession
229      */

230     public synchronized StandardSession getSession(Thread JavaDoc thread, String JavaDoc sessionKey)
231         throws SessionException {
232     debug(3, "get session: key = " + sessionKey);
233         SessionThread activeKey = new SessionThread(thread, sessionKey);
234         BasicSession s = null;
235         // First check if the session is in the passive state.
236
if (passiveCache.containsKey(sessionKey)) {
237             s = (BasicSession)passiveCache.remove(sessionKey);
238             activeCache.put(sessionKey, s);
239             activeThreadCache.put(activeKey, s);
240             s.incrementRefCount();
241         } else {
242             // The session must already be active.
243
if (activeThreadCache.containsKey(activeKey)) {
244                 // It's already checked out by the thread
245
s = (BasicSession)activeThreadCache.get(activeKey);
246             } else {
247                 // It's being checked out by a new thread
248
s = (BasicSession)activeCache.get(sessionKey);
249                 if (s != null) {
250                     activeThreadCache.put(activeKey, s);
251                     // Only increment the ref count when a new thread
252
// checks out the session.
253
s.incrementRefCount();
254                 }
255             }
256         }
257         return (StandardSession)s;
258     }
259
260
261     /**
262      * Removes a session from the cache. If the session
263      * doesn't exist the opration is ignored.
264      *
265      * @param sessionKey
266      * the session key associated with the session.
267      * @exception SessionException
268      * if the session cannot be retrieved.
269      */

270     public synchronized void removeSession(String JavaDoc sessionKey)
271         throws SessionException {
272     debug(3, "remove session: key = " + sessionKey);
273         Enumeration JavaDoc e = activeThreadCache.keys();
274         while (e.hasMoreElements()) {
275             SessionThread key = (SessionThread)e.nextElement();
276             if (key.sessionKey.equals(sessionKey)) {
277                 activeThreadCache.remove(key);
278             }
279         }
280         activeCache.remove(sessionKey);
281         passiveCache.remove(sessionKey);
282     }
283
284     /**
285      * Puts a session into the 'passive' state. A 'passive'
286      * session may be made persistent. Only the thread that
287      * put the session into the 'active' state may put
288      * the session into the 'passive' state.
289      *
290      * @param thread the thread that is currently associated
291      * with the session.
292      * @param sessionKey
293      * the session key for the session that will be made passive.
294      * @exception SessionException
295      * if the session cannot be retrieved.
296      */

297     public synchronized void passivateSession(Thread JavaDoc thread, String JavaDoc sessionKey)
298         throws SessionException {
299         // This is a bad place for this debug() to be.
300
// We should avoid any delay inside the synchronized block
301
//debug(3, "passivate session: key = " + sessionKey);
302
SessionThread activeKey = new SessionThread(thread, sessionKey);
303         if (activeThreadCache.containsKey(activeKey)) {
304             BasicSession s = (BasicSession)activeThreadCache.remove(activeKey);
305             if (s.decrementRefCount() == 0) {
306                 activeCache.remove(sessionKey);
307                 passiveCache.put(sessionKey, s);
308             }
309         }
310     }
311
312     /**
313      * Specifies if a key is currently bound to a session.
314      *
315      * @param sessionKey
316      * the session key to be tested.
317      * @return
318      * true if the session key is in use.
319      * @exception SessionException
320      * if the existence of the key cannot be determined.
321      */

322     public boolean containsKey(String JavaDoc sessionKey)
323         throws SessionException {
324         return (activeCache.containsKey(sessionKey)
325                 || passiveCache.containsKey(sessionKey));
326     }
327
328     /**
329      * Returns the current number of sessions.
330      *
331      * @return
332      * the 'active' session count.
333      * @exception SessionException
334      * if the size cannot be determined
335      */

336     public int size()
337         throws SessionException {
338         return (activeCache.size() + passiveCache.size());
339     }
340
341     /**
342      * Returns the current number of sessions that are paged to
343      * persistent store.
344      *
345      * @return
346      * the 'paged' session count.
347      * @exception SessionException
348      * if the size cannot be determined
349      */

350     public int pagedSize() throws SessionException {
351         return 0;
352     }
353
354     /**
355      * Returns an enumeration of the keys for all the sessions.
356      *
357      * @return
358      * the enumeration of session keys.
359      * @exception SessionException
360      * if the session enumeration cannot be retrieved.
361      */

362     public synchronized Enumeration JavaDoc keys() throws SessionException {
363         Vector JavaDoc v = new Vector JavaDoc();
364         Enumeration JavaDoc e;
365         e = activeCache.keys();
366         while (e.hasMoreElements()) {
367             v.addElement(e.nextElement());
368         }
369         e = passiveCache.keys();
370         while (e.hasMoreElements()) {
371             v.addElement(e.nextElement());
372         }
373         return v.elements();
374     }
375
376     /**
377      * Cleans up (removes) the oldest unused session from the passive cache.
378      *
379      * @exception SessionException if an error occurs.
380      */

381     private void cleanupNewSession() throws SessionException {
382         Enumeration JavaDoc e = passiveCache.keys();
383         StandardSession oldest = null;
384         while (e.hasMoreElements()) {
385             StandardSession s = (StandardSession)passiveCache.get(e.nextElement());
386             if (s.isNew()) {
387                 if ((oldest == null)
388                     || (s.getTimeCreated() < oldest.getTimeCreated())) {
389                     oldest = s;
390                 }
391             }
392         }
393         if (oldest != null) {
394             removeSession(oldest.getSessionKey());
395         }
396     }
397
398     /**
399      * Shuts dows the session home.
400      */

401     public void shutdown() {
402         // noop
403
}
404
405     /**
406      * Prints debug information under Logger.DEBUG.
407      *
408      * @param msg the message to print.
409      */

410     private void debug(String JavaDoc msg) {
411     debug(0, msg);
412     }
413
414     /**
415      * Prints debug information under Logger.DEBUG.
416      *
417      * @param level the debug level.
418      * @param msg the message to print.
419      */

420      protected void debug(int level, String JavaDoc msg) {
421      int dbg = Logger.DEBUG;
422      switch (level) {
423      case 1:
424          dbg = Logger.DEBUG1;
425          break;
426      case 2:
427          dbg = Logger.DEBUG2;
428          break;
429      case 3:
430          dbg = Logger.DEBUG3;
431          break;
432      case 4:
433          dbg = Logger.DEBUG4;
434          break;
435      case 5:
436          dbg = Logger.DEBUG5;
437          break;
438      case 6:
439          dbg = Logger.DEBUG6;
440          break;
441      case 7:
442          dbg = Logger.DEBUG7;
443          break;
444      case 8:
445          dbg = Logger.DEBUG8;
446          break;
447      case 9:
448          dbg = Logger.DEBUG9;
449          break;
450      default:
451          dbg = Logger.DEBUG;
452          break;
453      }
454      Enhydra.getLogChannel().write(dbg, "PersistentSessionHome("
455                                       + Thread.currentThread().getName()
456                                       + "): " + msg);
457     }
458 }
459
Popular Tags