View Javadoc

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