001: // ========================================================================
002: // Copyright 199-2004 Mort Bay Consulting Pty. Ltd.
003: // ------------------------------------------------------------------------
004: // Licensed under the Apache License, Version 2.0 (the "License");
005: // you may not use this file except in compliance with the License.
006: // You may obtain a copy of the License at
007: // http://www.apache.org/licenses/LICENSE-2.0
008: // Unless required by applicable law or agreed to in writing, software
009: // distributed under the License is distributed on an "AS IS" BASIS,
010: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011: // See the License for the specific language governing permissions and
012: // limitations under the License.
013: // ========================================================================
014:
015: package org.mortbay.jetty.servlet;
016:
017: import java.io.Serializable;
018: import java.util.ArrayList;
019: import java.util.Collections;
020: import java.util.Enumeration;
021: import java.util.EventListener;
022: import java.util.Iterator;
023: import java.util.List;
024: import java.util.Map;
025:
026: import javax.servlet.ServletContext;
027: import javax.servlet.http.Cookie;
028: import javax.servlet.http.HttpServletRequest;
029: import javax.servlet.http.HttpSession;
030: import javax.servlet.http.HttpSessionAttributeListener;
031: import javax.servlet.http.HttpSessionBindingEvent;
032: import javax.servlet.http.HttpSessionBindingListener;
033: import javax.servlet.http.HttpSessionContext;
034: import javax.servlet.http.HttpSessionEvent;
035: import javax.servlet.http.HttpSessionListener;
036:
037: import org.mortbay.component.AbstractLifeCycle;
038: import org.mortbay.jetty.HttpOnlyCookie;
039: import org.mortbay.jetty.Server;
040: import org.mortbay.jetty.SessionIdManager;
041: import org.mortbay.jetty.SessionManager;
042: import org.mortbay.jetty.handler.ContextHandler;
043: import org.mortbay.log.Log;
044: import org.mortbay.util.LazyList;
045:
046: /* ------------------------------------------------------------ */
047: /**
048: * An Abstract implementation of SessionManager. The partial implementation of
049: * SessionManager interface provides the majority of the handling required to
050: * implement a SessionManager. Concrete implementations of SessionManager based
051: * on AbstractSessionManager need only implement the newSession method to return
052: * a specialized version of the Session inner class that provides an attribute
053: * Map.
054: * <p>
055: * If the property
056: * org.mortbay.jetty.servlet.AbstractSessionManager.23Notifications is set to
057: * true, the 2.3 servlet spec notification style will be used.
058: * <p>
059: *
060: * @author Greg Wilkins (gregw)
061: */
062: public abstract class AbstractSessionManager extends AbstractLifeCycle
063: implements SessionManager {
064: /* ------------------------------------------------------------ */
065: public final static int __distantFuture = 60 * 60 * 24 * 7 * 52
066: * 20;
067:
068: private static final HttpSessionContext __nullSessionContext = new NullSessionContext();
069:
070: private boolean _usingCookies = true;
071: /* ------------------------------------------------------------ */
072: // Setting of max inactive interval for new sessions
073: // -1 means no timeout
074: protected int _dftMaxIdleSecs = -1;
075: protected SessionHandler _sessionHandler;
076: protected boolean _httpOnly = false;
077: protected int _maxSessions = 0;
078:
079: protected int _minSessions = 0;
080: protected SessionIdManager _sessionIdManager;
081: protected boolean _secureCookies = false;
082: protected Object _sessionAttributeListeners;
083: protected Object _sessionListeners;
084:
085: protected ClassLoader _loader;
086: protected ContextHandler.SContext _context;
087: protected String _sessionCookie = __DefaultSessionCookie;
088: protected String _sessionURL = __DefaultSessionURL;
089: protected String _sessionURLPrefix = ";" + _sessionURL + "=";
090: protected String _sessionDomain;
091: protected String _sessionPath;
092: protected int _maxCookieAge = -1;
093: protected int _refreshCookieAge;
094:
095: /* ------------------------------------------------------------ */
096: public AbstractSessionManager() {
097: }
098:
099: /* ------------------------------------------------------------ */
100: public Cookie access(HttpSession session, boolean secure) {
101: long now = System.currentTimeMillis();
102:
103: Session s = (Session) session;
104: s.access(now);
105:
106: // Do we need to refresh the cookie?
107: if (isUsingCookies()
108: && (s.isIdChanged() || (getMaxCookieAge() > 0
109: && getRefreshCookieAge() > 0 && ((now - s
110: .getCookieSetTime()) / 1000 > getRefreshCookieAge())))) {
111: Cookie cookie = getSessionCookie(session, _context
112: .getContextPath(), secure);
113: s.cookieSet();
114: s.setIdChanged(false);
115: return cookie;
116: }
117:
118: return null;
119: }
120:
121: /* ------------------------------------------------------------ */
122: public void addEventListener(EventListener listener) {
123: if (listener instanceof HttpSessionAttributeListener)
124: _sessionAttributeListeners = LazyList.add(
125: _sessionAttributeListeners, listener);
126: if (listener instanceof HttpSessionListener)
127: _sessionListeners = LazyList.add(_sessionListeners,
128: listener);
129: }
130:
131: /* ------------------------------------------------------------ */
132: public void clearEventListeners() {
133: _sessionAttributeListeners = null;
134: _sessionListeners = null;
135: }
136:
137: /* ------------------------------------------------------------ */
138: public void complete(HttpSession session) {
139: }
140:
141: /* ------------------------------------------------------------ */
142: public void doStart() throws Exception {
143: _context = ContextHandler.getCurrentContext();
144: _loader = Thread.currentThread().getContextClassLoader();
145:
146: newSessionMap();
147:
148: if (_sessionIdManager == null) {
149: Server server = getSessionHandler().getServer();
150: synchronized (server) {
151: _sessionIdManager = server.getSessionIdManager();
152: if (_sessionIdManager == null) {
153: _sessionIdManager = new HashSessionIdManager();
154: server.setSessionIdManager(_sessionIdManager);
155: }
156: }
157: }
158: if (!_sessionIdManager.isStarted())
159: _sessionIdManager.start();
160:
161: // Look for a session cookie name
162: String tmp = _context
163: .getInitParameter(SessionManager.__SessionCookieProperty);
164: if (tmp != null)
165: _sessionCookie = tmp;
166:
167: tmp = _context
168: .getInitParameter(SessionManager.__SessionURLProperty);
169: if (tmp != null) {
170: _sessionURL = tmp;
171: _sessionURLPrefix = ";" + _sessionURL + "=";
172: }
173:
174: // set up the max session cookie age if it isn't already
175: if (_maxCookieAge == -1) {
176: if (_context != null) {
177: String str = _context
178: .getInitParameter(SessionManager.__MaxAgeProperty);
179: if (str != null)
180: _maxCookieAge = Integer.parseInt(str.trim());
181: }
182: }
183: // set up the session domain if it isn't already
184: if (_sessionDomain == null) {
185: // only try the context initParams
186: if (_context != null)
187: _sessionDomain = _context
188: .getInitParameter(SessionManager.__SessionDomainProperty);
189: }
190:
191: // set up the sessionPath if it isn't already
192: if (_sessionPath == null) {
193: // only the context initParams
194: if (_context != null)
195: _sessionPath = _context
196: .getInitParameter(SessionManager.__SessionPathProperty);
197: }
198:
199: super .doStart();
200: }
201:
202: /* ------------------------------------------------------------ */
203: public void doStop() throws Exception {
204: super .doStop();
205:
206: invalidateSessions();
207:
208: _loader = null;
209: }
210:
211: /* ------------------------------------------------------------ */
212: /**
213: * @return Returns the httpOnly.
214: */
215: public boolean getHttpOnly() {
216: return _httpOnly;
217: }
218:
219: /* ------------------------------------------------------------ */
220: public HttpSession getHttpSession(String id) {
221: int dot = id.lastIndexOf('.');
222: String cluster_id = (dot > 0) ? id.substring(0, dot) : id;
223:
224: synchronized (this ) {
225: Session session = getSession(cluster_id);
226:
227: if (session != null && !session.getId().equals(id))
228: session.setIdChanged(true);
229: return session;
230: }
231: }
232:
233: /* ------------------------------------------------------------ */
234: /**
235: * @return Returns the metaManager used for cross context session management
236: */
237: public SessionIdManager getIdManager() {
238: return _sessionIdManager;
239: }
240:
241: /* ------------------------------------------------------------ */
242: public int getMaxCookieAge() {
243: return _maxCookieAge;
244: }
245:
246: /* ------------------------------------------------------------ */
247: /**
248: * @return seconds
249: */
250: public int getMaxInactiveInterval() {
251: return _dftMaxIdleSecs;
252: }
253:
254: /* ------------------------------------------------------------ */
255: public int getMaxSessions() {
256: return _maxSessions;
257: }
258:
259: /* ------------------------------------------------------------ */
260: /**
261: * @deprecated use {@link #getIdManager()}
262: */
263: public SessionIdManager getMetaManager() {
264: return getIdManager();
265: }
266:
267: /* ------------------------------------------------------------ */
268: public int getMinSessions() {
269: return _minSessions;
270: }
271:
272: /* ------------------------------------------------------------ */
273: public int getRefreshCookieAge() {
274: return _refreshCookieAge;
275: }
276:
277: /* ------------------------------------------------------------ */
278: /**
279: * @return Returns the secureCookies.
280: */
281: public boolean getSecureCookies() {
282: return _secureCookies;
283: }
284:
285: /* ------------------------------------------------------------ */
286: public String getSessionCookie() {
287: return _sessionCookie;
288: }
289:
290: /* ------------------------------------------------------------ */
291: public Cookie getSessionCookie(HttpSession session,
292: String contextPath, boolean requestIsSecure) {
293: if (isUsingCookies()) {
294: Cookie cookie = getHttpOnly() ? new HttpOnlyCookie(
295: _sessionCookie, session.getId()) : new Cookie(
296: _sessionCookie, session.getId());
297:
298: cookie
299: .setPath((contextPath == null || contextPath
300: .length() == 0) ? "/" : contextPath);
301: cookie.setMaxAge(getMaxCookieAge());
302: cookie.setSecure(requestIsSecure && getSecureCookies());
303:
304: // set up the overrides
305: if (_sessionDomain != null)
306: cookie.setDomain(_sessionDomain);
307: if (_sessionPath != null)
308: cookie.setPath(_sessionPath);
309:
310: return cookie;
311: }
312: return null;
313: }
314:
315: public String getSessionDomain() {
316: return _sessionDomain;
317: }
318:
319: /* ------------------------------------------------------------ */
320: /**
321: * @return Returns the sessionHandler.
322: */
323: public SessionHandler getSessionHandler() {
324: return _sessionHandler;
325: }
326:
327: /* ------------------------------------------------------------ */
328: /**
329: * @deprecated. Need to review if it is needed.
330: */
331: public abstract Map getSessionMap();
332:
333: /* ------------------------------------------------------------ */
334: public String getSessionPath() {
335: return _sessionPath;
336: }
337:
338: /* ------------------------------------------------------------ */
339: public abstract int getSessions();
340:
341: /* ------------------------------------------------------------ */
342: public String getSessionURL() {
343: return _sessionURL;
344: }
345:
346: /* ------------------------------------------------------------ */
347: public String getSessionURLPrefix() {
348: return _sessionURLPrefix;
349: }
350:
351: /* ------------------------------------------------------------ */
352: /**
353: * @return Returns the usingCookies.
354: */
355: public boolean isUsingCookies() {
356: return _usingCookies;
357: }
358:
359: /* ------------------------------------------------------------ */
360: public boolean isValid(HttpSession session) {
361: return ((Session) session).isValid();
362: }
363:
364: /* ------------------------------------------------------------ */
365: /**
366: * Create a new HttpSession for a request
367: */
368: public HttpSession newHttpSession(HttpServletRequest request) {
369: Session session = newSession(request);
370: session.setMaxInactiveInterval(_dftMaxIdleSecs);
371: addSession(session, true);
372: return session;
373: }
374:
375: /* ------------------------------------------------------------ */
376: public void removeEventListener(EventListener listener) {
377: if (listener instanceof HttpSessionAttributeListener)
378: _sessionAttributeListeners = LazyList.remove(
379: _sessionAttributeListeners, listener);
380: if (listener instanceof HttpSessionListener)
381: _sessionListeners = LazyList.remove(_sessionListeners,
382: listener);
383: }
384:
385: /* ------------------------------------------------------------ */
386: public void resetStats() {
387: _minSessions = getSessions();
388: _maxSessions = getSessions();
389: }
390:
391: /* ------------------------------------------------------------ */
392: /**
393: * @param httpOnly
394: * The httpOnly to set.
395: */
396: public void setHttpOnly(boolean httpOnly) {
397: _httpOnly = httpOnly;
398: }
399:
400: /* ------------------------------------------------------------ */
401: /**
402: * @param metaManager The metaManager used for cross context session management.
403: */
404: public void setIdManager(SessionIdManager metaManager) {
405: _sessionIdManager = metaManager;
406: }
407:
408: /* ------------------------------------------------------------ */
409: public void setMaxCookieAge(int maxCookieAgeInSeconds) {
410: _maxCookieAge = maxCookieAgeInSeconds;
411:
412: if (_maxCookieAge > 0 && _refreshCookieAge == 0)
413: _refreshCookieAge = _maxCookieAge / 3;
414:
415: }
416:
417: /* ------------------------------------------------------------ */
418: /**
419: * @param seconds
420: */
421: public void setMaxInactiveInterval(int seconds) {
422: _dftMaxIdleSecs = seconds;
423: }
424:
425: /* ------------------------------------------------------------ */
426: /**
427: * @deprecated use {@link #setIdManager(SessionIdManager)}
428: */
429: public void setMetaManager(SessionIdManager metaManager) {
430: setIdManager(metaManager);
431: }
432:
433: /* ------------------------------------------------------------ */
434: public void setRefreshCookieAge(int ageInSeconds) {
435: _refreshCookieAge = ageInSeconds;
436: }
437:
438: /* ------------------------------------------------------------ */
439: /**
440: * @param secureCookies
441: * The secureCookies to set.
442: */
443: public void setSecureCookies(boolean secureCookies) {
444: _secureCookies = secureCookies;
445: }
446:
447: public void setSessionCookie(String cookieName) {
448: _sessionCookie = cookieName;
449: }
450:
451: public void setSessionDomain(String domain) {
452: _sessionDomain = domain;
453: }
454:
455: /* ------------------------------------------------------------ */
456: /**
457: * @param sessionHandler
458: * The sessionHandler to set.
459: */
460: public void setSessionHandler(SessionHandler sessionHandler) {
461: _sessionHandler = sessionHandler;
462: }
463:
464: public void setSessionPath(String path) {
465: _sessionPath = path;
466: }
467:
468: public void setSessionURL(String url) {
469: _sessionURL = url;
470: }
471:
472: /* ------------------------------------------------------------ */
473: /**
474: * @param usingCookies
475: * The usingCookies to set.
476: */
477: public void setUsingCookies(boolean usingCookies) {
478: _usingCookies = usingCookies;
479: }
480:
481: protected abstract void addSession(Session session);
482:
483: /* ------------------------------------------------------------ */
484: /**
485: * Add the session Registers the session with this manager and registers the
486: * session ID with the sessionIDManager;
487: */
488: protected void addSession(Session session, boolean created) {
489: synchronized (_sessionIdManager) {
490: _sessionIdManager.addSession(session);
491: synchronized (this ) {
492: addSession(session);
493: if (getSessions() > this ._maxSessions)
494: this ._maxSessions = getSessions();
495: }
496: }
497:
498: if (created && _sessionListeners != null) {
499: HttpSessionEvent event = new HttpSessionEvent(session);
500: for (int i = 0; i < LazyList.size(_sessionListeners); i++)
501: ((HttpSessionListener) LazyList.get(_sessionListeners,
502: i)).sessionCreated(event);
503: }
504: }
505:
506: /* ------------------------------------------------------------ */
507: /**
508: * Get a known existingsession
509: * @param idInCluster The session ID in the cluster, stripped of any worker name.
510: * @return A Session or null if none exists.
511: */
512: protected abstract Session getSession(String idInCluster);
513:
514: protected abstract void invalidateSessions();
515:
516: /* ------------------------------------------------------------ */
517: /**
518: * Create a new session instance
519: * @param request
520: * @return
521: */
522: protected abstract Session newSession(HttpServletRequest request);
523:
524: // TODO delete this
525: protected final void newSessionMap() {
526: }
527:
528: /* ------------------------------------------------------------ */
529: /** Remove session from manager
530: * @param session The session to remove
531: * @param invalidate True if {@link HttpSessionListener#sessionDestroyed(HttpSessionEvent)} and
532: * {@link SessionIdManager#invalidateAll(String)} should be called.
533: */
534: protected void removeSession(Session session, boolean invalidate) {
535: if (invalidate && _sessionListeners != null) {
536: HttpSessionEvent event = new HttpSessionEvent(session);
537: for (int i = LazyList.size(_sessionListeners); i-- > 0;)
538: ((HttpSessionListener) LazyList.get(_sessionListeners,
539: i)).sessionDestroyed(event);
540: }
541:
542: // Remove session from context and global maps
543: synchronized (_sessionIdManager) {
544: String id = session.getClusterId();
545: _sessionIdManager.removeSession(session);
546:
547: synchronized (this ) {
548: removeSession(id);
549: }
550: if (invalidate)
551: _sessionIdManager.invalidateAll(id);
552: }
553: }
554:
555: /* ------------------------------------------------------------ */
556: protected abstract void removeSession(String idInCluster);
557:
558: /* ------------------------------------------------------------ */
559: /**
560: * Null returning implementation of HttpSessionContext
561: *
562: * @author Greg Wilkins (gregw)
563: */
564: public static class NullSessionContext implements
565: HttpSessionContext {
566: /* ------------------------------------------------------------ */
567: private NullSessionContext() {
568: }
569:
570: /* ------------------------------------------------------------ */
571: /**
572: * @deprecated From HttpSessionContext
573: */
574: public Enumeration getIds() {
575: return Collections.enumeration(Collections.EMPTY_LIST);
576: }
577:
578: /* ------------------------------------------------------------ */
579: /**
580: * @deprecated From HttpSessionContext
581: */
582: public HttpSession getSession(String id) {
583: return null;
584: }
585: }
586:
587: /* ------------------------------------------------------------ */
588: /* ------------------------------------------------------------ */
589: /* ------------------------------------------------------------ */
590: /**
591: *
592: * <p>
593: * Implements {@link javax.servlet.HttpSession} from the {@link javax.servlet} package.
594: * </p>
595: * @author gregw
596: *
597: */
598: public abstract class Session implements HttpSession, Serializable {
599: final String _clusterId;
600: final String _id;
601: boolean _idChanged;
602: final long _created;
603: long _cookieSet;
604: long _accessed;
605: boolean _invalid;
606: long _maxIdleMs = _dftMaxIdleSecs * 1000;
607: boolean _newSession;
608: Map _values;
609:
610: /* ------------------------------------------------------------- */
611: protected Session(HttpServletRequest request) {
612: _newSession = true;
613: _created = System.currentTimeMillis();
614: _clusterId = _sessionIdManager.newSessionId(request,
615: _created);
616: _id = getId(request);
617: _accessed = _created;
618: }
619:
620: /* ------------------------------------------------------------- */
621: protected Session(long created, String clusterId) {
622: _created = created;
623: _clusterId = clusterId;
624: _id = getId(null);
625: _accessed = _created;
626: }
627:
628: /* ------------------------------------------------------------- */
629: protected void initValues() {
630: _values = newAttributeMap();
631: }
632:
633: /* ------------------------------------------------------------ */
634: /** Get the session ID with any worker ID.
635: *
636: * @param request
637: * @return sessionId plus any worker ID.
638: */
639: protected String getId(HttpServletRequest request) {
640: String worker = request == null ? null : (String) request
641: .getAttribute("org.mortbay.http.ajp.JVMRoute");
642: if (worker != null)
643: return _clusterId + '.' + worker;
644:
645: if (_sessionIdManager.getWorkerName() != null)
646: return _clusterId + '.'
647: + _sessionIdManager.getWorkerName();
648:
649: return _clusterId;
650: }
651:
652: /* ------------------------------------------------------------ */
653: public synchronized Object getAttribute(String name) {
654: if (_invalid)
655: throw new IllegalStateException();
656: if (null == _values)
657: return null;
658: return _values.get(name);
659: }
660:
661: /* ------------------------------------------------------------ */
662: public synchronized Enumeration getAttributeNames() {
663: if (_invalid)
664: throw new IllegalStateException();
665: List names = _values == null ? Collections.EMPTY_LIST
666: : new ArrayList(_values.keySet());
667: return Collections.enumeration(names);
668: }
669:
670: /* ------------------------------------------------------------- */
671: public long getCookieSetTime() {
672: return _cookieSet;
673: }
674:
675: /* ------------------------------------------------------------- */
676: public long getCreationTime() throws IllegalStateException {
677: if (_invalid)
678: throw new IllegalStateException();
679: return _created;
680: }
681:
682: /* ------------------------------------------------------------- */
683: public String getId() throws IllegalStateException {
684: return _id;
685: }
686:
687: /* ------------------------------------------------------------- */
688: public long getLastAccessedTime() throws IllegalStateException {
689: if (_invalid)
690: throw new IllegalStateException();
691: return _accessed;
692: }
693:
694: /* ------------------------------------------------------------- */
695: public int getMaxInactiveInterval() {
696: if (_invalid)
697: throw new IllegalStateException();
698: return (int) (_maxIdleMs / 1000);
699: }
700:
701: /* ------------------------------------------------------------ */
702: /*
703: * @see javax.servlet.http.HttpSession#getServletContext()
704: */
705: public ServletContext getServletContext() {
706: return _context;
707: }
708:
709: /* ------------------------------------------------------------- */
710: /**
711: * @deprecated
712: */
713: public HttpSessionContext getSessionContext()
714: throws IllegalStateException {
715: if (_invalid)
716: throw new IllegalStateException();
717: return __nullSessionContext;
718: }
719:
720: /* ------------------------------------------------------------- */
721: /**
722: * @deprecated As of Version 2.2, this method is replaced by
723: * {@link #getAttribute}
724: */
725: public Object getValue(String name)
726: throws IllegalStateException {
727: return getAttribute(name);
728: }
729:
730: /* ------------------------------------------------------------- */
731: /**
732: * @deprecated As of Version 2.2, this method is replaced by
733: * {@link #getAttributeNames}
734: */
735: public synchronized String[] getValueNames()
736: throws IllegalStateException {
737: if (_invalid)
738: throw new IllegalStateException();
739: if (_values == null)
740: return new String[0];
741: String[] a = new String[_values.size()];
742: return (String[]) _values.keySet().toArray(a);
743: }
744:
745: /* ------------------------------------------------------------- */
746: public void invalidate() throws IllegalStateException {
747: if (Log.isDebugEnabled())
748: Log.debug("Invalidate session " + getId());
749: try {
750: // remove session from context and invalidate other sessions with same ID.
751: removeSession(this , true);
752:
753: // Notify listeners and unbind values
754: synchronized (this ) {
755: if (_invalid)
756: throw new IllegalStateException();
757:
758: if (_values != null) {
759: Iterator iter = _values.keySet().iterator();
760: while (iter.hasNext()) {
761: String key = (String) iter.next();
762: Object value = _values.get(key);
763: iter.remove();
764: unbindValue(key, value);
765:
766: if (_sessionAttributeListeners != null) {
767: HttpSessionBindingEvent event = new HttpSessionBindingEvent(
768: this , key, value);
769:
770: for (int i = 0; i < LazyList
771: .size(_sessionAttributeListeners); i++)
772: ((HttpSessionAttributeListener) LazyList
773: .get(
774: _sessionAttributeListeners,
775: i))
776: .attributeRemoved(event);
777: }
778: }
779: }
780: }
781: } finally {
782: // mark as invalid
783: _invalid = true;
784: }
785: }
786:
787: /* ------------------------------------------------------------- */
788: public boolean isIdChanged() {
789: return _idChanged;
790: }
791:
792: /* ------------------------------------------------------------- */
793: public boolean isNew() throws IllegalStateException {
794: if (_invalid)
795: throw new IllegalStateException();
796: return _newSession;
797: }
798:
799: /* ------------------------------------------------------------- */
800: /**
801: * @deprecated As of Version 2.2, this method is replaced by
802: * {@link #setAttribute}
803: */
804: public void putValue(java.lang.String name,
805: java.lang.Object value) throws IllegalStateException {
806: setAttribute(name, value);
807: }
808:
809: /* ------------------------------------------------------------ */
810: public synchronized void removeAttribute(String name) {
811: if (_invalid)
812: throw new IllegalStateException();
813: if (_values == null)
814: return;
815:
816: Object old = _values.remove(name);
817: if (old != null) {
818: unbindValue(name, old);
819: if (_sessionAttributeListeners != null) {
820: HttpSessionBindingEvent event = new HttpSessionBindingEvent(
821: this , name, old);
822:
823: for (int i = 0; i < LazyList
824: .size(_sessionAttributeListeners); i++)
825: ((HttpSessionAttributeListener) LazyList.get(
826: _sessionAttributeListeners, i))
827: .attributeRemoved(event);
828: }
829: }
830: }
831:
832: /* ------------------------------------------------------------- */
833: /**
834: * @deprecated As of Version 2.2, this method is replaced by
835: * {@link #removeAttribute}
836: */
837: public void removeValue(java.lang.String name)
838: throws IllegalStateException {
839: removeAttribute(name);
840: }
841:
842: /* ------------------------------------------------------------ */
843: public synchronized void setAttribute(String name, Object value) {
844: if (value == null) {
845: removeAttribute(name);
846: return;
847: }
848:
849: if (_invalid)
850: throw new IllegalStateException();
851: if (_values == null)
852: _values = newAttributeMap();
853: Object oldValue = _values.put(name, value);
854:
855: if (oldValue == null || !value.equals(oldValue)) {
856: unbindValue(name, oldValue);
857: bindValue(name, value);
858:
859: if (_sessionAttributeListeners != null) {
860: HttpSessionBindingEvent event = new HttpSessionBindingEvent(
861: this , name, oldValue == null ? value
862: : oldValue);
863:
864: for (int i = 0; i < LazyList
865: .size(_sessionAttributeListeners); i++) {
866: HttpSessionAttributeListener l = (HttpSessionAttributeListener) LazyList
867: .get(_sessionAttributeListeners, i);
868:
869: if (oldValue == null)
870: l.attributeAdded(event);
871: else if (value == null)
872: l.attributeRemoved(event);
873: else
874: l.attributeReplaced(event);
875: }
876: }
877: }
878: }
879:
880: /* ------------------------------------------------------------- */
881: public void setIdChanged(boolean changed) {
882: _idChanged = changed;
883: }
884:
885: /* ------------------------------------------------------------- */
886: public void setMaxInactiveInterval(int secs) {
887: _maxIdleMs = (long) secs * 1000;
888: }
889:
890: /* ------------------------------------------------------------- */
891: public String toString() {
892: return this .getClass().getName() + ":" + getId() + "@"
893: + hashCode();
894: }
895:
896: /* ------------------------------------------------------------ */
897: protected void access(long time) {
898: _newSession = false;
899: _accessed = time;
900: }
901:
902: /* ------------------------------------------------------------- */
903: /** If value implements HttpSessionBindingListener, call valueBound() */
904: protected void bindValue(java.lang.String name, Object value) {
905: if (value != null
906: && value instanceof HttpSessionBindingListener)
907: ((HttpSessionBindingListener) value)
908: .valueBound(new HttpSessionBindingEvent(this ,
909: name));
910: }
911:
912: /* ------------------------------------------------------------- */
913: protected String getClusterId() {
914: return _clusterId;
915: }
916:
917: /* ------------------------------------------------------------ */
918: protected boolean isValid() {
919: return !_invalid;
920: }
921:
922: /* ------------------------------------------------------------ */
923: protected abstract Map newAttributeMap();
924:
925: /* ------------------------------------------------------------- */
926: protected void cookieSet() {
927: _cookieSet = _accessed;
928: }
929:
930: /* ------------------------------------------------------------- */
931: /** If value implements HttpSessionBindingListener, call valueUnbound() */
932: protected void unbindValue(java.lang.String name, Object value) {
933: if (value != null
934: && value instanceof HttpSessionBindingListener)
935: ((HttpSessionBindingListener) value)
936: .valueUnbound(new HttpSessionBindingEvent(this,
937: name));
938: }
939: }
940:
941: }
|