KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > catalina > session > StandardSession


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

17
18
19 package org.apache.catalina.session;
20
21
22 import java.beans.PropertyChangeSupport JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.io.NotSerializableException JavaDoc;
25 import java.io.ObjectInputStream JavaDoc;
26 import java.io.ObjectOutputStream JavaDoc;
27 import java.io.Serializable JavaDoc;
28 import java.lang.reflect.Method JavaDoc;
29 import java.security.AccessController JavaDoc;
30 import java.security.Principal JavaDoc;
31 import java.security.PrivilegedAction JavaDoc;
32 import java.util.ArrayList JavaDoc;
33 import java.util.Enumeration JavaDoc;
34 import java.util.HashMap JavaDoc;
35 import java.util.Hashtable JavaDoc;
36 import java.util.Iterator JavaDoc;
37 import java.util.Map JavaDoc;
38 import java.util.concurrent.ConcurrentHashMap JavaDoc;
39 import java.util.concurrent.atomic.AtomicInteger JavaDoc;
40
41 import javax.servlet.ServletContext JavaDoc;
42 import javax.servlet.http.HttpSession JavaDoc;
43 import javax.servlet.http.HttpSessionActivationListener JavaDoc;
44 import javax.servlet.http.HttpSessionAttributeListener JavaDoc;
45 import javax.servlet.http.HttpSessionBindingEvent JavaDoc;
46 import javax.servlet.http.HttpSessionBindingListener JavaDoc;
47 import javax.servlet.http.HttpSessionContext JavaDoc;
48 import javax.servlet.http.HttpSessionEvent JavaDoc;
49 import javax.servlet.http.HttpSessionListener JavaDoc;
50
51 import org.apache.catalina.Context;
52 import org.apache.catalina.Globals;
53 import org.apache.catalina.Manager;
54 import org.apache.catalina.Session;
55 import org.apache.catalina.SessionEvent;
56 import org.apache.catalina.SessionListener;
57 import org.apache.catalina.util.Enumerator;
58 import org.apache.catalina.util.StringManager;
59
60 import org.apache.catalina.security.SecurityUtil;
61
62 /**
63  * Standard implementation of the <b>Session</b> interface. This object is
64  * serializable, so that it can be stored in persistent storage or transferred
65  * to a different JVM for distributable session support.
66  * <p>
67  * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the
68  * internal (Session) and application level (HttpSession) view of the session.
69  * However, because the class itself is not declared public, Java logic outside
70  * of the <code>org.apache.catalina.session</code> package cannot cast an
71  * HttpSession view of this instance back to a Session view.
72  * <p>
73  * <b>IMPLEMENTATION NOTE</b>: If you add fields to this class, you must
74  * make sure that you carry them over in the read/writeObject methods so
75  * that this class is properly serialized.
76  *
77  * @author Craig R. McClanahan
78  * @author Sean Legassick
79  * @author <a HREF="mailto:jon@latchkey.com">Jon S. Stevens</a>
80  * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
81  */

82
83 public class StandardSession
84     implements HttpSession JavaDoc, Session JavaDoc, Serializable JavaDoc {
85
86
87     protected static final boolean ACTIVITY_CHECK =
88         Globals.STRICT_SERVLET_COMPLIANCE
89         || Boolean.valueOf(System.getProperty("org.apache.catalina.session.StandardSession.ACTIVITY_CHECK", "false")).booleanValue();
90
91
92     // ----------------------------------------------------------- Constructors
93

94
95     /**
96      * Construct a new Session associated with the specified Manager.
97      *
98      * @param manager The manager with which this Session is associated
99      */

100     public StandardSession(Manager manager) {
101
102         super();
103         this.manager = manager;
104
105         // Initialize access count
106
if (ACTIVITY_CHECK) {
107             accessCount = new AtomicInteger JavaDoc();
108         }
109
110     }
111
112
113     // ----------------------------------------------------- Instance Variables
114

115
116     /**
117      * Type array.
118      */

119     protected static final String JavaDoc EMPTY_ARRAY[] = new String JavaDoc[0];
120
121
122     /**
123      * The dummy attribute value serialized when a NotSerializableException is
124      * encountered in <code>writeObject()</code>.
125      */

126     protected static final String JavaDoc NOT_SERIALIZED =
127         "___NOT_SERIALIZABLE_EXCEPTION___";
128
129
130     /**
131      * The collection of user data attributes associated with this Session.
132      */

133     protected Map JavaDoc attributes = new ConcurrentHashMap JavaDoc();
134
135
136     /**
137      * The authentication type used to authenticate our cached Principal,
138      * if any. NOTE: This value is not included in the serialized
139      * version of this object.
140      */

141     protected transient String JavaDoc authType = null;
142
143
144     /**
145      * The <code>java.lang.Method</code> for the
146      * <code>fireContainerEvent()</code> method of the
147      * <code>org.apache.catalina.core.StandardContext</code> method,
148      * if our Context implementation is of this class. This value is
149      * computed dynamically the first time it is needed, or after
150      * a session reload (since it is declared transient).
151      */

152     protected transient Method JavaDoc containerEventMethod = null;
153
154
155     /**
156      * The method signature for the <code>fireContainerEvent</code> method.
157      */

158     protected static final Class JavaDoc containerEventTypes[] =
159     { String JavaDoc.class, Object JavaDoc.class };
160
161
162     /**
163      * The time this session was created, in milliseconds since midnight,
164      * January 1, 1970 GMT.
165      */

166     protected long creationTime = 0L;
167
168
169     /**
170      * Set of attribute names which are not allowed to be persisted.
171      */

172     protected static final String JavaDoc[] excludedAttributes = {
173         Globals.SUBJECT_ATTR
174     };
175
176
177     /**
178      * We are currently processing a session expiration, so bypass
179      * certain IllegalStateException tests. NOTE: This value is not
180      * included in the serialized version of this object.
181      */

182     protected transient boolean expiring = false;
183
184
185     /**
186      * The facade associated with this session. NOTE: This value is not
187      * included in the serialized version of this object.
188      */

189     protected transient StandardSessionFacade facade = null;
190
191
192     /**
193      * The session identifier of this Session.
194      */

195     protected String JavaDoc id = null;
196
197
198     /**
199      * Descriptive information describing this Session implementation.
200      */

201     protected static final String JavaDoc info = "StandardSession/1.0";
202
203
204     /**
205      * The last accessed time for this Session.
206      */

207     protected long lastAccessedTime = creationTime;
208
209
210     /**
211      * The session event listeners for this Session.
212      */

213     protected transient ArrayList JavaDoc listeners = new ArrayList JavaDoc();
214
215
216     /**
217      * The Manager with which this Session is associated.
218      */

219     protected transient Manager manager = null;
220
221
222     /**
223      * The maximum time interval, in seconds, between client requests before
224      * the servlet container may invalidate this session. A negative time
225      * indicates that the session should never time out.
226      */

227     protected int maxInactiveInterval = -1;
228
229
230     /**
231      * Flag indicating whether this session is new or not.
232      */

233     protected boolean isNew = false;
234
235
236     /**
237      * Flag indicating whether this session is valid or not.
238      */

239     protected boolean isValid = false;
240
241     
242     /**
243      * Internal notes associated with this session by Catalina components
244      * and event listeners. <b>IMPLEMENTATION NOTE:</b> This object is
245      * <em>not</em> saved and restored across session serializations!
246      */

247     protected transient Map JavaDoc notes = new Hashtable JavaDoc();
248
249
250     /**
251      * The authenticated Principal associated with this session, if any.
252      * <b>IMPLEMENTATION NOTE:</b> This object is <i>not</i> saved and
253      * restored across session serializations!
254      */

255     protected transient Principal JavaDoc principal = null;
256
257
258     /**
259      * The string manager for this package.
260      */

261     protected static StringManager sm =
262         StringManager.getManager(Constants.Package);
263
264
265     /**
266      * The HTTP session context associated with this session.
267      */

268     protected static HttpSessionContext JavaDoc sessionContext = null;
269
270
271     /**
272      * The property change support for this component. NOTE: This value
273      * is not included in the serialized version of this object.
274      */

275     protected transient PropertyChangeSupport JavaDoc support =
276         new PropertyChangeSupport JavaDoc(this);
277
278
279     /**
280      * The current accessed time for this session.
281      */

282     protected long thisAccessedTime = creationTime;
283
284
285     /**
286      * The access count for this session.
287      */

288     protected transient AtomicInteger JavaDoc accessCount = null;
289
290     
291     // ----------------------------------------------------- Session Properties
292

293
294     /**
295      * Return the authentication type used to authenticate our cached
296      * Principal, if any.
297      */

298     public String JavaDoc getAuthType() {
299
300         return (this.authType);
301
302     }
303
304
305     /**
306      * Set the authentication type used to authenticate our cached
307      * Principal, if any.
308      *
309      * @param authType The new cached authentication type
310      */

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

326     public void setCreationTime(long time) {
327
328         this.creationTime = time;
329         this.lastAccessedTime = time;
330         this.thisAccessedTime = time;
331
332     }
333
334
335     /**
336      * Return the session identifier for this session.
337      */

338     public String JavaDoc getId() {
339
340         return (this.id);
341
342     }
343
344
345     /**
346      * Return the session identifier for this session.
347      */

348     public String JavaDoc getIdInternal() {
349
350         return (this.id);
351
352     }
353
354
355     /**
356      * Set the session identifier for this session.
357      *
358      * @param id The new session identifier
359      */

360     public void setId(String JavaDoc id) {
361
362         if ((this.id != null) && (manager != null))
363             manager.remove(this);
364
365         this.id = id;
366
367         if (manager != null)
368             manager.add(this);
369         tellNew();
370     }
371
372
373     /**
374      * Inform the listeners about the new session.
375      *
376      */

377     public void tellNew() {
378
379         // Notify interested session event listeners
380
fireSessionEvent(Session.SESSION_CREATED_EVENT, null);
381
382         // Notify interested application event listeners
383
Context JavaDoc context = (Context JavaDoc) manager.getContainer();
384         Object JavaDoc listeners[] = context.getApplicationLifecycleListeners();
385         if (listeners != null) {
386             HttpSessionEvent JavaDoc event =
387                 new HttpSessionEvent JavaDoc(getSession());
388             for (int i = 0; i < listeners.length; i++) {
389                 if (!(listeners[i] instanceof HttpSessionListener JavaDoc))
390                     continue;
391                 HttpSessionListener JavaDoc listener =
392                     (HttpSessionListener JavaDoc) listeners[i];
393                 try {
394                     fireContainerEvent(context,
395                                        "beforeSessionCreated",
396                                        listener);
397                     listener.sessionCreated(event);
398                     fireContainerEvent(context,
399                                        "afterSessionCreated",
400                                        listener);
401                 } catch (Throwable JavaDoc t) {
402                     try {
403                         fireContainerEvent(context,
404                                            "afterSessionCreated",
405                                            listener);
406                     } catch (Exception JavaDoc e) {
407                         ;
408                     }
409                     manager.getContainer().getLogger().error
410                         (sm.getString("standardSession.sessionEvent"), t);
411                 }
412             }
413         }
414
415     }
416
417
418     /**
419      * Return descriptive information about this Session implementation and
420      * the corresponding version number, in the format
421      * <code>&lt;description&gt;/&lt;version&gt;</code>.
422      */

423     public String JavaDoc getInfo() {
424
425         return (info);
426
427     }
428
429
430     /**
431      * Return the last time the client sent a request associated with this
432      * session, as the number of milliseconds since midnight, January 1, 1970
433      * GMT. Actions that your application takes, such as getting or setting
434      * a value associated with the session, do not affect the access time.
435      */

436     public long getLastAccessedTime() {
437
438         if (!isValidInternal()) {
439             throw new IllegalStateException JavaDoc
440                 (sm.getString("standardSession.getLastAccessedTime.ise"));
441         }
442
443         return (this.lastAccessedTime);
444     }
445
446     /**
447      * Return the last client access time without invalidation check
448      * @see #getLastAccessedTime().
449      */

450     public long getLastAccessedTimeInternal() {
451         return (this.lastAccessedTime);
452     }
453
454     /**
455      * Return the Manager within which this Session is valid.
456      */

457     public Manager getManager() {
458
459         return (this.manager);
460
461     }
462
463
464     /**
465      * Set the Manager within which this Session is valid.
466      *
467      * @param manager The new Manager
468      */

469     public void setManager(Manager manager) {
470
471         this.manager = manager;
472
473     }
474
475
476     /**
477      * Return the maximum time interval, in seconds, between client requests
478      * before the servlet container will invalidate the session. A negative
479      * time indicates that the session should never time out.
480      */

481     public int getMaxInactiveInterval() {
482
483         return (this.maxInactiveInterval);
484
485     }
486
487
488     /**
489      * Set the maximum time interval, in seconds, between client requests
490      * before the servlet container will invalidate the session. A negative
491      * time indicates that the session should never time out.
492      *
493      * @param interval The new maximum interval
494      */

495     public void setMaxInactiveInterval(int interval) {
496
497         this.maxInactiveInterval = interval;
498         if (isValid && interval == 0) {
499             expire();
500         }
501
502     }
503
504
505     /**
506      * Set the <code>isNew</code> flag for this session.
507      *
508      * @param isNew The new value for the <code>isNew</code> flag
509      */

510     public void setNew(boolean isNew) {
511
512         this.isNew = isNew;
513
514     }
515
516
517     /**
518      * Return the authenticated Principal that is associated with this Session.
519      * This provides an <code>Authenticator</code> with a means to cache a
520      * previously authenticated Principal, and avoid potentially expensive
521      * <code>Realm.authenticate()</code> calls on every request. If there
522      * is no current associated Principal, return <code>null</code>.
523      */

524     public Principal JavaDoc getPrincipal() {
525
526         return (this.principal);
527
528     }
529
530
531     /**
532      * Set the authenticated Principal that is associated with this Session.
533      * This provides an <code>Authenticator</code> with a means to cache a
534      * previously authenticated Principal, and avoid potentially expensive
535      * <code>Realm.authenticate()</code> calls on every request.
536      *
537      * @param principal The new Principal, or <code>null</code> if none
538      */

539     public void setPrincipal(Principal JavaDoc principal) {
540
541         Principal JavaDoc oldPrincipal = this.principal;
542         this.principal = principal;
543         support.firePropertyChange("principal", oldPrincipal, this.principal);
544
545     }
546
547
548     /**
549      * Return the <code>HttpSession</code> for which this object
550      * is the facade.
551      */

552     public HttpSession JavaDoc getSession() {
553
554         if (facade == null){
555             if (SecurityUtil.isPackageProtectionEnabled()){
556                 final StandardSession fsession = this;
557                 facade = (StandardSessionFacade)AccessController.doPrivileged(new PrivilegedAction JavaDoc(){
558                     public Object JavaDoc run(){
559                         return new StandardSessionFacade(fsession);
560                     }
561                 });
562             } else {
563                 facade = new StandardSessionFacade(this);
564             }
565         }
566         return (facade);
567
568     }
569
570
571     /**
572      * Return the <code>isValid</code> flag for this session.
573      */

574     public boolean isValid() {
575
576         if (this.expiring) {
577             return true;
578         }
579
580         if (!this.isValid) {
581             return false;
582         }
583
584         if (ACTIVITY_CHECK && accessCount.get() > 0) {
585             return true;
586         }
587
588         if (maxInactiveInterval >= 0) {
589             long timeNow = System.currentTimeMillis();
590             int timeIdle = (int) ((timeNow - thisAccessedTime) / 1000L);
591             if (timeIdle >= maxInactiveInterval) {
592                 expire(true);
593             }
594         }
595
596         return (this.isValid);
597     }
598
599
600     /**
601      * Set the <code>isValid</code> flag for this session.
602      *
603      * @param isValid The new value for the <code>isValid</code> flag
604      */

605     public void setValid(boolean isValid) {
606         this.isValid = isValid;
607     }
608
609
610     // ------------------------------------------------- Session Public Methods
611

612
613     /**
614      * Update the accessed time information for this session. This method
615      * should be called by the context when a request comes in for a particular
616      * session, even if the application does not reference it.
617      */

618     public void access() {
619
620         this.lastAccessedTime = this.thisAccessedTime;
621         this.thisAccessedTime = System.currentTimeMillis();
622         
623         if (ACTIVITY_CHECK) {
624             accessCount.incrementAndGet();
625         }
626
627     }
628
629
630     /**
631      * End the access.
632      */

633     public void endAccess() {
634
635         isNew = false;
636
637         if (ACTIVITY_CHECK) {
638             accessCount.decrementAndGet();
639         }
640
641     }
642
643
644     /**
645      * Add a session event listener to this component.
646      */

647     public void addSessionListener(SessionListener JavaDoc listener) {
648
649         listeners.add(listener);
650
651     }
652
653
654     /**
655      * Perform the internal processing required to invalidate this session,
656      * without triggering an exception if the session has already expired.
657      */

658     public void expire() {
659
660         expire(true);
661
662     }
663
664
665     /**
666      * Perform the internal processing required to invalidate this session,
667      * without triggering an exception if the session has already expired.
668      *
669      * @param notify Should we notify listeners about the demise of
670      * this session?
671      */

672     public void expire(boolean notify) {
673
674         // Mark this session as "being expired" if needed
675
if (expiring)
676             return;
677
678         synchronized (this) {
679
680             if (manager == null)
681                 return;
682
683             expiring = true;
684         
685             // Notify interested application event listeners
686
// FIXME - Assumes we call listeners in reverse order
687
Context JavaDoc context = (Context JavaDoc) manager.getContainer();
688             Object JavaDoc listeners[] = context.getApplicationLifecycleListeners();
689             if (notify && (listeners != null)) {
690                 HttpSessionEvent JavaDoc event =
691                     new HttpSessionEvent JavaDoc(getSession());
692                 for (int i = 0; i < listeners.length; i++) {
693                     int j = (listeners.length - 1) - i;
694                     if (!(listeners[j] instanceof HttpSessionListener JavaDoc))
695                         continue;
696                     HttpSessionListener JavaDoc listener =
697                         (HttpSessionListener JavaDoc) listeners[j];
698                     try {
699                         fireContainerEvent(context,
700                                            "beforeSessionDestroyed",
701                                            listener);
702                         listener.sessionDestroyed(event);
703                         fireContainerEvent(context,
704                                            "afterSessionDestroyed",
705                                            listener);
706                     } catch (Throwable JavaDoc t) {
707                         try {
708                             fireContainerEvent(context,
709                                                "afterSessionDestroyed",
710                                                listener);
711                         } catch (Exception JavaDoc e) {
712                             ;
713                         }
714                         manager.getContainer().getLogger().error
715                             (sm.getString("standardSession.sessionEvent"), t);
716                     }
717                 }
718             }
719             if (ACTIVITY_CHECK) {
720                 accessCount.set(0);
721             }
722             setValid(false);
723
724             /*
725              * Compute how long this session has been alive, and update
726              * session manager's related properties accordingly
727              */

728             long timeNow = System.currentTimeMillis();
729             int timeAlive = (int) ((timeNow - creationTime)/1000);
730             synchronized (manager) {
731                 if (timeAlive > manager.getSessionMaxAliveTime()) {
732                     manager.setSessionMaxAliveTime(timeAlive);
733                 }
734                 int numExpired = manager.getExpiredSessions();
735                 numExpired++;
736                 manager.setExpiredSessions(numExpired);
737                 int average = manager.getSessionAverageAliveTime();
738                 average = ((average * (numExpired-1)) + timeAlive)/numExpired;
739                 manager.setSessionAverageAliveTime(average);
740             }
741
742             // Remove this session from our manager's active sessions
743
manager.remove(this);
744
745             // Notify interested session event listeners
746
if (notify) {
747                 fireSessionEvent(Session.SESSION_DESTROYED_EVENT, null);
748             }
749
750             // We have completed expire of this session
751
expiring = false;
752
753             // Unbind any objects associated with this session
754
String JavaDoc keys[] = keys();
755             for (int i = 0; i < keys.length; i++)
756                 removeAttributeInternal(keys[i], notify);
757
758         }
759
760     }
761
762
763     /**
764      * Perform the internal processing required to passivate
765      * this session.
766      */

767     public void passivate() {
768
769         // Notify interested session event listeners
770
fireSessionEvent(Session.SESSION_PASSIVATED_EVENT, null);
771
772         // Notify ActivationListeners
773
HttpSessionEvent JavaDoc event = null;
774         String JavaDoc keys[] = keys();
775         for (int i = 0; i < keys.length; i++) {
776             Object JavaDoc attribute = attributes.get(keys[i]);
777             if (attribute instanceof HttpSessionActivationListener JavaDoc) {
778                 if (event == null)
779                     event = new HttpSessionEvent JavaDoc(getSession());
780                 try {
781                     ((HttpSessionActivationListener JavaDoc)attribute)
782                         .sessionWillPassivate(event);
783                 } catch (Throwable JavaDoc t) {
784                     manager.getContainer().getLogger().error
785                         (sm.getString("standardSession.attributeEvent"), t);
786                 }
787             }
788         }
789
790     }
791
792
793     /**
794      * Perform internal processing required to activate this
795      * session.
796      */

797     public void activate() {
798
799         // Initialize access count
800
if (ACTIVITY_CHECK) {
801             accessCount = new AtomicInteger JavaDoc();
802         }
803         
804         // Notify interested session event listeners
805
fireSessionEvent(Session.SESSION_ACTIVATED_EVENT, null);
806
807         // Notify ActivationListeners
808
HttpSessionEvent JavaDoc event = null;
809         String JavaDoc keys[] = keys();
810         for (int i = 0; i < keys.length; i++) {
811             Object JavaDoc attribute = attributes.get(keys[i]);
812             if (attribute instanceof HttpSessionActivationListener JavaDoc) {
813                 if (event == null)
814                     event = new HttpSessionEvent JavaDoc(getSession());
815                 try {
816                     ((HttpSessionActivationListener JavaDoc)attribute)
817                         .sessionDidActivate(event);
818                 } catch (Throwable JavaDoc t) {
819                     manager.getContainer().getLogger().error
820                         (sm.getString("standardSession.attributeEvent"), t);
821                 }
822             }
823         }
824
825     }
826
827
828     /**
829      * Return the object bound with the specified name to the internal notes
830      * for this session, or <code>null</code> if no such binding exists.
831      *
832      * @param name Name of the note to be returned
833      */

834     public Object JavaDoc getNote(String JavaDoc name) {
835
836         return (notes.get(name));
837
838     }
839
840
841     /**
842      * Return an Iterator containing the String names of all notes bindings
843      * that exist for this session.
844      */

845     public Iterator JavaDoc getNoteNames() {
846
847         return (notes.keySet().iterator());
848
849     }
850
851
852     /**
853      * Release all object references, and initialize instance variables, in
854      * preparation for reuse of this object.
855      */

856     public void recycle() {
857
858         // Reset the instance variables associated with this Session
859
attributes.clear();
860         setAuthType(null);
861         creationTime = 0L;
862         expiring = false;
863         id = null;
864         lastAccessedTime = 0L;
865         maxInactiveInterval = -1;
866         accessCount = null;
867         notes.clear();
868         setPrincipal(null);
869         isNew = false;
870         isValid = false;
871         manager = null;
872
873     }
874
875
876     /**
877      * Remove any object bound to the specified name in the internal notes
878      * for this session.
879      *
880      * @param name Name of the note to be removed
881      */

882     public void removeNote(String JavaDoc name) {
883
884         notes.remove(name);
885
886     }
887
888
889     /**
890      * Remove a session event listener from this component.
891      */

892     public void removeSessionListener(SessionListener JavaDoc listener) {
893
894         listeners.remove(listener);
895
896     }
897
898
899     /**
900      * Bind an object to a specified name in the internal notes associated
901      * with this session, replacing any existing binding for this name.
902      *
903      * @param name Name to which the object should be bound
904      * @param value Object to be bound to the specified name
905      */

906     public void setNote(String JavaDoc name, Object JavaDoc value) {
907
908         notes.put(name, value);
909
910     }
911
912
913     /**
914      * Return a string representation of this object.
915      */

916     public String JavaDoc toString() {
917
918         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
919         sb.append("StandardSession[");
920         sb.append(id);
921         sb.append("]");
922         return (sb.toString());
923
924     }
925
926
927     // ------------------------------------------------ Session Package Methods
928

929
930     /**
931      * Read a serialized version of the contents of this session object from
932      * the specified object input stream, without requiring that the
933      * StandardSession itself have been serialized.
934      *
935      * @param stream The object input stream to read from
936      *
937      * @exception ClassNotFoundException if an unknown class is specified
938      * @exception IOException if an input/output error occurs
939      */

940     public void readObjectData(ObjectInputStream JavaDoc stream)
941         throws ClassNotFoundException JavaDoc, IOException JavaDoc {
942
943         readObject(stream);
944
945     }
946
947
948     /**
949      * Write a serialized version of the contents of this session object to
950      * the specified object output stream, without requiring that the
951      * StandardSession itself have been serialized.
952      *
953      * @param stream The object output stream to write to
954      *
955      * @exception IOException if an input/output error occurs
956      */

957     public void writeObjectData(ObjectOutputStream JavaDoc stream)
958         throws IOException JavaDoc {
959
960         writeObject(stream);
961
962     }
963
964
965     // ------------------------------------------------- HttpSession Properties
966

967
968     /**
969      * Return the time when this session was created, in milliseconds since
970      * midnight, January 1, 1970 GMT.
971      *
972      * @exception IllegalStateException if this method is called on an
973      * invalidated session
974      */

975     public long getCreationTime() {
976
977         if (!isValidInternal())
978             throw new IllegalStateException JavaDoc
979                 (sm.getString("standardSession.getCreationTime.ise"));
980
981         return (this.creationTime);
982
983     }
984
985
986     /**
987      * Return the ServletContext to which this session belongs.
988      */

989     public ServletContext JavaDoc getServletContext() {
990
991         if (manager == null)
992             return (null);
993         Context JavaDoc context = (Context JavaDoc) manager.getContainer();
994         if (context == null)
995             return (null);
996         else
997             return (context.getServletContext());
998
999     }
1000
1001
1002    /**
1003     * Return the session context with which this session is associated.
1004     *
1005     * @deprecated As of Version 2.1, this method is deprecated and has no
1006     * replacement. It will be removed in a future version of the
1007     * Java Servlet API.
1008     */

1009    public HttpSessionContext JavaDoc getSessionContext() {
1010
1011        if (sessionContext == null)
1012            sessionContext = new StandardSessionContext();
1013        return (sessionContext);
1014
1015    }
1016
1017
1018    // ----------------------------------------------HttpSession Public Methods
1019

1020
1021    /**
1022     * Return the object bound with the specified name in this session, or
1023     * <code>null</code> if no object is bound with that name.
1024     *
1025     * @param name Name of the attribute to be returned
1026     *
1027     * @exception IllegalStateException if this method is called on an
1028     * invalidated session
1029     */

1030    public Object JavaDoc getAttribute(String JavaDoc name) {
1031
1032        if (!isValidInternal())
1033            throw new IllegalStateException JavaDoc
1034                (sm.getString("standardSession.getAttribute.ise"));
1035
1036        return (attributes.get(name));
1037
1038    }
1039
1040
1041    /**
1042     * Return an <code>Enumeration</code> of <code>String</code> objects
1043     * containing the names of the objects bound to this session.
1044     *
1045     * @exception IllegalStateException if this method is called on an
1046     * invalidated session
1047     */

1048    public Enumeration JavaDoc getAttributeNames() {
1049
1050        if (!isValidInternal())
1051            throw new IllegalStateException JavaDoc
1052                (sm.getString("standardSession.getAttributeNames.ise"));
1053
1054        return (new Enumerator(attributes.keySet(), true));
1055
1056    }
1057
1058
1059    /**
1060     * Return the object bound with the specified name in this session, or
1061     * <code>null</code> if no object is bound with that name.
1062     *
1063     * @param name Name of the value to be returned
1064     *
1065     * @exception IllegalStateException if this method is called on an
1066     * invalidated session
1067     *
1068     * @deprecated As of Version 2.2, this method is replaced by
1069     * <code>getAttribute()</code>
1070     */

1071    public Object JavaDoc getValue(String JavaDoc name) {
1072
1073        return (getAttribute(name));
1074
1075    }
1076
1077
1078    /**
1079     * Return the set of names of objects bound to this session. If there
1080     * are no such objects, a zero-length array is returned.
1081     *
1082     * @exception IllegalStateException if this method is called on an
1083     * invalidated session
1084     *
1085     * @deprecated As of Version 2.2, this method is replaced by
1086     * <code>getAttributeNames()</code>
1087     */

1088    public String JavaDoc[] getValueNames() {
1089
1090        if (!isValidInternal())
1091            throw new IllegalStateException JavaDoc
1092                (sm.getString("standardSession.getValueNames.ise"));
1093
1094        return (keys());
1095
1096    }
1097
1098
1099    /**
1100     * Invalidates this session and unbinds any objects bound to it.
1101     *
1102     * @exception IllegalStateException if this method is called on
1103     * an invalidated session
1104     */

1105    public void invalidate() {
1106
1107        if (!isValidInternal())
1108            throw new IllegalStateException JavaDoc
1109                (sm.getString("standardSession.invalidate.ise"));
1110
1111        // Cause this session to expire
1112
expire();
1113
1114    }
1115
1116
1117    /**
1118     * Return <code>true</code> if the client does not yet know about the
1119     * session, or if the client chooses not to join the session. For
1120     * example, if the server used only cookie-based sessions, and the client
1121     * has disabled the use of cookies, then a session would be new on each
1122     * request.
1123     *
1124     * @exception IllegalStateException if this method is called on an
1125     * invalidated session
1126     */

1127    public boolean isNew() {
1128
1129        if (!isValidInternal())
1130            throw new IllegalStateException JavaDoc
1131                (sm.getString("standardSession.isNew.ise"));
1132
1133        return (this.isNew);
1134
1135    }
1136
1137
1138
1139    /**
1140     * Bind an object to this session, using the specified name. If an object
1141     * of the same name is already bound to this session, the object is
1142     * replaced.
1143     * <p>
1144     * After this method executes, and if the object implements
1145     * <code>HttpSessionBindingListener</code>, the container calls
1146     * <code>valueBound()</code> on the object.
1147     *
1148     * @param name Name to which the object is bound, cannot be null
1149     * @param value Object to be bound, cannot be null
1150     *
1151     * @exception IllegalStateException if this method is called on an
1152     * invalidated session
1153     *
1154     * @deprecated As of Version 2.2, this method is replaced by
1155     * <code>setAttribute()</code>
1156     */

1157    public void putValue(String JavaDoc name, Object JavaDoc value) {
1158
1159        setAttribute(name, value);
1160
1161    }
1162
1163
1164    /**
1165     * Remove the object bound with the specified name from this session. If
1166     * the session does not have an object bound with this name, this method
1167     * does nothing.
1168     * <p>
1169     * After this method executes, and if the object implements
1170     * <code>HttpSessionBindingListener</code>, the container calls
1171     * <code>valueUnbound()</code> on the object.
1172     *
1173     * @param name Name of the object to remove from this session.
1174     *
1175     * @exception IllegalStateException if this method is called on an
1176     * invalidated session
1177     */

1178    public void removeAttribute(String JavaDoc name) {
1179
1180        removeAttribute(name, true);
1181
1182    }
1183
1184
1185    /**
1186     * Remove the object bound with the specified name from this session. If
1187     * the session does not have an object bound with this name, this method
1188     * does nothing.
1189     * <p>
1190     * After this method executes, and if the object implements
1191     * <code>HttpSessionBindingListener</code>, the container calls
1192     * <code>valueUnbound()</code> on the object.
1193     *
1194     * @param name Name of the object to remove from this session.
1195     * @param notify Should we notify interested listeners that this
1196     * attribute is being removed?
1197     *
1198     * @exception IllegalStateException if this method is called on an
1199     * invalidated session
1200     */

1201    public void removeAttribute(String JavaDoc name, boolean notify) {
1202
1203        // Validate our current state
1204
if (!isValidInternal())
1205            throw new IllegalStateException JavaDoc
1206                (sm.getString("standardSession.removeAttribute.ise"));
1207
1208        removeAttributeInternal(name, notify);
1209
1210    }
1211
1212
1213    /**
1214     * Remove the object bound with the specified name from this session. If
1215     * the session does not have an object bound with this name, this method
1216     * does nothing.
1217     * <p>
1218     * After this method executes, and if the object implements
1219     * <code>HttpSessionBindingListener</code>, the container calls
1220     * <code>valueUnbound()</code> on the object.
1221     *
1222     * @param name Name of the object to remove from this session.
1223     *
1224     * @exception IllegalStateException if this method is called on an
1225     * invalidated session
1226     *
1227     * @deprecated As of Version 2.2, this method is replaced by
1228     * <code>removeAttribute()</code>
1229     */

1230    public void removeValue(String JavaDoc name) {
1231
1232        removeAttribute(name);
1233
1234    }
1235
1236
1237    /**
1238     * Bind an object to this session, using the specified name. If an object
1239     * of the same name is already bound to this session, the object is
1240     * replaced.
1241     * <p>
1242     * After this method executes, and if the object implements
1243     * <code>HttpSessionBindingListener</code>, the container calls
1244     * <code>valueBound()</code> on the object.
1245     *
1246     * @param name Name to which the object is bound, cannot be null
1247     * @param value Object to be bound, cannot be null
1248     *
1249     * @exception IllegalArgumentException if an attempt is made to add a
1250     * non-serializable object in an environment marked distributable.
1251     * @exception IllegalStateException if this method is called on an
1252     * invalidated session
1253     */

1254    public void setAttribute(String JavaDoc name, Object JavaDoc value) {
1255        setAttribute(name,value,true);
1256    }
1257    /**
1258     * Bind an object to this session, using the specified name. If an object
1259     * of the same name is already bound to this session, the object is
1260     * replaced.
1261     * <p>
1262     * After this method executes, and if the object implements
1263     * <code>HttpSessionBindingListener</code>, the container calls
1264     * <code>valueBound()</code> on the object.
1265     *
1266     * @param name Name to which the object is bound, cannot be null
1267     * @param value Object to be bound, cannot be null
1268     * @param notify whether to notify session listeners
1269     * @exception IllegalArgumentException if an attempt is made to add a
1270     * non-serializable object in an environment marked distributable.
1271     * @exception IllegalStateException if this method is called on an
1272     * invalidated session
1273     */

1274
1275    public void setAttribute(String JavaDoc name, Object JavaDoc value, boolean notify) {
1276
1277        // Name cannot be null
1278
if (name == null)
1279            throw new IllegalArgumentException JavaDoc
1280                (sm.getString("standardSession.setAttribute.namenull"));
1281
1282        // Null value is the same as removeAttribute()
1283
if (value == null) {
1284            removeAttribute(name);
1285            return;
1286        }
1287
1288        // Validate our current state
1289
if (!isValidInternal())
1290            throw new IllegalStateException JavaDoc
1291                (sm.getString("standardSession.setAttribute.ise"));
1292        if ((manager != null) && manager.getDistributable() &&
1293          !(value instanceof Serializable JavaDoc))
1294            throw new IllegalArgumentException JavaDoc
1295                (sm.getString("standardSession.setAttribute.iae"));
1296
1297        // Construct an event with the new value
1298
HttpSessionBindingEvent JavaDoc event = null;
1299
1300        // Call the valueBound() method if necessary
1301
if (notify && value instanceof HttpSessionBindingListener JavaDoc) {
1302            // Don't call any notification if replacing with the same value
1303
Object JavaDoc oldValue = attributes.get(name);
1304            if (value != oldValue) {
1305                event = new HttpSessionBindingEvent JavaDoc(getSession(), name, value);
1306                try {
1307                    ((HttpSessionBindingListener JavaDoc) value).valueBound(event);
1308                } catch (Throwable JavaDoc t){
1309                    manager.getContainer().getLogger().error
1310                    (sm.getString("standardSession.bindingEvent"), t);
1311                }
1312            }
1313        }
1314
1315        // Replace or add this attribute
1316
Object JavaDoc unbound = attributes.put(name, value);
1317
1318        // Call the valueUnbound() method if necessary
1319
if (notify && (unbound != null) && (unbound != value) &&
1320            (unbound instanceof HttpSessionBindingListener JavaDoc)) {
1321            try {
1322                ((HttpSessionBindingListener JavaDoc) unbound).valueUnbound
1323                    (new HttpSessionBindingEvent JavaDoc(getSession(), name));
1324            } catch (Throwable JavaDoc t) {
1325                manager.getContainer().getLogger().error
1326                    (sm.getString("standardSession.bindingEvent"), t);
1327            }
1328        }
1329        
1330        if ( !notify ) return;
1331        
1332        // Notify interested application event listeners
1333
Context JavaDoc context = (Context JavaDoc) manager.getContainer();
1334        Object JavaDoc listeners[] = context.getApplicationEventListeners();
1335        if (listeners == null)
1336            return;
1337        for (int i = 0; i < listeners.length; i++) {
1338            if (!(listeners[i] instanceof HttpSessionAttributeListener JavaDoc))
1339                continue;
1340            HttpSessionAttributeListener JavaDoc listener =
1341                (HttpSessionAttributeListener JavaDoc) listeners[i];
1342            try {
1343                if (unbound != null) {
1344                    fireContainerEvent(context,
1345                                       "beforeSessionAttributeReplaced",
1346                                       listener);
1347                    if (event == null) {
1348                        event = new HttpSessionBindingEvent JavaDoc
1349                            (getSession(), name, unbound);
1350                    }
1351                    listener.attributeReplaced(event);
1352                    fireContainerEvent(context,
1353                                       "afterSessionAttributeReplaced",
1354                                       listener);
1355                } else {
1356                    fireContainerEvent(context,
1357                                       "beforeSessionAttributeAdded",
1358                                       listener);
1359                    if (event == null) {
1360                        event = new HttpSessionBindingEvent JavaDoc
1361                            (getSession(), name, value);
1362                    }
1363                    listener.attributeAdded(event);
1364                    fireContainerEvent(context,
1365                                       "afterSessionAttributeAdded",
1366                                       listener);
1367                }
1368            } catch (Throwable JavaDoc t) {
1369                try {
1370                    if (unbound != null) {
1371                        fireContainerEvent(context,
1372                                           "afterSessionAttributeReplaced",
1373                                           listener);
1374                    } else {
1375                        fireContainerEvent(context,
1376                                           "afterSessionAttributeAdded",
1377                                           listener);
1378                    }
1379                } catch (Exception JavaDoc e) {
1380                    ;
1381                }
1382                manager.getContainer().getLogger().error
1383                    (sm.getString("standardSession.attributeEvent"), t);
1384            }
1385        }
1386
1387    }
1388
1389
1390    // ------------------------------------------ HttpSession Protected Methods
1391

1392
1393    /**
1394     * Return the <code>isValid</code> flag for this session without any expiration
1395     * check.
1396     */

1397    protected boolean isValidInternal() {
1398        return (this.isValid || this.expiring);
1399    }
1400
1401
1402    /**
1403     * Read a serialized version of this session object from the specified
1404     * object input stream.
1405     * <p>
1406     * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager
1407     * is not restored by this method, and must be set explicitly.
1408     *
1409     * @param stream The input stream to read from
1410     *
1411     * @exception ClassNotFoundException if an unknown class is specified
1412     * @exception IOException if an input/output error occurs
1413     */

1414    protected void readObject(ObjectInputStream JavaDoc stream)
1415        throws ClassNotFoundException JavaDoc, IOException JavaDoc {
1416
1417        // Deserialize the scalar instance variables (except Manager)
1418
authType = null; // Transient only
1419
creationTime = ((Long JavaDoc) stream.readObject()).longValue();
1420        lastAccessedTime = ((Long JavaDoc) stream.readObject()).longValue();
1421        maxInactiveInterval = ((Integer JavaDoc) stream.readObject()).intValue();
1422        isNew = ((Boolean JavaDoc) stream.readObject()).booleanValue();
1423        isValid = ((Boolean JavaDoc) stream.readObject()).booleanValue();
1424        thisAccessedTime = ((Long JavaDoc) stream.readObject()).longValue();
1425        principal = null; // Transient only
1426
// setId((String) stream.readObject());
1427
id = (String JavaDoc) stream.readObject();
1428        if (manager.getContainer().getLogger().isDebugEnabled())
1429            manager.getContainer().getLogger().debug
1430                ("readObject() loading session " + id);
1431
1432        // Deserialize the attribute count and attribute values
1433
if (attributes == null)
1434            attributes = new Hashtable JavaDoc();
1435        int n = ((Integer JavaDoc) stream.readObject()).intValue();
1436        boolean isValidSave = isValid;
1437        isValid = true;
1438        for (int i = 0; i < n; i++) {
1439            String JavaDoc name = (String JavaDoc) stream.readObject();
1440            Object JavaDoc value = (Object JavaDoc) stream.readObject();
1441            if ((value instanceof String JavaDoc) && (value.equals(NOT_SERIALIZED)))
1442                continue;
1443            if (manager.getContainer().getLogger().isDebugEnabled())
1444                manager.getContainer().getLogger().debug(" loading attribute '" + name +
1445                    "' with value '" + value + "'");
1446            attributes.put(name, value);
1447        }
1448        isValid = isValidSave;
1449
1450        if (listeners == null) {
1451            listeners = new ArrayList JavaDoc();
1452        }
1453
1454        if (notes == null) {
1455            notes = new Hashtable JavaDoc();
1456        }
1457    }
1458
1459
1460    /**
1461     * Write a serialized version of this session object to the specified
1462     * object output stream.
1463     * <p>
1464     * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored
1465     * in the serialized representation of this Session. After calling
1466     * <code>readObject()</code>, you must set the associated Manager
1467     * explicitly.
1468     * <p>
1469     * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable
1470     * will be unbound from the session, with appropriate actions if it
1471     * implements HttpSessionBindingListener. If you do not want any such
1472     * attributes, be sure the <code>distributable</code> property of the
1473     * associated Manager is set to <code>true</code>.
1474     *
1475     * @param stream The output stream to write to
1476     *
1477     * @exception IOException if an input/output error occurs
1478     */

1479    protected void writeObject(ObjectOutputStream JavaDoc stream) throws IOException JavaDoc {
1480
1481        // Write the scalar instance variables (except Manager)
1482
stream.writeObject(new Long JavaDoc(creationTime));
1483        stream.writeObject(new Long JavaDoc(lastAccessedTime));
1484        stream.writeObject(new Integer JavaDoc(maxInactiveInterval));
1485        stream.writeObject(new Boolean JavaDoc(isNew));
1486        stream.writeObject(new Boolean JavaDoc(isValid));
1487        stream.writeObject(new Long JavaDoc(thisAccessedTime));
1488        stream.writeObject(id);
1489        if (manager.getContainer().getLogger().isDebugEnabled())
1490            manager.getContainer().getLogger().debug
1491                ("writeObject() storing session " + id);
1492
1493        // Accumulate the names of serializable and non-serializable attributes
1494
String JavaDoc keys[] = keys();
1495        ArrayList JavaDoc saveNames = new ArrayList JavaDoc();
1496        ArrayList JavaDoc saveValues = new ArrayList JavaDoc();
1497        for (int i = 0; i < keys.length; i++) {
1498            Object JavaDoc value = attributes.get(keys[i]);
1499            if (value == null)
1500                continue;
1501            else if ( (value instanceof Serializable JavaDoc)
1502                    && (!exclude(keys[i]) )) {
1503                saveNames.add(keys[i]);
1504                saveValues.add(value);
1505            } else {
1506                removeAttributeInternal(keys[i], true);
1507            }
1508        }
1509
1510        // Serialize the attribute count and the Serializable attributes
1511
int n = saveNames.size();
1512        stream.writeObject(new Integer JavaDoc(n));
1513        for (int i = 0; i < n; i++) {
1514            stream.writeObject((String JavaDoc) saveNames.get(i));
1515            try {
1516                stream.writeObject(saveValues.get(i));
1517                if (manager.getContainer().getLogger().isDebugEnabled())
1518                    manager.getContainer().getLogger().debug
1519                        (" storing attribute '" + saveNames.get(i) +
1520                        "' with value '" + saveValues.get(i) + "'");
1521            } catch (NotSerializableException JavaDoc e) {
1522                manager.getContainer().getLogger().warn
1523                    (sm.getString("standardSession.notSerializable",
1524                     saveNames.get(i), id), e);
1525                stream.writeObject(NOT_SERIALIZED);
1526                if (manager.getContainer().getLogger().isDebugEnabled())
1527                    manager.getContainer().getLogger().debug
1528                       (" storing attribute '" + saveNames.get(i) +
1529                        "' with value NOT_SERIALIZED");
1530            }
1531        }
1532
1533    }
1534
1535
1536    /**
1537     * Exclude attribute that cannot be serialized.
1538     * @param name the attribute's name
1539     */

1540    protected boolean exclude(String JavaDoc name){
1541
1542        for (int i = 0; i < excludedAttributes.length; i++) {
1543            if (name.equalsIgnoreCase(excludedAttributes[i]))
1544                return true;
1545        }
1546
1547        return false;
1548    }
1549
1550
1551    // ------------------------------------------------------ Protected Methods
1552

1553
1554    /**
1555     * Fire container events if the Context implementation is the
1556     * <code>org.apache.catalina.core.StandardContext</code>.
1557     *
1558     * @param context Context for which to fire events
1559     * @param type Event type
1560     * @param data Event data
1561     *
1562     * @exception Exception occurred during event firing
1563     */

1564    protected void fireContainerEvent(Context JavaDoc context,
1565                                    String JavaDoc type, Object JavaDoc data)
1566        throws Exception JavaDoc {
1567
1568        if (!"org.apache.catalina.core.StandardContext".equals
1569            (context.getClass().getName())) {
1570            return; // Container events are not supported
1571
}
1572        // NOTE: Race condition is harmless, so do not synchronize
1573
if (containerEventMethod == null) {
1574            containerEventMethod =
1575                context.getClass().getMethod("fireContainerEvent",
1576                                             containerEventTypes);
1577        }
1578        Object JavaDoc containerEventParams[] = new Object JavaDoc[2];
1579        containerEventParams[0] = type;
1580        containerEventParams[1] = data;
1581        containerEventMethod.invoke(context, containerEventParams);
1582
1583    }
1584                                      
1585
1586
1587    /**
1588     * Notify all session event listeners that a particular event has
1589     * occurred for this Session. The default implementation performs
1590     * this notification synchronously using the calling thread.
1591     *
1592     * @param type Event type
1593     * @param data Event data
1594     */

1595    public void fireSessionEvent(String JavaDoc type, Object JavaDoc data) {
1596        if (listeners.size() < 1)
1597            return;
1598        SessionEvent JavaDoc event = new SessionEvent JavaDoc(this, type, data);
1599        SessionListener JavaDoc list[] = new SessionListener JavaDoc[0];
1600        synchronized (listeners) {
1601            list = (SessionListener JavaDoc[]) listeners.toArray(list);
1602        }
1603
1604        for (int i = 0; i < list.length; i++){
1605            ((SessionListener JavaDoc) list[i]).sessionEvent(event);
1606        }
1607
1608    }
1609
1610
1611    /**
1612     * Return the names of all currently defined session attributes
1613     * as an array of Strings. If there are no defined attributes, a
1614     * zero-length array is returned.
1615     */

1616    protected String JavaDoc[] keys() {
1617
1618        return ((String JavaDoc[]) attributes.keySet().toArray(EMPTY_ARRAY));
1619
1620    }
1621
1622
1623    /**
1624     * Remove the object bound with the specified name from this session. If
1625     * the session does not have an object bound with this name, this method
1626     * does nothing.
1627     * <p>
1628     * After this method executes, and if the object implements
1629     * <code>HttpSessionBindingListener</code>, the container calls
1630     * <code>valueUnbound()</code> on the object.
1631     *
1632     * @param name Name of the object to remove from this session.
1633     * @param notify Should we notify interested listeners that this
1634     * attribute is being removed?
1635     */

1636    protected void removeAttributeInternal(String JavaDoc name, boolean notify) {
1637
1638        // Remove this attribute from our collection
1639
Object JavaDoc value = attributes.remove(name);
1640
1641        // Do we need to do valueUnbound() and attributeRemoved() notification?
1642
if (!notify || (value == null)) {
1643            return;
1644        }
1645
1646        // Call the valueUnbound() method if necessary
1647
HttpSessionBindingEvent JavaDoc event = null;
1648        if (value instanceof HttpSessionBindingListener JavaDoc) {
1649            event = new HttpSessionBindingEvent JavaDoc(getSession(), name, value);
1650            ((HttpSessionBindingListener JavaDoc) value).valueUnbound(event);
1651        }
1652
1653        // Notify interested application event listeners
1654
Context JavaDoc context = (Context JavaDoc) manager.getContainer();
1655        Object JavaDoc listeners[] = context.getApplicationEventListeners();
1656        if (listeners == null)
1657            return;
1658        for (int i = 0; i < listeners.length; i++) {
1659            if (!(listeners[i] instanceof HttpSessionAttributeListener JavaDoc))
1660                continue;
1661            HttpSessionAttributeListener JavaDoc listener =
1662                (HttpSessionAttributeListener JavaDoc) listeners[i];
1663            try {
1664                fireContainerEvent(context,
1665                                   "beforeSessionAttributeRemoved",
1666                                   listener);
1667                if (event == null) {
1668                    event = new HttpSessionBindingEvent JavaDoc
1669                        (getSession(), name, value);
1670                }
1671                listener.attributeRemoved(event);
1672                fireContainerEvent(context,
1673                                   "afterSessionAttributeRemoved",
1674                                   listener);
1675            } catch (Throwable JavaDoc t) {
1676                try {
1677                    fireContainerEvent(context,
1678                                       "afterSessionAttributeRemoved",
1679                                       listener);
1680                } catch (Exception JavaDoc e) {
1681                    ;
1682                }
1683                manager.getContainer().getLogger().error
1684                    (sm.getString("standardSession.attributeEvent"), t);
1685            }
1686        }
1687
1688    }
1689
1690
1691}
1692
1693
1694// ------------------------------------------------------------ Protected Class
1695

1696
1697/**
1698 * This class is a dummy implementation of the <code>HttpSessionContext</code>
1699 * interface, to conform to the requirement that such an object be returned
1700 * when <code>HttpSession.getSessionContext()</code> is called.
1701 *
1702 * @author Craig R. McClanahan
1703 *
1704 * @deprecated As of Java Servlet API 2.1 with no replacement. The
1705 * interface will be removed in a future version of this API.
1706 */

1707
1708final class StandardSessionContext implements HttpSessionContext JavaDoc {
1709
1710
1711    protected HashMap JavaDoc dummy = new HashMap JavaDoc();
1712
1713    /**
1714     * Return the session identifiers of all sessions defined
1715     * within this context.
1716     *
1717     * @deprecated As of Java Servlet API 2.1 with no replacement.
1718     * This method must return an empty <code>Enumeration</code>
1719     * and will be removed in a future version of the API.
1720     */

1721    public Enumeration JavaDoc getIds() {
1722
1723        return (new Enumerator(dummy));
1724
1725    }
1726
1727
1728    /**
1729     * Return the <code>HttpSession</code> associated with the
1730     * specified session identifier.
1731     *
1732     * @param id Session identifier for which to look up a session
1733     *
1734     * @deprecated As of Java Servlet API 2.1 with no replacement.
1735     * This method must return null and will be removed in a
1736     * future version of the API.
1737     */

1738    public HttpSession JavaDoc getSession(String JavaDoc id) {
1739
1740        return (null);
1741
1742    }
1743
1744
1745
1746}
1747
Popular Tags