1 16 package org.mortbay.j2ee.session; 17 18 20 import java.lang.reflect.Method ; 21 import java.util.ArrayList ; 22 import java.util.Collection ; 23 import java.util.HashMap ; 24 import java.util.Iterator ; 25 import java.util.Map ; 26 27 import org.jfox.ioc.logger.Logger; 28 29 31 35 38 46 47 abstract public class 48 AbstractReplicatedStore 49 extends AbstractStore 50 { 51 protected final static Logger _log=Logger.getLogger(AbstractReplicatedStore.class); 52 53 protected ClassLoader _loader; 54 55 public 56 AbstractReplicatedStore() 57 { 58 super(); 59 _loader=Thread.currentThread().getContextClassLoader(); 60 } 61 62 public ClassLoader getLoader() {return _loader;} 63 public void setLoader(ClassLoader loader) {_loader=loader;} 64 65 private final static ThreadLocal _replicating=new ThreadLocal (); 68 public static boolean getReplicating() {return _replicating.get()==Boolean.TRUE;} 69 public static void setReplicating(boolean replicating) {_replicating.set(replicating?Boolean.TRUE:Boolean.FALSE);} 70 72 public Object 73 clone() 74 { 75 AbstractReplicatedStore ars=(AbstractReplicatedStore)super.clone(); 76 ars.setLoader(getLoader()); 77 return ars; 78 } 79 80 protected Map _sessions=new HashMap (); 81 82 public int 83 getSessions() 84 { 85 return _sessions.size(); 86 } 87 88 91 public void 92 destroy() { 94 _log.trace("destroying..."); 95 _sessions.clear(); 96 _sessions=null; 97 setManager(null); 98 super.destroy(); 99 _log.trace("...destroyed"); 100 } 101 102 105 public State 106 newState(String id, int maxInactiveInterval) 107 throws Exception 108 { 109 long creationTime=System.currentTimeMillis(); 110 111 if (!AbstractReplicatedStore.getReplicating()) 112 { 113 Object [] argInstances = {id, new Long (creationTime), new Integer (maxInactiveInterval), new Integer (_actualMaxInactiveInterval)}; 114 publish(null, CREATE_SESSION, argInstances); 115 } 116 117 createSession(id, creationTime, maxInactiveInterval, _actualMaxInactiveInterval); 118 119 return loadState(id); 122 } 123 124 public State 125 loadState(String id) 126 { 127 130 Object tmp; 131 synchronized (_sessions) {tmp=_sessions.get(id);} 132 return (State)tmp; 133 } 134 135 public void 136 storeState(State state) 137 { 138 try 139 { 140 String id=state.getId(); 141 synchronized (_sessions){_sessions.put(id, state);} 142 } 143 catch (Exception e) 144 { 145 _log.error("error storing session", e); 146 } 147 } 148 149 public void 150 removeState(State state) 151 throws Exception 152 { 153 String id=state.getId(); 154 155 if (!AbstractReplicatedStore.getReplicating()) 156 { 157 Object [] argInstances = {id}; 158 publish(null, DESTROY_SESSION, argInstances); 159 } 160 161 destroySession(id); 162 } 163 164 167 public void 168 scavenge() 169 throws Exception 170 { 171 _log.trace("starting distributed scavenging..."); 172 Collection copy; 173 synchronized (_sessions) { copy=new ArrayList (_sessions.values()); } 174 if (_log.isTraceEnabled()) 175 { 176 int n; 177 synchronized (_subscribers) { n = _subscribers.size(); } 178 _log.trace(copy.size()+" distributed sessions, "+n+" subscribers"); 179 } 180 int n = 0; 181 for (Iterator i = copy.iterator(); i.hasNext(); ) 182 { 183 LocalState state = (LocalState) i.next(); 184 if (! state.isValid(_scavengerExtraTime)) 185 { 186 String id = state.getId(); 187 if (_log.isDebugEnabled()) _log.debug("scavenging distributed session "+id); 188 destroySession(id); 189 i.remove(); 190 ++n; 191 } 192 } 193 if (_log.isTraceEnabled()) _log.trace("scavenged "+n+" distributed sessions"); 194 _log.trace("...finished distributed scavenging"); 195 } 196 197 200 public void passivateSession(StateAdaptor sa) {} 201 public boolean isDistributed() {return true;} 202 203 206 public String 207 getContextPath() 208 { 209 return getManager().getContextPath(); 210 } 211 212 215 protected static Map _methodToInteger=new HashMap (); 216 protected static Method [] _integerToMethod=new Method [8]; 217 protected static Method CREATE_SESSION; 218 protected static Method DESTROY_SESSION; 219 protected static Method TOUCH_SESSIONS; 220 protected static Method SET_LAST_ACCESSED_TIME; 221 222 static 223 { 224 try 229 { 230 int index=0; 231 Method m=null; 232 233 m=CREATE_SESSION=AbstractReplicatedStore.class.getMethod("createSession", new Class []{String .class, Long.TYPE, Integer.TYPE, Integer.TYPE}); 235 _integerToMethod[index]=m; 236 _methodToInteger.put(m.getName(), new Integer (index)); 237 index++; 238 239 m=DESTROY_SESSION=AbstractReplicatedStore.class.getMethod("destroySession", new Class []{String .class}); 240 _integerToMethod[index]=m; 241 _methodToInteger.put(m.getName(), new Integer (index)); 242 index++; 243 244 m=TOUCH_SESSIONS=AbstractReplicatedStore.class.getMethod("touchSessions", new Class []{String [].class, Long.TYPE}); 245 _integerToMethod[index]=m; 246 _methodToInteger.put(m.getName(), new Integer (index)); 247 index++; 248 249 m=SET_LAST_ACCESSED_TIME=State.class.getMethod("setLastAccessedTime", new Class []{Long.TYPE}); 251 _integerToMethod[index]=m; 252 _methodToInteger.put(m.getName(), new Integer (index)); 253 index++; 254 255 m=State.class.getMethod("setMaxInactiveInterval", new Class []{Integer.TYPE}); 256 _integerToMethod[index]=m; 257 _methodToInteger.put(m.getName(), new Integer (index)); 258 index++; 259 260 m=State.class.getMethod("setAttribute", new Class []{String .class, Object .class, Boolean.TYPE}); 261 _integerToMethod[index]=m; 262 _methodToInteger.put(m.getName(), new Integer (index)); 263 index++; 264 265 m=State.class.getMethod("setAttributes", new Class []{Map .class}); 266 _integerToMethod[index]=m; 267 _methodToInteger.put(m.getName(), new Integer (index)); 268 index++; 269 270 m=State.class.getMethod("removeAttribute", new Class []{String .class, Boolean.TYPE}); 271 _integerToMethod[index]=m; 272 _methodToInteger.put(m.getName(), new Integer (index)); 273 index++; 274 } 275 catch (Exception e) 276 { 277 System.err.println("AbstractReplicatedStore: something went wrong building dispatch tables"); 278 e.printStackTrace(System.err); 279 } 280 } 281 282 abstract protected void publish(String id, Method method, Object [] argInstances); 283 284 protected void 285 dispatch(String id, Integer methodId, Object [] argInstances) 286 { 287 try 288 { 289 AbstractReplicatedStore.setReplicating(true); 290 291 Object target=null; 292 if (id==null) 293 { 294 target=this; 296 } 297 else 298 { 299 synchronized (_subscribers){target=_subscribers.get(id);} 301 } 302 303 try 304 { 305 Method method=_integerToMethod[methodId.intValue()]; 306 if (target==null) 307 _log.warn("null target for "+method); 308 else 309 method.invoke(target, argInstances); 310 } 311 catch (Exception e) 312 { 313 _log.error("this should never happen - code version mismatch ?", e); 314 } 315 } 316 finally 317 { 318 AbstractReplicatedStore.setReplicating(false); 319 } 320 } 321 322 public void 323 createSession(String id, long creationTime, int maxInactiveInterval, int actualMaxInactiveInterval) 324 { 325 if (_log.isTraceEnabled()) _log.trace("creating replicated session: "+id); 326 State state=new LocalState(id, creationTime, maxInactiveInterval, actualMaxInactiveInterval); 327 synchronized(_sessions) {_sessions.put(id, state);} 328 329 if (AbstractReplicatedStore.getReplicating()) 330 { 331 getManager().getHttpSession(id); } 334 } 335 336 public void 337 destroySession(String id) 338 { 339 if (_log.isTraceEnabled()) _log.trace("destroying replicated session: "+id); 340 if(getManager().sessionExists(id)) 341 getManager().destroySession(getManager().getHttpSession(id)); 342 synchronized(_sessions) {_sessions.remove(id);} 343 } 344 345 public void 346 touchSessions(String [] ids, long time) 347 { 348 for (int i=0;i<ids.length;i++) 350 { 351 String id=ids[i]; 352 Object target; 353 synchronized (_subscribers){target=_subscribers.get(id);} 356 try 357 { 358 ((StateInterceptor)target).setLastAccessedTime(time); 359 } 360 catch (Exception e) 361 { 362 _log.warn("unable to touch session: "+id+" probably already removed"); 363 } 364 } 365 } 366 367 370 protected Map _subscribers=new HashMap (); 371 372 public void 373 subscribe(String id, Object o) 374 { 375 _log.trace("subscribing: "+id); 376 synchronized (_subscribers) {_subscribers.put(id, o);} 377 } 378 379 public void 380 unsubscribe(String id) 381 { 382 _log.trace("unsubscribing: "+id); 383 synchronized (_subscribers) {_subscribers.remove(id);} 384 } 385 } 386 | Popular Tags |