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