1 7 8 package org.jboss.web.tomcat.tc5.session; 9 10 import java.io.IOException ; 11 import java.util.*; 12 import javax.management.ObjectName ; 13 14 import org.jboss.cache.CacheException; 15 import org.jboss.cache.Fqn; 16 import org.jboss.cache.TreeCache; 17 import org.jboss.cache.TreeCacheListener; 18 import org.jboss.cache.TreeCacheMBean; 19 import org.jboss.cache.lock.TimeoutException; 20 import org.jboss.invocation.MarshalledValue; 21 import org.jboss.logging.Logger; 22 import org.jboss.mx.util.MBeanProxyExt; 23 import org.jboss.web.tomcat.tc5.Tomcat5; 24 import org.jgroups.View; 25 26 36 public class JBossCacheService implements TreeCacheListener 37 { 38 private TreeCacheMBean proxy_; 39 private ObjectName cacheServiceName_; 40 protected static Logger log_ = Logger.getLogger(JBossCacheService.class); 41 public static final String SESSION = "JSESSION"; 42 public static final String ATTRIBUTE = "ATTRIBUTE"; 43 public static final String KEY = "ATRR_KEY"; 44 private static final int RETRY = 3; 45 private static final String VERSION_KEY = "VERSION"; 47 private String jvmRoute_; 49 private String webAppPath_; 51 private List newSessionIDList_; 53 54 private ClassLoader tcl_; 56 private JBossCacheManager manager_; 57 58 public JBossCacheService() throws ClusteringNotSupportedException 59 { 60 try 62 { 63 cacheServiceName_ = new ObjectName (Tomcat5.DEFAULT_CACHE_NAME); 64 proxy_ = (TreeCacheMBean) MBeanProxyExt.create(TreeCacheMBean.class, cacheServiceName_); 67 if (proxy_ == null) 68 { 69 throw new RuntimeException ("JBossCacheService: locate null TomcatCacheMbean"); 70 } 71 72 newSessionIDList_ = new ArrayList(); 73 } 74 catch (Throwable e) 75 { 76 String str = cacheServiceName_ + " service to Tomcat clustering not found"; 77 log_.error(str); 78 throw new ClusteringNotSupportedException(str); 79 } 80 } 81 82 public void start(ClassLoader tcl, JBossCacheManager manager) 83 { 84 tcl_ = tcl; 85 manager_ = manager; 86 jvmRoute_ = null; 87 proxy_.addTreeCacheListener(this); 88 String path = manager_.getContainer().getName(); 89 if( path.length() == 0 || path.equals("/")) { 90 webAppPath_ = "ROOT"; 92 } if ( path.startsWith("/") ) { 93 webAppPath_ = path.substring(1); 94 } else { 95 webAppPath_ = path; 96 } 97 log_.debug("Old and new web app path are: " +path + ", " +webAppPath_); 98 } 99 100 public void stop() 101 { 102 proxy_.removeTreeCacheListener(this); 103 } 104 105 111 public List findSessionIDs() 112 { 113 List ids = new ArrayList(); 114 try { 115 Object [] objs = new Object []{SESSION, webAppPath_}; 117 Fqn path = new Fqn( objs ); 118 Set names = proxy_.getChildrenNames(path); 120 121 if( names == null ) return ids; 122 for(Iterator it = names.iterator(); it.hasNext();) { 123 Object id = it.next(); 124 if(id==null) continue; 125 ids.add(id); 126 if(log_.isTraceEnabled()) { 127 log_.trace("Retrieving through web app path with fqn: " +path + " and session id: " +id); 128 } 129 } 130 } catch (CacheException e) { 131 e.printStackTrace(); 132 throw new RuntimeException ("JBossCacheService: exception occurred in cache getChildrenNames ... ", e); 133 } 134 return ids; 135 } 136 137 public Object getSession(String id) 138 { 139 String realId = stripJvmRoute(id); 140 Fqn fqn = getSessionFqn(realId); 141 return getUnMarshalledValue(_get(fqn, realId)); 142 } 143 144 public void putSession(String id, Object session) 145 { 146 String realId = stripJvmRoute(id); 147 Fqn fqn = getSessionFqn(realId); 148 _put(fqn, realId, getMarshalledValue(session)); 156 _put(fqn, VERSION_KEY, new Integer (((ClusteredSession)session).getVersion())); 158 } 159 160 public Object removeSession(String id) 161 { 162 String realId = stripJvmRoute(id); 163 Fqn fqn = getSessionFqn(realId); 164 if (log_.isDebugEnabled()) 165 { 166 log_.debug("Remove session from distributed store. Fqn: " + fqn); 167 } 168 Object obj = getUnMarshalledValue(_remove(fqn, realId)); 169 _remove(fqn); 173 return obj; 174 } 175 176 public void removeSessionLocal(String id) 177 { 178 String realId = stripJvmRoute(id); 179 Fqn fqn = getSessionFqn(realId); 180 if (log_.isDebugEnabled()) 181 { 182 log_.debug("Remove session from my own distributed store only. Fqn: " + fqn); 183 } 184 _evict(fqn); 185 } 186 187 public boolean exists(String id) 188 { 189 String realId = stripJvmRoute(id); 190 Fqn fqn = getSessionFqn(realId); 191 return proxy_.exists(fqn); 192 } 193 194 public Object getAttribute(String id, String key) 195 { 196 String realId = stripJvmRoute(id); 197 Fqn fqn = getAttributeFqn(realId); 198 return getUnMarshalledValue(_get(fqn, key)); 199 } 200 201 public Object putAttribute(String id, String key, Object value) 202 { 203 String realId = stripJvmRoute(id); 204 Fqn fqn = getAttributeFqn(realId); 205 return _put(fqn, key, getMarshalledValue(value)); 206 } 207 208 public void putAttribute(String id, Map map) 209 { 210 String realId = stripJvmRoute(id); 211 Fqn fqn = getAttributeFqn(realId); 212 Set set = map.keySet(); 213 Iterator it = set.iterator(); 214 while (it.hasNext()) 215 { 216 String key = (String ) it.next(); 217 _put(fqn, key, getMarshalledValue(map.get(key))); 218 } 219 } 220 221 public void removeAttributes(String id) 222 { 223 String realId = stripJvmRoute(id); 224 Fqn fqn = getAttributeFqn(realId); 225 _remove(fqn); 226 } 227 228 public Object removeAttribute(String id, String key) 229 { 230 String realId = stripJvmRoute(id); 231 Fqn fqn = getAttributeFqn(realId); 232 if (log_.isDebugEnabled()) 233 { 234 log_.debug("Remove attribute from distributed store. Fqn: " + fqn + " key: " + key); 235 } 236 return getUnMarshalledValue(_remove(fqn, key)); 237 } 238 239 public void removeAttributeLocal(String id) 240 { 241 String realId = stripJvmRoute(id); 242 Fqn fqn = getAttributeFqn(realId); 243 if (log_.isDebugEnabled()) 244 { 245 log_.debug("Remove attributes from my own distributed store only. Fqn: " + fqn); 246 } 247 _evict(fqn); 248 } 249 250 255 public Set getAttributeKeys(String id) 256 { 257 if (id == null || id.length() == 0) 258 throw new IllegalArgumentException ("JBossCacheService: id is either null or empty"); 259 260 String realId = stripJvmRoute(id); 261 Fqn fqn = getAttributeFqn(realId); 262 try 263 { 264 return proxy_.getKeys(fqn); 265 } 266 catch (CacheException e) 267 { 268 e.printStackTrace(); 269 } 270 return null; 271 } 272 273 279 public Map getAttributes(String id) 280 { 281 if (id == null || id.length() == 0) return new HashMap(); 282 Set set = getAttributeKeys(id); 283 String realId = stripJvmRoute(id); 284 Fqn fqn = getAttributeFqn(realId); 285 Map map = new HashMap(); 286 if(set == null) return map; 287 for (Iterator it = set.iterator(); it.hasNext();) 288 { 289 String key = (String ) it.next(); 290 Object value = getAttribute(id, key); 291 map.put(key, value); 292 } 293 return map; 294 } 295 296 300 public List getNewSessionsInStore() 301 { 302 List list = new ArrayList(); 303 synchronized(newSessionIDList_) 304 { 305 if(newSessionIDList_.size() != 0) 306 { 307 list.addAll(newSessionIDList_); 308 newSessionIDList_.clear(); 309 } 310 } 311 return list; 312 } 313 314 321 protected Object _get(Fqn fqn, String id) 322 { 323 Exception ex = null; 324 for (int i = 0; i < RETRY; i++) 325 { 326 try 327 { 328 return proxy_.get(fqn, id); 329 } 330 catch (TimeoutException e) 331 { 332 e.printStackTrace(); 333 ex = e; 334 } 335 catch (Exception e) 336 { 337 e.printStackTrace(); 338 throw new RuntimeException ("JBossCacheService: exception occurred in cache get ... ", e); 339 } 340 } 341 throw new RuntimeException ("JBossCacheService: exception occurred in cache get after retry ... ", ex); 342 } 343 344 352 protected Object _put(Fqn fqn, String id, Object value) 353 { 354 Exception ex = null; 355 for (int i = 0; i < RETRY; i++) 356 { 357 try 358 { 359 return proxy_.put(fqn, id, value); 360 } 361 catch (TimeoutException e) 362 { 363 e.printStackTrace(); 364 ex = e; 365 } 366 catch (Exception e) 367 { 368 e.printStackTrace(); 369 throw new RuntimeException ("JBossCacheService: exception occurred in cache put ... ", e); 370 } 371 } 372 throw new RuntimeException ("JBossCacheService: exception occurred in cache put after retry ... ", ex); 373 } 374 375 376 382 protected void _put(Fqn fqn, Map map) 383 { 384 Exception ex = null; 385 for (int i = 0; i < RETRY; i++) 386 { 387 try 388 { 389 proxy_.put(fqn, map); 390 return; 391 } 392 catch (TimeoutException e) 393 { 394 e.printStackTrace(); 395 ex = e; 396 } 397 catch (Exception e) 398 { 399 e.printStackTrace(); 400 throw new RuntimeException ("JBossCacheService: exception occurred in cache put ... ", e); 401 } 402 } 403 throw new RuntimeException ("JBossCacheService: exception occurred in cache put after retry ... ", ex); 404 } 405 406 413 protected Object _remove(Fqn fqn, String id) 414 { 415 Exception ex = null; 416 for (int i = 0; i < RETRY; i++) 417 { 418 try 419 { 420 return proxy_.remove(fqn, id); 421 } 422 catch (TimeoutException e) 423 { 424 e.printStackTrace(); 425 ex = e; 426 } 427 catch (Exception e) 428 { 429 e.printStackTrace(); 430 throw new RuntimeException ("JBossCacheService: exception occurred in cache remove ... ", e); 431 } 432 } 433 throw new RuntimeException ("JBossCacheService: exception occurred in cache remove after retry ... ", ex); 434 } 435 436 441 protected void _remove(Fqn fqn) 442 { 443 Exception ex = null; 444 for (int i = 0; i < RETRY; i++) 445 { 446 try 447 { 448 proxy_.remove(fqn); 449 return; 450 } 451 catch (TimeoutException e) 452 { 453 e.printStackTrace(); 454 ex = e; 455 } 456 catch (Exception e) 457 { 458 e.printStackTrace(); 459 throw new RuntimeException ("JBossCacheService: exception occurred in cache remove ... ", e); 460 } 461 } 462 throw new RuntimeException ("JBossCacheService: exception occurred in cache remove after retry ... ", ex); 463 } 464 465 470 protected void _evict(Fqn fqn) 471 { 472 Exception ex = null; 473 for (int i = 0; i < RETRY; i++) 474 { 475 try 476 { 477 proxy_.evict(fqn); 478 return; 479 } 480 catch (TimeoutException e) 481 { 482 e.printStackTrace(); 483 ex = e; 484 } 485 catch (Exception e) 486 { 487 e.printStackTrace(); 488 throw new RuntimeException ("JBossCacheService: exception occurred in cache evict ... ", e); 489 } 490 } 491 throw new RuntimeException ("JBossCacheService: exception occurred in cache evict after retry ... ", ex); 492 } 493 494 495 503 private String stripJvmRoute(String id) 504 { 505 int index = id.indexOf("."); 507 if (index > 0) 508 { 509 if(jvmRoute_ == null) 510 jvmRoute_ = id.substring(index); 511 512 return id.substring(0, index); 513 } 514 else 515 { 516 return id; 517 } 518 } 519 520 private Fqn getSessionFqn(String id) 521 { 522 Object [] objs = new Object []{SESSION, webAppPath_, id}; 524 return new Fqn(objs); 525 } 526 527 private Fqn getAttributeFqn(String id) 528 { 529 Object [] objs = new Object []{SESSION, webAppPath_, id, ATTRIBUTE}; 531 return new Fqn(objs); 532 } 533 534 private Object getMarshalledValue(Object value) 535 { 536 try 537 { 538 return new MarshalledValue(value); 539 } 540 catch (IOException e) 541 { 542 e.printStackTrace(); 543 return null; 544 } 545 } 546 547 private Object getUnMarshalledValue(Object mv) 548 { 549 if (mv == null) return null; 550 ClassLoader prevTCL = Thread.currentThread().getContextClassLoader(); 552 Thread.currentThread().setContextClassLoader(tcl_); 553 try 554 { 555 return ((MarshalledValue) mv).get(); 556 } 557 catch (IOException e) 558 { 559 e.printStackTrace(); 560 return null; 561 } 562 catch (ClassNotFoundException e) 563 { 564 e.printStackTrace(); 565 return null; 566 } 567 finally 568 { 569 Thread.currentThread().setContextClassLoader(prevTCL); 570 } 571 } 572 573 575 public void nodeCreated(Fqn fqn) 576 { 577 } 579 580 public void nodeRemoved(Fqn fqn) 581 { 582 nodeDirty(fqn); 583 } 584 585 589 public void nodeLoaded(Fqn fqn) 590 { 591 } 592 593 public void nodeModified(Fqn fqn) 594 { 595 nodeDirty(fqn); 596 } 597 598 protected void nodeDirty(Fqn fqn) 599 { 600 Integer version = (Integer )_get(fqn, VERSION_KEY); 602 if(version != null) 603 { 604 String realId = getIdFromFqn(fqn); 605 606 617 618 ClusteredSession session = (ClusteredSession)manager_.findLocalSession(realId); 619 if( session != null ) 621 { 622 if( session.isNewData(version.intValue())) 623 { 624 session.setIsOutdated(true); 626 if(log_.isDebugEnabled()) 627 { 628 log_.debug("nodeDirty(): session in-memory data is invalidated with id: " +realId 629 + " and verion id: " +version.intValue()); 630 } 631 } 632 } else 633 { 634 640 synchronized(newSessionIDList_) 641 { 642 if(!newSessionIDList_.contains(realId)) 643 newSessionIDList_.add(realId); 644 } 645 } 646 } 647 } 648 649 protected String getIdFromFqn(Fqn fqn) 650 { 651 return (String )fqn.get(fqn.size()-1); 652 } 653 654 public void nodeVisited(Fqn fqn) 655 { 656 } 658 659 public void cacheStarted(TreeCache cache) 660 { 661 } 663 664 public void cacheStopped(TreeCache cache) 665 { 666 } 668 669 public void viewChange(View new_view) 670 { 671 } 673 674 public void nodeEvicted(Fqn fqn) 675 { 676 } 678 679 } 680 | Popular Tags |