1 24 25 package com.rift.coad.lib.bean; 26 27 import java.lang.ClassLoader ; 29 import java.lang.reflect.InvocationHandler ; 30 import java.lang.reflect.Method ; 31 import java.util.Date ; 32 import java.util.regex.Matcher ; 33 import java.util.regex.Pattern ; 34 import java.lang.reflect.Proxy ; 35 import java.lang.reflect.InvocationTargetException ; 36 import javax.naming.Context ; 37 import javax.naming.InitialContext ; 38 import javax.transaction.Status ; 39 import javax.transaction.UserTransaction ; 40 41 import org.apache.log4j.Logger; 43 44 import com.rift.coad.lib.Resource; 46 import com.rift.coad.lib.ResourceIndex; 47 import com.rift.coad.lib.ResourceReleasedException; 48 import com.rift.coad.lib.cache.CacheRegistry; 49 import com.rift.coad.lib.cache.CacheEntry; 50 import com.rift.coad.lib.cache.KeySyncCache; 51 import com.rift.coad.lib.cache.KeySyncCacheManager; 52 import com.rift.coad.lib.common.ClassUtil; 53 import com.rift.coad.lib.common.RandomGuid; 54 import com.rift.coad.lib.deployment.BeanInfo; 55 import com.rift.coad.lib.security.Validator; 56 import com.rift.coad.lib.security.ThreadsPermissionContainer; 57 import org.objectweb.carol.jndi.enc.java.javaURLContextFactory; 58 59 60 66 public class BeanHandler implements InvocationHandler , CacheEntry { 67 68 protected Logger log = 70 Logger.getLogger(BeanHandler.class.getName()); 71 72 private String id = null; 74 private BeanInfo beanInfo = null; 75 private String role = null; 76 private Object subObject = null; 77 private ThreadsPermissionContainer permissions = null; 78 private ClassLoader classLoader = null; 79 private Date touchTime = null; 80 private boolean released = false; 81 private BeanCache beanCacheRef = null; 82 private TransactionBeanCache transactionBeanCacheRef = null; 83 private ProxyCache proxyCacheRef = null; 84 private TransactionProxyCache transactionProxyCacheRef = null; 85 private KeySyncCache keySyncCache = null; 86 private Context context = null; 87 private UserTransaction ut = null; 88 89 90 public BeanHandler(BeanInfo beanInfo, Object subObject, String role, 91 ThreadsPermissionContainer permissions, 92 ClassLoader classLoader) 93 throws BeanException { 94 try { 95 touch(); 96 id = RandomGuid.getInstance().getGuid(); 97 this.beanInfo = beanInfo; 98 this.subObject = subObject; 99 this.role = role; 100 this.permissions = permissions; 101 this.classLoader = classLoader; 102 context = new InitialContext (); 103 ut = (UserTransaction )context.lookup("java:comp/UserTransaction"); 104 } catch (Exception ex) { 105 throw new BeanException("Failed to instanciate the handler for [" 106 + subObject.getClass().getName() + "] because : " 107 + ex.getMessage(),ex); 108 } 109 } 110 111 114 public Object invoke(Object proxy, Method method, Object [] args) 115 throws Throwable { 116 if (log.isDebugEnabled()) { 117 log.debug("Calling method [" + method.toString() + "]"); 118 } 119 120 if (isReleased()) { 122 throw new ResourceReleasedException( 123 "This beans resources have been released."); 124 } 125 126 boolean validated = false; 127 touch(); 128 try { 129 Validator.validate(this.getClass(),role); 130 validated = true; 131 permissions.pushRole(role); 132 133 Method subMethod = subObject.getClass().getMethod(method.getName(), 135 method.getParameterTypes()); 136 137 Pattern addPattern = Pattern.compile(BeanPattern.ADD_PATTERN); 139 Pattern findPattern = Pattern.compile(BeanPattern.FIND_PATTERN); 140 Pattern removePattern = Pattern.compile(BeanPattern.REMOVE_PATTERN); 141 142 if (beanInfo.getCacheResults() && !beanInfo.getTransaction() && 144 addPattern.matcher(method.getName()).find() && 145 subMethod.getReturnType().isInterface() && 146 !ClassUtil.testForParent(subMethod.getReturnType(), 147 java.io.Serializable .class)) { 148 return addMethod(method,args); 149 } else if (beanInfo.getCacheResults() && beanInfo.getTransaction() && 150 addPattern.matcher(method.getName()).find() && 151 subMethod.getReturnType().isInterface() && 152 !ClassUtil.testForParent(subMethod.getReturnType(), 153 java.io.Serializable .class)) { 154 return transactionAddMethod(method,args); 155 } else if (beanInfo.getCacheResults() && 156 !beanInfo.getTransaction() && 157 findPattern.matcher(method.getName()).find() && 158 subMethod.getReturnType().isInterface() && 159 !ClassUtil.testForParent(subMethod.getReturnType(), 160 java.io.Serializable .class) && 161 args.length == 1) { 162 return findMethod(method,args); 163 } else if (beanInfo.getCacheResults() && 164 beanInfo.getTransaction() && 165 findPattern.matcher(method.getName()).find() && 166 subMethod.getReturnType().isInterface() && 167 !ClassUtil.testForParent(subMethod.getReturnType(), 168 java.io.Serializable .class) && 169 args.length == 1) { 170 return transactionFindMethod(method,args); 171 } else if (beanInfo.getCacheResults() && 172 !beanInfo.getTransaction() && 173 removePattern.matcher(method.getName()).find() && 174 !ClassUtil.testForParent(subMethod.getReturnType(), 175 java.io.Serializable .class) && 176 args.length == 1) { 177 return removeMethod(method,args); 178 } else if (beanInfo.getCacheResults() && 179 beanInfo.getTransaction() && 180 removePattern.matcher(method.getName()).find() && 181 !ClassUtil.testForParent(subMethod.getReturnType(), 182 java.io.Serializable .class) && 183 args.length == 1) { 184 return removeMethod(method,args); 185 } 186 187 Object result = subMethod.invoke(subObject,args); 189 190 if (subMethod.getReturnType().isInterface() && 192 !ClassUtil.testForParent(subMethod.getReturnType(), 193 java.io.Serializable .class)) { 194 try { 195 BeanHandler handler = new BeanHandler(beanInfo, result, 196 beanInfo.getRole(),permissions,classLoader); 197 Object newProxy = (Object )Proxy.newProxyInstance( 198 classLoader, 199 result.getClass().getInterfaces(),handler); 200 ProxyCache proxyCache = getProxyCache(); 201 proxyCache.addCacheEntry(beanInfo.getCacheTimeout(), newProxy, 202 handler); 203 return newProxy; 204 } catch (Exception ex) { 205 log.error("Failed to create the proxy return object : " + 206 ex.getMessage(),ex); 207 throw new BeanException( 208 "Failed to create the proxy return object : " + 209 ex.getMessage(),ex); 210 } 211 } 212 213 return result; 215 } catch (InvocationTargetException ex) { 216 log.error("An exception was thrown by the sub object : " + 217 ex.getMessage(),ex); 218 throw ex.getTargetException(); 219 } finally { 220 if (validated == true) { 221 permissions.popRole(role); 222 } 223 } 224 } 225 226 227 234 public boolean isExpired(Date expiryDate) { 235 return touchTime.getTime() < expiryDate.getTime(); 236 } 237 238 239 242 public synchronized void cacheRelease() { 243 if (subObject instanceof Resource) { 244 ((Resource)subObject).releaseResource(); 245 } 246 released = true; 247 } 248 249 250 253 public synchronized void touch() { 254 touchTime = new Date (); 255 } 256 257 258 263 protected String getId() { 264 return id; 265 } 266 267 270 public int hashCode() { 271 return id.hashCode(); 272 } 273 274 275 281 public boolean equals(Object rhs) { 282 if (!(rhs instanceof BeanHandler)) { 283 return false; 284 } 285 return id.equals(((BeanHandler)rhs).getId()); 286 } 287 288 289 294 private synchronized boolean isReleased() { 295 return released; 296 } 297 298 299 307 private Object addMethod(Method subMethod, Object [] args) throws Throwable { 308 309 Object result = subMethod.invoke(subObject,args); 311 try { 312 BeanHandler handler = new BeanHandler(beanInfo, result, 313 beanInfo.getRole(),permissions,classLoader); 314 Object proxy = (Object )Proxy.newProxyInstance( 315 classLoader, 316 result.getClass().getInterfaces(),handler); 317 if (result instanceof ResourceIndex) { 318 BeanCache beanCache = getBeanCache(); 319 beanCache.addCacheEntry(beanInfo.getCacheTimeout(), 320 ((ResourceIndex)result).getPrimaryKey(), result, 321 proxy, handler); 322 } else { 323 ProxyCache proxyCache = getProxyCache(); 324 proxyCache.addCacheEntry(beanInfo.getCacheTimeout(), proxy, 325 handler); 326 } 327 return proxy; 328 } catch (Exception ex) { 329 log.error("Failed to create the proxy return object : " + 330 ex.getMessage(),ex); 331 throw new BeanException( 332 "Failed to create the proxy return object : " + 333 ex.getMessage(),ex); 334 } 335 } 336 337 338 346 private Object transactionAddMethod(Method subMethod, Object [] args) throws 347 Throwable { 348 boolean ownTransaction = false; 349 try { 350 if (ut.getStatus() == Status.STATUS_NO_TRANSACTION) { 351 ut.begin(); 352 ownTransaction = true; 353 } 354 } catch (Exception ex) { 355 log.error("Failed to start the transacton : " + 356 ex.getMessage(),ex); 357 throw new BeanException( 358 "Failed to start the transacton : " + 359 ex.getMessage(),ex); 360 } 361 362 Object result = null; 364 try { 365 result = subMethod.invoke(subObject,args); 366 } catch (Throwable ex) { 367 if (ownTransaction) { 368 try { 369 if (ut.getStatus() == Status.STATUS_ACTIVE) { 370 ut.rollback(); 371 } 372 } catch (Exception ex2) { 373 log.error("Failed to rollback the changes : " + 374 ex2.getMessage(),ex2); 375 } 376 } 377 throw ex; 378 } 379 try { 380 BeanHandler handler = new BeanHandler(beanInfo, result, 381 beanInfo.getRole(),permissions,classLoader); 382 Object proxy = (Object )Proxy.newProxyInstance( 383 classLoader, 384 result.getClass().getInterfaces(),handler); 385 386 if (result instanceof ResourceIndex) { 387 388 TransactionBeanCache transactionBeanCache = 389 getTransactionBeanCache(); 390 System.out.println("Add a new entry to the cache [" + 391 beanInfo.getCacheTimeout() + "] [" + 392 ((ResourceIndex)result).getPrimaryKey() + "]"); 393 transactionBeanCache.addCacheEntry(beanInfo.getCacheTimeout(), 394 ((ResourceIndex)result).getPrimaryKey(), result, 395 proxy, handler); 396 } else { 397 System.out.println("Add a new entry to the cache [" + 398 beanInfo.getCacheTimeout() + "]"); 399 TransactionProxyCache transactionProxyCache = 400 getTransactionProxyCache(); 401 transactionProxyCache.addCacheEntry(beanInfo.getCacheTimeout(), 402 proxy, handler); 403 } 404 if (ownTransaction) { 405 ut.commit(); 406 } 407 return proxy; 408 } catch (Throwable ex) { 409 log.error("Failed to create the proxy return object : " + 410 ex.getMessage(),ex); 411 if (ownTransaction) { 412 try { 413 if (ut.getStatus() == Status.STATUS_ACTIVE) { 414 ut.rollback(); 415 } 416 } catch (Exception ex2) { 417 log.error("Failed to rollback the changes : " + 418 ex2.getMessage(),ex2); 419 } 420 } 421 throw new BeanException( 422 "Failed to create the proxy return object : " + 423 ex.getMessage(),ex); 424 } 425 } 426 427 428 436 private Object findMethod(Method subMethod, Object [] args) throws Throwable { 437 438 Object syncObj = getKeySyncCache().getKeySync(args[0]); 440 synchronized(syncObj) { 441 BeanCache beanCache = null; 442 try { 443 beanCache = getBeanCache(); 444 BeanCacheEntry cacheEntry = 445 beanCache.getEntry(args[0]); 446 if (cacheEntry != null) { 447 if (cacheEntry.getProxy() == null){ 448 BeanHandler handler = new BeanHandler(beanInfo, 449 cacheEntry.getWrappedObject(), 450 beanInfo.getRole(),permissions,classLoader); 451 cacheEntry.setBeanHandler(handler); 452 Object proxy = (Object )Proxy.newProxyInstance( 453 classLoader, 454 cacheEntry.getWrappedObject().getClass(). 455 getInterfaces(),handler); 456 cacheEntry.setProxy(proxy); 457 } 458 return cacheEntry.getProxy(); 459 } 460 } catch (Exception ex) { 461 log.error("Failed to check the cache : " + 462 ex.getMessage(),ex); 463 throw new BeanException( 464 "Failed to check the cache : " + 465 ex.getMessage(),ex); 466 } 467 468 Object result = subMethod.invoke(subObject,args); 469 470 try { 471 BeanHandler handler = new BeanHandler(beanInfo, result, 472 beanInfo.getRole(),permissions,classLoader); 473 Object proxy = (Object )Proxy.newProxyInstance( 474 classLoader, 475 result.getClass().getInterfaces(),handler); 476 beanCache.addCacheEntry(beanInfo.getCacheTimeout(), 477 args[0], result, proxy, handler); 478 return proxy; 479 } catch (Exception ex) { 480 log.error("Failed to create the proxy return object : " + 481 ex.getMessage(),ex); 482 throw new BeanException( 483 "Failed to create the proxy return object : " + 484 ex.getMessage(),ex); 485 } 486 } 487 } 488 489 490 498 private Object transactionFindMethod(Method subMethod, Object [] args) throws 499 Throwable { 500 boolean ownTransaction = false; 501 try { 502 if (ut.getStatus() == Status.STATUS_NO_TRANSACTION) { 503 ut.begin(); 504 ownTransaction = true; 505 } 506 } catch (Exception ex) { 507 log.error("Failed to start the transacton : " + 508 ex.getMessage(),ex); 509 throw new BeanException( 510 "Failed to start the transacton : " + 511 ex.getMessage(),ex); 512 } 513 514 TransactionBeanCache transactionBeanCache = null; 515 try { 516 transactionBeanCache = getTransactionBeanCache(); 517 BeanCacheEntry cacheEntry = 518 transactionBeanCache.getCacheEntry(args[0]); 519 if (cacheEntry != null) { 520 if (cacheEntry.getProxy() == null){ 521 BeanHandler handler = new BeanHandler(beanInfo, 522 cacheEntry.getWrappedObject(), 523 beanInfo.getRole(),permissions,classLoader); 524 cacheEntry.setBeanHandler(handler); 525 Object proxy = (Object )Proxy.newProxyInstance( 526 classLoader, 527 cacheEntry.getWrappedObject().getClass(). 528 getInterfaces(),handler); 529 cacheEntry.setProxy(proxy); 530 } 531 if (ownTransaction) { 532 ut.commit(); 533 } 534 return cacheEntry.getProxy(); 535 } 536 } catch (Throwable ex) { 537 log.error("Failed to check the cache : " + 538 ex.getMessage(),ex); 539 if (ownTransaction) { 540 try { 541 if (ut.getStatus() == Status.STATUS_ACTIVE) { 542 ut.rollback(); 543 } 544 } catch (Exception ex2) { 545 log.error("Failed to rollback the changes : " + 546 ex2.getMessage(),ex2); 547 } 548 } 549 throw new BeanException( 550 "Failed to check the cache : " + 551 ex.getMessage(),ex); 552 } 553 554 Object result = null; 555 try { 556 result = subMethod.invoke(subObject,args); 557 } catch (Throwable ex) { 558 if (ownTransaction) { 559 try { 560 if (ut.getStatus() == Status.STATUS_ACTIVE) { 561 ut.rollback(); 562 } 563 } catch (Exception ex2) { 564 log.error("Failed to rollback the changes : " + 565 ex2.getMessage(),ex2); 566 } 567 } 568 throw ex; 569 } 570 571 try { 572 BeanHandler handler = new BeanHandler(beanInfo, result, 573 beanInfo.getRole(),permissions,classLoader); 574 Object proxy = (Object )Proxy.newProxyInstance( 575 classLoader, 576 result.getClass().getInterfaces(),handler); 577 transactionBeanCache.addCacheEntry(beanInfo.getCacheTimeout(), 578 args[0], result, proxy, handler); 579 if (ownTransaction) { 580 ut.commit(); 581 } 582 return proxy; 583 } catch (Throwable ex) { 584 log.error("Failed to create the proxy return object : " + 585 ex.getMessage(),ex); 586 if (ownTransaction) { 587 try { 588 if (ut.getStatus() == Status.STATUS_ACTIVE) { 589 ut.rollback(); 590 } 591 } catch (Exception ex2) { 592 log.error("Failed to rollback the changes : " + 593 ex2.getMessage(),ex2); 594 } 595 } 596 throw new BeanException( 597 "Failed to create the proxy return object : " + 598 ex.getMessage(),ex); 599 } 600 } 601 602 603 611 private Object removeMethod(Method subMethod, Object [] args) throws Throwable { 612 Object syncObj = getKeySyncCache().getKeySync(args[0]); 614 synchronized(syncObj) { 615 Object result = subMethod.invoke(subObject,args); 616 617 try { 618 BeanCache beanCache = getBeanCache(); 619 beanCache.removeCacheEntry(args[0]); 620 } catch (Exception ex) { 621 log.error("Failed to remove bean cache entry : " + 622 ex.getMessage(),ex); 623 throw new BeanException( 624 "Failed to remove bean cache entry : " + 625 ex.getMessage(),ex); 626 } 627 return result; 628 } 629 } 630 631 632 640 private Object transactionRemoveMethod(Method subMethod, Object [] args) 641 throws Throwable { 642 boolean ownTransaction = false; 643 try { 644 if (ut.getStatus() == Status.STATUS_NO_TRANSACTION) { 645 ut.begin(); 646 ownTransaction = true; 647 } 648 } catch (Exception ex) { 649 log.error("Failed to start the transacton : " + 650 ex.getMessage(),ex); 651 throw new BeanException( 652 "Failed to start the transacton : " + 653 ex.getMessage(),ex); 654 } 655 Object result = null; 656 try { 657 result = subMethod.invoke(subObject,args); 658 } catch (Throwable ex) { 659 if (ownTransaction) { 660 try { 661 if (ut.getStatus() == Status.STATUS_ACTIVE) { 662 ut.rollback(); 663 } 664 } catch (Exception ex2) { 665 log.error("Failed to rollback the changes : " + 666 ex2.getMessage(),ex2); 667 } 668 } 669 throw ex; 670 } 671 672 try { 673 TransactionBeanCache transactionBeanCache = 674 getTransactionBeanCache(); 675 transactionBeanCache.removeCacheEntry(args[0]); 676 if (ownTransaction) { 677 ut.commit(); 678 } 679 } catch (Throwable ex) { 680 log.error("Failed to remove bean cache entry : " + 681 ex.getMessage(),ex); 682 if (ownTransaction) { 683 try { 684 if (ut.getStatus() == Status.STATUS_ACTIVE) { 685 ut.rollback(); 686 } 687 } catch (Exception ex2) { 688 log.error("Failed to rollback the changes : " + 689 ex2.getMessage(),ex2); 690 } 691 } 692 throw new BeanException( 693 "Failed to remove bean cache entry : " + 694 ex.getMessage(),ex); 695 } 696 return result; 697 } 698 699 700 706 private synchronized BeanCache getBeanCache() throws Throwable { 707 if (beanCacheRef == null) { 708 BeanCacheManager manager = (BeanCacheManager) 709 CacheRegistry.getInstance(). 710 getCache(BeanCacheManager.class); 711 beanCacheRef = manager.getBeanCache(subObject); 712 } 713 return beanCacheRef; 714 } 715 716 717 723 private synchronized TransactionBeanCache getTransactionBeanCache() throws 724 Throwable { 725 if (transactionBeanCacheRef == null) { 726 TransactionBeanCacheManager manager = (TransactionBeanCacheManager) 727 CacheRegistry.getInstance(). 728 getCache(TransactionBeanCacheManager.class); 729 transactionBeanCacheRef = manager.getBeanCache(subObject); 730 } 731 return transactionBeanCacheRef; 732 } 733 734 735 741 private synchronized ProxyCache getProxyCache() throws Throwable { 742 if (proxyCacheRef == null) { 743 proxyCacheRef = 744 (ProxyCache)CacheRegistry.getInstance(). 745 getCache(ProxyCache.class); 746 } 747 return proxyCacheRef; 748 } 749 750 751 757 private synchronized TransactionProxyCache getTransactionProxyCache() throws 758 Throwable { 759 if (transactionProxyCacheRef == null) { 760 transactionProxyCacheRef = 761 (TransactionProxyCache)CacheRegistry.getInstance(). 762 getCache(TransactionProxyCache.class); 763 } 764 return transactionProxyCacheRef; 765 } 766 767 768 774 private synchronized KeySyncCache getKeySyncCache() throws Throwable { 775 try { 776 if (keySyncCache == null) { 777 KeySyncCacheManager keySyncCacheManager = 778 (KeySyncCacheManager)CacheRegistry.getInstance(). 779 getCache(KeySyncCacheManager.class); 780 keySyncCache = keySyncCacheManager.getKeySyncCache(this); 781 } 782 return keySyncCache; 783 } catch (Exception ex) { 784 log.error("Failed to retrieve the key sync cache object ref : " + 785 ex.getMessage(),ex); 786 throw new BeanException( 787 "Failed to retrieve the key sync cache object ref : " + 788 ex.getMessage(),ex); 789 } 790 } 791 792 793 794 } 795 | Popular Tags |