KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > web > tomcat > tc5 > session > ClusteredSessionCMP


1 /*
2  * JBoss, the OpenSource WebOS
3  *
4  * Distributable under LGPL license.
5  * See terms of license at gnu.org.
6  */

7 package org.jboss.web.tomcat.tc5.session;
8
9 import org.apache.catalina.Manager;
10 import org.jboss.ha.httpsession.interfaces.SerializableHttpSession;
11 import java.beans.PropertyChangeSupport JavaDoc;
12 import java.io.IOException JavaDoc;
13 import java.security.Principal JavaDoc;
14 import java.util.ArrayList JavaDoc;
15 import java.util.Enumeration JavaDoc;
16 import java.util.HashMap JavaDoc;
17 import java.util.HashSet JavaDoc;
18 import javax.servlet.http.HttpSession JavaDoc;
19 import javax.servlet.http.HttpSessionContext JavaDoc;
20 import org.apache.catalina.util.Enumerator;
21 import org.apache.catalina.util.StringManager;
22 import org.apache.catalina.session.StandardSession;
23 import org.jboss.metadata.WebMetaData;
24 import org.jboss.logging.Logger;
25
26 /** Implementation of a clustered session for the ClusteredHttpSession-Service
27  * @see org.jboss.ha.httpsession.server.ClusteredHTTPSessionService
28  *
29  * It is based on the standard catalina class org.apache.catalina.session.StandardSession
30  * (Revision: 1.25.2.1 Release: 4.0.3)
31  *
32  * <p><b>Revisions:</b>
33  *
34  * <p><b>23.11.2003 Sacha Labourey:</b>
35  * <ul>
36  * <li> Avoid unnecessary session replication (3 policies)</li>
37  * </ul>
38
39  @see org.jboss.ha.httpsession.server.ClusteredHTTPSessionService
40
41  @author Thomas Peuss <jboss@peuss.de>
42  @author Sacha Labourey <sacha.labourey@jboss.org>
43  @version $Revision: 1.1.2.2 $
44  */

45 class ClusteredSessionCMP
46     extends StandardSession
47     implements SerializableHttpSession
48 {
49     private static final long serialVersionUID = -758573655613558722L;
50     private static Logger log = Logger.getLogger(ClusteredSessionCMP.class);
51
52    // ----------------------------------------------------- Instance Variables
53

54
55    /**
56     * Descriptive information describing this Session implementation.
57     */

58    protected static final String JavaDoc info = "ClusteredSessionCMP/1.0";
59
60
61    /**
62     * The Manager with which this Session is associated.
63     */

64    private transient Manager manager = null;
65
66
67    /**
68     * The string manager for this package.
69     */

70    private static StringManager sm =
71          StringManager.getManager("org.jboss.web.tomcat.session");
72
73    protected transient boolean isSessionModifiedSinceLastSave = true;
74    protected transient int replicationType = WebMetaData.REPLICATION_TYPE_SYNC;
75    protected transient boolean replicationTypeAlreadySet = false;
76
77    public ClusteredSessionCMP(JBossManagerCMP manager)
78    {
79       super(manager);
80       this.manager = manager;
81    }
82
83    /**
84     * Initialize fields marked as transient after loading this session
85     * from the distributed store
86     * @param manager the manager for this session
87     */

88    protected void initAfterLoad(JBossManagerCMP manager)
89    {
90       setManager(manager);
91       expiring = false;
92       listeners = new ArrayList JavaDoc();
93       notes = new HashMap JavaDoc();
94       support = new PropertyChangeSupport JavaDoc(this);
95       this.replicationType = manager.getReplicationType ();
96       this.replicationTypeAlreadySet = false;
97
98
99       // Notify all attributes of type HttpSessionActivationListener (SRV 7.7.2)
100
this.activate();
101    }
102    // SerializableHttpSession-methods --------------------------------------------
103

104    /**
105     * Are attributes modified?
106     * @param previousVersion The version to diff with
107     */

108    public boolean areAttributesModified(SerializableHttpSession previousVersion)
109    {
110      // return true;
111
if (this == previousVersion)
112       {
113          if (log.isDebugEnabled())
114             log.debug ("Are current session " + this.id + " attributes modified? : " + isSessionModifiedSinceLastSave);
115          return isSessionModifiedSinceLastSave;
116       }
117       else
118       {
119          return true;
120       }
121    }
122
123    /**
124     * Get the creation time of this session
125     */

126    public long getContentCreationTime()
127    {
128       return this.getCreationTime();
129    }
130
131    /**
132     * Get the last access time for this session
133     */

134    public long getContentLastAccessTime()
135    {
136       return this.getLastAccessedTime();
137    }
138
139    public void sessionHasBeenStored ()
140    {
141       isSessionModifiedSinceLastSave = false;
142       replicationTypeAlreadySet = false;
143    }
144
145    public int getReplicationTypeForSession ()
146    {
147       return this.replicationType;
148    }
149
150    public void setReplicationTypeForSession (int type)
151    {
152       this.replicationType = type;
153    }
154
155    public boolean isReplicationTypeAlreadySet()
156    {
157       return replicationTypeAlreadySet;
158    }
159    // ----------------------------------------------------- Session Properties
160

161
162    /**
163     * Set the creation time for this session. This method is called by the
164     * Manager when an existing Session instance is reused.
165     *
166     * @param time The new creation time
167     */

168    public void setCreationTime(long time)
169    {
170        super.setCreationTime(time);
171        sessionIsDirty();
172    }
173
174
175    /**
176     * Set the authenticated Principal that is associated with this Session.
177     * This provides an <code>Authenticator</code> with a means to cache a
178     * previously authenticated Principal, and avoid potentially expensive
179     * <code>Realm.authenticate()</code> calls on every request.
180     *
181     * @param principal The new Principal, or <code>null</code> if none
182     */

183    public void setPrincipal(Principal JavaDoc principal)
184    {
185
186       Principal JavaDoc oldPrincipal = this.principal;
187       this.principal = principal;
188       support.firePropertyChange("principal", oldPrincipal, this.principal);
189
190       if ( (oldPrincipal != null && ! oldPrincipal.equals(principal) ) ||
191            (oldPrincipal == null && principal != null) )
192          sessionIsDirty();
193
194    }
195
196    /**
197     * Set the Manager within which this Session is valid.
198     *
199     * @param manager The new Manager
200     */

201    public void setManager(Manager manager) {
202
203      super.setManager(manager);
204
205      this.manager=manager;
206    }
207
208    // ------------------------------------------------- Session Public Methods
209

210
211    /**
212     * Return a string representation of this object.
213     */

214    public String JavaDoc toString()
215    {
216
217       StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
218       sb.append("ClusteredSessionCMP[");
219       sb.append(id);
220       sb.append("]");
221       return (sb.toString());
222
223    }
224
225
226    // ------------------------------------------------ Session Package Methods
227

228
229
230    // ----------------------------------------------HttpSession Public Methods
231

232    public void access()
233    {
234       super.access();
235
236       // If we do not use the local cache the session is dirty
237
// after every access.
238
if (!((JBossManagerCMP)manager).isUseLocalCache())
239       {
240          this.sessionIsDirty();
241       }
242    }
243
244    /**
245     * Return the object bound with the specified name in this session, or
246     * <code>null</code> if no object is bound with that name.
247     *
248     * @param name Name of the attribute to be returned
249     *
250     * @exception IllegalStateException if this method is called on an
251     * invalidated session
252     */

253    public Object JavaDoc getAttribute(String JavaDoc name)
254    {
255
256       if (!isValid)
257          throw new IllegalStateException JavaDoc
258                (sm.getString("clusteredSession.getAttribute.ise"));
259
260       synchronized (attributes)
261       {
262          Object JavaDoc result = attributes.get(name);
263
264          if (result != null)
265          {
266             int invalidationPolicy = ((AbstractJBossManager)manager).getInvalidateSessionPolicy();
267
268             if (invalidationPolicy == WebMetaData.SESSION_INVALIDATE_SET_AND_GET)
269             {
270                sessionIsDirty();
271             }
272             else if (invalidationPolicy == WebMetaData.SESSION_INVALIDATE_SET_AND_NON_PRIMITIVE_GET)
273             {
274                if ( ! (result instanceof String JavaDoc ||
275                   result instanceof Integer JavaDoc ||
276                   result instanceof Long JavaDoc ||
277                   result instanceof Byte JavaDoc ||
278                   result instanceof Short JavaDoc ||
279                   result instanceof Float JavaDoc ||
280                   result instanceof Double JavaDoc ||
281                   result instanceof Character JavaDoc ||
282                   result instanceof Boolean JavaDoc)
283                   )
284                {
285                   sessionIsDirty();
286                }
287             }
288          }
289
290          return result;
291       }
292
293    }
294
295
296    /**
297     * Remove the object bound with the specified name from this session. If
298     * the session does not have an object bound with this name, this method
299     * does nothing.
300     * <p>
301     * After this method executes, and if the object implements
302     * <code>HttpSessionBindingListener</code>, the container calls
303     * <code>valueUnbound()</code> on the object.
304     *
305     * @param name Name of the object to remove from this session.
306     *
307     * @exception IllegalStateException if this method is called on an
308     * invalidated session
309     */

310    public void removeAttribute(String JavaDoc name, boolean notify)
311    {
312       // Remove this attribute from our collection
313
boolean found = false;
314       synchronized (attributes)
315       {
316          found = attributes.containsKey(name);
317          if (found)
318          {
319             // Session is now dirty
320
sessionIsDirty ();
321          }
322          else
323          {
324             return;
325          }
326       }
327
328       super.removeAttribute(name, notify);
329    }
330
331    /** Override to copy the attributes key set to avoid ConcurrentModification
332     * exceptions.
333     *
334     * Return an <code>Enumeration</code> of <code>String</code> objects
335     * containing the names of the objects bound to this session.
336     *
337     * @exception IllegalStateException if this method is called on an
338     * invalidated session
339     */

340    public Enumeration JavaDoc getAttributeNames()
341    {
342        if (!isValid())
343        {
344            throw new IllegalStateException JavaDoc
345                (sm.getString("standardSession.getAttributeNames.ise"));
346    }
347
348       synchronized (attributes)
349       {
350          HashSet JavaDoc keys = new HashSet JavaDoc(attributes.keySet());
351          Enumeration JavaDoc iter = new Enumerator(keys);
352          return iter;
353       }
354    }
355
356    /**
357     * Bind an object to this session, using the specified name. If an object
358     * of the same name is already bound to this session, the object is
359     * replaced.
360     * <p>
361     * After this method executes, and if the object implements
362     * <code>HttpSessionBindingListener</code>, the container calls
363     * <code>valueBound()</code> on the object.
364     *
365     * @param name Name to which the object is bound, cannot be null
366     * @param value Object to be bound, cannot be null
367     *
368     * @exception IllegalArgumentException if an attempt is made to add a
369     * non-serializable object in an environment marked distributable.
370     * @exception IllegalStateException if this method is called on an
371     * invalidated session
372     */

373    public void setAttribute(String JavaDoc name, Object JavaDoc value)
374    {
375
376        super.setAttribute(name, value);
377
378        // Session is dirty
379
sessionIsDirty ();
380    }
381
382
383    /**
384     * Log a message on the Logger associated with our Manager (if any).
385     *
386     * @param message Message to be logged
387     */

388    protected void log(String JavaDoc message)
389    {
390       log.debug(message);
391    }
392
393
394    /**
395     * Log a message on the Logger associated with our Manager (if any).
396     *
397     * @param message Message to be logged
398     * @param throwable Associated exception
399     */

400    protected void log(String JavaDoc message, Throwable JavaDoc throwable)
401    {
402       log.error(message, throwable);
403    }
404
405
406     protected void writeObject(java.io.ObjectOutputStream JavaDoc out)
407         throws IOException JavaDoc
408     {
409        synchronized (attributes)
410        {
411           out.defaultWriteObject();
412        }
413     }
414     protected void readObject(java.io.ObjectInputStream JavaDoc in)
415         throws IOException JavaDoc, ClassNotFoundException JavaDoc
416     {
417        in.defaultReadObject();
418     }
419
420    protected void sessionIsDirty ()
421    {
422       // Session is dirty
423
isSessionModifiedSinceLastSave = true;
424    }
425 }
426
427
428 // -------------------------------------------------------------- Private Class
429

430
431 /**
432  * This class is a dummy implementation of the <code>HttpSessionContext</code>
433  * interface, to conform to the requirement that such an object be returned
434  * when <code>HttpSession.getSessionContext()</code> is called.
435  *
436  * @author Craig R. McClanahan
437  *
438  * @deprecated As of Java Servlet API 2.1 with no replacement. The
439  * interface will be removed in a future version of this API.
440  */

441
442 final class ClusteredSessionContext implements HttpSessionContext JavaDoc
443 {
444
445
446    private HashMap JavaDoc dummy = new HashMap JavaDoc();
447
448    /**
449     * Return the session identifiers of all sessions defined
450     * within this context.
451     *
452     * @deprecated As of Java Servlet API 2.1 with no replacement.
453     * This method must return an empty <code>Enumeration</code>
454     * and will be removed in a future version of the API.
455     */

456    public Enumeration JavaDoc getIds()
457    {
458
459       return (new Enumerator(dummy));
460
461    }
462
463
464    /**
465     * Return the <code>HttpSession</code> associated with the
466     * specified session identifier.
467     *
468     * @param id Session identifier for which to look up a session
469     *
470     * @deprecated As of Java Servlet API 2.1 with no replacement.
471     * This method must return null and will be removed in a
472     * future version of the API.
473     */

474    public HttpSession getSession(String JavaDoc id)
475    {
476
477       return (null);
478
479    }
480
481
482 }
483
Popular Tags