• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 //  ========================================================================
3 //  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
4 //  ------------------------------------------------------------------------
5 //  All rights reserved. This program and the accompanying materials
6 //  are made available under the terms of the Eclipse Public License v1.0
7 //  and Apache License v2.0 which accompanies this distribution.
8 //
9 //      The Eclipse Public License is available at
10 //      http://www.eclipse.org/legal/epl-v10.html
11 //
12 //      The Apache License v2.0 is available at
13 //      http://www.opensource.org/licenses/apache2.0.php
14 //
15 //  You may elect to redistribute this code under either of these licenses.
16 //  ========================================================================
17 //
18 
19 package org.eclipse.jetty.server.session;
20 
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.Enumeration;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30 
31 import javax.servlet.ServletContext;
32 import javax.servlet.http.HttpServletRequest;
33 import javax.servlet.http.HttpSessionActivationListener;
34 import javax.servlet.http.HttpSessionBindingEvent;
35 import javax.servlet.http.HttpSessionBindingListener;
36 import javax.servlet.http.HttpSessionContext;
37 import javax.servlet.http.HttpSessionEvent;
38 
39 import org.eclipse.jetty.util.log.Logger;
40 
41 /**
42  *
43  * <p>
44  * Implements {@link javax.servlet.http.HttpSession} from the <code>javax.servlet</code> package.
45  * </p>
46  *
47  */
48 @SuppressWarnings("deprecation")
49 public abstract class AbstractSession implements AbstractSessionManager.SessionIf
50 {
51     final static Logger LOG = SessionHandler.LOG;
52 
53     private final AbstractSessionManager _manager;
54     private final String _clusterId; // ID unique within cluster
55     private final String _nodeId;    // ID unique within node
56     private final Map<String,Object> _attributes=new HashMap<String, Object>();
57     private boolean _idChanged;
58     private final long _created;
59     private long _cookieSet;
60     private long _accessed;         // the time of the last access
61     private long _lastAccessed;     // the time of the last access excluding this one
62     private boolean _invalid;
63     private boolean _doInvalidate;
64     private long _maxIdleMs;
65     private boolean _newSession;
66     private int _requests;
67 
68 
69 
70     /* ------------------------------------------------------------- */
AbstractSession(AbstractSessionManager abstractSessionManager, HttpServletRequest request)71     protected AbstractSession(AbstractSessionManager abstractSessionManager, HttpServletRequest request)
72     {
73         _manager = abstractSessionManager;
74 
75         _newSession=true;
76         _created=System.currentTimeMillis();
77         _clusterId=_manager._sessionIdManager.newSessionId(request,_created);
78         _nodeId=_manager._sessionIdManager.getNodeId(_clusterId,request);
79         _accessed=_created;
80         _lastAccessed=_created;
81         _requests=1;
82         _maxIdleMs=_manager._dftMaxIdleSecs>0?_manager._dftMaxIdleSecs*1000L:-1;
83         if (LOG.isDebugEnabled())
84             LOG.debug("new session & id "+_nodeId+" "+_clusterId);
85     }
86 
87     /* ------------------------------------------------------------- */
AbstractSession(AbstractSessionManager abstractSessionManager, long created, long accessed, String clusterId)88     protected AbstractSession(AbstractSessionManager abstractSessionManager, long created, long accessed, String clusterId)
89     {
90         _manager = abstractSessionManager;
91         _created=created;
92         _clusterId=clusterId;
93         _nodeId=_manager._sessionIdManager.getNodeId(_clusterId,null);
94         _accessed=accessed;
95         _lastAccessed=accessed;
96         _requests=1;
97         _maxIdleMs=_manager._dftMaxIdleSecs>0?_manager._dftMaxIdleSecs*1000L:-1;
98         if (LOG.isDebugEnabled())
99             LOG.debug("new session "+_nodeId+" "+_clusterId);
100     }
101 
102     /* ------------------------------------------------------------- */
103     /**
104      * asserts that the session is valid
105      */
checkValid()106     protected void checkValid() throws IllegalStateException
107     {
108         if (_invalid)
109             throw new IllegalStateException();
110     }
111 
112     /* ------------------------------------------------------------- */
getSession()113     public AbstractSession getSession()
114     {
115         return this;
116     }
117 
118     /* ------------------------------------------------------------- */
getAccessed()119     public long getAccessed()
120     {
121         synchronized (this)
122         {
123             return _accessed;
124         }
125     }
126 
127     /* ------------------------------------------------------------ */
getAttribute(String name)128     public Object getAttribute(String name)
129     {
130         synchronized (this)
131         {
132             checkValid();
133             return _attributes.get(name);
134         }
135     }
136 
137     /* ------------------------------------------------------------ */
getAttributes()138     public int getAttributes()
139     {
140         synchronized (this)
141         {
142             checkValid();
143             return _attributes.size();
144         }
145     }
146 
147     /* ------------------------------------------------------------ */
148     @SuppressWarnings({ "unchecked" })
getAttributeNames()149     public Enumeration<String> getAttributeNames()
150     {
151         synchronized (this)
152         {
153             checkValid();
154             List<String> names=_attributes==null?Collections.EMPTY_LIST:new ArrayList<String>(_attributes.keySet());
155             return Collections.enumeration(names);
156         }
157     }
158 
159     /* ------------------------------------------------------------ */
getNames()160     public Set<String> getNames()
161     {
162         synchronized (this)
163         {
164             return new HashSet<String>(_attributes.keySet());
165         }
166     }
167 
168     /* ------------------------------------------------------------- */
getCookieSetTime()169     public long getCookieSetTime()
170     {
171         return _cookieSet;
172     }
173 
174     /* ------------------------------------------------------------- */
getCreationTime()175     public long getCreationTime() throws IllegalStateException
176     {
177         return _created;
178     }
179 
180     /* ------------------------------------------------------------ */
getId()181     public String getId() throws IllegalStateException
182     {
183         return _manager._nodeIdInSessionId?_nodeId:_clusterId;
184     }
185 
186     /* ------------------------------------------------------------- */
getNodeId()187     public String getNodeId()
188     {
189         return _nodeId;
190     }
191 
192     /* ------------------------------------------------------------- */
getClusterId()193     public String getClusterId()
194     {
195         return _clusterId;
196     }
197 
198     /* ------------------------------------------------------------- */
getLastAccessedTime()199     public long getLastAccessedTime() throws IllegalStateException
200     {
201         checkValid();
202         return _lastAccessed;
203     }
204 
205     /* ------------------------------------------------------------- */
setLastAccessedTime(long time)206     public void setLastAccessedTime(long time)
207     {
208         _lastAccessed = time;
209     }
210 
211     /* ------------------------------------------------------------- */
getMaxInactiveInterval()212     public int getMaxInactiveInterval()
213     {
214         checkValid();
215         return (int)(_maxIdleMs/1000);
216     }
217 
218     /* ------------------------------------------------------------ */
219     /*
220      * @see javax.servlet.http.HttpSession#getServletContext()
221      */
getServletContext()222     public ServletContext getServletContext()
223     {
224         return _manager._context;
225     }
226 
227     /* ------------------------------------------------------------- */
228     @Deprecated
getSessionContext()229     public HttpSessionContext getSessionContext() throws IllegalStateException
230     {
231         checkValid();
232         return AbstractSessionManager.__nullSessionContext;
233     }
234 
235     /* ------------------------------------------------------------- */
236     /**
237      * @deprecated As of Version 2.2, this method is replaced by
238      *             {@link #getAttribute}
239      */
240     @Deprecated
getValue(String name)241     public Object getValue(String name) throws IllegalStateException
242     {
243         return getAttribute(name);
244     }
245 
246     /* ------------------------------------------------------------- */
247     /**
248      * @deprecated As of Version 2.2, this method is replaced by
249      *             {@link #getAttributeNames}
250      */
251     @Deprecated
getValueNames()252     public String[] getValueNames() throws IllegalStateException
253     {
254         synchronized(this)
255         {
256             checkValid();
257             if (_attributes==null)
258                 return new String[0];
259             String[] a=new String[_attributes.size()];
260             return (String[])_attributes.keySet().toArray(a);
261         }
262     }
263 
264     /* ------------------------------------------------------------ */
getAttributeMap()265     protected  Map<String,Object> getAttributeMap ()
266     {
267         return _attributes;
268     }
269 
270     /* ------------------------------------------------------------ */
addAttributes(Map<String,Object> map)271     protected void addAttributes(Map<String,Object> map)
272     {
273         _attributes.putAll(map);
274     }
275 
276     /* ------------------------------------------------------------ */
access(long time)277     protected boolean access(long time)
278     {
279         synchronized(this)
280         {
281             if (_invalid)
282                 return false;
283             _newSession=false;
284             _lastAccessed=_accessed;
285             _accessed=time;
286 
287             if (_maxIdleMs>0 && _lastAccessed>0 && _lastAccessed + _maxIdleMs < time)
288             {
289                 invalidate();
290                 return false;
291             }
292             _requests++;
293             return true;
294         }
295     }
296 
297     /* ------------------------------------------------------------ */
complete()298     protected void complete()
299     {
300         synchronized(this)
301         {
302             _requests--;
303             if (_doInvalidate && _requests<=0  )
304                 doInvalidate();
305         }
306     }
307 
308 
309     /* ------------------------------------------------------------- */
timeout()310     protected void timeout() throws IllegalStateException
311     {
312         // remove session from context and invalidate other sessions with same ID.
313         _manager.removeSession(this,true);
314 
315         // Notify listeners and unbind values
316         boolean do_invalidate=false;
317         synchronized (this)
318         {
319             if (!_invalid)
320             {
321                 if (_requests<=0)
322                     do_invalidate=true;
323                 else
324                     _doInvalidate=true;
325             }
326         }
327         if (do_invalidate)
328             doInvalidate();
329     }
330 
331     /* ------------------------------------------------------------- */
invalidate()332     public void invalidate() throws IllegalStateException
333     {
334         // remove session from context and invalidate other sessions with same ID.
335         _manager.removeSession(this,true);
336         doInvalidate();
337     }
338 
339     /* ------------------------------------------------------------- */
doInvalidate()340     protected void doInvalidate() throws IllegalStateException
341     {
342         try
343         {
344             LOG.debug("invalidate {}",_clusterId);
345             if (isValid())
346                 clearAttributes();
347         }
348         finally
349         {
350             synchronized (this)
351             {
352                 // mark as invalid
353                 _invalid=true;
354             }
355         }
356     }
357 
358     /* ------------------------------------------------------------- */
clearAttributes()359     public void clearAttributes()
360     {
361         while (_attributes!=null && _attributes.size()>0)
362         {
363             ArrayList<String> keys;
364             synchronized(this)
365             {
366                 keys=new ArrayList<String>(_attributes.keySet());
367             }
368 
369             Iterator<String> iter=keys.iterator();
370             while (iter.hasNext())
371             {
372                 String key=(String)iter.next();
373 
374                 Object value;
375                 synchronized(this)
376                 {
377                     value=doPutOrRemove(key,null);
378                 }
379                 unbindValue(key,value);
380 
381                 _manager.doSessionAttributeListeners(this,key,value,null);
382             }
383         }
384         if (_attributes!=null)
385             _attributes.clear();
386     }
387 
388     /* ------------------------------------------------------------- */
isIdChanged()389     public boolean isIdChanged()
390     {
391         return _idChanged;
392     }
393 
394     /* ------------------------------------------------------------- */
isNew()395     public boolean isNew() throws IllegalStateException
396     {
397         checkValid();
398         return _newSession;
399     }
400 
401     /* ------------------------------------------------------------- */
402     /**
403      * @deprecated As of Version 2.2, this method is replaced by
404      *             {@link #setAttribute}
405      */
406     @Deprecated
putValue(java.lang.String name, java.lang.Object value)407     public void putValue(java.lang.String name, java.lang.Object value) throws IllegalStateException
408     {
409         setAttribute(name,value);
410     }
411 
412     /* ------------------------------------------------------------ */
removeAttribute(String name)413     public void removeAttribute(String name)
414     {
415         setAttribute(name,null);
416     }
417 
418     /* ------------------------------------------------------------- */
419     /**
420      * @deprecated As of Version 2.2, this method is replaced by
421      *             {@link #removeAttribute}
422      */
423     @Deprecated
removeValue(java.lang.String name)424     public void removeValue(java.lang.String name) throws IllegalStateException
425     {
426         removeAttribute(name);
427     }
428 
429     /* ------------------------------------------------------------ */
doPutOrRemove(String name, Object value)430     protected Object doPutOrRemove(String name, Object value)
431     {
432         return value==null?_attributes.remove(name):_attributes.put(name,value);
433     }
434 
435     /* ------------------------------------------------------------ */
doGet(String name)436     protected Object doGet(String name)
437     {
438         return _attributes.get(name);
439     }
440 
441     /* ------------------------------------------------------------ */
setAttribute(String name, Object value)442     public void setAttribute(String name, Object value)
443     {
444         Object old=null;
445         synchronized (this)
446         {
447             checkValid();
448             old=doPutOrRemove(name,value);
449         }
450 
451         if (value==null || !value.equals(old))
452         {
453             if (old!=null)
454                 unbindValue(name,old);
455             if (value!=null)
456                 bindValue(name,value);
457 
458             _manager.doSessionAttributeListeners(this,name,old,value);
459 
460         }
461     }
462 
463     /* ------------------------------------------------------------- */
setIdChanged(boolean changed)464     public void setIdChanged(boolean changed)
465     {
466         _idChanged=changed;
467     }
468 
469     /* ------------------------------------------------------------- */
setMaxInactiveInterval(int secs)470     public void setMaxInactiveInterval(int secs)
471     {
472         _maxIdleMs=(long)secs*1000L;
473     }
474 
475     /* ------------------------------------------------------------- */
476     @Override
toString()477     public String toString()
478     {
479         return this.getClass().getName()+":"+getId()+"@"+hashCode();
480     }
481 
482     /* ------------------------------------------------------------- */
483     /** If value implements HttpSessionBindingListener, call valueBound() */
bindValue(java.lang.String name, Object value)484     public void bindValue(java.lang.String name, Object value)
485     {
486         if (value!=null&&value instanceof HttpSessionBindingListener)
487             ((HttpSessionBindingListener)value).valueBound(new HttpSessionBindingEvent(this,name));
488     }
489 
490     /* ------------------------------------------------------------ */
isValid()491     public boolean isValid()
492     {
493         return !_invalid;
494     }
495 
496     /* ------------------------------------------------------------- */
cookieSet()497     protected void cookieSet()
498     {
499         synchronized (this)
500         {
501             _cookieSet=_accessed;
502         }
503     }
504 
505     /* ------------------------------------------------------------ */
getRequests()506     public int getRequests()
507     {
508         synchronized (this)
509         {
510             return _requests;
511         }
512     }
513 
514     /* ------------------------------------------------------------ */
setRequests(int requests)515     public void setRequests(int requests)
516     {
517         synchronized (this)
518         {
519             _requests=requests;
520         }
521     }
522 
523     /* ------------------------------------------------------------- */
524     /** If value implements HttpSessionBindingListener, call valueUnbound() */
unbindValue(java.lang.String name, Object value)525     public void unbindValue(java.lang.String name, Object value)
526     {
527         if (value!=null&&value instanceof HttpSessionBindingListener)
528             ((HttpSessionBindingListener)value).valueUnbound(new HttpSessionBindingEvent(this,name));
529     }
530 
531     /* ------------------------------------------------------------- */
willPassivate()532     public void willPassivate()
533     {
534         synchronized(this)
535         {
536             HttpSessionEvent event = new HttpSessionEvent(this);
537             for (Iterator<Object> iter = _attributes.values().iterator(); iter.hasNext();)
538             {
539                 Object value = iter.next();
540                 if (value instanceof HttpSessionActivationListener)
541                 {
542                     HttpSessionActivationListener listener = (HttpSessionActivationListener) value;
543                     listener.sessionWillPassivate(event);
544                 }
545             }
546         }
547     }
548 
549     /* ------------------------------------------------------------- */
didActivate()550     public void didActivate()
551     {
552         synchronized(this)
553         {
554             HttpSessionEvent event = new HttpSessionEvent(this);
555             for (Iterator<Object> iter = _attributes.values().iterator(); iter.hasNext();)
556             {
557                 Object value = iter.next();
558                 if (value instanceof HttpSessionActivationListener)
559                 {
560                     HttpSessionActivationListener listener = (HttpSessionActivationListener) value;
561                     listener.sessionDidActivate(event);
562                 }
563             }
564         }
565     }
566 
567 
568 }
569