1 7 package winstone; 8 9 import java.io.File ; 10 import java.io.FileInputStream ; 11 import java.io.FileOutputStream ; 12 import java.io.IOException ; 13 import java.io.InputStream ; 14 import java.io.ObjectInputStream ; 15 import java.io.ObjectOutputStream ; 16 import java.io.OutputStream ; 17 import java.io.Serializable ; 18 import java.util.ArrayList ; 19 import java.util.Collections ; 20 import java.util.Enumeration ; 21 import java.util.HashMap ; 22 import java.util.HashSet ; 23 import java.util.Hashtable ; 24 import java.util.Iterator ; 25 import java.util.List ; 26 import java.util.Map ; 27 import java.util.Set ; 28 29 import javax.servlet.ServletContext ; 30 import javax.servlet.http.HttpSession ; 31 import javax.servlet.http.HttpSessionActivationListener ; 32 import javax.servlet.http.HttpSessionAttributeListener ; 33 import javax.servlet.http.HttpSessionBindingEvent ; 34 import javax.servlet.http.HttpSessionBindingListener ; 35 import javax.servlet.http.HttpSessionEvent ; 36 import javax.servlet.http.HttpSessionListener ; 37 38 44 public class WinstoneSession implements HttpSession , Serializable { 45 public static final String SESSION_COOKIE_NAME = "JSESSIONID"; 46 47 private String sessionId; 48 private WebAppConfiguration webAppConfig; 49 private Map sessionData; 50 private long createTime; 51 private long lastAccessedTime; 52 private int maxInactivePeriod; 53 private boolean isNew; 54 private boolean isInvalidated; 55 private HttpSessionAttributeListener sessionAttributeListeners[]; 56 private HttpSessionListener sessionListeners[]; 57 private HttpSessionActivationListener sessionActivationListeners[]; 58 private boolean distributable; 59 private Object sessionMonitor = new Boolean (true); 60 private Set requestsUsingMe; 61 62 65 public WinstoneSession(String sessionId) { 66 this.sessionId = sessionId; 67 this.sessionData = new HashMap (); 68 this.requestsUsingMe = new HashSet (); 69 this.createTime = System.currentTimeMillis(); 70 this.isNew = true; 71 this.isInvalidated = false; 72 } 73 74 public void setWebAppConfiguration(WebAppConfiguration webAppConfig) { 75 this.webAppConfig = webAppConfig; 76 this.distributable = webAppConfig.isDistributable(); 77 } 78 79 public void sendCreatedNotifies() { 80 for (int n = 0; n < this.sessionListeners.length; n++) { 82 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 83 Thread.currentThread().setContextClassLoader(this.webAppConfig.getLoader()); 84 this.sessionListeners[n].sessionCreated(new HttpSessionEvent (this)); 85 Thread.currentThread().setContextClassLoader(cl); 86 } 87 } 88 89 public void setSessionActivationListeners( 90 HttpSessionActivationListener listeners[]) { 91 this.sessionActivationListeners = listeners; 92 } 93 94 public void setSessionAttributeListeners( 95 HttpSessionAttributeListener listeners[]) { 96 this.sessionAttributeListeners = listeners; 97 } 98 99 public void setSessionListeners(HttpSessionListener listeners[]) { 100 this.sessionListeners = listeners; 101 } 102 103 public void setLastAccessedDate(long time) { 104 this.lastAccessedTime = time; 105 } 106 107 public void setIsNew(boolean isNew) { 108 this.isNew = isNew; 109 } 110 111 public void addUsed(WinstoneRequest request) { 112 this.requestsUsingMe.add(request); 113 } 114 115 public void removeUsed(WinstoneRequest request) { 116 this.requestsUsingMe.remove(request); 117 } 118 119 public boolean isUnusedByRequests() { 120 return this.requestsUsingMe.isEmpty(); 121 } 122 123 public boolean isExpired() { 124 long nowDate = System.currentTimeMillis(); 126 long maxInactive = getMaxInactiveInterval() * 1000; 127 return ((maxInactive > 0) && (nowDate - this.lastAccessedTime > maxInactive )); 128 } 129 130 public Object getAttribute(String name) { 132 if (this.isInvalidated) { 133 throw new IllegalStateException (Launcher.RESOURCES.getString("WinstoneSession.InvalidatedSession")); 134 } 135 Object att = null; 136 synchronized (this.sessionMonitor) { 137 att = this.sessionData.get(name); 138 } 139 return att; 140 } 141 142 public Enumeration getAttributeNames() { 143 if (this.isInvalidated) { 144 throw new IllegalStateException (Launcher.RESOURCES.getString("WinstoneSession.InvalidatedSession")); 145 } 146 Enumeration names = null; 147 synchronized (this.sessionMonitor) { 148 names = Collections.enumeration(this.sessionData.keySet()); 149 } 150 return names; 151 } 152 153 public void setAttribute(String name, Object value) { 154 if (this.isInvalidated) { 155 throw new IllegalStateException (Launcher.RESOURCES.getString("WinstoneSession.InvalidatedSession")); 156 } 157 if (this.distributable && (value != null) 159 && !(value instanceof java.io.Serializable )) 160 throw new IllegalArgumentException (Launcher.RESOURCES.getString( 161 "WinstoneSession.AttributeNotSerializable", new String [] { 162 name, value.getClass().getName() })); 163 164 if (value instanceof HttpSessionBindingListener ) { 166 HttpSessionBindingListener hsbl = (HttpSessionBindingListener ) value; 167 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 168 Thread.currentThread().setContextClassLoader(this.webAppConfig.getLoader()); 169 hsbl.valueBound(new HttpSessionBindingEvent (this, name, value)); 170 Thread.currentThread().setContextClassLoader(cl); 171 } 172 173 Object oldValue = null; 174 synchronized (this.sessionMonitor) { 175 oldValue = this.sessionData.get(name); 176 if (value == null) { 177 this.sessionData.remove(name); 178 } else { 179 this.sessionData.put(name, value); 180 } 181 } 182 183 if (oldValue instanceof HttpSessionBindingListener ) { 185 HttpSessionBindingListener hsbl = (HttpSessionBindingListener ) oldValue; 186 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 187 Thread.currentThread().setContextClassLoader(this.webAppConfig.getLoader()); 188 hsbl.valueUnbound(new HttpSessionBindingEvent (this, name, oldValue)); 189 Thread.currentThread().setContextClassLoader(cl); 190 } 191 192 if (oldValue != null) 194 for (int n = 0; n < this.sessionAttributeListeners.length; n++) { 195 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 196 Thread.currentThread().setContextClassLoader(this.webAppConfig.getLoader()); 197 this.sessionAttributeListeners[n].attributeReplaced( 198 new HttpSessionBindingEvent (this, name, oldValue)); 199 Thread.currentThread().setContextClassLoader(cl); 200 } 201 202 else 203 for (int n = 0; n < this.sessionAttributeListeners.length; n++) { 204 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 205 Thread.currentThread().setContextClassLoader(this.webAppConfig.getLoader()); 206 this.sessionAttributeListeners[n].attributeAdded( 207 new HttpSessionBindingEvent (this, name, value)); 208 Thread.currentThread().setContextClassLoader(cl); 209 210 } 211 } 212 213 public void removeAttribute(String name) { 214 if (this.isInvalidated) { 215 throw new IllegalStateException (Launcher.RESOURCES.getString("WinstoneSession.InvalidatedSession")); 216 } 217 Object value = null; 218 synchronized (this.sessionMonitor) { 219 value = this.sessionData.get(name); 220 this.sessionData.remove(name); 221 } 222 223 if (value instanceof HttpSessionBindingListener ) { 225 HttpSessionBindingListener hsbl = (HttpSessionBindingListener ) value; 226 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 227 Thread.currentThread().setContextClassLoader(this.webAppConfig.getLoader()); 228 hsbl.valueUnbound(new HttpSessionBindingEvent (this, name)); 229 Thread.currentThread().setContextClassLoader(cl); 230 } 231 if (value != null) 232 for (int n = 0; n < this.sessionAttributeListeners.length; n++) { 233 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 234 Thread.currentThread().setContextClassLoader(this.webAppConfig.getLoader()); 235 this.sessionAttributeListeners[n].attributeRemoved( 236 new HttpSessionBindingEvent (this, name, value)); 237 Thread.currentThread().setContextClassLoader(cl); 238 } 239 } 240 241 public long getCreationTime() { 242 if (this.isInvalidated) { 243 throw new IllegalStateException (Launcher.RESOURCES.getString("WinstoneSession.InvalidatedSession")); 244 } 245 return this.createTime; 246 } 247 248 public long getLastAccessedTime() { 249 if (this.isInvalidated) { 250 throw new IllegalStateException (Launcher.RESOURCES.getString("WinstoneSession.InvalidatedSession")); 251 } 252 return this.lastAccessedTime; 253 } 254 255 public String getId() { 256 return this.sessionId; 257 } 258 259 public int getMaxInactiveInterval() { 260 return this.maxInactivePeriod; 261 } 262 263 public void setMaxInactiveInterval(int interval) { 264 this.maxInactivePeriod = interval; 265 } 266 267 public boolean isNew() { 268 if (this.isInvalidated) { 269 throw new IllegalStateException (Launcher.RESOURCES.getString("WinstoneSession.InvalidatedSession")); 270 } 271 return this.isNew; 272 } 273 274 public ServletContext getServletContext() { 275 return this.webAppConfig; 276 } 277 278 public void invalidate() { 279 if (this.isInvalidated) { 280 throw new IllegalStateException (Launcher.RESOURCES.getString("WinstoneSession.InvalidatedSession")); 281 } 282 for (int n = this.sessionListeners.length - 1; n >= 0; n--) { 284 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 285 Thread.currentThread().setContextClassLoader(this.webAppConfig.getLoader()); 286 this.sessionListeners[n].sessionDestroyed(new HttpSessionEvent (this)); 287 Thread.currentThread().setContextClassLoader(cl); 288 } 289 290 List keys = new ArrayList (this.sessionData.keySet()); 291 for (Iterator i = keys.iterator(); i.hasNext();) 292 removeAttribute((String ) i.next()); 293 synchronized (this.sessionMonitor) { 294 this.sessionData.clear(); 295 } 296 this.isInvalidated = true; 297 this.webAppConfig.removeSessionById(this.sessionId); 298 } 299 300 303 public void passivate() { 304 for (int n = 0; n < this.sessionActivationListeners.length; n++) { 306 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 307 Thread.currentThread().setContextClassLoader(this.webAppConfig.getLoader()); 308 this.sessionActivationListeners[n].sessionWillPassivate( 309 new HttpSessionEvent (this)); 310 Thread.currentThread().setContextClassLoader(cl); 311 } 312 313 synchronized (this.sessionMonitor) { 319 this.sessionData.clear(); 320 } 321 this.webAppConfig.removeSessionById(this.sessionId); 322 } 323 324 327 public void activate(WebAppConfiguration webAppConfig) { 328 this.webAppConfig = webAppConfig; 329 webAppConfig.setSessionListeners(this); 330 331 for (int n = 0; n < this.sessionActivationListeners.length; n++) { 333 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 334 Thread.currentThread().setContextClassLoader(this.webAppConfig.getLoader()); 335 this.sessionActivationListeners[n].sessionDidActivate( 336 new HttpSessionEvent (this)); 337 Thread.currentThread().setContextClassLoader(cl); 338 } 339 } 340 341 344 public void saveToTemp() { 345 File toDir = getSessionTempDir(this.webAppConfig); 346 synchronized (this.sessionMonitor) { 347 OutputStream out = null; 348 ObjectOutputStream objOut = null; 349 try { 350 File toFile = new File (toDir, this.sessionId + ".ser"); 351 out = new FileOutputStream (toFile, false); 352 objOut = new ObjectOutputStream (out); 353 objOut.writeObject(this); 354 } catch (IOException err) { 355 Logger.log(Logger.ERROR, Launcher.RESOURCES, 356 "WinstoneSession.ErrorSavingSession", err); 357 } finally { 358 if (objOut != null) { 359 try {objOut.close();} catch (IOException err) {} 360 } 361 if (out != null) { 362 try {out.close();} catch (IOException err) {} 363 } 364 } 365 } 366 } 367 368 public static File getSessionTempDir(WebAppConfiguration webAppConfig) { 369 File tmpDir = (File ) webAppConfig.getAttribute("javax.servlet.context.tempdir"); 370 File sessionsDir = new File (tmpDir, "WEB-INF" + File.separator + "winstoneSessions"); 371 if (!sessionsDir.exists()) { 372 sessionsDir.mkdirs(); 373 } 374 return sessionsDir; 375 } 376 377 public static void loadSessions(WebAppConfiguration webAppConfig) { 378 int expiredCount = 0; 379 File tempDir = getSessionTempDir(webAppConfig); 381 File possibleSessionFiles[] = tempDir.listFiles(); 382 for (int n = 0; n < possibleSessionFiles.length; n++) { 383 if (possibleSessionFiles[n].getName().endsWith(".ser")) { 384 InputStream in = null; 385 ObjectInputStream objIn = null; 386 try { 387 in = new FileInputStream (possibleSessionFiles[n]); 388 objIn = new ObjectInputStream (in); 389 WinstoneSession session = (WinstoneSession) objIn.readObject(); 390 session.setWebAppConfiguration(webAppConfig); 391 webAppConfig.setSessionListeners(session); 392 if (session.isExpired()) { 393 session.invalidate(); 394 expiredCount++; 395 } else { 396 webAppConfig.addSession(session.getId(), session); 397 Logger.log(Logger.DEBUG, Launcher.RESOURCES, 398 "WinstoneSession.RestoredSession", session.getId()); 399 } 400 } catch (Throwable err) { 401 Logger.log(Logger.ERROR, Launcher.RESOURCES, 402 "WinstoneSession.ErrorLoadingSession", err); 403 } finally { 404 if (objIn != null) { 405 try {objIn.close();} catch (IOException err) {} 406 } 407 if (in != null) { 408 try {in.close();} catch (IOException err) {} 409 } 410 possibleSessionFiles[n].delete(); 411 } 412 } 413 } 414 if (expiredCount > 0) { 415 Logger.log(Logger.DEBUG, Launcher.RESOURCES, 416 "WebAppConfig.InvalidatedSessions", expiredCount + ""); 417 } 418 } 419 420 428 private void writeObject(java.io.ObjectOutputStream out) throws IOException { 429 out.writeUTF(sessionId); 430 out.writeLong(createTime); 431 out.writeLong(lastAccessedTime); 432 out.writeInt(maxInactivePeriod); 433 out.writeBoolean(isNew); 434 out.writeBoolean(distributable); 435 436 Map copy = new HashMap (sessionData); 438 Set keys = new HashSet (copy.keySet()); 439 for (Iterator i = keys.iterator(); i.hasNext();) { 440 String key = (String ) i.next(); 441 if (!(copy.get(key) instanceof Serializable )) { 442 Logger.log(Logger.WARNING, Launcher.RESOURCES, 443 "WinstoneSession.SkippingNonSerializable", 444 new String [] { key, 445 copy.get(key).getClass().getName() }); 446 } 447 copy.remove(key); 448 } 449 out.writeInt(copy.size()); 450 for (Iterator i = copy.keySet().iterator(); i.hasNext();) { 451 String key = (String ) i.next(); 452 out.writeUTF(key); 453 out.writeObject(copy.get(key)); 454 } 455 } 456 457 465 private void readObject(java.io.ObjectInputStream in) throws IOException , 466 ClassNotFoundException { 467 this.sessionId = in.readUTF(); 468 this.createTime = in.readLong(); 469 this.lastAccessedTime = in.readLong(); 470 this.maxInactivePeriod = in.readInt(); 471 this.isNew = in.readBoolean(); 472 this.distributable = in.readBoolean(); 473 474 this.sessionData = new Hashtable (); 476 this.requestsUsingMe = new HashSet (); 477 int entryCount = in.readInt(); 478 for (int n = 0; n < entryCount; n++) { 479 String key = in.readUTF(); 480 Object variable = in.readObject(); 481 this.sessionData.put(key, variable); 482 } 483 this.sessionMonitor = new Boolean (true); 484 } 485 486 489 public Object getValue(String name) { 490 return getAttribute(name); 491 } 492 493 496 public void putValue(String name, Object value) { 497 setAttribute(name, value); 498 } 499 500 503 public void removeValue(String name) { 504 removeAttribute(name); 505 } 506 507 510 public String [] getValueNames() { 511 return (String []) this.sessionData.keySet().toArray(new String [0]); 512 } 513 514 517 public javax.servlet.http.HttpSessionContext getSessionContext() { 518 return null; 519 } } 521 | Popular Tags |