KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > catalina > cluster > session > DeltaSession


1 /*
2  * Copyright 1999,2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.catalina.cluster.session;
18
19 import java.beans.PropertyChangeSupport JavaDoc;
20 import java.io.IOException JavaDoc;
21 import java.io.NotSerializableException JavaDoc;
22 import java.io.ObjectInputStream JavaDoc;
23 import java.io.ObjectOutputStream JavaDoc;
24 import java.io.Serializable JavaDoc;
25 import java.lang.reflect.Method JavaDoc;
26 import java.security.AccessController JavaDoc;
27 import java.security.Principal JavaDoc;
28 import java.security.PrivilegedAction JavaDoc;
29 import java.util.ArrayList JavaDoc;
30 import java.util.Enumeration JavaDoc;
31 import java.util.HashMap JavaDoc;
32 import java.util.Iterator JavaDoc;
33
34 import javax.servlet.ServletContext JavaDoc;
35 import javax.servlet.http.HttpSession JavaDoc;
36 import javax.servlet.http.HttpSessionAttributeListener JavaDoc;
37 import javax.servlet.http.HttpSessionBindingEvent JavaDoc;
38 import javax.servlet.http.HttpSessionBindingListener JavaDoc;
39 import javax.servlet.http.HttpSessionContext JavaDoc;
40 import javax.servlet.http.HttpSessionEvent JavaDoc;
41 import javax.servlet.http.HttpSessionListener JavaDoc;
42
43 import org.apache.catalina.Context;
44 import org.apache.catalina.Manager;
45 import org.apache.catalina.Session;
46 import org.apache.catalina.SessionEvent;
47 import org.apache.catalina.SessionListener;
48 import org.apache.catalina.cluster.ClusterSession;
49 import org.apache.catalina.realm.GenericPrincipal;
50 import org.apache.catalina.util.Enumerator;
51 import org.apache.catalina.util.StringManager;
52
53 /**
54  *
55  * Similar to the StandardSession, this code is identical, but for update and
56  * some small issues, simply copied in the first release. This session will keep
57  * track of deltas during a request.
58  * <p>
59  * <b>IMPLEMENTATION NOTE </b>: An instance of this class represents both the
60  * internal (Session) and application level (HttpSession) view of the session.
61  * However, because the class itself is not declared public, Java logic outside
62  * of the <code>org.apache.catalina.session</code> package cannot cast an
63  * HttpSession view of this instance back to a Session view.
64  * <p>
65  * <b>IMPLEMENTATION NOTE </b>: If you add fields to this class, you must make
66  * sure that you carry them over in the read/writeObject methods so that this
67  * class is properly serialized.
68  *
69  * @author Filip Hanik
70  * @author Craig R. McClanahan
71  * @author Sean Legassick
72  * @author <a HREF="mailto:jon@latchkey.com">Jon S. Stevens </a>
73  * @version $Revision: 1.30 $ $Date: 2005/03/03 14:06:36 $
74  */

75
76 public class DeltaSession implements HttpSession JavaDoc, Session JavaDoc, Serializable JavaDoc,
77         ClusterSession {
78
79     public static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory
80             .getLog(DeltaManager.class);
81
82     /**
83      * The string manager for this package.
84      */

85     protected static StringManager smp = StringManager
86             .getManager(Constants.Package);
87
88     // ----------------------------------------------------------- Constructors
89

90     /**
91      * Construct a new Session associated with the specified Manager.
92      *
93      * @param manager
94      * The manager with which this Session is associated
95      */

96     public DeltaSession(Manager manager) {
97
98         super();
99         this.manager = manager;
100         this.resetDeltaRequest();
101     }
102
103     // ----------------------------------------------------- Instance Variables
104

105     /**
106      * The dummy attribute value serialized when a NotSerializableException is
107      * encountered in <code>writeObject()</code>.
108      */

109     private static final String JavaDoc NOT_SERIALIZED = "___NOT_SERIALIZABLE_EXCEPTION___";
110
111     /**
112      * The collection of user data attributes associated with this Session.
113      */

114     private HashMap JavaDoc attributes = new HashMap JavaDoc();
115
116     /**
117      * The authentication type used to authenticate our cached Principal, if
118      * any. NOTE: This value is not included in the serialized version of this
119      * object.
120      */

121     private transient String JavaDoc authType = null;
122
123     /**
124      * The <code>java.lang.Method</code> for the
125      * <code>fireContainerEvent()</code> method of the
126      * <code>org.apache.catalina.core.StandardContext</code> method, if our
127      * Context implementation is of this class. This value is computed
128      * dynamically the first time it is needed, or after a session reload (since
129      * it is declared transient).
130      */

131     private transient Method JavaDoc containerEventMethod = null;
132
133     /**
134      * The method signature for the <code>fireContainerEvent</code> method.
135      */

136     private static final Class JavaDoc containerEventTypes[] = { String JavaDoc.class,
137             Object JavaDoc.class };
138
139     /**
140      * The time this session was created, in milliseconds since midnight,
141      * January 1, 1970 GMT.
142      */

143     private long creationTime = 0L;
144
145     /**
146      * The debugging detail level for this component. NOTE: This value is not
147      * included in the serialized version of this object.
148      */

149     private transient int debug = 0;
150
151     /**
152      * We are currently processing a session expiration, so bypass certain
153      * IllegalStateException tests. NOTE: This value is not included in the
154      * serialized version of this object.
155      */

156     private transient boolean expiring = false;
157
158     /**
159      * The facade associated with this session. NOTE: This value is not included
160      * in the serialized version of this object.
161      */

162     private transient DeltaSessionFacade facade = null;
163
164     /**
165      * The session identifier of this Session.
166      */

167     private String JavaDoc id = null;
168
169     /**
170      * Descriptive information describing this Session implementation.
171      */

172     private static final String JavaDoc info = "DeltaSession/1.0";
173
174     /**
175      * The last accessed time for this Session.
176      */

177     private long lastAccessedTime = creationTime;
178
179     /**
180      * The session event listeners for this Session.
181      */

182     private transient ArrayList JavaDoc listeners = new ArrayList JavaDoc();
183
184     /**
185      * The Manager with which this Session is associated.
186      */

187     private transient Manager manager = null;
188
189     /**
190      * The maximum time interval, in seconds, between client requests before the
191      * servlet container may invalidate this session. A negative time indicates
192      * that the session should never time out.
193      */

194     private int maxInactiveInterval = -1;
195
196     /**
197      * Flag indicating whether this session is new or not.
198      */

199     private boolean isNew = false;
200
201     /**
202      * Flag indicating whether this session is valid or not.
203      */

204     private boolean isValid = false;
205
206     /**
207      * Internal notes associated with this session by Catalina components and
208      * event listeners. <b>IMPLEMENTATION NOTE: </b> This object is <em>not</em>
209      * saved and restored across session serializations!
210      */

211     private transient HashMap JavaDoc notes = new HashMap JavaDoc();
212
213     /**
214      * The authenticated Principal associated with this session, if any.
215      * <b>IMPLEMENTATION NOTE: </b> This object is <i>not </i> saved and
216      * restored across session serializations!
217      */

218     private transient Principal JavaDoc principal = null;
219
220     /**
221      * The string manager for this package.
222      */

223     private static StringManager sm = StringManager
224             .getManager(Constants.Package);
225
226     /**
227      * The HTTP session context associated with this session.
228      */

229     private static HttpSessionContext JavaDoc sessionContext = null;
230
231     /**
232      * The property change support for this component. NOTE: This value is not
233      * included in the serialized version of this object.
234      */

235     private transient PropertyChangeSupport JavaDoc support = new PropertyChangeSupport JavaDoc(
236             this);
237
238     /**
239      * The current accessed time for this session.
240      */

241     private long thisAccessedTime = creationTime;
242
243     /**
244      * only the primary session will expire, or be able to expire due to
245      * inactivity. This is set to false as soon as I receive this session over
246      * the wire in a session message. That means that someone else has made a
247      * request on another server.
248      */

249     private transient boolean isPrimarySession = true;
250
251     /**
252      * The delta request contains all the action info
253      *
254      */

255     private transient DeltaRequest deltaRequest = null;
256
257     /**
258      * Last time the session was replicatd, used for distributed expiring of
259      * session
260      */

261     private transient long lastTimeReplicated = System.currentTimeMillis();
262
263     /**
264      * The access count for this session
265      */

266     protected transient int accessCount = 0;
267
268     // ----------------------------------------------------- Session Properties
269

270     /**
271      * returns true if this session is the primary session, if that is the case,
272      * the manager can expire it upon timeout.
273      */

274     public boolean isPrimarySession() {
275         return isPrimarySession;
276     }
277
278     /**
279      * Sets whether this is the primary session or not.
280      *
281      * @param primarySession
282      * Flag value
283      */

284     public void setPrimarySession(boolean primarySession) {
285         this.isPrimarySession = primarySession;
286     }
287
288     /**
289      * Return the authentication type used to authenticate our cached Principal,
290      * if any.
291      */

292     public String JavaDoc getAuthType() {
293
294         return (this.authType);
295
296     }
297
298     /**
299      * Set the authentication type used to authenticate our cached Principal, if
300      * any.
301      *
302      * @param authType
303      * The new cached authentication type
304      */

305     public void setAuthType(String JavaDoc authType) {
306
307         String JavaDoc oldAuthType = this.authType;
308         this.authType = authType;
309         support.firePropertyChange("authType", oldAuthType, this.authType);
310
311     }
312
313     /**
314      * Set the creation time for this session. This method is called by the
315      * Manager when an existing Session instance is reused.
316      *
317      * @param time
318      * The new creation time
319      */

320     public void setCreationTime(long time) {
321
322         this.creationTime = time;
323         this.lastAccessedTime = time;
324         this.thisAccessedTime = time;
325
326     }
327
328     /**
329      * Return the session identifier for this session.
330      */

331     public String JavaDoc getId() {
332
333         return (this.id);
334
335     }
336
337     /**
338      * Set the session identifier for this session.
339      *
340      * @param id
341      * The new session identifier
342      */

343     public void setId(String JavaDoc id) {
344
345         if ((this.id != null) && (manager != null))
346             manager.remove(this);
347
348         this.id = id;
349
350         if (manager != null)
351             manager.add(this);
352         tellNew();
353         if ( deltaRequest == null ) resetDeltaRequest();
354         else deltaRequest.setSessionId(id);
355     }
356
357     /**
358      * Inform the listeners about the new session.
359      *
360      */

361     public void tellNew() {
362
363         // Notify interested session event listeners
364
fireSessionEvent(Session.SESSION_CREATED_EVENT, null);
365
366         // Notify interested application event listeners
367
Context JavaDoc context = (Context JavaDoc) manager.getContainer();
368         //fix for standalone manager without container
369
if (context != null) {
370             Object JavaDoc listeners[] = context.getApplicationLifecycleListeners();
371             if (listeners != null) {
372                 HttpSessionEvent JavaDoc event = new HttpSessionEvent JavaDoc(getSession());
373                 for (int i = 0; i < listeners.length; i++) {
374                     if (!(listeners[i] instanceof HttpSessionListener JavaDoc))
375                         continue;
376                     HttpSessionListener JavaDoc listener = (HttpSessionListener JavaDoc) listeners[i];
377                     try {
378                         fireContainerEvent(context, "beforeSessionCreated",
379                                 listener);
380                         listener.sessionCreated(event);
381                         fireContainerEvent(context, "afterSessionCreated",
382                                 listener);
383                     } catch (Throwable JavaDoc t) {
384                         try {
385                             fireContainerEvent(context, "afterSessionCreated",
386                                     listener);
387                         } catch (Exception JavaDoc e) {
388                             ;
389                         }
390                         // FIXME - should we do anything besides log these?
391
log.error(sm.getString("standardSession.sessionEvent"),
392                                 t);
393                     }
394                 }
395             }
396         }//end if
397
//end fix
398

399     }
400
401     /**
402      * Return descriptive information about this Session implementation and the
403      * corresponding version number, in the format
404      * <code>&lt;description&gt;/&lt;version&gt;</code>.
405      */

406     public String JavaDoc getInfo() {
407
408         return (info);
409
410     }
411
412     /**
413      * Return the last time the client sent a request associated with this
414      * session, as the number of milliseconds since midnight, January 1, 1970
415      * GMT. Actions that your application takes, such as getting or setting a
416      * value associated with the session, do not affect the access time.
417      */

418     public long getLastAccessedTime() {
419         if (!isValid) {
420             throw new IllegalStateException JavaDoc(sm
421                     .getString("standardSession.getLastAccessedTime"));
422
423         }
424         return (this.lastAccessedTime);
425
426     }
427
428     /**
429      * Return the Manager within which this Session is valid.
430      */

431     public Manager getManager() {
432
433         return (this.manager);
434
435     }
436
437     /**
438      * Set the Manager within which this Session is valid.
439      *
440      * @param manager
441      * The new Manager
442      */

443     public void setManager(Manager manager) {
444
445         this.manager = manager;
446
447     }
448
449     /**
450      * Return the maximum time interval, in seconds, between client requests
451      * before the servlet container will invalidate the session. A negative time
452      * indicates that the session should never time out.
453      */

454     public int getMaxInactiveInterval() {
455
456         return (this.maxInactiveInterval);
457
458     }
459
460     /**
461      * Set the maximum time interval, in seconds, between client requests before
462      * the servlet container will invalidate the session. A negative time
463      * indicates that the session should never time out.
464      *
465      * @param interval
466      * The new maximum interval
467      */

468     public void setMaxInactiveInterval(int interval) {
469         setMaxInactiveInterval(interval, true);
470     }
471
472     public void setMaxInactiveInterval(int interval, boolean addDeltaRequest) {
473
474         this.maxInactiveInterval = interval;
475         if (isValid && interval == 0) {
476             expire();
477         } else {
478             if (addDeltaRequest && (deltaRequest != null))
479                 deltaRequest.setMaxInactiveInterval(interval);
480         }
481
482     }
483
484     /**
485      * Set the <code>isNew</code> flag for this session.
486      *
487      * @param isNew
488      * The new value for the <code>isNew</code> flag
489      */

490     public void setNew(boolean isNew) {
491         setNew(isNew, true);
492     }
493
494     public void setNew(boolean isNew, boolean addDeltaRequest) {
495         this.isNew = isNew;
496         if (addDeltaRequest && (deltaRequest != null))
497             deltaRequest.setNew(isNew);
498     }
499
500     /**
501      * Return the authenticated Principal that is associated with this Session.
502      * This provides an <code>Authenticator</code> with a means to cache a
503      * previously authenticated Principal, and avoid potentially expensive
504      * <code>Realm.authenticate()</code> calls on every request. If there is
505      * no current associated Principal, return <code>null</code>.
506      */

507     public Principal JavaDoc getPrincipal() {
508
509         return (this.principal);
510
511     }
512
513     /**
514      * Set the authenticated Principal that is associated with this Session.
515      * This provides an <code>Authenticator</code> with a means to cache a
516      * previously authenticated Principal, and avoid potentially expensive
517      * <code>Realm.authenticate()</code> calls on every request.
518      *
519      * @param principal
520      * The new Principal, or <code>null</code> if none
521      */

522     public void setPrincipal(Principal JavaDoc principal) {
523         setPrincipal(principal, true);
524     }
525
526     public void setPrincipal(Principal JavaDoc principal, boolean addDeltaRequest) {
527         Principal JavaDoc oldPrincipal = this.principal;
528         this.principal = principal;
529         support.firePropertyChange("principal", oldPrincipal, this.principal);
530         if (addDeltaRequest && (deltaRequest != null))
531             deltaRequest.setPrincipal(principal);
532     }
533
534     /**
535      * Return the <code>HttpSession</code> for which this object is the
536      * facade.
537      */

538     public HttpSession JavaDoc getSession() {
539
540         if (facade == null) {
541             if (System.getSecurityManager() != null) {
542                 final DeltaSession fsession = this;
543                 facade = (DeltaSessionFacade) AccessController
544                         .doPrivileged(new PrivilegedAction JavaDoc() {
545                             public Object JavaDoc run() {
546                                 return new DeltaSessionFacade(fsession);
547                             }
548                         });
549             } else {
550                 facade = new DeltaSessionFacade(this);
551             }
552         }
553         return (facade);
554
555     }
556
557     /**
558      * Return the <code>isValid</code> flag for this session.
559      */

560     public boolean isValid() {
561
562         if (this.expiring) {
563             return true;
564         }
565
566         if (!this.isValid) {
567             return false;
568         }
569
570         if (accessCount > 0) {
571             return true;
572         }
573
574         if (maxInactiveInterval >= 0) {
575             long timeNow = System.currentTimeMillis();
576             int timeIdle = (int) ((timeNow - lastAccessedTime) / 1000L);
577             if ((timeIdle >= maxInactiveInterval) && (isPrimarySession())) {
578                 expire(true);
579             } else if (timeIdle >= (2 * maxInactiveInterval)) {
580                 //if the session has been idle twice as long as allowed,
581
//the primary session has probably crashed, and no other
582
//requests are coming in. that is why we do this. otherwise
583
//we would have a memory leak
584
expire(true, false);
585             }
586         }
587
588         return (this.isValid);
589     }
590
591     /**
592      * Set the <code>isValid</code> flag for this session.
593      *
594      * @param isValid
595      * The new value for the <code>isValid</code> flag
596      */

597     public void setValid(boolean isValid) {
598
599         this.isValid = isValid;
600     }
601
602     // ------------------------------------------------- Session Public Methods
603

604     /**
605      * Update the accessed time information for this session. This method should
606      * be called by the context when a request comes in for a particular
607      * session, even if the application does not reference it.
608      */

609     public void access() {
610
611         this.lastAccessedTime = this.thisAccessedTime;
612         this.thisAccessedTime = System.currentTimeMillis();
613
614         evaluateIfValid();
615
616         accessCount++;
617     }
618
619     public void endAccess() {
620         isNew = false;
621         accessCount--;
622     }
623
624     /**
625      * Add a session event listener to this component.
626      */

627     public void addSessionListener(SessionListener JavaDoc listener) {
628
629         synchronized (listeners) {
630             listeners.add(listener);
631         }
632
633     }
634
635     /**
636      * Perform the internal processing required to invalidate this session,
637      * without triggering an exception if the session has already expired.
638      */

639     public void expire() {
640
641         expire(true);
642
643     }
644
645     /**
646      * Perform the internal processing required to invalidate this session,
647      * without triggering an exception if the session has already expired.
648      *
649      * @param notify
650      * Should we notify listeners about the demise of this session?
651      */

652     public void expire(boolean notify) {
653         expire(notify, true);
654     }
655
656     public void expire(boolean notify, boolean notifyCluster) {
657
658         // Mark this session as "being expired" if needed
659
if (expiring)
660             return;
661         String JavaDoc expiredId = getId();
662
663         synchronized (this) {
664
665             if (manager == null)
666                 return;
667
668             expiring = true;
669
670             // Notify interested application event listeners
671
// FIXME - Assumes we call listeners in reverse order
672
Context JavaDoc context = (Context JavaDoc) manager.getContainer();
673             //fix for standalone manager without container
674
if (context != null) {
675                 Object JavaDoc listeners[] = context.getApplicationLifecycleListeners();
676                 if (notify && (listeners != null)) {
677                     HttpSessionEvent JavaDoc event = new HttpSessionEvent JavaDoc(getSession());
678                     for (int i = 0; i < listeners.length; i++) {
679                         int j = (listeners.length - 1) - i;
680                         if (!(listeners[j] instanceof HttpSessionListener JavaDoc))
681                             continue;
682                         HttpSessionListener JavaDoc listener = (HttpSessionListener JavaDoc) listeners[j];
683                         try {
684                             fireContainerEvent(context,
685                                     "beforeSessionDestroyed", listener);
686                             listener.sessionDestroyed(event);
687                             fireContainerEvent(context,
688                                     "afterSessionDestroyed", listener);
689                         } catch (Throwable JavaDoc t) {
690                             try {
691                                 fireContainerEvent(context,
692                                         "afterSessionDestroyed", listener);
693                             } catch (Exception JavaDoc e) {
694                                 ;
695                             }
696                             // FIXME - should we do anything besides log these?
697
log.error(sm
698                                     .getString("standardSession.sessionEvent"),
699                                     t);
700                         }
701                     }
702                 }
703             }//end if
704
//end fix
705
accessCount = 0;
706             setValid(false);
707
708             // Remove this session from our manager's active sessions
709
if (manager != null)
710                 manager.remove(this);
711
712             // Notify interested session event listeners
713
if (notify) {
714                 fireSessionEvent(Session.SESSION_DESTROYED_EVENT, null);
715             }
716
717             // We have completed expire of this session
718
expiring = false;
719
720             // Unbind any objects associated with this session
721
String JavaDoc keys[] = keys();
722             for (int i = 0; i < keys.length; i++)
723                 removeAttributeInternal(keys[i], notify, false);
724
725             if (notifyCluster) {
726                 if (log.isDebugEnabled())
727                     log.debug(smp.getString("deltaSession.notifying",
728                             ((DeltaManager) manager).getName(), new Boolean JavaDoc(
729                                     isPrimarySession()), expiredId));
730                 ((DeltaManager) manager).sessionExpired(expiredId);
731             }
732
733         }
734
735     }
736
737     /**
738      * Return the object bound with the specified name to the internal notes for
739      * this session, or <code>null</code> if no such binding exists.
740      *
741      * @param name
742      * Name of the note to be returned
743      */

744     public Object JavaDoc getNote(String JavaDoc name) {
745
746         synchronized (notes) {
747             return (notes.get(name));
748         }
749
750     }
751
752     /**
753      * Return an Iterator containing the String names of all notes bindings that
754      * exist for this session.
755      */

756     public Iterator JavaDoc getNoteNames() {
757
758         synchronized (notes) {
759             return (notes.keySet().iterator());
760         }
761
762     }
763
764     /**
765      * Release all object references, and initialize instance variables, in
766      * preparation for reuse of this object.
767      */

768     public void recycle() {
769
770         // Reset the instance variables associated with this Session
771
attributes.clear();
772         setAuthType(null);
773         creationTime = 0L;
774         expiring = false;
775         id = null;
776         lastAccessedTime = 0L;
777         maxInactiveInterval = -1;
778         accessCount = 0;
779         notes.clear();
780         setPrincipal(null);
781         isNew = false;
782         isValid = false;
783         manager = null;
784         deltaRequest.clear();
785
786     }
787
788     /**
789      * Remove any object bound to the specified name in the internal notes for
790      * this session.
791      *
792      * @param name
793      * Name of the note to be removed
794      */

795     public void removeNote(String JavaDoc name) {
796
797         synchronized (notes) {
798             notes.remove(name);
799         }
800
801     }
802
803     /**
804      * Remove a session event listener from this component.
805      */

806     public void removeSessionListener(SessionListener JavaDoc listener) {
807
808         synchronized (listeners) {
809             listeners.remove(listener);
810         }
811
812     }
813
814     /**
815      * Bind an object to a specified name in the internal notes associated with
816      * this session, replacing any existing binding for this name.
817      *
818      * @param name
819      * Name to which the object should be bound
820      * @param value
821      * Object to be bound to the specified name
822      */

823     public void setNote(String JavaDoc name, Object JavaDoc value) {
824
825         synchronized (notes) {
826             notes.put(name, value);
827         }
828
829     }
830
831     /**
832      * Return a string representation of this object.
833      */

834     public String JavaDoc toString() {
835
836         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
837         sb.append("StandardSession[");
838         sb.append(id);
839         sb.append("]");
840         return (sb.toString());
841
842     }
843
844     // ------------------------------------------------ Session Package Methods
845

846     /**
847      * Read a serialized version of the contents of this session object from the
848      * specified object input stream, without requiring that the StandardSession
849      * itself have been serialized.
850      *
851      * @param stream
852      * The object input stream to read from
853      *
854      * @exception ClassNotFoundException
855      * if an unknown class is specified
856      * @exception IOException
857      * if an input/output error occurs
858      */

859     public void readObjectData(ObjectInputStream JavaDoc stream)
860             throws ClassNotFoundException JavaDoc, IOException JavaDoc {
861
862         readObject(stream);
863
864     }
865
866     /**
867      * Write a serialized version of the contents of this session object to the
868      * specified object output stream, without requiring that the
869      * StandardSession itself have been serialized.
870      *
871      * @param stream
872      * The object output stream to write to
873      *
874      * @exception IOException
875      * if an input/output error occurs
876      */

877     public void writeObjectData(ObjectOutputStream JavaDoc stream) throws IOException JavaDoc {
878
879         writeObject(stream);
880
881     }
882
883     public void resetDeltaRequest() {
884         if (deltaRequest == null) {
885             deltaRequest = new DeltaRequest(getId(), false);
886         } else {
887             deltaRequest.reset();
888             deltaRequest.setSessionId(getId());
889         }
890     }
891
892     public DeltaRequest getDeltaRequest() {
893         if (deltaRequest == null)
894             resetDeltaRequest();
895         return deltaRequest;
896     }
897
898     // ------------------------------------------------- HttpSession Properties
899

900     /**
901      * Return the time when this session was created, in milliseconds since
902      * midnight, January 1, 1970 GMT.
903      *
904      * @exception IllegalStateException
905      * if this method is called on an invalidated session
906      */

907     public long getCreationTime() {
908
909         if (!expiring && !isValid)
910             throw new IllegalStateException JavaDoc(sm
911                     .getString("standardSession.getCreationTime.ise"));
912
913         return (this.creationTime);
914
915     }
916
917     /**
918      * Return the ServletContext to which this session belongs.
919      */

920     public ServletContext JavaDoc getServletContext() {
921
922         if (manager == null)
923             return (null);
924         Context JavaDoc context = (Context JavaDoc) manager.getContainer();
925         if (context == null)
926             return (null);
927         else
928             return (context.getServletContext());
929
930     }
931
932     /**
933      * Return the session context with which this session is associated.
934      *
935      * @deprecated As of Version 2.1, this method is deprecated and has no
936      * replacement. It will be removed in a future version of the
937      * Java Servlet API.
938      */

939     public HttpSessionContext JavaDoc getSessionContext() {
940
941         if (sessionContext == null)
942             sessionContext = new StandardSessionContext();
943         return (sessionContext);
944
945     }
946
947     // ----------------------------------------------HttpSession Public Methods
948

949     /**
950      * Return the object bound with the specified name in this session, or
951      * <code>null</code> if no object is bound with that name.
952      *
953      * @param name
954      * Name of the attribute to be returned
955      *
956      * @exception IllegalStateException
957      * if this method is called on an invalidated session
958      */

959     public Object JavaDoc getAttribute(String JavaDoc name) {
960
961         if (!isValid())
962             throw new IllegalStateException JavaDoc(sm
963                     .getString("standardSession.getAttribute.ise"));
964
965         synchronized (attributes) {
966             return (attributes.get(name));
967         }
968
969     }
970
971     /**
972      * Return an <code>Enumeration</code> of <code>String</code> objects
973      * containing the names of the objects bound to this session.
974      *
975      * @exception IllegalStateException
976      * if this method is called on an invalidated session
977      */

978     public Enumeration JavaDoc getAttributeNames() {
979
980         if (!isValid())
981             throw new IllegalStateException JavaDoc(sm
982                     .getString("standardSession.getAttributeNames.ise"));
983
984         synchronized (attributes) {
985             return (new Enumerator(attributes.keySet(), true));
986         }
987
988     }
989
990     /**
991      * Return the object bound with the specified name in this session, or
992      * <code>null</code> if no object is bound with that name.
993      *
994      * @param name
995      * Name of the value to be returned
996      *
997      * @exception IllegalStateException
998      * if this method is called on an invalidated session
999      *
1000     * @deprecated As of Version 2.2, this method is replaced by
1001     * <code>getAttribute()</code>
1002     */

1003    public Object JavaDoc getValue(String JavaDoc name) {
1004
1005        return (getAttribute(name));
1006
1007    }
1008
1009    /**
1010     * Return the set of names of objects bound to this session. If there are no
1011     * such objects, a zero-length array is returned.
1012     *
1013     * @exception IllegalStateException
1014     * if this method is called on an invalidated session
1015     *
1016     * @deprecated As of Version 2.2, this method is replaced by
1017     * <code>getAttributeNames()</code>
1018     */

1019    public String JavaDoc[] getValueNames() {
1020
1021        if (!isValid())
1022            throw new IllegalStateException JavaDoc(sm
1023                    .getString("standardSession.getValueNames.ise"));
1024
1025        return (keys());
1026
1027    }
1028
1029    /**
1030     * Invalidates this session and unbinds any objects bound to it.
1031     *
1032     * @exception IllegalStateException
1033     * if this method is called on an invalidated session
1034     */

1035    public void invalidate() {
1036
1037        if (!isValid())
1038            throw new IllegalStateException JavaDoc(sm
1039                    .getString("standardSession.invalidate.ise"));
1040
1041        // Cause this session to expire
1042
expire();
1043
1044    }
1045
1046    /**
1047     * Return <code>true</code> if the client does not yet know about the
1048     * session, or if the client chooses not to join the session. For example,
1049     * if the server used only cookie-based sessions, and the client has
1050     * disabled the use of cookies, then a session would be new on each request.
1051     *
1052     * @exception IllegalStateException
1053     * if this method is called on an invalidated session
1054     */

1055    public boolean isNew() {
1056
1057        if (!isValid())
1058            throw new IllegalStateException JavaDoc(sm
1059                    .getString("standardSession.isNew.ise"));
1060
1061        return (this.isNew);
1062
1063    }
1064
1065    /**
1066     * Bind an object to this session, using the specified name. If an object of
1067     * the same name is already bound to this session, the object is replaced.
1068     * <p>
1069     * After this method executes, and if the object implements
1070     * <code>HttpSessionBindingListener</code>, the container calls
1071     * <code>valueBound()</code> on the object.
1072     *
1073     * @param name
1074     * Name to which the object is bound, cannot be null
1075     * @param value
1076     * Object to be bound, cannot be null
1077     *
1078     * @exception IllegalStateException
1079     * if this method is called on an invalidated session
1080     *
1081     * @deprecated As of Version 2.2, this method is replaced by
1082     * <code>setAttribute()</code>
1083     */

1084    public void putValue(String JavaDoc name, Object JavaDoc value) {
1085
1086        setAttribute(name, value);
1087
1088    }
1089
1090    /**
1091     * Remove the object bound with the specified name from this session. If the
1092     * session does not have an object bound with this name, this method does
1093     * nothing.
1094     * <p>
1095     * After this method executes, and if the object implements
1096     * <code>HttpSessionBindingListener</code>, the container calls
1097     * <code>valueUnbound()</code> on the object.
1098     *
1099     * @param name
1100     * Name of the object to remove from this session.
1101     *
1102     * @exception IllegalStateException
1103     * if this method is called on an invalidated session
1104     */

1105    public void removeAttribute(String JavaDoc name) {
1106
1107        removeAttribute(name, true);
1108
1109    }
1110
1111    /**
1112     * Remove the object bound with the specified name from this session. If the
1113     * session does not have an object bound with this name, this method does
1114     * nothing.
1115     * <p>
1116     * After this method executes, and if the object implements
1117     * <code>HttpSessionBindingListener</code>, the container calls
1118     * <code>valueUnbound()</code> on the object.
1119     *
1120     * @param name
1121     * Name of the object to remove from this session.
1122     * @param notify
1123     * Should we notify interested listeners that this attribute is
1124     * being removed?
1125     *
1126     * @exception IllegalStateException
1127     * if this method is called on an invalidated session
1128     */

1129    public void removeAttribute(String JavaDoc name, boolean notify) {
1130        removeAttribute(name, notify, true);
1131    }
1132
1133    public void removeAttribute(String JavaDoc name, boolean notify,
1134            boolean addDeltaRequest) {
1135
1136        // Validate our current state
1137
if (!isValid())
1138            throw new IllegalStateException JavaDoc(sm
1139                    .getString("standardSession.removeAttribute.ise"));
1140        removeAttributeInternal(name, notify, addDeltaRequest);
1141    }
1142
1143    /**
1144     * Remove the object bound with the specified name from this session. If the
1145     * session does not have an object bound with this name, this method does
1146     * nothing.
1147     * <p>
1148     * After this method executes, and if the object implements
1149     * <code>HttpSessionBindingListener</code>, the container calls
1150     * <code>valueUnbound()</code> on the object.
1151     *
1152     * @param name
1153     * Name of the object to remove from this session.
1154     *
1155     * @exception IllegalStateException
1156     * if this method is called on an invalidated session
1157     *
1158     * @deprecated As of Version 2.2, this method is replaced by
1159     * <code>removeAttribute()</code>
1160     */

1161    public void removeValue(String JavaDoc name) {
1162
1163        removeAttribute(name);
1164
1165    }
1166
1167    /**
1168     * Bind an object to this session, using the specified name. If an object of
1169     * the same name is already bound to this session, the object is replaced.
1170     * <p>
1171     * After this method executes, and if the object implements
1172     * <code>HttpSessionBindingListener</code>, the container calls
1173     * <code>valueBound()</code> on the object.
1174     *
1175     * @param name
1176     * Name to which the object is bound, cannot be null
1177     * @param value
1178     * Object to be bound, cannot be null
1179     *
1180     * @exception IllegalArgumentException
1181     * if an attempt is made to add a non-serializable object in
1182     * an environment marked distributable.
1183     * @exception IllegalStateException
1184     * if this method is called on an invalidated session
1185     */

1186    public void setAttribute(String JavaDoc name, Object JavaDoc value) {
1187        setAttribute(name, value, true, true);
1188    }
1189
1190    public void setAttribute(String JavaDoc name, Object JavaDoc value, boolean notify,
1191            boolean addDeltaRequest) {
1192
1193        // Name cannot be null
1194
if (name == null)
1195            throw new IllegalArgumentException JavaDoc(sm
1196                    .getString("standardSession.setAttribute.namenull"));
1197
1198        // Null value is the same as removeAttribute()
1199
if (value == null) {
1200            removeAttribute(name);
1201            return;
1202        }
1203
1204        if (!(value instanceof java.io.Serializable JavaDoc)) {
1205            throw new IllegalArgumentException JavaDoc("Attribute [" + name
1206                    + "] is not serializable");
1207        }
1208
1209        if (addDeltaRequest && (deltaRequest != null))
1210            deltaRequest.setAttribute(name, value);
1211
1212        // Validate our current state
1213
if (!isValid())
1214            throw new IllegalStateException JavaDoc(sm
1215                    .getString("standardSession.setAttribute.ise"));
1216        if ((manager != null) && manager.getDistributable()
1217                && !(value instanceof Serializable JavaDoc))
1218            throw new IllegalArgumentException JavaDoc(sm
1219                    .getString("standardSession.setAttribute.iae"));
1220
1221        // Construct an event with the new value
1222
HttpSessionBindingEvent JavaDoc event = null;
1223
1224        // Call the valueBound() method if necessary
1225
if (value instanceof HttpSessionBindingListener JavaDoc && notify) {
1226            event = new HttpSessionBindingEvent JavaDoc(getSession(), name, value);
1227            try {
1228                ((HttpSessionBindingListener JavaDoc) value).valueBound(event);
1229            } catch (Exception JavaDoc x) {
1230                log.error(smp.getString("deltaSession.valueBound.ex"), x);
1231            }
1232        }
1233
1234        // Replace or add this attribute
1235
Object JavaDoc unbound = attributes.put(name, value);
1236
1237        // Call the valueUnbound() method if necessary
1238
if ((unbound != null) && notify
1239                && (unbound instanceof HttpSessionBindingListener JavaDoc)) {
1240            try {
1241                ((HttpSessionBindingListener JavaDoc) unbound)
1242                        .valueUnbound(new HttpSessionBindingEvent JavaDoc(
1243                                (HttpSession JavaDoc) getSession(), name));
1244            } catch (Exception JavaDoc x) {
1245                log.error(smp.getString("deltaSession.valueBinding.ex"), x);
1246            }
1247
1248        }
1249
1250        //dont notify any listeners
1251
if (!notify)
1252            return;
1253
1254        // Notify interested application event listeners
1255
Context JavaDoc context = (Context JavaDoc) manager.getContainer();
1256        //fix for standalone manager without container
1257
if (context != null) {
1258            Object JavaDoc listeners[] = context.getApplicationEventListeners();
1259            if (listeners == null)
1260                return;
1261            for (int i = 0; i < listeners.length; i++) {
1262                if (!(listeners[i] instanceof HttpSessionAttributeListener JavaDoc))
1263                    continue;
1264                HttpSessionAttributeListener JavaDoc listener = (HttpSessionAttributeListener JavaDoc) listeners[i];
1265                try {
1266                    if (unbound != null) {
1267                        fireContainerEvent(context,
1268                                "beforeSessionAttributeReplaced", listener);
1269                        if (event == null) {
1270                            event = new HttpSessionBindingEvent JavaDoc(getSession(),
1271                                    name, unbound);
1272                        }
1273                        listener.attributeReplaced(event);
1274                        fireContainerEvent(context,
1275                                "afterSessionAttributeReplaced", listener);
1276                    } else {
1277                        fireContainerEvent(context,
1278                                "beforeSessionAttributeAdded", listener);
1279                        if (event == null) {
1280                            event = new HttpSessionBindingEvent JavaDoc(getSession(),
1281                                    name, unbound);
1282                        }
1283                        listener.attributeAdded(event);
1284                        fireContainerEvent(context,
1285                                "afterSessionAttributeAdded", listener);
1286                    }
1287                } catch (Throwable JavaDoc t) {
1288                    try {
1289                        if (unbound != null) {
1290                            fireContainerEvent(context,
1291                                    "afterSessionAttributeReplaced", listener);
1292                        } else {
1293                            fireContainerEvent(context,
1294                                    "afterSessionAttributeAdded", listener);
1295                        }
1296                    } catch (Exception JavaDoc e) {
1297                        ;
1298                    }
1299                    // FIXME - should we do anything besides log these?
1300
log
1301                            .error(
1302                                    sm
1303                                            .getString("standardSession.attributeEvent"),
1304                                    t);
1305                }
1306            } //for
1307
}//end if
1308
//end fix
1309

1310    }
1311
1312    // -------------------------------------------- HttpSession Private Methods
1313

1314    /**
1315     * Read a serialized version of this session object from the specified
1316     * object input stream.
1317     * <p>
1318     * <b>IMPLEMENTATION NOTE </b>: The reference to the owning Manager is not
1319     * restored by this method, and must be set explicitly.
1320     *
1321     * @param stream
1322     * The input stream to read from
1323     *
1324     * @exception ClassNotFoundException
1325     * if an unknown class is specified
1326     * @exception IOException
1327     * if an input/output error occurs
1328     */

1329    private void readObject(ObjectInputStream JavaDoc stream)
1330            throws ClassNotFoundException JavaDoc, IOException JavaDoc {
1331
1332        // Deserialize the scalar instance variables (except Manager)
1333
authType = null; // Transient only
1334
creationTime = ((Long JavaDoc) stream.readObject()).longValue();
1335        lastAccessedTime = ((Long JavaDoc) stream.readObject()).longValue();
1336        maxInactiveInterval = ((Integer JavaDoc) stream.readObject()).intValue();
1337        isNew = ((Boolean JavaDoc) stream.readObject()).booleanValue();
1338        isValid = ((Boolean JavaDoc) stream.readObject()).booleanValue();
1339        thisAccessedTime = ((Long JavaDoc) stream.readObject()).longValue();
1340        boolean hasPrincipal = stream.readBoolean();
1341        principal = null;
1342        if (hasPrincipal) {
1343            principal = SerializablePrincipal.readPrincipal(stream,
1344                    getManager().getContainer().getRealm());
1345        }
1346
1347        // setId((String) stream.readObject());
1348
id = (String JavaDoc) stream.readObject();
1349        if (log.isDebugEnabled())
1350            log.debug(smp.getString("deltaSession.readSession", id));
1351
1352        // Deserialize the attribute count and attribute values
1353
if (attributes == null)
1354            attributes = new HashMap JavaDoc();
1355        int n = ((Integer JavaDoc) stream.readObject()).intValue();
1356        boolean isValidSave = isValid;
1357        isValid = true;
1358        for (int i = 0; i < n; i++) {
1359            String JavaDoc name = (String JavaDoc) stream.readObject();
1360            Object JavaDoc value = (Object JavaDoc) stream.readObject();
1361            if ((value instanceof String JavaDoc) && (value.equals(NOT_SERIALIZED)))
1362                continue;
1363            //if (log.isTraceEnabled())
1364
// log.trace(smp.getString("deltaSession.readAttribute", id,name,value));
1365
synchronized (attributes) {
1366                attributes.put(name, value);
1367            }
1368        }
1369        isValid = isValidSave;
1370    }
1371
1372    /**
1373     * Write a serialized version of this session object to the specified object
1374     * output stream.
1375     * <p>
1376     * <b>IMPLEMENTATION NOTE </b>: The owning Manager will not be stored in the
1377     * serialized representation of this Session. After calling
1378     * <code>readObject()</code>, you must set the associated Manager
1379     * explicitly.
1380     * <p>
1381     * <b>IMPLEMENTATION NOTE </b>: Any attribute that is not Serializable will
1382     * be unbound from the session, with appropriate actions if it implements
1383     * HttpSessionBindingListener. If you do not want any such attributes, be
1384     * sure the <code>distributable</code> property of the associated Manager
1385     * is set to <code>true</code>.
1386     *
1387     * @param stream
1388     * The output stream to write to
1389     *
1390     * @exception IOException
1391     * if an input/output error occurs
1392     */

1393    private void writeObject(ObjectOutputStream JavaDoc stream) throws IOException JavaDoc {
1394
1395        // Write the scalar instance variables (except Manager)
1396
stream.writeObject(new Long JavaDoc(creationTime));
1397        stream.writeObject(new Long JavaDoc(lastAccessedTime));
1398        stream.writeObject(new Integer JavaDoc(maxInactiveInterval));
1399        stream.writeObject(new Boolean JavaDoc(isNew));
1400        stream.writeObject(new Boolean JavaDoc(isValid));
1401        stream.writeObject(new Long JavaDoc(thisAccessedTime));
1402        stream.writeBoolean(getPrincipal() != null);
1403        if (getPrincipal() != null) {
1404            SerializablePrincipal.writePrincipal((GenericPrincipal) principal,
1405                    stream);
1406        }
1407
1408        stream.writeObject(id);
1409        if (log.isDebugEnabled())
1410            log.debug(smp.getString("deltaSession.writeSession",id));
1411
1412        // Accumulate the names of serializable and non-serializable attributes
1413
String JavaDoc keys[] = keys();
1414        ArrayList JavaDoc saveNames = new ArrayList JavaDoc();
1415        ArrayList JavaDoc saveValues = new ArrayList JavaDoc();
1416        for (int i = 0; i < keys.length; i++) {
1417            Object JavaDoc value = null;
1418            synchronized (attributes) {
1419                value = attributes.get(keys[i]);
1420            }
1421            if (value == null)
1422                continue;
1423            else if (value instanceof Serializable JavaDoc) {
1424                saveNames.add(keys[i]);
1425                saveValues.add(value);
1426            }
1427        }
1428
1429        // Serialize the attribute count and the Serializable attributes
1430
int n = saveNames.size();
1431        stream.writeObject(new Integer JavaDoc(n));
1432        for (int i = 0; i < n; i++) {
1433            stream.writeObject((String JavaDoc) saveNames.get(i));
1434            try {
1435                stream.writeObject(saveValues.get(i));
1436                // if (log.isDebugEnabled())
1437
// log.debug(" storing attribute '" + saveNames.get(i) +
1438
// "' with value '" + saveValues.get(i) + "'");
1439
} catch (NotSerializableException JavaDoc e) {
1440                log.error(sm.getString("standardSession.notSerializable",
1441                        saveNames.get(i), id), e);
1442                stream.writeObject(NOT_SERIALIZED);
1443                log.error(" storing attribute '" + saveNames.get(i)
1444                        + "' with value NOT_SERIALIZED");
1445            }
1446        }
1447
1448    }
1449
1450    private void evaluateIfValid() {
1451        /*
1452         * If this session has expired or is in the process of expiring or will
1453         * never expire, return
1454         */

1455        if (!this.isValid || expiring || maxInactiveInterval < 0)
1456            return;
1457
1458        isValid();
1459
1460    }
1461
1462    // -------------------------------------------------------- Private Methods
1463

1464    /**
1465     * Fire container events if the Context implementation is the
1466     * <code>org.apache.catalina.core.StandardContext</code>.
1467     *
1468     * @param context
1469     * Context for which to fire events
1470     * @param type
1471     * Event type
1472     * @param data
1473     * Event data
1474     *
1475     * @exception Exception
1476     * occurred during event firing
1477     */

1478    private void fireContainerEvent(Context JavaDoc context, String JavaDoc type, Object JavaDoc data)
1479            throws Exception JavaDoc {
1480
1481        if (!"org.apache.catalina.core.StandardContext".equals(context
1482                .getClass().getName())) {
1483            return; // Container events are not supported
1484
}
1485        // NOTE: Race condition is harmless, so do not synchronize
1486
if (containerEventMethod == null) {
1487            containerEventMethod = context.getClass().getMethod(
1488                    "fireContainerEvent", containerEventTypes);
1489        }
1490        Object JavaDoc containerEventParams[] = new Object JavaDoc[2];
1491        containerEventParams[0] = type;
1492        containerEventParams[1] = data;
1493        containerEventMethod.invoke(context, containerEventParams);
1494
1495    }
1496
1497    /**
1498     * Notify all session event listeners that a particular event has occurred
1499     * for this Session. The default implementation performs this notification
1500     * synchronously using the calling thread.
1501     *
1502     * @param type
1503     * Event type
1504     * @param data
1505     * Event data
1506     */

1507    public void fireSessionEvent(String JavaDoc type, Object JavaDoc data) {
1508        if (listeners.size() < 1)
1509            return;
1510        SessionEvent JavaDoc event = new SessionEvent JavaDoc(this, type, data);
1511        SessionListener JavaDoc list[] = new SessionListener JavaDoc[0];
1512        synchronized (listeners) {
1513            list = (SessionListener JavaDoc[]) listeners.toArray(list);
1514        }
1515
1516        for (int i = 0; i < list.length; i++) {
1517            ((SessionListener JavaDoc) list[i]).sessionEvent(event);
1518        }
1519
1520    }
1521
1522    /**
1523     * Return the names of all currently defined session attributes as an array
1524     * of Strings. If there are no defined attributes, a zero-length array is
1525     * returned.
1526     */

1527    protected String JavaDoc[] keys() {
1528
1529        String JavaDoc results[] = new String JavaDoc[0];
1530        synchronized (attributes) {
1531            return ((String JavaDoc[]) attributes.keySet().toArray(results));
1532        }
1533
1534    }
1535
1536    /**
1537     * Return the value of an attribute without a check for validity.
1538     */

1539    protected Object JavaDoc getAttributeInternal(String JavaDoc name) {
1540
1541        synchronized (attributes) {
1542            return (attributes.get(name));
1543        }
1544
1545    }
1546
1547    protected void removeAttributeInternal(String JavaDoc name, boolean notify,
1548            boolean addDeltaRequest) {
1549
1550        // Remove this attribute from our collection
1551
Object JavaDoc value = attributes.remove(name);
1552        if (value == null)
1553            return;
1554
1555        if (addDeltaRequest && (deltaRequest != null))
1556            deltaRequest.removeAttribute(name);
1557
1558        // Do we need to do valueUnbound() and attributeRemoved() notification?
1559
if (!notify) {
1560            return;
1561        }
1562
1563        // Call the valueUnbound() method if necessary
1564
HttpSessionBindingEvent JavaDoc event = new HttpSessionBindingEvent JavaDoc(
1565                (HttpSession JavaDoc) getSession(), name, value);
1566        if ((value != null) && (value instanceof HttpSessionBindingListener JavaDoc))
1567            try {
1568                ((HttpSessionBindingListener JavaDoc) value).valueUnbound(event);
1569            } catch (Exception JavaDoc x) {
1570                log.error(smp.getString("deltaSession.valueUnbound.ex"), x);
1571            }
1572
1573        // Notify interested application event listeners
1574
Context JavaDoc context = (Context JavaDoc) manager.getContainer();
1575        //fix for standalone manager without container
1576
if (context != null) {
1577            Object JavaDoc listeners[] = context.getApplicationEventListeners();
1578            if (listeners == null)
1579                return;
1580            for (int i = 0; i < listeners.length; i++) {
1581                if (!(listeners[i] instanceof HttpSessionAttributeListener JavaDoc))
1582                    continue;
1583                HttpSessionAttributeListener JavaDoc listener = (HttpSessionAttributeListener JavaDoc) listeners[i];
1584                try {
1585                    fireContainerEvent(context,
1586                            "beforeSessionAttributeRemoved", listener);
1587                    listener.attributeRemoved(event);
1588                    fireContainerEvent(context, "afterSessionAttributeRemoved",
1589                            listener);
1590                } catch (Throwable JavaDoc t) {
1591                    try {
1592                        fireContainerEvent(context,
1593                                "afterSessionAttributeRemoved", listener);
1594                    } catch (Exception JavaDoc e) {
1595                        ;
1596                    }
1597                    // FIXME - should we do anything besides log these?
1598
log
1599                            .error(
1600                                    sm
1601                                            .getString("standardSession.attributeEvent"),
1602                                    t);
1603                }
1604            } //for
1605
}//end if
1606
//end fix
1607

1608    }
1609
1610    protected long getLastTimeReplicated() {
1611        return lastTimeReplicated;
1612    }
1613
1614    protected void setLastTimeReplicated(long lastTimeReplicated) {
1615        this.lastTimeReplicated = lastTimeReplicated;
1616    }
1617
1618    protected void setAccessCount(int accessCount) {
1619        this.accessCount = accessCount;
1620    }
1621
1622    protected int getAccessCount() {
1623        return accessCount;
1624    }
1625
1626}
1627
1628// -------------------------------------------------------------- Private Class
1629

1630/**
1631 * This class is a dummy implementation of the <code>HttpSessionContext</code>
1632 * interface, to conform to the requirement that such an object be returned when
1633 * <code>HttpSession.getSessionContext()</code> is called.
1634 *
1635 * @author Craig R. McClanahan
1636 *
1637 * @deprecated As of Java Servlet API 2.1 with no replacement. The interface
1638 * will be removed in a future version of this API.
1639 */

1640
1641final class StandardSessionContext implements HttpSessionContext JavaDoc {
1642
1643    private HashMap JavaDoc dummy = new HashMap JavaDoc();
1644
1645    /**
1646     * Return the session identifiers of all sessions defined within this
1647     * context.
1648     *
1649     * @deprecated As of Java Servlet API 2.1 with no replacement. This method
1650     * must return an empty <code>Enumeration</code> and will be
1651     * removed in a future version of the API.
1652     */

1653    public Enumeration JavaDoc getIds() {
1654
1655        return (new Enumerator(dummy));
1656
1657    }
1658
1659    /**
1660     * Return the <code>HttpSession</code> associated with the specified
1661     * session identifier.
1662     *
1663     * @param id
1664     * Session identifier for which to look up a session
1665     *
1666     * @deprecated As of Java Servlet API 2.1 with no replacement. This method
1667     * must return null and will be removed in a future version of
1668     * the API.
1669     */

1670    public HttpSession JavaDoc getSession(String JavaDoc id) {
1671
1672        return (null);
1673
1674    }
1675
1676}
Popular Tags