KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > server > session > SessionImpl


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.server.session;
31
32 import com.caucho.log.Log;
33 import com.caucho.server.cluster.ClusterObject;
34 import com.caucho.server.cluster.Store;
35 import com.caucho.server.security.AbstractAuthenticator;
36 import com.caucho.server.security.ServletAuthenticator;
37 import com.caucho.util.Alarm;
38 import com.caucho.util.CacheListener;
39 import com.caucho.util.L10N;
40 import com.caucho.vfs.IOExceptionWrapper;
41
42 import javax.servlet.ServletContext JavaDoc;
43 import javax.servlet.http.*;
44 import java.io.IOException JavaDoc;
45 import java.io.NotSerializableException JavaDoc;
46 import java.io.ObjectInputStream JavaDoc;
47 import java.io.ObjectOutputStream JavaDoc;
48 import java.io.Serializable JavaDoc;
49 import java.security.Principal JavaDoc;
50 import java.util.*;
51 import java.util.logging.Level JavaDoc;
52 import java.util.logging.Logger JavaDoc;
53
54 /**
55  * Implements a HTTP session.
56  */

57 public class SessionImpl implements HttpSession, CacheListener {
58   static protected final Logger JavaDoc log = Log.open(SessionImpl.class);
59   static final L10N L = new L10N(SessionImpl.class);
60
61   static final String JavaDoc LOGIN = "caucho.login";
62
63   // the session's identifier
64
private String JavaDoc _id;
65
66   // the owning session manager
67
protected SessionManager _manager;
68   // the session store
69

70   // Map containing the actual values.
71
protected Map<String JavaDoc,Object JavaDoc> _values;
72
73   // time the session was created
74
private long _creationTime;
75   // time the session was last accessed
76
long _accessTime;
77   // maximum time the session may stay alive.
78
long _maxInactiveInterval;
79   // true if the session is new
80
private boolean _isNew = true;
81   // true if the session is still valid, i.e. not invalidated
82
boolean _isValid = true;
83   // true if the session is closing
84
boolean _isClosing = false;
85   // true if the session is being closed from an invalidation
86
boolean _isInvalidating = false;
87   //To protect for threading
88
private int _useCount;
89
90   private ClusterObject _clusterObject;
91   // The logged-in user
92
private Principal JavaDoc _user;
93
94   // index of the owning srun
95
private int _srunIndex = -1;
96
97   /**
98    * Create a new session object.
99    *
100    * @param manager the owning session manager.
101    * @param id the session identifier.
102    * @param creationTime the time in milliseconds when the session was created.
103    */

104   public SessionImpl(SessionManager manager, String JavaDoc id, long creationTime)
105   {
106     _manager = manager;
107
108     _creationTime = creationTime;
109     _accessTime = creationTime;
110     _maxInactiveInterval = manager.getSessionTimeout();
111
112     _id = id;
113
114     // Finds the owning JVM from the session encoding
115
char ch = id.charAt(0);
116     int length = manager.getSrunLength();
117
118     if (length > 0)
119       _srunIndex = SessionManager.decode(ch) % length;
120     else
121       _srunIndex = 0;
122
123     _values = createValueMap();
124
125     if (log.isLoggable(Level.FINE))
126       log.fine("create session " + id);
127   }
128
129   /**
130    * Returns the time the session was created.
131    */

132   public long getCreationTime()
133   {
134     // this test forced by TCK
135
if (! _isValid)
136       throw new IllegalStateException JavaDoc(L.l("Can't call getCreationTime() when session is no longer valid."));
137
138     return _creationTime;
139   }
140
141   /**
142    * Returns the session identifier.
143    */

144   public String JavaDoc getId()
145   {
146     return _id;
147   }
148
149   /**
150    * Returns the index of the owning srun for distributed sessions.
151    */

152   int getSrunIndex()
153   {
154     return _srunIndex;
155   }
156
157   /**
158    * Sets the cluster object.
159    */

160   void setClusterObject(ClusterObject clusterObject)
161   {
162     _clusterObject = clusterObject;
163     if (clusterObject != null)
164       clusterObject.update();
165   }
166
167   /**
168    * Returns the last access time.
169    */

170   public long getLastAccessedTime()
171   {
172     // this test forced by TCK
173
if (! _isValid)
174       throw new IllegalStateException JavaDoc(L.l("Can't call getLastAccessedTime() when session is no longer valid."));
175
176     return _accessTime;
177   }
178
179   /**
180    * Returns the time the session is allowed to be alive.
181    *
182    * @return time allowed to live in seconds
183    */

184   public int getMaxInactiveInterval()
185   {
186     if (Long.MAX_VALUE / 2 <= _maxInactiveInterval)
187       return -1;
188     else
189       return (int) (_maxInactiveInterval / 1000);
190   }
191
192   /**
193    * Sets the maximum time a session is allowed to be alive.
194    *
195    * @param value time allowed to live in seconds
196    */

197   public void setMaxInactiveInterval(int value)
198   {
199     if (value < 0)
200       _maxInactiveInterval = Long.MAX_VALUE / 2;
201     else
202       _maxInactiveInterval = ((long) value) * 1000;
203
204     if (_clusterObject != null)
205       _clusterObject.setExpireInterval(_maxInactiveInterval);
206   }
207
208   /**
209    * Returns the session context.
210    *
211    * @deprecated
212    */

213   public HttpSessionContext getSessionContext()
214   {
215     return null;
216   }
217
218   /**
219    * Returns the servlet context.
220    */

221   public ServletContext JavaDoc getServletContext()
222   {
223     return _manager.getWebApp();
224   }
225
226   /**
227    * Returns the session manager.
228    */

229   public SessionManager getManager()
230   {
231     return _manager;
232   }
233
234   /**
235    * Returns the authenticator
236    */

237   public ServletAuthenticator getAuthenticator()
238   {
239     return _manager.getWebApp().getAuthenticator();
240   }
241
242   /**
243    * Returns the user
244    */

245   public Principal JavaDoc getUser()
246   {
247     if (_user != null)
248       return _user;
249
250     if (_isValid) {
251       _user = (Principal JavaDoc) getAttribute(LOGIN);
252     }
253
254     return _user;
255   }
256
257   /**
258    * Sets the user
259    */

260   public void setUser(Principal JavaDoc user)
261   {
262     _user = user;
263
264     setAttribute(LOGIN, user);
265   }
266
267   /**
268    * Returns the named attribute from the session.
269    */

270   public Object JavaDoc getAttribute(String JavaDoc name)
271   {
272     if (! _isValid)
273       throw new IllegalStateException JavaDoc(L.l("Can't call getAttribute() when session is no longer valid."));
274
275     synchronized (_values) {
276       return _values.get(name);
277     }
278   }
279
280   /**
281    * Sets a session attribute. If the value is a listener, notify it
282    * of the change. If the value has changed mark the session as changed
283    * for persistent sessions.
284    *
285    * @param name the name of the attribute
286    * @param value the value of the attribute
287    */

288   public void setAttribute(String JavaDoc name, Object JavaDoc value)
289   {
290     if (! _isValid)
291       throw new IllegalStateException JavaDoc(L.l("Can't call setAttribute(String, Object) when session is no longer valid."));
292
293     Object JavaDoc oldValue;
294
295     if (value != null &&
296     ! (value instanceof Serializable JavaDoc) &&
297     log.isLoggable(Level.FINE)) {
298       log.fine(L.l("session attribute '{0}' value is non-serializable type '{1}'",
299            name, value.getClass().getName()));
300     }
301
302     synchronized (_values) {
303       if (value != null)
304         oldValue = _values.put(name, value);
305       else
306         oldValue = _values.remove(name);
307     }
308
309     // server/017p
310
if (_clusterObject != null) // && value != oldValue)
311
_clusterObject.change();
312
313     if (oldValue instanceof HttpSessionBindingListener) {
314       HttpSessionBindingListener listener;
315       listener = (HttpSessionBindingListener) oldValue;
316
317       listener.valueUnbound(new HttpSessionBindingEvent(SessionImpl.this,
318                             name, oldValue));
319     }
320
321     if (value instanceof HttpSessionBindingListener) {
322       HttpSessionBindingListener listener;
323       listener = (HttpSessionBindingListener) value;
324
325       listener.valueBound(new HttpSessionBindingEvent(SessionImpl.this,
326                               name, value));
327     }
328
329     // Notify the attribute listeners
330
ArrayList listeners = _manager.getAttributeListeners();
331     if (listeners != null) {
332       HttpSessionBindingEvent event;
333
334       if (oldValue != null)
335         event = new HttpSessionBindingEvent(this, name, oldValue);
336       else
337         event = new HttpSessionBindingEvent(this, name, value);
338
339       for (int i = 0; i < listeners.size(); i++) {
340         HttpSessionAttributeListener listener;
341         listener = (HttpSessionAttributeListener) listeners.get(i);
342
343         if (oldValue != null)
344           listener.attributeReplaced(event);
345         else
346           listener.attributeAdded(event);
347       }
348     }
349   }
350
351   /**
352    * Create the map used to store values.
353    */

354   protected Map<String JavaDoc,Object JavaDoc> createValueMap()
355   {
356     return new Hashtable<String JavaDoc,Object JavaDoc>(8);
357   }
358
359   /**
360    * Remove a session attribute. If the value is a listener, notify it
361    * of the change.
362    *
363    * @param name the name of the attribute to remove
364    */

365   public void removeAttribute(String JavaDoc name)
366   {
367     if (! _isValid)
368       throw new IllegalStateException JavaDoc(L.l("Can't call removeAttribute(String) when session is no longer valid."));
369
370     Object JavaDoc oldValue = _values.remove(name);
371
372     if (_clusterObject != null && oldValue != null)
373       _clusterObject.change();
374
375     notifyValueUnbound(name, oldValue);
376   }
377
378   /**
379    * Return an enumeration of all the sessions' attribute names.
380    *
381    * @return enumeration of the attribute names.
382    */

383   public Enumeration getAttributeNames()
384   {
385     synchronized (_values) {
386       if (! _isValid)
387     throw new IllegalStateException JavaDoc(L.l("Can't call getAttributeNames() when session is no longer valid."));
388
389       return Collections.enumeration(_values.keySet());
390     }
391   }
392
393   /**
394    * @deprecated
395    */

396   public Object JavaDoc getValue(String JavaDoc name)
397   {
398     return getAttribute(name);
399   }
400
401   /**
402    * @deprecated
403    */

404   public void putValue(String JavaDoc name, Object JavaDoc value)
405   {
406     setAttribute(name, value);
407   }
408
409   /**
410    * @deprecated
411    */

412   public void removeValue(String JavaDoc name)
413   {
414     removeAttribute(name);
415   }
416
417   /**
418    * @deprecated
419    */

420   public String JavaDoc []getValueNames()
421   {
422     synchronized (_values) {
423       if (! _isValid)
424     throw new IllegalStateException JavaDoc(L.l("Can't call getValueNames() when session is no longer valid."));
425
426       if (_values == null)
427     return new String JavaDoc[0];
428
429       String JavaDoc []s = new String JavaDoc[_values.size()];
430
431       Enumeration e = getAttributeNames();
432       int count = 0;
433       while (e.hasMoreElements())
434     s[count++] = (String JavaDoc) e.nextElement();
435
436       return s;
437     }
438   }
439
440   /**
441    * Returns true if the session is new.
442    */

443   public boolean isNew()
444   {
445     if (! _isValid)
446       throw new IllegalStateException JavaDoc(L.l("Can't call isNew() when session is no longer valid."));
447
448     return _isNew;
449   }
450
451   /**
452    * Returns true if the session is valid.
453    */

454   public boolean isValid()
455   {
456     return _isValid;
457   }
458
459   /**
460    * Set the session valid or invalid.
461    */

462   void setValid(boolean isValid)
463   {
464     _isValid = isValid;
465   }
466
467   boolean isClosing()
468   {
469     return _isClosing;
470   }
471
472   /**
473    * Callback when the session is removed from the session cache, generally
474    * because the session cache is full.
475    */

476   public void removeEvent()
477   {
478     synchronized (this) {
479       if (_isInvalidating || _useCount <= 0)
480     _isClosing = true;
481     }
482
483     //System.out.println("REMOVE: " + this);
484
if (! _isClosing) {
485       log.warning(L.l("session {0} LRU while in use. Consider increasing session-count.",
486              _id));
487     }
488     
489     boolean isValid = _isValid;
490
491     if (log.isLoggable(Level.FINE))
492       log.fine("remove session " + _id);
493
494     long now = Alarm.getCurrentTime();
495
496     Store store = _manager.getSessionStore();
497
498     // server/015k
499
if (_isInvalidating ||
500     store == null || _accessTime + getMaxInactiveInterval() < now)
501       notifyDestroy();
502
503     invalidateLocal();
504   }
505
506   private void notifyDestroy()
507   {
508     ArrayList listeners = _manager.getListeners();
509
510     if (listeners != null) {
511       HttpSessionEvent event = new HttpSessionEvent(this);
512
513       for (int i = listeners.size() - 1; i >= 0; i--) {
514         HttpSessionListener listener;
515         listener = (HttpSessionListener) listeners.get(i);
516
517         listener.sessionDestroyed(event);
518       }
519     }
520   }
521
522   /**
523    * Invalidates the session.
524    */

525   public void invalidate()
526   {
527     _isInvalidating = true;
528
529     invalidate(false);
530   }
531
532   /**
533    * Invalidates the session.
534    */

535   public void invalidate(boolean isLRU)
536   {
537     if (log.isLoggable(Level.FINE)) {
538
539       if (log.isLoggable(Level.FINEST))
540         log.log(Level.FINEST, "invalidate session " + _id, new Exception JavaDoc());
541       else
542         log.fine("invalidate session " + _id);
543     }
544
545     if (! _isValid)
546       throw new IllegalStateException JavaDoc(L.l("Can't call invalidate() when session is no longer valid."));
547
548     ServletAuthenticator auth = getAuthenticator();
549     if (! isLRU
550     || ! (auth instanceof AbstractAuthenticator)
551     || ((AbstractAuthenticator) auth).getLogoutOnSessionTimeout()) {
552       // server/12i1
553
logout(isLRU ? this : null);
554     }
555
556     /*
557     boolean invalidateAfterListener = _manager.isInvalidateAfterListener();
558     if (! invalidateAfterListener)
559       _isValid = false;
560     */

561
562     try {
563       // server/017s
564
/*
565       if (_clusterObject != null) {
566     _clusterObject.remove();
567     notifyDestroy();
568       }
569       */

570
571       _manager.removeSession(this);
572
573       invalidateImpl(isLRU);
574
575       _isValid = false;
576     } finally {
577       _isValid = false;
578     }
579   }
580
581   /**
582    * Logs out the user
583    */

584   public void logout()
585   {
586     // server/12bw
587
logout(null);
588   }
589
590   /**
591    * Logs out the user
592    *
593    * @param session the session in case of timeout and single-signon
594    */

595   public void logout(SessionImpl timeoutSession)
596   {
597     if (_user != null) {
598       if (_isValid)
599         removeAttribute(LOGIN);
600       Principal JavaDoc user = _user;
601       _user = null;
602
603       try {
604     ServletAuthenticator auth = getAuthenticator();
605
606     if (auth != null)
607       auth.logout(_manager.getWebApp(), timeoutSession, _id, user);
608       } catch (Exception JavaDoc e) {
609         log.log(Level.WARNING, e.toString(), e);
610       }
611     }
612   }
613
614   /**
615    * Invalidate the session, removing it from the manager,
616    * unbinding the values, and removing it from the store.
617    */

618   void invalidateImpl(boolean isLRU)
619   {
620     boolean invalidateAfterListener = _manager.isInvalidateAfterListener();
621     if (! invalidateAfterListener)
622       _isValid = false;
623
624     try {
625       ClusterObject clusterObject = _clusterObject;
626       // _clusterObject = null;
627

628       if (clusterObject != null && _isInvalidating)
629     clusterObject.remove();
630     } catch (Throwable JavaDoc e) {
631       log.log(Level.FINE, e.toString(), e);
632     }
633
634     invalidateLocal();
635   }
636
637   /**
638    * unbinds the session and saves if necessary.
639    */

640   private void invalidateLocal()
641   {
642     ClusterObject clusterObject = _clusterObject;
643     if (_isValid && ! _isInvalidating && clusterObject != null) {
644       if (_manager.isSaveOnlyOnShutdown()) {
645     clusterObject.update();
646
647     try {
648       clusterObject.store(this);
649     } catch (Throwable JavaDoc e) {
650       log.log(Level.WARNING, "Can't serialize session", e);
651     }
652       }
653     }
654
655     unbind(); // we're invalidating, not passivating
656
}
657
658   /**
659    * Creates a new session.
660    */

661   void create(long now)
662   {
663     if (log.isLoggable(Level.FINE)) {
664       log.fine("create session " + _id);
665     }
666
667     // e.g. server 'C' when 'A' and 'B' have no record of session
668
if (_isValid)
669       unbind();
670
671     _isValid = true;
672     _isNew = true;
673     _accessTime = now;
674     _creationTime = now;
675
676     if (_clusterObject != null)
677       _clusterObject.setValid();
678   }
679
680   /**
681    * Returns true if the session is in use.
682    */

683   public boolean inUse()
684   {
685     return _useCount > 0;
686   }
687
688   /**
689    * Set true if the session is in use.
690    */

691   boolean addUse()
692   {
693     synchronized (this) {
694       if (_isClosing)
695     return false;
696       
697       _useCount++;
698
699       return true;
700     }
701   }
702
703   /**
704    * Set true if the session is in use.
705    */

706   void endUse()
707   {
708     synchronized (this) {
709       _useCount--;
710     }
711   }
712
713   /**
714    * Clears the session when reading a bad saved session.
715    */

716   void reset(long now)
717   {
718     if (log.isLoggable(Level.FINE))
719       log.fine("reset session " + _id);
720
721     unbind();
722     _isValid = true;
723     _isNew = true;
724     _accessTime = now;
725     _creationTime = now;
726   }
727
728   /**
729    * Loads the session.
730    */

731   public boolean load()
732   {
733     boolean isValid;
734
735     // server/01k0
736
if (_useCount > 1)
737       return true;
738
739     ClusterObject clusterObject = _clusterObject;
740     if (clusterObject != null)
741       isValid = clusterObject.load(this);
742     else
743       isValid = true;
744
745     return isValid;
746   }
747
748   /**
749    * Passivates the session.
750    */

751   public void passivate()
752   {
753     unbind();
754   }
755
756   /**
757    * Cleans up the session.
758    */

759   public void unbind()
760   {
761     if (_values.size() == 0)
762       return;
763
764     ClusterObject clusterObject = _clusterObject;
765
766     ArrayList<String JavaDoc> names = new ArrayList<String JavaDoc>();
767     ArrayList<Object JavaDoc> values = new ArrayList<Object JavaDoc>();
768     
769     synchronized (this) {
770       //System.out.println("UNBIND: " + this + " " + clusterObject + " " + System.identityHashCode(this));
771

772       /*
773       if (_useCount > 0)
774     Thread.dumpStack();
775       */

776
777       Iterator<Map.Entry<String JavaDoc,Object JavaDoc>> iter = _values.entrySet().iterator();
778       while (iter.hasNext()) {
779     Map.Entry<String JavaDoc,Object JavaDoc> entry = iter.next();
780
781     names.add(entry.getKey());
782     values.add(entry.getValue());
783       }
784
785       _values.clear();
786
787       if (clusterObject != null)
788     clusterObject.update();
789     }
790
791     for (int i = 0; i < names.size(); i++) {
792       String JavaDoc name = names.get(i);
793       Object JavaDoc value = values.get(i);
794
795       notifyValueUnbound(name, value);
796     }
797   }
798
799   /**
800    * Notify any value unbound listeners.
801    */

802   private void notifyValueUnbound(String JavaDoc name, Object JavaDoc oldValue)
803   {
804     if (oldValue == null)
805       return;
806
807     if (oldValue instanceof HttpSessionBindingListener) {
808       HttpSessionBindingListener listener;
809       listener = (HttpSessionBindingListener) oldValue;
810
811       listener.valueUnbound(new HttpSessionBindingEvent(this,
812                             name,
813                             oldValue));
814     }
815
816     // Notify the attributes listeners
817
ArrayList listeners = _manager.getAttributeListeners();
818     if (listeners != null) {
819       HttpSessionBindingEvent event;
820
821       event = new HttpSessionBindingEvent(this, name, oldValue);
822
823       for (int i = 0; i < listeners.size(); i++) {
824         HttpSessionAttributeListener listener;
825         listener = (HttpSessionAttributeListener) listeners.get(i);
826
827         listener.attributeRemoved(event);
828       }
829     }
830   }
831
832   /*
833    * Set the current access time to now.
834    */

835   void setAccess(long now)
836   {
837     _isNew = false;
838
839     if (_clusterObject != null)
840       _clusterObject.access();
841
842     _accessTime = now;
843   }
844
845   /**
846    * Cleaning up session stuff at the end of a request.
847    *
848    * <p>If the session data has changed and we have persistent sessions,
849    * save the session. However, if save-on-shutdown is true, only save
850    * on a server shutdown.
851    */

852   public void finish()
853   {
854     int count;
855
856     _accessTime = Alarm.getCurrentTime();
857
858     synchronized (this) {
859       if (_useCount > 1) {
860     _useCount--;
861     return;
862       }
863     }
864
865     try {
866       saveAfterRequest();
867     } finally {
868       synchronized (this) {
869     _useCount--;
870       }
871     }
872   }
873
874   /**
875    * Save changes before any flush.
876    */

877   public final void saveBeforeFlush()
878   {
879     if (_manager == null || ! _manager.isSaveBeforeFlush())
880       return;
881
882     save();
883   }
884
885   /**
886    * Flush changes before the headers.
887    */

888   public final void saveBeforeHeaders()
889   {
890     if (_manager == null || ! _manager.isSaveBeforeHeaders())
891       return;
892
893     save();
894   }
895
896   /**
897    * Flush changes after a request completes.
898    */

899   public final void saveAfterRequest()
900   {
901     if (_manager == null || ! _manager.isSaveAfterRequest())
902       return;
903
904     save();
905   }
906
907   /**
908    * Saves changes to the session.
909    */

910   public final void save()
911   {
912     try {
913       ClusterObject clusterObject = _clusterObject;
914       if (clusterObject != null) {
915     clusterObject.store(this);
916       }
917     } catch (Throwable JavaDoc e) {
918       log.log(Level.WARNING, "Can't serialize session", e);
919     }
920   }
921
922   /**
923    * Store on shutdown.
924    */

925   void saveOnShutdown()
926   {
927     try {
928       ClusterObject clusterObject = _clusterObject;
929
930       if (clusterObject != null) {
931     clusterObject.change();
932     clusterObject.store(this);
933       }
934     } catch (Throwable JavaDoc e) {
935       log.log(Level.WARNING, "Can't serialize session", e);
936     }
937   }
938
939   /**
940    * Loads the object from the input stream.
941    */

942   public void load(ObjectInputStream JavaDoc in)
943     throws IOException JavaDoc
944   {
945     synchronized (_values) {
946       unbind();
947
948       try {
949     int size = in.readInt();
950
951     //System.out.println("LOAD: " + size + " " + this + " " + _clusterObject + System.identityHashCode(this));
952

953     for (int i = 0; i < size; i++) {
954       String JavaDoc key = in.readUTF();
955       Object JavaDoc value = in.readObject();
956
957       if (value != null)
958         setAttribute(key, value);
959     }
960       } catch (Exception JavaDoc e) {
961     e.printStackTrace();
962     
963     throw IOExceptionWrapper.create(e);
964       }
965
966       ArrayList<HttpSessionActivationListener> listeners;
967       listeners = _manager.getActivationListeners();
968       for (int i = 0; listeners != null && i < listeners.size(); i++) {
969     HttpSessionActivationListener listener = listeners.get(i);
970     HttpSessionEvent event = new HttpSessionEvent(this);
971
972     listener.sessionDidActivate(event);
973       }
974     }
975   }
976
977   /**
978    * Returns true if the session is empty.
979    */

980   public boolean isEmpty()
981   {
982     return _values == null || _values.size() == 0;
983   }
984
985   /**
986    * Saves the object to the input stream.
987    */

988   public void store(ObjectOutputStream JavaDoc out)
989     throws IOException JavaDoc
990   {
991     synchronized (_values) {
992       Set set = getEntrySet();
993
994       int size = set == null ? 0 : set.size();
995
996       out.writeInt(size);
997
998       if (size == 0)
999     return;
1000
1001      ArrayList<HttpSessionActivationListener> listeners;
1002      listeners = _manager.getActivationListeners();
1003      for (int i = 0; listeners != null && i < listeners.size(); i++) {
1004    HttpSessionActivationListener listener = listeners.get(i);
1005    HttpSessionEvent event = new HttpSessionEvent(this);
1006    listener.sessionWillPassivate(event);
1007      }
1008
1009      boolean ignoreNonSerializable =
1010    getManager().getIgnoreSerializationErrors();
1011
1012      Map.Entry []entries = new Map.Entry[set.size()];
1013      
1014      Iterator iter = set.iterator();
1015      int i = 0;
1016      while (iter.hasNext()) {
1017    entries[i++] = (Map.Entry) iter.next();
1018      }
1019
1020      Arrays.sort(entries, KEY_COMPARATOR);
1021
1022      for (i = 0; i < entries.length; i++) {
1023    Map.Entry entry = entries[i];
1024    Object JavaDoc value = entry.getValue();
1025
1026    out.writeUTF((String JavaDoc) entry.getKey());
1027    if (ignoreNonSerializable && ! (value instanceof Serializable JavaDoc)) {
1028      out.writeObject(null);
1029      continue;
1030    }
1031
1032    try {
1033      out.writeObject(value);
1034    } catch (NotSerializableException JavaDoc e) {
1035      log.warning(L.l("Failed storing persistent session attribute `{0}'. Persistent session values must extend java.io.Serializable.\n{1}", entry.getKey(), String.valueOf(e)));
1036      throw e;
1037    }
1038      }
1039    }
1040  }
1041
1042  /**
1043   * Returns the set of values in the session
1044   */

1045  Set getEntrySet()
1046  {
1047    synchronized (_values) {
1048      if (! _isValid)
1049    throw new IllegalStateException JavaDoc(L.l("Can't call getEntrySet() when session is no longer valid."));
1050
1051      return _values.entrySet();
1052    }
1053  }
1054
1055  public boolean canLog()
1056  {
1057    return log.isLoggable(Level.FINE);
1058  }
1059
1060  public void log(String JavaDoc value)
1061  {
1062    log.fine(value);
1063  }
1064
1065  public String JavaDoc toString()
1066  {
1067    return "SessionImpl[" + getId() + "]";
1068  }
1069
1070  private static Comparator KEY_COMPARATOR = new Comparator() {
1071      public int compare(Object JavaDoc aObj, Object JavaDoc bObj)
1072      {
1073    Map.Entry a = (Map.Entry) aObj;
1074    Map.Entry b = (Map.Entry) bObj;
1075
1076    String JavaDoc aStr = (String JavaDoc) a.getKey();
1077    String JavaDoc bStr = (String JavaDoc) b.getKey();
1078
1079    return aStr.compareTo(bStr);
1080      }
1081    };
1082}
1083
Popular Tags