KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > winstone > WinstoneSession


1 /*
2  * Copyright 2003-2006 Rick Knowles <winstone-devel at lists sourceforge net>
3  * Distributed under the terms of either:
4  * - the common development and distribution license (CDDL), v1.0; or
5  * - the GNU Lesser General Public License, v2.1 or later
6  */

7 package winstone;
8
9 import java.io.File JavaDoc;
10 import java.io.FileInputStream JavaDoc;
11 import java.io.FileOutputStream JavaDoc;
12 import java.io.IOException JavaDoc;
13 import java.io.InputStream JavaDoc;
14 import java.io.ObjectInputStream JavaDoc;
15 import java.io.ObjectOutputStream JavaDoc;
16 import java.io.OutputStream JavaDoc;
17 import java.io.Serializable JavaDoc;
18 import java.util.ArrayList JavaDoc;
19 import java.util.Collections JavaDoc;
20 import java.util.Enumeration JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.HashSet JavaDoc;
23 import java.util.Hashtable JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.Map JavaDoc;
27 import java.util.Set JavaDoc;
28
29 import javax.servlet.ServletContext JavaDoc;
30 import javax.servlet.http.HttpSession JavaDoc;
31 import javax.servlet.http.HttpSessionActivationListener JavaDoc;
32 import javax.servlet.http.HttpSessionAttributeListener JavaDoc;
33 import javax.servlet.http.HttpSessionBindingEvent JavaDoc;
34 import javax.servlet.http.HttpSessionBindingListener JavaDoc;
35 import javax.servlet.http.HttpSessionEvent JavaDoc;
36 import javax.servlet.http.HttpSessionListener JavaDoc;
37
38 /**
39  * Http session implementation for Winstone.
40  *
41  * @author <a HREF="mailto:rick_knowles@hotmail.com">Rick Knowles</a>
42  * @version $Id: WinstoneSession.java,v 1.10 2006/08/27 07:19:47 rickknowles Exp $
43  */

44 public class WinstoneSession implements HttpSession JavaDoc, Serializable JavaDoc {
45     public static final String JavaDoc SESSION_COOKIE_NAME = "JSESSIONID";
46
47     private String JavaDoc sessionId;
48     private WebAppConfiguration webAppConfig;
49     private Map JavaDoc sessionData;
50     private long createTime;
51     private long lastAccessedTime;
52     private int maxInactivePeriod;
53     private boolean isNew;
54     private boolean isInvalidated;
55     private HttpSessionAttributeListener JavaDoc sessionAttributeListeners[];
56     private HttpSessionListener JavaDoc sessionListeners[];
57     private HttpSessionActivationListener JavaDoc sessionActivationListeners[];
58     private boolean distributable;
59     private Object JavaDoc sessionMonitor = new Boolean JavaDoc(true);
60     private Set JavaDoc requestsUsingMe;
61
62     /**
63      * Constructor
64      */

65     public WinstoneSession(String JavaDoc sessionId) {
66         this.sessionId = sessionId;
67         this.sessionData = new HashMap JavaDoc();
68         this.requestsUsingMe = new HashSet JavaDoc();
69         this.createTime = System.currentTimeMillis();
70         this.isNew = true;
71         this.isInvalidated = false;
72     }
73
74     public void setWebAppConfiguration(WebAppConfiguration webAppConfig) {
75         this.webAppConfig = webAppConfig;
76         this.distributable = webAppConfig.isDistributable();
77     }
78     
79     public void sendCreatedNotifies() {
80         // Notify session listeners of new session
81
for (int n = 0; n < this.sessionListeners.length; n++) {
82             ClassLoader JavaDoc cl = Thread.currentThread().getContextClassLoader();
83             Thread.currentThread().setContextClassLoader(this.webAppConfig.getLoader());
84             this.sessionListeners[n].sessionCreated(new HttpSessionEvent JavaDoc(this));
85             Thread.currentThread().setContextClassLoader(cl);
86         }
87     }
88
89     public void setSessionActivationListeners(
90             HttpSessionActivationListener JavaDoc listeners[]) {
91         this.sessionActivationListeners = listeners;
92     }
93
94     public void setSessionAttributeListeners(
95             HttpSessionAttributeListener JavaDoc listeners[]) {
96         this.sessionAttributeListeners = listeners;
97     }
98
99     public void setSessionListeners(HttpSessionListener JavaDoc listeners[]) {
100         this.sessionListeners = listeners;
101     }
102
103     public void setLastAccessedDate(long time) {
104         this.lastAccessedTime = time;
105     }
106
107     public void setIsNew(boolean isNew) {
108         this.isNew = isNew;
109     }
110     
111     public void addUsed(WinstoneRequest request) {
112         this.requestsUsingMe.add(request);
113     }
114     
115     public void removeUsed(WinstoneRequest request) {
116         this.requestsUsingMe.remove(request);
117     }
118     
119     public boolean isUnusedByRequests() {
120         return this.requestsUsingMe.isEmpty();
121     }
122     
123     public boolean isExpired() {
124         // check if it's expired yet
125
long nowDate = System.currentTimeMillis();
126         long maxInactive = getMaxInactiveInterval() * 1000;
127         return ((maxInactive > 0) && (nowDate - this.lastAccessedTime > maxInactive ));
128     }
129
130     // Implementation methods
131
public Object JavaDoc getAttribute(String JavaDoc name) {
132         if (this.isInvalidated) {
133             throw new IllegalStateException JavaDoc(Launcher.RESOURCES.getString("WinstoneSession.InvalidatedSession"));
134         }
135         Object JavaDoc att = null;
136         synchronized (this.sessionMonitor) {
137             att = this.sessionData.get(name);
138         }
139         return att;
140     }
141
142     public Enumeration JavaDoc getAttributeNames() {
143         if (this.isInvalidated) {
144             throw new IllegalStateException JavaDoc(Launcher.RESOURCES.getString("WinstoneSession.InvalidatedSession"));
145         }
146         Enumeration JavaDoc names = null;
147         synchronized (this.sessionMonitor) {
148             names = Collections.enumeration(this.sessionData.keySet());
149         }
150         return names;
151     }
152
153     public void setAttribute(String JavaDoc name, Object JavaDoc value) {
154         if (this.isInvalidated) {
155             throw new IllegalStateException JavaDoc(Launcher.RESOURCES.getString("WinstoneSession.InvalidatedSession"));
156         }
157         // Check for serializability if distributable
158
if (this.distributable && (value != null)
159                 && !(value instanceof java.io.Serializable JavaDoc))
160             throw new IllegalArgumentException JavaDoc(Launcher.RESOURCES.getString(
161                     "WinstoneSession.AttributeNotSerializable", new String JavaDoc[] {
162                             name, value.getClass().getName() }));
163
164         // valueBound must be before binding
165
if (value instanceof HttpSessionBindingListener JavaDoc) {
166             HttpSessionBindingListener JavaDoc hsbl = (HttpSessionBindingListener JavaDoc) value;
167             ClassLoader JavaDoc cl = Thread.currentThread().getContextClassLoader();
168             Thread.currentThread().setContextClassLoader(this.webAppConfig.getLoader());
169             hsbl.valueBound(new HttpSessionBindingEvent JavaDoc(this, name, value));
170             Thread.currentThread().setContextClassLoader(cl);
171         }
172
173         Object JavaDoc oldValue = null;
174         synchronized (this.sessionMonitor) {
175             oldValue = this.sessionData.get(name);
176             if (value == null) {
177                 this.sessionData.remove(name);
178             } else {
179                 this.sessionData.put(name, value);
180             }
181         }
182
183         // valueUnbound must be after unbinding
184
if (oldValue instanceof HttpSessionBindingListener JavaDoc) {
185             HttpSessionBindingListener JavaDoc hsbl = (HttpSessionBindingListener JavaDoc) oldValue;
186             ClassLoader JavaDoc cl = Thread.currentThread().getContextClassLoader();
187             Thread.currentThread().setContextClassLoader(this.webAppConfig.getLoader());
188             hsbl.valueUnbound(new HttpSessionBindingEvent JavaDoc(this, name, oldValue));
189             Thread.currentThread().setContextClassLoader(cl);
190         }
191
192         // Notify other listeners
193
if (oldValue != null)
194             for (int n = 0; n < this.sessionAttributeListeners.length; n++) {
195                 ClassLoader JavaDoc cl = Thread.currentThread().getContextClassLoader();
196                 Thread.currentThread().setContextClassLoader(this.webAppConfig.getLoader());
197                 this.sessionAttributeListeners[n].attributeReplaced(
198                         new HttpSessionBindingEvent JavaDoc(this, name, oldValue));
199                 Thread.currentThread().setContextClassLoader(cl);
200             }
201                 
202         else
203             for (int n = 0; n < this.sessionAttributeListeners.length; n++) {
204                 ClassLoader JavaDoc cl = Thread.currentThread().getContextClassLoader();
205                 Thread.currentThread().setContextClassLoader(this.webAppConfig.getLoader());
206                 this.sessionAttributeListeners[n].attributeAdded(
207                         new HttpSessionBindingEvent JavaDoc(this, name, value));
208                 Thread.currentThread().setContextClassLoader(cl);
209                 
210             }
211     }
212
213     public void removeAttribute(String JavaDoc name) {
214         if (this.isInvalidated) {
215             throw new IllegalStateException JavaDoc(Launcher.RESOURCES.getString("WinstoneSession.InvalidatedSession"));
216         }
217         Object JavaDoc value = null;
218         synchronized (this.sessionMonitor) {
219             value = this.sessionData.get(name);
220             this.sessionData.remove(name);
221         }
222
223         // Notify listeners
224
if (value instanceof HttpSessionBindingListener JavaDoc) {
225             HttpSessionBindingListener JavaDoc hsbl = (HttpSessionBindingListener JavaDoc) value;
226             ClassLoader JavaDoc cl = Thread.currentThread().getContextClassLoader();
227             Thread.currentThread().setContextClassLoader(this.webAppConfig.getLoader());
228             hsbl.valueUnbound(new HttpSessionBindingEvent JavaDoc(this, name));
229             Thread.currentThread().setContextClassLoader(cl);
230         }
231         if (value != null)
232             for (int n = 0; n < this.sessionAttributeListeners.length; n++) {
233                 ClassLoader JavaDoc cl = Thread.currentThread().getContextClassLoader();
234                 Thread.currentThread().setContextClassLoader(this.webAppConfig.getLoader());
235                 this.sessionAttributeListeners[n].attributeRemoved(
236                         new HttpSessionBindingEvent JavaDoc(this, name, value));
237                 Thread.currentThread().setContextClassLoader(cl);
238             }
239     }
240
241     public long getCreationTime() {
242         if (this.isInvalidated) {
243             throw new IllegalStateException JavaDoc(Launcher.RESOURCES.getString("WinstoneSession.InvalidatedSession"));
244         }
245         return this.createTime;
246     }
247
248     public long getLastAccessedTime() {
249         if (this.isInvalidated) {
250             throw new IllegalStateException JavaDoc(Launcher.RESOURCES.getString("WinstoneSession.InvalidatedSession"));
251         }
252         return this.lastAccessedTime;
253     }
254
255     public String JavaDoc getId() {
256         return this.sessionId;
257     }
258
259     public int getMaxInactiveInterval() {
260         return this.maxInactivePeriod;
261     }
262
263     public void setMaxInactiveInterval(int interval) {
264         this.maxInactivePeriod = interval;
265     }
266
267     public boolean isNew() {
268         if (this.isInvalidated) {
269             throw new IllegalStateException JavaDoc(Launcher.RESOURCES.getString("WinstoneSession.InvalidatedSession"));
270         }
271         return this.isNew;
272     }
273
274     public ServletContext JavaDoc getServletContext() {
275         return this.webAppConfig;
276     }
277
278     public void invalidate() {
279         if (this.isInvalidated) {
280             throw new IllegalStateException JavaDoc(Launcher.RESOURCES.getString("WinstoneSession.InvalidatedSession"));
281         }
282         // Notify session listeners of invalidated session -- backwards
283
for (int n = this.sessionListeners.length - 1; n >= 0; n--) {
284             ClassLoader JavaDoc cl = Thread.currentThread().getContextClassLoader();
285             Thread.currentThread().setContextClassLoader(this.webAppConfig.getLoader());
286             this.sessionListeners[n].sessionDestroyed(new HttpSessionEvent JavaDoc(this));
287             Thread.currentThread().setContextClassLoader(cl);
288         }
289
290         List JavaDoc keys = new ArrayList JavaDoc(this.sessionData.keySet());
291         for (Iterator JavaDoc i = keys.iterator(); i.hasNext();)
292             removeAttribute((String JavaDoc) i.next());
293         synchronized (this.sessionMonitor) {
294             this.sessionData.clear();
295         }
296         this.isInvalidated = true;
297         this.webAppConfig.removeSessionById(this.sessionId);
298     }
299
300     /**
301      * Called after the session has been serialized to another server.
302      */

303     public void passivate() {
304         // Notify session listeners of invalidated session
305
for (int n = 0; n < this.sessionActivationListeners.length; n++) {
306             ClassLoader JavaDoc cl = Thread.currentThread().getContextClassLoader();
307             Thread.currentThread().setContextClassLoader(this.webAppConfig.getLoader());
308             this.sessionActivationListeners[n].sessionWillPassivate(
309                     new HttpSessionEvent JavaDoc(this));
310             Thread.currentThread().setContextClassLoader(cl);
311         }
312
313         // Question: Is passivation equivalent to invalidation ? Should all
314
// entries be removed ?
315
// List keys = new ArrayList(this.sessionData.keySet());
316
// for (Iterator i = keys.iterator(); i.hasNext(); )
317
// removeAttribute((String) i.next());
318
synchronized (this.sessionMonitor) {
319             this.sessionData.clear();
320         }
321         this.webAppConfig.removeSessionById(this.sessionId);
322     }
323
324     /**
325      * Called after the session has been deserialized from another server.
326      */

327     public void activate(WebAppConfiguration webAppConfig) {
328         this.webAppConfig = webAppConfig;
329         webAppConfig.setSessionListeners(this);
330
331         // Notify session listeners of invalidated session
332
for (int n = 0; n < this.sessionActivationListeners.length; n++) {
333             ClassLoader JavaDoc cl = Thread.currentThread().getContextClassLoader();
334             Thread.currentThread().setContextClassLoader(this.webAppConfig.getLoader());
335             this.sessionActivationListeners[n].sessionDidActivate(
336                     new HttpSessionEvent JavaDoc(this));
337             Thread.currentThread().setContextClassLoader(cl);
338         }
339     }
340     
341     /**
342      * Save this session to the temp dir defined for this webapp
343      */

344     public void saveToTemp() {
345         File JavaDoc toDir = getSessionTempDir(this.webAppConfig);
346         synchronized (this.sessionMonitor) {
347             OutputStream JavaDoc out = null;
348             ObjectOutputStream JavaDoc objOut = null;
349             try {
350                 File JavaDoc toFile = new File JavaDoc(toDir, this.sessionId + ".ser");
351                 out = new FileOutputStream JavaDoc(toFile, false);
352                 objOut = new ObjectOutputStream JavaDoc(out);
353                 objOut.writeObject(this);
354             } catch (IOException JavaDoc err) {
355                 Logger.log(Logger.ERROR, Launcher.RESOURCES,
356                         "WinstoneSession.ErrorSavingSession", err);
357             } finally {
358                 if (objOut != null) {
359                     try {objOut.close();} catch (IOException JavaDoc err) {}
360                 }
361                 if (out != null) {
362                     try {out.close();} catch (IOException JavaDoc err) {}
363                 }
364             }
365         }
366     }
367     
368     public static File JavaDoc getSessionTempDir(WebAppConfiguration webAppConfig) {
369         File JavaDoc tmpDir = (File JavaDoc) webAppConfig.getAttribute("javax.servlet.context.tempdir");
370         File JavaDoc sessionsDir = new File JavaDoc(tmpDir, "WEB-INF" + File.separator + "winstoneSessions");
371         if (!sessionsDir.exists()) {
372             sessionsDir.mkdirs();
373         }
374         return sessionsDir;
375     }
376     
377     public static void loadSessions(WebAppConfiguration webAppConfig) {
378         int expiredCount = 0;
379         // Iterate through the files in the dir, instantiate and then add to the sessions set
380
File JavaDoc tempDir = getSessionTempDir(webAppConfig);
381         File JavaDoc possibleSessionFiles[] = tempDir.listFiles();
382         for (int n = 0; n < possibleSessionFiles.length; n++) {
383             if (possibleSessionFiles[n].getName().endsWith(".ser")) {
384                 InputStream JavaDoc in = null;
385                 ObjectInputStream JavaDoc objIn = null;
386                 try {
387                     in = new FileInputStream JavaDoc(possibleSessionFiles[n]);
388                     objIn = new ObjectInputStream JavaDoc(in);
389                     WinstoneSession session = (WinstoneSession) objIn.readObject();
390                     session.setWebAppConfiguration(webAppConfig);
391                     webAppConfig.setSessionListeners(session);
392                     if (session.isExpired()) {
393                         session.invalidate();
394                         expiredCount++;
395                     } else {
396                         webAppConfig.addSession(session.getId(), session);
397                         Logger.log(Logger.DEBUG, Launcher.RESOURCES,
398                                 "WinstoneSession.RestoredSession", session.getId());
399                     }
400                 } catch (Throwable JavaDoc err) {
401                     Logger.log(Logger.ERROR, Launcher.RESOURCES,
402                             "WinstoneSession.ErrorLoadingSession", err);
403                 } finally {
404                     if (objIn != null) {
405                         try {objIn.close();} catch (IOException JavaDoc err) {}
406                     }
407                     if (in != null) {
408                         try {in.close();} catch (IOException JavaDoc err) {}
409                     }
410                     possibleSessionFiles[n].delete();
411                 }
412             }
413         }
414         if (expiredCount > 0) {
415             Logger.log(Logger.DEBUG, Launcher.RESOURCES,
416                     "WebAppConfig.InvalidatedSessions", expiredCount + "");
417         }
418     }
419
420     /**
421      * Serialization implementation. This makes sure to only serialize the parts
422      * we want to send to another server.
423      *
424      * @param out
425      * The stream to write the contents to
426      * @throws IOException
427      */

428     private void writeObject(java.io.ObjectOutputStream JavaDoc out) throws IOException JavaDoc {
429         out.writeUTF(sessionId);
430         out.writeLong(createTime);
431         out.writeLong(lastAccessedTime);
432         out.writeInt(maxInactivePeriod);
433         out.writeBoolean(isNew);
434         out.writeBoolean(distributable);
435
436         // Write the map, but first remove non-serializables
437
Map JavaDoc copy = new HashMap JavaDoc(sessionData);
438         Set JavaDoc keys = new HashSet JavaDoc(copy.keySet());
439         for (Iterator JavaDoc i = keys.iterator(); i.hasNext();) {
440             String JavaDoc key = (String JavaDoc) i.next();
441             if (!(copy.get(key) instanceof Serializable JavaDoc)) {
442                 Logger.log(Logger.WARNING, Launcher.RESOURCES,
443                                 "WinstoneSession.SkippingNonSerializable",
444                                 new String JavaDoc[] { key,
445                                         copy.get(key).getClass().getName() });
446             }
447             copy.remove(key);
448         }
449         out.writeInt(copy.size());
450         for (Iterator JavaDoc i = copy.keySet().iterator(); i.hasNext();) {
451             String JavaDoc key = (String JavaDoc) i.next();
452             out.writeUTF(key);
453             out.writeObject(copy.get(key));
454         }
455     }
456
457     /**
458      * Deserialization implementation
459      *
460      * @param in
461      * The source of stream data
462      * @throws IOException
463      * @throws ClassNotFoundException
464      */

465     private void readObject(java.io.ObjectInputStream JavaDoc in) throws IOException JavaDoc,
466             ClassNotFoundException JavaDoc {
467         this.sessionId = in.readUTF();
468         this.createTime = in.readLong();
469         this.lastAccessedTime = in.readLong();
470         this.maxInactivePeriod = in.readInt();
471         this.isNew = in.readBoolean();
472         this.distributable = in.readBoolean();
473
474         // Read the map
475
this.sessionData = new Hashtable JavaDoc();
476         this.requestsUsingMe = new HashSet JavaDoc();
477         int entryCount = in.readInt();
478         for (int n = 0; n < entryCount; n++) {
479             String JavaDoc key = in.readUTF();
480             Object JavaDoc variable = in.readObject();
481             this.sessionData.put(key, variable);
482         }
483         this.sessionMonitor = new Boolean JavaDoc(true);
484     }
485
486     /**
487      * @deprecated
488      */

489     public Object JavaDoc getValue(String JavaDoc name) {
490         return getAttribute(name);
491     }
492
493     /**
494      * @deprecated
495      */

496     public void putValue(String JavaDoc name, Object JavaDoc value) {
497         setAttribute(name, value);
498     }
499
500     /**
501      * @deprecated
502      */

503     public void removeValue(String JavaDoc name) {
504         removeAttribute(name);
505     }
506
507     /**
508      * @deprecated
509      */

510     public String JavaDoc[] getValueNames() {
511         return (String JavaDoc[]) this.sessionData.keySet().toArray(new String JavaDoc[0]);
512     }
513
514     /**
515      * @deprecated
516      */

517     public javax.servlet.http.HttpSessionContext JavaDoc getSessionContext() {
518         return null;
519     } // deprecated
520
}
521
Popular Tags