Source code: com/lutris/appserver/server/session/persistent/PersistentSessionHome.java
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: PersistentSessionHome.java,v 1.4.14.1 2000/10/19 17:59:06 jasona Exp $
22 */
23
24 package com.lutris.appserver.server.session.persistent;
25
26 import com.lutris.appserver.server.Enhydra;
27 import com.lutris.appserver.server.session.*;
28 import com.lutris.appserver.server.sql.*;
29 import com.lutris.logging.*;
30 import com.lutris.util.*;
31 import java.util.*;
32 import java.sql.*;
33
34 /**
35 * PersistentSessionHome writes all passive sessions
36 * to a database. The sessions are written by serializing
37 * all the data (excluding the session manager) that is
38 * associated with a session. This requires that
39 * the session data and user associated with a session
40 * are serializable. PersistentSessionHome
41 * should be used by applications that want failover support
42 * or that want to run in a clustered environment.<p>
43 *
44 * The session data is written to a table in the database
45 * that is defined as (Informix):<p>
46 *
47 * <pre>
48 * CREATE TABLE PersistentSession
49 * (
50 * sessionKey VARCHAR(64) NOT NULL,
51 * isNew CHAR(1) DEFAULT "1" NOT NULL,
52 * timeCreated DECIMAL(19,0),
53 * timeLastUsed DECIMAL(19,0),
54 * timeExpires DECIMAL(19,0),
55 * maxIdleTime DECIMAL(19,0),
56 * maxNoUserIdleTime INTEGER,
57 * userName VARCHAR(255),
58 * data BYTE,
59 * PRIMARY KEY(sessionKey)
60 * )
61 * </pre>
62 *
63 * The configuration settings for PersistentSessionHome:<p>
64 *
65 * <ul>
66 *
67 * <li><code>DatabaseName: {String}</code><p>
68 * The database that will be accessed. This session is optional. If
69 * not set then the default database is accessed.
70 *
71 * <li><code>DBTableName: {String}</code><p>
72 * The name of the table in the database where session data
73 * will be written. The default table name is "PersistentSession".<p>
74 *
75 * </ul>
76 *
77 * @see StandardSessionManager
78 * @version $Revision: 1.4.14.1 $
79 * @author Kyle Clark
80 */
81 public class PersistentSessionHome extends PagedSessionHome {
82
83 /**
84 * The name of the database that will be accessed.
85 */
86 static String dbName = null;
87
88 /**
89 * The name of the database table where session information
90 * will be stored.
91 */
92 static String dbTableName = "PersistentSession"; // Default
93
94 /**
95 * Configuration keys.
96 */
97 private static final String DB_NAME_KEY = "DatabaseName";
98 private static final String DB_TABLE_NAME_KEY = "DBTableName";
99
100 /**
101 * @param sessionMgr
102 * The session manager associated with this session home.
103 * @param config
104 * Object parsed from configuration file. This should be
105 * for the section containing the standard session home configuration.
106 * @param loader
107 * The class load to use when load objects from persistent store.
108 * @exception ConfigException
109 * signifies a problem in the configuration file.
110 * @exception SessionException
111 * if the initialization fails.
112 */
113 public PersistentSessionHome(StandardSessionManager sessionMgr,
114 Config config, ClassLoader loader)
115 throws SessionException, ConfigException {
116 super(sessionMgr, config, loader);
117 if (config.containsKey(DB_TABLE_NAME_KEY)) {
118 dbTableName = config.getString(DB_TABLE_NAME_KEY);
119 }
120 debug(DB_TABLE_NAME_KEY + " = " + dbTableName);
121 dbName = getDatabaseName(config);
122 if (dbName != null) {
123 debug(DB_NAME_KEY + " = " + dbName);
124 } else {
125 debug(DB_NAME_KEY + " = DEFAULT");
126 }
127 }
128
129 /**
130 * Returns the name of the database being accessed by this manager.
131 *
132 * @return the database name. May be null if the default database is
133 * being accessed.
134 */
135 public String getDatabaseName() {
136 return dbName;
137 }
138
139 /**
140 * Returns the name of the database that should be accessed.
141 *
142 * @param config the config in whihc to look up the database
143 * setting.
144 * @return the database name. May be null if the default database is
145 * being accessed.
146 * @exception ConfigException if an error occurs.
147 */
148 public static String getDatabaseName(Config config) throws ConfigException {
149 String s = null;
150 if (config.containsKey(DB_NAME_KEY)) {
151 s = config.getString(DB_NAME_KEY);
152 if (s.length() == 0) {
153 s = null;
154 }
155 }
156 return s;
157 }
158
159 /**
160 * Creates a new session object. This method is intended to be
161 * overriden by classes that extend PagedSessionHome.
162 *
163 * @return a new session.
164 */
165 protected PagedSession newSession(StandardSessionManager mgr,
166 String sessionKey)
167 throws SessionException {
168 PersistentSession session = new PersistentSession(mgr, sessionKey, this);
169 DBUtil.dbInsert(session, dbName);
170 return session;
171 }
172
173 /**
174 * Deletes a paged session. If the session doesn't exist then this
175 * is a noop.
176 *
177 * @param sessionKey the key identifying the session
178 * that should be deleted.
179 */
180 protected void deleteSession(String sessionKey)
181 throws SessionException {
182 // Delete from database
183 DBUtil.dbDelete(sessionKey, dbName);
184 }
185
186 /**
187 * Pages a session to disk.
188 *
189 * @param session the session to page.
190 * @exception SessionException if the paged session could not be
191 * paged out.
192 */
193 protected synchronized void pageOut(PagedSession s) throws SessionException {
194 // N.B. it is possible for the session to be removed
195 // from the database if running in a clustered environment.
196 // The idle timer in another application instance may run
197 // while this session is in the active state.
198 // If it was removed then the update would fail and we
199 // need to re-insert.
200 if (DBUtil.dbUpdate((PersistentSession)s, dbName) <= 0) {
201 DBUtil.dbInsert((PersistentSession)s, dbName);
202 }
203 }
204
205 /**
206 * Reads a paged session from disk.
207 *
208 * @param sessionKey the key identifying the session that should
209 * be paged in.
210 * @return the paged session that was read in.
211 * @exception SessionException if the paged session could not be
212 * read in or does not exist.
213 */
214 protected synchronized PagedSession pageIn(String sessionKey) throws SessionException {
215 SessionQuery sessionQuery = new SessionQuery(sessionKey, loader);
216 PersistentSession s = (PersistentSession)DBUtil.dbQuery(sessionQuery, dbName);
217 if (s != null) {
218 s.restoreSessionHome(this);
219 s.restoreSessionManager(sessionMgr);
220 }
221 return s;
222 }
223
224 /**
225 * Returns the number of paged sessions.
226 */
227 protected synchronized int getPagedSessionCount() throws SessionException {
228 SizeQuery sizeQuery = new SizeQuery();
229 Integer size = (Integer)DBUtil.dbQuery(sizeQuery, dbName);
230 return size.intValue();
231 }
232
233 /**
234 * Returns true if the specified session key is in use
235 * by a session that has been paged out.
236 *
237 * @param sessionKey the session key to test.
238 * @return true if the session key is in use by a paged session.
239 */
240 protected boolean pagedSessionKeyExists(String sessionKey)
241 throws SessionException {
242 KeyExistsQuery keyExistsQuery = new KeyExistsQuery(sessionKey);
243 Boolean exists = (Boolean)DBUtil.dbQuery(keyExistsQuery, dbName);
244 return exists.booleanValue();
245 }
246
247 /**
248 * Returns an enumeration of the keys of all the sessions that have
249 * been paged out to persistent storage.
250 *
251 * @return the session key enumeration.
252 * @exception SessionException if an error occurs.
253 */
254 protected Enumeration getPagedSessionKeys() throws SessionException {
255 return (Enumeration)DBUtil.dbQuery(new KeysQuery(), dbName);
256 }
257
258 /**
259 * Removes a session that is new and paged.
260 *
261 * @exception SessionException if an error occurs.
262 */
263 protected boolean cleanupNewPagedSession() throws SessionException {
264 String key = null;
265 UnusedQuery unusedQuery = new UnusedQuery();
266 key = (String)DBUtil.dbQuery(unusedQuery, dbName);
267 if (key != null) {
268 removeSession(key);
269 return true;
270 }
271 return false;
272 }
273
274 /**
275 * Shuts dows the session home.
276 */
277 public void shutdown() {
278 // TODO
279 }
280
281 /**
282 * Prints debug information under Logger.DEBUG.
283 *
284 * @param msg the message to print.
285 */
286 protected void debug(String msg) {
287 debug(0, msg);
288 }
289
290 /**
291 * Prints debug information under Logger.DEBUG.
292 *
293 * @param level the debug level.
294 * @param msg the message to print.
295 */
296 protected void debug(int level, String msg) {
297 int dbg = Logger.DEBUG;
298 switch (level) {
299 case 1:
300 dbg = Logger.DEBUG1;
301 break;
302 case 2:
303 dbg = Logger.DEBUG2;
304 break;
305 case 3:
306 dbg = Logger.DEBUG3;
307 break;
308 case 4:
309 dbg = Logger.DEBUG4;
310 break;
311 case 5:
312 dbg = Logger.DEBUG5;
313 break;
314 case 6:
315 dbg = Logger.DEBUG6;
316 break;
317 case 7:
318 dbg = Logger.DEBUG7;
319 break;
320 case 8:
321 dbg = Logger.DEBUG8;
322 break;
323 case 9:
324 dbg = Logger.DEBUG9;
325 break;
326 default:
327 dbg = Logger.DEBUG;
328 break;
329 }
330
331 Enhydra.getLogChannel().write(dbg, "PersistentSessionHome("
332 + Thread.currentThread().getName()
333 + "): " + msg);
334 }
335
336 }
337
338
339
340