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
26
27
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;
37 private final String _nodeId;
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;
43 private long _lastAccessed;
44 private boolean _invalid;
45 private boolean _doInvalidate;
46 private long _maxIdleMs;
47 private boolean _newSession;
48 private int _requests;
49
50
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
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
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
214
215
216 @Deprecated
217 public Object getValue(String name) throws IllegalStateException
218 {
219 return getAttribute(name);
220 }
221
222
223
224
225
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
277 _manager.removeSession(this,true);
278
279
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
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
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
365
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
382
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
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
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 }