1 29 30 package com.caucho.quercus.lib.session; 31 32 import com.caucho.config.ConfigException; 33 import com.caucho.quercus.env.Env; 34 import com.caucho.quercus.env.SessionArrayValue; 35 import com.caucho.util.*; 36 37 import java.io.IOException ; 38 import java.io.ObjectInputStream ; 39 import java.io.ObjectOutputStream ; 40 import java.util.ArrayList ; 41 import java.util.Iterator ; 42 import java.util.logging.Level ; 43 import java.util.logging.Logger ; 44 45 49 public class QuercusSessionManager { 50 static protected final L10N L = new L10N(QuercusSessionManager.class); 51 static protected final Logger log 52 = Logger.getLogger(QuercusSessionManager.class.getName()); 53 54 private static int FALSE = 0; 55 private static int COOKIE = 1; 56 private static int TRUE = 2; 57 58 private static int UNSET = 0; 59 private static int SET_TRUE = 1; 60 private static int SET_FALSE = 2; 61 62 protected LruCache<String ,SessionArrayValue> _sessions; 64 private int _totalSessions; 66 67 protected Iterator <SessionArrayValue> _sessionIter; 69 protected ArrayList <SessionArrayValue> _sessionList 71 = new ArrayList <SessionArrayValue>(); 72 73 protected int _sessionMax = 4096; 75 private long _sessionTimeout = 30 * 60 * 1000L; 76 77 private int _reuseSessionId = COOKIE; 78 private int _cookieLength = 18; 79 80 private int _alwaysLoadSession; 81 private boolean _alwaysSaveSession; 82 private boolean _saveOnlyOnShutdown; 83 84 private boolean _isModuloSessionId = false; 85 private boolean _isAppendServerIndex = false; 86 private boolean _isTwoDigitSessionIndex = false; 87 88 protected boolean _isClosed; 89 90 92 protected Object _statisticsLock = new Object (); 94 protected long _sessionCreateCount; 95 protected long _sessionTimeoutCount; 96 97 100 public QuercusSessionManager() 101 { 102 _sessions = new LruCache<String ,SessionArrayValue>(_sessionMax); 103 _sessionIter = _sessions.values(); 104 } 105 106 109 boolean getAlwaysSaveSession() 110 { 111 return _alwaysSaveSession; 112 } 113 114 117 public void setAlwaysSaveSession(boolean save) 118 { 119 _alwaysSaveSession = save; 120 } 121 122 125 boolean getAlwaysLoadSession() 126 { 127 return _alwaysLoadSession == SET_TRUE; 128 } 129 130 133 public void setAlwaysLoadSession(boolean load) 134 { 135 _alwaysLoadSession = load ? SET_TRUE : SET_FALSE; 136 } 137 138 141 public boolean getSaveOnlyOnShutdown() 142 { 143 return _saveOnlyOnShutdown; 144 } 145 146 149 public void setSaveOnlyOnShutdown(boolean save) 150 { 151 _saveOnlyOnShutdown = save; 152 } 153 154 157 public void setSaveOnShutdown(boolean save) 158 { 159 log.warning("<save-on-shutdown> is deprecated. Use <save-only-on-shutdown> instead"); 160 161 setSaveOnlyOnShutdown(save); 162 } 163 164 167 public void setCookieLength(int cookieLength) 168 { 169 if (cookieLength < 7) 170 cookieLength = 7; 171 172 _cookieLength = cookieLength; 173 } 174 175 178 public int getActiveSessionCount() 179 { 180 if (_sessions == null) 181 return -1; 182 else 183 return _sessions.size(); 184 } 185 186 189 public long getSessionCreateCount() 190 { 191 return _sessionCreateCount; 192 } 193 194 197 public long getSessionTimeoutCount() 198 { 199 return _sessionTimeoutCount; 200 } 201 202 206 public int getReuseSessionId() 207 { 208 return _reuseSessionId; 209 } 210 211 215 public void setReuseSessionId(String reuse) 216 throws ConfigException 217 { 218 if (reuse == null) 219 _reuseSessionId = COOKIE; 220 else if (reuse.equalsIgnoreCase("true") || 221 reuse.equalsIgnoreCase("yes") || 222 reuse.equalsIgnoreCase("cookie")) 223 _reuseSessionId = COOKIE; 224 else if (reuse.equalsIgnoreCase("false") || reuse.equalsIgnoreCase("no")) 225 _reuseSessionId = FALSE; 226 else if (reuse.equalsIgnoreCase("all")) 227 _reuseSessionId = TRUE; 228 else 229 throw new ConfigException(L.l("'{0}' is an invalid value for reuse-session-id. 'true' or 'false' are the allowed values.", 230 reuse)); 231 } 232 233 236 public boolean isClosed() 237 { 238 return _isClosed; 239 } 240 241 244 public int getSessionMax() 245 { 246 return _sessionMax; 247 } 248 249 252 public void setSessionMax(int max) 253 { 254 _sessionMax = max; 255 } 256 257 261 public void removeSession(String sessionId) 262 { 263 _sessions.remove(sessionId); 264 265 remove(sessionId); 266 } 267 268 protected void remove(String sessionId) 269 { 270 } 271 272 278 public void load(ObjectInputStream in, Object obj) 279 throws IOException 280 { 281 SessionArrayValue session = (SessionArrayValue) obj; 282 283 session.load(null, in); 284 } 285 286 289 public boolean isEmpty(Object obj) 290 { 291 SessionArrayValue session = (SessionArrayValue) obj; 292 293 return session.isEmpty(); 294 } 295 296 299 public void setCookieAppendServerIndex(boolean isAppend) 300 { 301 _isAppendServerIndex = isAppend; 302 } 303 304 311 public SessionArrayValue createSession(Env env, String oldId, long now) 312 { 313 String id = oldId; 314 315 if (id == null || id.length() < 4) 316 id = createSessionId(env); 317 318 SessionArrayValue session = create(env, id, now); 319 320 if (session == null) 321 return null; 322 323 synchronized (_statisticsLock) { 324 _sessionCreateCount++; 325 } 326 327 return session; 328 } 329 330 335 public String createSessionId(Env env) 336 { 337 String id; 338 339 do { 340 CharBuffer sb = new CharBuffer(); 341 342 Base64.encode(sb, RandomUtil.getRandomLong()); 343 Base64.encode(sb, Alarm.getCurrentTime()); 344 345 id = sb.toString(); 346 } while (getSession(env, id, 0) != null); 347 348 if (id == null || id.equals("")) 349 throw new RuntimeException (); 350 351 return id; 352 } 353 354 366 public SessionArrayValue getSession(Env env, String key, long now) 367 { 368 SessionArrayValue session; 369 boolean isNew = false; 370 boolean killSession = false; 371 372 if (_sessions == null) 373 return null; 374 375 session = _sessions.get(key); 377 378 if (session != null && ! session.getId().equals(key)) 379 throw new IllegalStateException (key + " != " + session.getId()); 380 381 if (session != null) { 382 if (session.inUse()) 383 return (SessionArrayValue)session.copy(env); 384 } 385 386 if (session == null) 387 return null; 388 389 if (isNew) { 390 isNew = ! load(env, session, now); 391 } 392 else if (! getSaveOnlyOnShutdown() && ! session.load()) { 393 session.reset(now); 395 isNew = true; 396 } 397 398 if (! isNew) 399 session.setAccess(now); 400 401 return (SessionArrayValue)session.copy(env); 402 } 403 404 public void saveSession(Env env, SessionArrayValue session) 405 { 406 SessionArrayValue copy = (SessionArrayValue) session.copy(env); 407 408 _sessions.put(session.getId(), copy); 409 session.finish(); 410 } 411 412 416 protected SessionArrayValue create(Env env, String key, long now) 417 { 418 SessionArrayValue session 419 = new SessionArrayValue(key, now, _sessionTimeout); 420 421 session = _sessions.putIfNew(key, session); 424 425 if (! key.equals(session.getId())) 426 throw new IllegalStateException (key + " != " + session.getId()); 427 428 return (SessionArrayValue)session.copy(env); 429 } 430 431 440 protected boolean load(Env env, SessionArrayValue session, long now) 441 { 442 try { 443 if (session.inUse()) { 444 return true; 445 } 446 else if (now <= 0) { 447 return false; 448 } 449 else if (session.load()) { 450 session.setAccess(now); 451 return true; 452 } 453 else { 454 session.reset(now); 455 } 456 } catch (Exception e) { 457 log.log(Level.FINE, e.toString(), e); 458 session.reset(now); 459 } 460 461 return false; 462 } 463 464 467 public void handleAlarm(Alarm alarm) 468 { 469 try { 470 _sessionList.clear(); 471 472 int liveSessions = 0; 473 474 if (_isClosed) 475 return; 476 477 long now = Alarm.getCurrentTime(); 478 long accessWindow = 0; 479 480 synchronized (_sessions) { 481 _sessionIter = _sessions.values(_sessionIter); 482 483 while (_sessionIter.hasNext()) { 484 SessionArrayValue session = _sessionIter.next(); 485 486 long maxIdleTime = session.getMaxInactiveInterval() + accessWindow; 487 488 if (session.inUse()) 489 liveSessions++; 490 else if (session.getAccessTime() + maxIdleTime < now) 491 _sessionList.add(session); 492 else 493 liveSessions++; 494 } 495 } 496 497 synchronized (_statisticsLock) { 498 _sessionTimeoutCount += _sessionList.size(); 499 } 500 501 for (int i = 0; i < _sessionList.size(); i++) { 502 SessionArrayValue session = _sessionList.get(i); 503 504 try { 505 long maxIdleTime = session.getMaxInactiveInterval(); 506 _sessions.remove(session.getId()); 507 508 session.invalidate(); 509 } catch (Throwable e) { 510 log.log(Level.FINER, e.toString(), e); 511 } 512 } 513 } finally { 514 518 } 519 } 520 521 524 public void close() 525 { 526 synchronized (this) { 527 if (_isClosed) 528 return; 529 _isClosed = true; 530 } 531 532 if (_sessions == null) 533 return; 534 535 537 _sessionList.clear(); 538 539 ArrayList <SessionArrayValue> list = new ArrayList <SessionArrayValue>(); 540 541 boolean isError = false; 542 543 synchronized (_sessions) { 544 _sessionIter = _sessions.values(_sessionIter); 545 546 while (_sessionIter.hasNext()) { 547 SessionArrayValue session = _sessionIter.next(); 548 549 if (session.isValid()) 550 list.add(session); 551 } 552 } 553 554 for (int i = list.size() - 1; i >= 0; i--) { 555 SessionArrayValue session = list.get(i); 556 557 try { 558 if (session.isValid()) { 559 synchronized (session) { 560 if (! session.isEmpty()) 561 session.storeOnShutdown(); 562 } 563 } 564 565 _sessions.remove(session.getId()); 566 } catch (Exception e) { 567 if (! isError) 568 log.log(Level.WARNING, "Can't store session: " + e, e); 569 isError = true; 570 } 571 } 572 } 573 574 577 public void notifyRemove(String id) 578 { 579 SessionArrayValue session = _sessions.remove(id); 580 581 if (session != null) 582 session.invalidate(); 583 } 584 585 588 public void notifyUpdate(String id) 589 { 590 } 591 592 595 public void store(ObjectOutputStream out, Object obj) 596 throws IOException 597 { 598 SessionArrayValue session = (SessionArrayValue) obj; 599 600 session.store(out); 601 } 602 } 603 | Popular Tags |