1 7 package org.jboss.cache.aop; 8 9 import org.jboss.aop.Advised; 10 import org.jboss.aop.ClassInstanceAdvisor; 11 import org.jboss.aop.InstanceAdvisor; 12 import org.jboss.aop.advice.Interceptor; 13 import org.jboss.aop.proxy.ClassProxy; 14 import org.jboss.cache.*; 15 import org.jboss.cache.eviction.AopEvictionPolicy; 16 import org.jboss.cache.transaction.BatchModeTransactionManager; 17 import org.jboss.util.NestedRuntimeException; 18 import org.jgroups.JChannel; 19 import org.apache.commons.logging.Log; 20 import org.apache.commons.logging.LogFactory; 21 22 import javax.transaction.Status ; 23 import javax.transaction.SystemException ; 24 import javax.transaction.TransactionManager ; 25 import java.io.Serializable ; 26 import java.lang.reflect.Field ; 27 import java.util.*; 28 29 32 public class TreeCacheAopDelegate 33 { 34 protected TreeCacheAop cache_; 35 protected final static Log log=LogFactory.getLog(TreeCacheAopDelegate.class); 36 protected InternalDelegate internal_; 37 38 public TreeCacheAopDelegate(TreeCacheAop cache) 39 { 40 cache_ = cache; 41 internal_ = new InternalDelegate(cache); 42 } 43 44 protected Object _getObject(Fqn fqn) throws CacheException 45 { 46 Object pojo = internal_.getObjectInstance(fqn); 47 if ( pojo != null) { 48 return pojo; 50 } 51 52 Class clazz = internal_.peekAopClazz(fqn); 54 if (clazz == null) 56 return null; 57 58 CachedType type = cache_.getCachedType(clazz); 59 Object obj = null; 60 if (Advised.class.isAssignableFrom(clazz)) { 61 String refFqn = internal_.getRefFqn(fqn); 62 if (refFqn == null) { try { 64 obj = clazz.newInstance(); 65 } 66 catch(Exception e) { 67 throw new CacheException("failed creating instance of " + clazz.getName(), e); 68 } 69 InstanceAdvisor advisor = ((Advised) obj)._getInstanceAdvisor(); 71 advisor.appendInterceptor(new CacheInterceptor(cache_, fqn, type)); 72 } else { 73 if (log.isDebugEnabled()) { 77 log.debug("getObject(): obtain value from reference fqn: " + refFqn); 78 } 79 obj = cache_.getObject(refFqn); 80 } 81 82 } else { try { 84 if(Map.class.isAssignableFrom(clazz)) { 85 obj=CollectionInterceptorUtil.createProxy(clazz, new CachedMapInterceptor(cache_, fqn, clazz)); 86 } else if(List.class.isAssignableFrom(clazz)) { 87 obj=CollectionInterceptorUtil.createProxy(clazz, new CachedListInterceptor(cache_, fqn, clazz)); 88 } else if(Set.class.isAssignableFrom(clazz)) { 89 obj=CollectionInterceptorUtil.createProxy(clazz, new CachedSetInterceptor(cache_, fqn, clazz)); 90 } else { 91 obj=cache_.peek(fqn, "value"); 93 } 94 } 95 catch(Exception e) { 96 throw new CacheException("failure creating proxy", e); 97 } 98 } 99 100 internal_.setPOJO(fqn, obj); 101 return obj; 102 } 103 104 protected Object retrieveCurrentValue(Fqn fqn, Object obj) throws CacheException { 105 Object oldValue = null; 106 Object pojo = internal_.getObjectInstance(fqn); 107 if (pojo != null) { 108 if (pojo == obj) { 109 return obj; 111 } 112 113 log.debug("putObject(): old class type: " + pojo); 116 if (obj.getClass().isInstance(pojo)) { 117 if (log.isDebugEnabled()) { 118 log.debug("putObject(): obj is same class type as the old one"); 119 } 120 oldValue = cache_.getObject(fqn); 121 } else { 122 oldValue = cache_.removeObject(fqn); 123 } 124 } else { 125 Class claz1 = internal_.peekAopClazz(fqn); 127 if (claz1 != null && 128 obj.getClass().getName().equals(claz1.getName())) { 129 if (log.isDebugEnabled()) { 130 log.debug("putObject(): obj is same primitive class type as the old one"); 131 } 132 } 133 } 134 return oldValue; 135 } 136 137 144 protected Object _putObject(Fqn fqn, Object obj) throws CacheException 145 { 146 AopUtil.checkObjectType(obj); 147 if (obj == null) { 148 return cache_.removeObject(fqn); 149 } 150 Object oldValue = retrieveCurrentValue(fqn, obj); 152 if(oldValue == obj) return obj; 154 if(log.isDebugEnabled()) { 156 log.debug("putObject(): fqn: " + fqn); 157 } 158 159 if (obj instanceof Advised) { 161 CachedType type = cache_.getCachedType(obj.getClass()); 162 InstanceAdvisor advisor = ((Advised) obj)._getInstanceAdvisor(); 164 if(advisor == null) 165 throw new RuntimeException ("_putObject(): InstanceAdvisor is null for: " +obj); 166 167 if(handleCircularReference(fqn, advisor, obj, type)) 169 { 170 return oldValue; 171 } else if (handleObjectGraph(fqn, advisor, type, obj)) { return oldValue; 173 } 174 175 _regularPutObject(fqn, obj, advisor, type); 176 177 182 } else if (_collectionPutObject(fqn, obj)) { 183 } else if (obj instanceof Serializable ) { if (log.isDebugEnabled()) { 186 log.debug("putObject(): obj (" + obj.getClass() + ") is non-advisable but is Serializable. "); 187 } 188 189 internal_.putAopClazz(fqn, obj.getClass()); 190 191 internal_.setPOJO(fqn, obj); 192 cache_.put(fqn, "value", obj); 194 } 195 196 return oldValue; 197 } 198 199 protected void _regularPutObject(Fqn fqn, Object obj, InstanceAdvisor advisor, CachedType type) throws CacheException 200 { 201 if (advisor == null) { 203 advisor = new ClassInstanceAdvisor(obj); 204 ((Advised) obj)._setInstanceAdvisor(advisor); 205 } 206 207 advisor.appendInterceptor(new CacheInterceptor(cache_, fqn, type)); 209 internal_.resetRefCount(fqn); 211 internal_.putAopClazz(fqn, type.getType()); 214 215 for (Iterator i = type.getFields().iterator(); i.hasNext();) { 216 Field field = (Field ) i.next(); 217 Object value = null; 218 try { 219 value=field.get(obj); 220 } 221 catch(IllegalAccessException e) { 222 throw new CacheException("field access failed", e); 223 } 224 CachedType fieldType = cache_.getCachedType(field.getType()); 225 if (fieldType.isImmediate()) { 226 cache_.put(fqn, field.getName(), value); 227 } else { 228 Fqn tmpFqn = new Fqn(fqn, field.getName()); 229 _putObject(tmpFqn, value); 230 if( value instanceof Map || value instanceof List || value instanceof Set ) { 235 Object newValue = cache_.getObject(tmpFqn); 236 try { 237 field.set(obj, newValue); 238 } catch (IllegalAccessException e) { 239 log.error("_putObject(): Can't swap out the Collection class of field " +field.getName() + 240 "Exception " +e); 241 throw new CacheException("_putObject(): Can't swap out the Collection class of field \" +field.getName()," 242 +e); 243 } 244 } 245 } 246 } 247 248 internal_.setPOJO(fqn, obj); 250 if (log.isDebugEnabled()) { 252 log.debug("putObject(): inserting with fqn: " + fqn.toString()); 253 } 254 } 255 256 protected boolean _collectionPutObject(Fqn fqn, Object obj) throws CacheException { 257 boolean isCollection = false; 258 259 if (obj instanceof Map) { 260 if (log.isDebugEnabled()) { 261 log.debug("putObject(): aspectized obj is a Map type of size: " + ((Map) obj).size()); 262 } 263 264 cache_.removeObject(fqn); 266 internal_.putAopClazz(fqn, obj.getClass()); 267 268 Object oldObj = obj; 270 if( !(obj instanceof ClassProxy)) { 271 Class clazz = obj.getClass(); 272 try { 273 obj=CollectionInterceptorUtil.createProxy(clazz, new CachedMapInterceptor(cache_, fqn, clazz)); 274 } catch (Exception e) { 275 throw new CacheException("failure creating proxy", e); 276 } 277 } 278 279 Map map = (Map) oldObj; 280 281 for (Iterator i = map.entrySet().iterator(); i.hasNext();) { 282 Map.Entry entry = (Map.Entry) i.next(); 283 _putObject(new Fqn(fqn, entry.getKey()), entry.getValue()); 284 } 285 286 internal_.setPOJO(fqn, obj); 287 isCollection = true; 288 } else if (obj instanceof List) { 289 if (log.isDebugEnabled()) { 290 log.debug("putObject(): aspectized obj is a List type of size: " 291 + ((List) obj).size()); 292 } 293 294 List list = (List) obj; 295 cache_.removeObject(fqn); 297 internal_.putAopClazz(fqn, obj.getClass()); 298 299 if( !(obj instanceof ClassProxy)) { 301 Class clazz = obj.getClass(); 302 try { 303 obj=CollectionInterceptorUtil.createProxy(clazz, new CachedListInterceptor(cache_, fqn, clazz)); 304 } catch (Exception e) { 305 throw new CacheException("failure creating proxy", e); 306 } 307 } 308 309 int idx = 0; 310 for (Iterator i = list.iterator(); i.hasNext();) { 311 _putObject(new Fqn(fqn, new Integer (idx++)), i.next()); 312 } 313 315 internal_.setPOJO(fqn, obj); 316 isCollection = true; 317 } else if (obj instanceof Set) { 318 if (log.isDebugEnabled()) { 319 log.debug("putObject(): aspectized obj is a Set type of size: " 320 + ((Set) obj).size()); 321 } 322 323 Set set = (Set) obj; 324 cache_.removeObject(fqn); 326 internal_.putAopClazz(fqn, obj.getClass()); 327 328 if( !(obj instanceof ClassProxy)) { 330 Class clazz = obj.getClass(); 331 try { 332 obj=CollectionInterceptorUtil.createProxy(clazz, new CachedSetInterceptor(cache_, fqn, clazz)); 333 } catch (Exception e) { 334 throw new CacheException("failure creating proxy", e); 335 } 336 } 337 338 int idx = 0; 339 for (Iterator i = set.iterator(); i.hasNext();) { 340 _putObject(new Fqn(fqn, new Integer (idx++)), i.next()); 341 } 342 344 internal_.setPOJO(fqn, obj); 345 isCollection = true; 346 } 347 348 return isCollection; 349 } 350 351 protected Object _removeObject(Fqn fqn, boolean removeCacheInterceptor) throws CacheException 352 { 353 Class clazz = internal_.peekAopClazz(fqn); 354 if (clazz == null) 355 { 356 if (log.isTraceEnabled()) { 357 log.trace("removeObject(): clasz is null. fqn: " + fqn); 358 } 359 return null; 360 } 361 362 if (log.isDebugEnabled()) { 363 log.debug("removeObject(): removing object from fqn: " + fqn); 364 } 365 366 Object result = cache_.getObject(fqn); 367 if(result == null) 368 { 369 if(cache_.exists(fqn)) 370 cache_.remove(fqn); 372 return null; 373 } 374 375 if (Advised.class.isAssignableFrom(clazz)) { 377 _regularRemoveObject(fqn, removeCacheInterceptor, result, clazz); 378 } else if (_collectionRemoveObject(fqn, removeCacheInterceptor)) { 379 } 380 381 cache_.remove(fqn); 383 return result; 385 } 386 387 protected void _regularRemoveObject(Fqn fqn, boolean removeCacheInterceptor, Object result, Class clazz) throws CacheException 388 { 389 String refFqn = internal_.getRefFqn(fqn); 390 InstanceAdvisor advisor = ((Advised) result)._getInstanceAdvisor(); 391 if (refFqn != null) { 393 if (log.isDebugEnabled()) { 394 log.debug("removeObject(): removing object fqn: " + fqn + " but is actually from ref fqn: " + refFqn); 395 } 396 removeRefFqn(fqn, refFqn, removeCacheInterceptor); 397 } else { 398 CachedType type = cache_.getCachedType(clazz); 399 for (Iterator i = type.getFields().iterator(); i.hasNext();) { 400 Field field = (Field ) i.next(); 401 CachedType fieldType = cache_.getCachedType(field.getType()); 402 if (!fieldType.isImmediate()) { 403 Object obj = _removeObject(new Fqn(fqn, field.getName()), removeCacheInterceptor); 404 if (obj == null) continue; 405 } 406 } 407 if(removeCacheInterceptor) { 409 CacheInterceptor interceptor = (CacheInterceptor) AopUtil.findCacheInterceptor(advisor); 410 if (interceptor != null) 415 { 416 if (log.isDebugEnabled()) { 417 log.debug("removeObject(): removed cache interceptor fqn: " + fqn + " interceptor: "+interceptor); 418 } 419 advisor.removeInterceptor(interceptor.getName()); 420 } 421 } 422 } 423 424 } 425 426 protected boolean _collectionRemoveObject(Fqn fqn, boolean removeCacheInterceptor) throws CacheException 427 { 428 boolean isCollection = false; 429 Class clazz = internal_.peekAopClazz(fqn); 430 431 if (Map.class.isAssignableFrom(clazz)) { 432 Map values = cache_.get(fqn).getChildren(); 433 if (values != null) { 434 ArrayList list = new ArrayList(values.keySet()); for (int i=0; i < list.size(); i++) { 436 Object key = list.get(i); 437 _removeObject(new Fqn(fqn, key), removeCacheInterceptor); 438 } 439 } 440 isCollection = true; 441 } else if (Collection.class.isAssignableFrom(clazz)) { 442 Map values = cache_.get(fqn).getChildren(); 443 int size = values == null ? 0 : values.size(); 444 for (int i = 0; i < size; i++) { 445 _removeObject(new Fqn(fqn, new Integer (i)), removeCacheInterceptor); 446 } 447 isCollection = true; 448 } 449 return isCollection; 450 } 451 452 456 protected boolean handleCircularReference(Fqn fqn, InstanceAdvisor advisor, Object obj, CachedType type) 457 throws CacheException 458 { 459 Fqn internalFqn; 460 if ((internalFqn = checkCircularReference(fqn, advisor, obj)) != null) { 461 cache_.removeObject(fqn); 464 this.addRefFqn(fqn, internalFqn.toString()); 465 internal_.putAopClazz(fqn, type.getType()); 466 return true; 467 } 468 else { 469 return false; 470 } 471 472 } 473 474 protected Fqn checkCircularReference(Fqn fqn, InstanceAdvisor advisor, Object obj) 475 { 476 478 Fqn originalFqn = null; 479 Interceptor interceptor = AopUtil.findCacheInterceptor(advisor); 481 if (interceptor == null) { 482 return null; 483 } 484 485 originalFqn = ((CacheInterceptor) interceptor).getFqn(); 487 488 if (fqn.isChildOf(originalFqn)) { 492 if (log.isDebugEnabled()) { 493 log.debug("checkCircularReference(): is child for circular ref fqn " + originalFqn); 494 } 495 return originalFqn; 496 } 497 return null; 498 } 499 500 511 protected boolean handleObjectGraph(Fqn fqn, InstanceAdvisor advisor, CachedType type, Object obj) throws CacheException 512 { 513 Fqn internalFqn = getObjectGraphInternalFqn(fqn, advisor, type, obj); 514 if(internalFqn == null) return false; 515 516 cache_.removeObject(fqn); 518 519 this.addRefFqn(fqn, internalFqn.toString()); 521 internal_.putAopClazz(fqn, type.getType()); 522 523 return true; 524 } 525 526 protected Fqn getObjectGraphInternalFqn(Fqn fqn, InstanceAdvisor advisor, CachedType type, Object obj) throws CacheException { 527 if (advisor == null) return null; 529 Fqn originalFqn = null; 530 Fqn internalFqn = null; 531 Interceptor interceptor = AopUtil.findCacheInterceptor(advisor); 533 if (interceptor == null) { 534 if (log.isDebugEnabled()) { 535 log.debug("handleMultipleReference(): No multiple refernce found for fqn: " + fqn); 536 } 537 return null; 539 } 540 541 originalFqn = ((CacheInterceptor) interceptor).getFqn(); 543 if( fqn.equals(originalFqn) ) return null; 546 547 if (log.isDebugEnabled()) { 548 log.debug("handleObjectGraph(): Found multiple refernce at original fqn: " + originalFqn); 549 } 550 551 if (internal_.isInternalNode(originalFqn)) { 555 if (log.isDebugEnabled()) { 556 log.debug("handleObjectGraph(): is child for fqn " + originalFqn); 557 } 558 559 cache_.removeObject(fqn); 561 return originalFqn; 562 } else { 563 internalFqn = internal_.createInternalNode(originalFqn); 565 Object oldValue = cache_.removeObject(originalFqn); 567 cache_.putObject(internalFqn, obj); 569 570 this.addRefFqn(originalFqn, internalFqn.toString()); 572 internal_.putAopClazz(originalFqn, type.getType()); 573 574 if (log.isDebugEnabled()) { 575 log.debug("handleObjectGraph(): relocate the original fqn: " + originalFqn + 576 " to JBossInternal: " + internalFqn + " with obj: " + oldValue); 577 } 579 return internalFqn; 581 } 582 } 583 584 589 void addRefFqn(Fqn fqn, String refFqn) throws CacheException { 590 synchronized (this) { 591 internal_.incrementRefCount(Fqn.fromString(refFqn)); 593 internal_.resetRefCount(fqn); internal_.setRefFqn(fqn, refFqn); 596 } 597 } 598 599 void removeRefFqn(Fqn fqn, String refFqn, boolean removeCacheInterceptor) throws CacheException { 600 synchronized (this) { 601 if (internal_.decrementRefCount(Fqn.fromString(refFqn)) == 0) { 604 _removeObject(Fqn.fromString(refFqn), removeCacheInterceptor); 605 } else { 606 internal_.removeRefFqn(fqn); 607 } 608 } 609 610 internal_.removeRefFqn(fqn); 611 } 612 613 boolean isAopNode(Fqn fqn) 614 { 615 try { 616 return (internal_.isAopNode(fqn)); 617 } catch (Exception e) { 618 log.warn("isAopNode(): cache get operation generated exception " +e); 619 return false; 620 } 621 } 622 } 623 | Popular Tags |