1 4 package com.tc.aspectwerkz.intercept; 5 6 import java.util.ArrayList ; 7 import java.util.HashMap ; 8 import java.util.Iterator ; 9 import java.util.List ; 10 import java.lang.reflect.Field ; 11 12 13 import com.tc.aspectwerkz.joinpoint.management.JoinPointType; 14 import com.tc.aspectwerkz.reflect.impl.asm.AsmClassInfo; 15 import com.tc.aspectwerkz.reflect.impl.java.JavaClassInfo; 16 import com.tc.aspectwerkz.reflect.ClassInfo; 17 import com.tc.aspectwerkz.reflect.ReflectionInfo; 18 import com.tc.aspectwerkz.transform.TransformationConstants; 19 import com.tc.aspectwerkz.transform.inlining.AsmHelper; 20 import com.tc.aspectwerkz.transform.inlining.EmittedJoinPoint; 21 import com.tc.aspectwerkz.expression.PointcutType; 22 import com.tc.aspectwerkz.expression.ExpressionInfo; 23 import com.tc.aspectwerkz.expression.ExpressionContext; 24 25 31 public class AdvisableImpl implements Advisable { 32 33 private static final String EXPRESSION_NAMESPACE = "___AW_ADVISABLE_AW___"; 34 35 public static final ClassInfo CLASS_INFO; 36 public static final String ADD_ADVICE_METHOD_NAME = "aw_addAdvice"; 37 public static final String ADD_ADVICE_METHOD_DESC = "(Ljava/lang/String;Lcom/tc/aspectwerkz/intercept/Advice;)V"; 38 public static final String REMOVE_ADVICE_METHOD_NAME = "aw_removeAdvice"; 39 public static final String REMOVE_ADVICE_METHOD_DESC = "(Ljava/lang/String;Ljava/lang/Class;)V"; 40 public static final AroundAdvice[] EMPTY_AROUND_ADVICE_ARRAY = new AroundAdvice[0]; 41 public static final BeforeAdvice[] EMPTY_BEFORE_ADVICE_ARRAY = new BeforeAdvice[0]; 42 public static final AfterAdvice[] EMPTY_AFTER_ADVICE_ARRAY = new AfterAdvice[0]; 43 public static final AfterReturningAdvice[] EMPTY_AFTER_RETURNING_ADVICE_ARRAY = new AfterReturningAdvice[0]; 44 public static final AfterThrowingAdvice[] EMPTY_AFTER_THROWING_ADVICE_ARRAY = new AfterThrowingAdvice[0]; 45 46 static { 47 final Class clazz = AdvisableImpl.class; 48 try { 49 CLASS_INFO = AsmClassInfo.getClassInfo(clazz.getName(), clazz.getClassLoader()); 50 } catch (Exception e) { 51 throw new Error ("could not create class info for [" + clazz.getName() + ']'); 52 } 53 } 54 55 private final Advisable m_targetInstance; 56 private final HashMap m_emittedJoinPoints; 57 58 private final HashMap m_aroundAdvice = new HashMap (); 59 private final HashMap m_beforeAdvice = new HashMap (); 60 private final HashMap m_afterAdvice = new HashMap (); 61 private final HashMap m_afterReturningAdvice = new HashMap (); 62 private final HashMap m_afterThrowingAdvice = new HashMap (); 63 64 69 public AdvisableImpl(final Object targetInstance) { 70 if (!(targetInstance instanceof Advisable)) { 71 throw new RuntimeException ( 72 "advisable mixin applied to target class that does not implement the Advisable interface" 73 ); 74 } 75 m_targetInstance = (Advisable) targetInstance; 76 77 try { 78 Field f = targetInstance.getClass().getDeclaredField("aw$emittedJoinPoints"); 79 f.setAccessible(true); 80 m_emittedJoinPoints = (HashMap ) f.get(null); 81 } catch (Exception e) { 82 throw new RuntimeException ( 83 "advisable mixin applied to target class cannot access reflective information: " + e.toString() 84 ); 85 } 86 } 87 88 92 public void aw_addAdvice(final String pointcut, final Advice advice) { 93 addAdvice(pointcut, advice); 94 } 95 96 100 public void aw_removeAdvice(final String pointcut, final Class adviceClass) { 101 removeAdvice(pointcut, adviceClass); 102 } 103 104 108 public AroundAdvice[] aw$getAroundAdvice(final int joinPointHash) { 109 Object advice = m_aroundAdvice.get(new Integer (joinPointHash)); 110 if (advice == null) { 111 return EMPTY_AROUND_ADVICE_ARRAY; 112 } else { 113 return (AroundAdvice[]) advice; 114 } 115 } 116 117 121 public BeforeAdvice[] aw$getBeforeAdvice(final int joinPointHash) { 122 Object advice = m_beforeAdvice.get(new Integer (joinPointHash)); 123 if (advice == null) { 124 return EMPTY_BEFORE_ADVICE_ARRAY; 125 } else { 126 return (BeforeAdvice[]) advice; 127 } 128 } 129 130 134 public AfterAdvice[] aw$getAfterAdvice(final int joinPointHash) { 135 Object advice = m_afterAdvice.get(new Integer (joinPointHash)); 136 if (advice == null) { 137 return EMPTY_AFTER_ADVICE_ARRAY; 138 } else { 139 return (AfterAdvice[]) advice; 140 } 141 } 142 143 147 public AfterReturningAdvice[] aw$getAfterReturningAdvice(final int joinPointHash) { 148 Object advice = m_afterReturningAdvice.get(new Integer (joinPointHash)); 149 if (advice == null) { 150 return EMPTY_AFTER_RETURNING_ADVICE_ARRAY; 151 } else { 152 return (AfterReturningAdvice[]) advice; 153 } 154 } 155 156 160 public AfterThrowingAdvice[] aw$getAfterThrowingAdvice(final int joinPointIndex) { 161 Object advice = m_afterThrowingAdvice.get(new Integer (joinPointIndex)); 162 if (advice == null) { 163 return EMPTY_AFTER_THROWING_ADVICE_ARRAY; 164 } else { 165 return (AfterThrowingAdvice[]) advice; 166 } 167 } 168 169 173 private void addAdvice(final String pointcut, 174 final Advice advice) { 175 ExpressionInfo expressionInfo = new ExpressionInfo(pointcut, EXPRESSION_NAMESPACE); 176 for (Iterator it = m_emittedJoinPoints.values().iterator(); it.hasNext();) { 180 EmittedJoinPoint emittedJoinPoint = (EmittedJoinPoint) it.next(); 181 if (match(expressionInfo, PointcutType.EXECUTION, emittedJoinPoint) 182 || match(expressionInfo, PointcutType.CALL, emittedJoinPoint) 183 || match(expressionInfo, PointcutType.HANDLER, emittedJoinPoint) 184 || match(expressionInfo, PointcutType.GET, emittedJoinPoint) 185 || match(expressionInfo, PointcutType.SET, emittedJoinPoint) 186 ) { 188 int hash = emittedJoinPoint.getJoinPointClassName().hashCode(); 189 addAroundAdvice(advice, hash); 190 addBeforeAdvice(advice, hash); 191 addAfterAdvice(advice, hash); 192 addAfterReturningAdvice(advice, hash); 193 addAfterThrowingAdvice(advice, hash); 194 } 195 } 196 } 197 198 202 private void removeAdvice(final String pointcut, 203 final Class adviceClass) { 204 ExpressionInfo expressionInfo = new ExpressionInfo(pointcut, EXPRESSION_NAMESPACE); 205 for (Iterator it = m_emittedJoinPoints.values().iterator(); it.hasNext();) { 209 EmittedJoinPoint emittedJoinPoint = (EmittedJoinPoint) it.next(); 210 if (match(expressionInfo, PointcutType.EXECUTION, emittedJoinPoint) 211 || match(expressionInfo, PointcutType.CALL, emittedJoinPoint) 212 || match(expressionInfo, PointcutType.HANDLER, emittedJoinPoint) 213 || match(expressionInfo, PointcutType.GET, emittedJoinPoint) 214 || match(expressionInfo, PointcutType.SET, emittedJoinPoint) 215 ) { 217 int hash = emittedJoinPoint.getJoinPointClassName().hashCode(); 218 removeAroundAdvice(adviceClass, hash); 219 removeBeforeAdvice(adviceClass, hash); 220 removeAfterAdvice(adviceClass, hash); 221 removeAfterReturningAdvice(adviceClass, hash); 222 removeAfterThrowingAdvice(adviceClass, hash); 223 } 224 } 225 } 226 227 231 private void addAroundAdvice(final Advice advice, int joinPointHash) { 232 if (advice instanceof AroundAdvice) { 233 AroundAdvice aroundAdvice = (AroundAdvice) advice; 234 AroundAdvice[] advices; 235 AroundAdvice[] olds = aw$getAroundAdvice(joinPointHash); 236 if (olds != null) { 237 advices = new AroundAdvice[olds.length + 1]; 238 System.arraycopy(olds, 0, advices, 0, olds.length); 239 advices[advices.length - 1] = aroundAdvice; 240 } else { 241 advices = new AroundAdvice[]{aroundAdvice}; 242 } 243 m_aroundAdvice.put(new Integer (joinPointHash), advices); 244 } 245 } 246 247 251 private void addBeforeAdvice(final Advice advice, int joinPointHash) { 252 if (advice instanceof BeforeAdvice) { 253 BeforeAdvice beforeAdvice = (BeforeAdvice) advice; 254 BeforeAdvice[] advices; 255 BeforeAdvice[] olds = aw$getBeforeAdvice(joinPointHash); 256 if (olds != null) { 257 advices = new BeforeAdvice[olds.length + 1]; 258 System.arraycopy(olds, 0, advices, 0, olds.length); 259 advices[advices.length - 1] = beforeAdvice; 260 } else { 261 advices = new BeforeAdvice[]{beforeAdvice}; 262 } 263 m_beforeAdvice.put(new Integer (joinPointHash), advices); 264 } 265 } 266 267 271 private void addAfterAdvice(final Advice advice, int joinPointHash) { 272 if (advice instanceof AfterAdvice) { 273 AfterAdvice afterFinallyAdvice = (AfterAdvice) advice; 274 AfterAdvice[] advices; 275 AfterAdvice[] olds = aw$getAfterAdvice(joinPointHash); 276 if (olds != null) { 277 advices = new AfterAdvice[olds.length + 1]; 278 System.arraycopy(olds, 0, advices, 0, olds.length); 279 advices[advices.length - 1] = afterFinallyAdvice; 280 } else { 281 advices = new AfterAdvice[]{afterFinallyAdvice}; 282 } 283 m_afterAdvice.put(new Integer (joinPointHash), advices); 284 } 285 } 286 287 291 private void addAfterReturningAdvice(final Advice advice, int joinPointHash) { 292 if (advice instanceof AfterReturningAdvice) { 293 AfterReturningAdvice afterReturningAdvice = (AfterReturningAdvice) advice; 294 AfterReturningAdvice[] advices; 295 AfterReturningAdvice[] olds = aw$getAfterReturningAdvice(joinPointHash); 296 if (olds != null) { 297 advices = new AfterReturningAdvice[olds.length + 1]; 298 System.arraycopy(olds, 0, advices, 0, olds.length); 299 advices[advices.length - 1] = afterReturningAdvice; 300 } else { 301 advices = new AfterReturningAdvice[]{afterReturningAdvice}; 302 } 303 m_afterReturningAdvice.put(new Integer (joinPointHash), advices); 304 } 305 } 306 307 311 private void addAfterThrowingAdvice(final Advice advice, int joinPointHash) { 312 if (advice instanceof AfterThrowingAdvice) { 313 AfterThrowingAdvice afterThrowingAdvice = (AfterThrowingAdvice) advice; 314 AfterThrowingAdvice[] advices; 315 AfterThrowingAdvice[] olds = aw$getAfterThrowingAdvice(joinPointHash); 316 if (olds != null) { 317 advices = new AfterThrowingAdvice[olds.length + 1]; 318 System.arraycopy(olds, 0, advices, 0, olds.length); 319 advices[advices.length - 1] = afterThrowingAdvice; 320 } else { 321 advices = new AfterThrowingAdvice[]{afterThrowingAdvice}; 322 } 323 m_afterThrowingAdvice.put(new Integer (joinPointHash), advices); 324 } 325 } 326 327 331 private void removeAroundAdvice(final Class adviceClass, int joinPointHash) { 332 if (isAroundAdvice(adviceClass)) { 333 AroundAdvice[] oldArray = aw$getAroundAdvice(joinPointHash); 334 if (oldArray.length == 0) { 335 } else if (oldArray.length == 1) { 337 m_aroundAdvice.put(new Integer (joinPointHash), EMPTY_AROUND_ADVICE_ARRAY); 338 } else { 339 List newArrayList = new ArrayList (); 340 for (int i = 0; i < oldArray.length; i++) { 341 AroundAdvice aroundAdvice = oldArray[i]; 342 if (!aroundAdvice.getClass().equals(adviceClass)) { 343 newArrayList.add(aroundAdvice); 344 } 345 } 346 m_aroundAdvice.put( 347 new Integer (joinPointHash), 348 newArrayList.toArray(new AroundAdvice[newArrayList.size()]) 349 ); 350 } 351 } 352 } 353 354 358 private void removeBeforeAdvice(final Class adviceClass, int joinPointHash) { 359 if (isBeforeAdvice(adviceClass)) { 360 BeforeAdvice[] oldArray = aw$getBeforeAdvice(joinPointHash); 361 if (oldArray.length == 0) { 362 } else if (oldArray.length == 1) { 364 m_beforeAdvice.put(new Integer (joinPointHash), EMPTY_BEFORE_ADVICE_ARRAY); 365 } else { 366 List newArrayList = new ArrayList (); 367 for (int i = 0; i < oldArray.length; i++) { 368 BeforeAdvice beforeAdvice = oldArray[i]; 369 if (!beforeAdvice.getClass().equals(adviceClass)) { 370 newArrayList.add(beforeAdvice); 371 } 372 } 373 m_beforeAdvice.put( 374 new Integer (joinPointHash), 375 newArrayList.toArray(new BeforeAdvice[newArrayList.size()]) 376 ); 377 } 378 } 379 } 380 381 385 private void removeAfterAdvice(final Class adviceClass, int joinPointHash) { 386 if (isAfterAdvice(adviceClass)) { 387 AfterAdvice[] oldArray = aw$getAfterAdvice(joinPointHash); 388 if (oldArray.length == 0) { 389 } else if (oldArray.length == 1) { 391 m_afterAdvice.put(new Integer (joinPointHash), EMPTY_AFTER_ADVICE_ARRAY); 392 } else { 393 List newArrayList = new ArrayList (); 394 for (int i = 0; i < oldArray.length; i++) { 395 AfterAdvice afterAdvice = oldArray[i]; 396 if (!afterAdvice.getClass().equals(adviceClass)) { 397 newArrayList.add(afterAdvice); 398 } 399 } 400 m_afterAdvice.put( 401 new Integer (joinPointHash), 402 newArrayList.toArray(new AfterAdvice[newArrayList.size()]) 403 ); 404 } 405 } 406 } 407 408 412 private void removeAfterReturningAdvice(final Class adviceClass, int joinPointHash) { 413 if (isAfterReturningAdvice(adviceClass)) { 414 AfterReturningAdvice[] oldArray = aw$getAfterReturningAdvice(joinPointHash); 415 if (oldArray.length == 0) { 416 } else if (oldArray.length == 1) { 418 m_afterReturningAdvice.put(new Integer (joinPointHash), EMPTY_AFTER_RETURNING_ADVICE_ARRAY); 419 } else { 420 List newArrayList = new ArrayList (); 421 for (int i = 0; i < oldArray.length; i++) { 422 AfterReturningAdvice afterReturningAdvice = oldArray[i]; 423 if (!afterReturningAdvice.getClass().equals(adviceClass)) { 424 newArrayList.add(afterReturningAdvice); 425 } 426 } 427 m_afterReturningAdvice.put( 428 new Integer (joinPointHash), 429 newArrayList.toArray(new AfterReturningAdvice[newArrayList.size()]) 430 ); 431 } 432 } 433 } 434 435 439 private void removeAfterThrowingAdvice(final Class adviceClass, int joinPointHash) { 440 if (isAfterThrowingAdvice(adviceClass)) { 441 AfterThrowingAdvice[] oldArray = aw$getAfterThrowingAdvice(joinPointHash); 442 if (oldArray.length == 0) { 443 } else if (oldArray.length == 1) { 445 m_afterThrowingAdvice.put(new Integer (joinPointHash), EMPTY_AFTER_THROWING_ADVICE_ARRAY); 446 } else { 447 List newArrayList = new ArrayList (); 448 for (int i = 0; i < oldArray.length; i++) { 449 AfterThrowingAdvice advice = oldArray[i]; 450 if (!advice.getClass().equals(adviceClass)) { 451 newArrayList.add(advice); 452 } 453 } 454 m_afterThrowingAdvice.put( 455 new Integer (joinPointHash), 456 newArrayList.toArray(new AfterThrowingAdvice[newArrayList.size()]) 457 ); 458 } 459 } 460 } 461 462 private boolean isAroundAdvice(final Class adviceClass) { 463 if (adviceClass == AroundAdvice.class) { 464 return true; 465 } 466 Class [] interfaces = adviceClass.getInterfaces(); 467 for (int i = 0; i < interfaces.length; i++) { 468 Class anInterface = interfaces[i]; 469 if (anInterface == AroundAdvice.class) { 470 return true; 471 } 472 } 473 return false; 474 } 475 476 private boolean isBeforeAdvice(final Class adviceClass) { 477 if (adviceClass == BeforeAdvice.class) { 478 return true; 479 } 480 Class [] interfaces = adviceClass.getInterfaces(); 481 for (int i = 0; i < interfaces.length; i++) { 482 Class anInterface = interfaces[i]; 483 if (anInterface == BeforeAdvice.class) { 484 return true; 485 } 486 } 487 return false; 488 } 489 490 private boolean isAfterAdvice(final Class adviceClass) { 491 if (adviceClass == AfterAdvice.class) { 492 return true; 493 } 494 Class [] interfaces = adviceClass.getInterfaces(); 495 for (int i = 0; i < interfaces.length; i++) { 496 Class anInterface = interfaces[i]; 497 if (anInterface == AfterAdvice.class) { 498 return true; 499 } 500 } 501 return false; 502 } 503 504 private boolean isAfterReturningAdvice(final Class adviceClass) { 505 if (adviceClass == AfterReturningAdvice.class) { 506 return true; 507 } 508 Class [] interfaces = adviceClass.getInterfaces(); 509 for (int i = 0; i < interfaces.length; i++) { 510 Class anInterface = interfaces[i]; 511 if (anInterface == AfterReturningAdvice.class) { 512 return true; 513 } 514 } 515 return false; 516 } 517 518 private boolean isAfterThrowingAdvice(final Class adviceClass) { 519 if (adviceClass == AfterThrowingAdvice.class) { 520 return true; 521 } 522 Class [] interfaces = adviceClass.getInterfaces(); 523 for (int i = 0; i < interfaces.length; i++) { 524 Class anInterface = interfaces[i]; 525 if (anInterface == AfterThrowingAdvice.class) { 526 return true; 527 } 528 } 529 return false; 530 } 531 532 540 private boolean match(ExpressionInfo expression, PointcutType pointcutType, EmittedJoinPoint emittedJoinPoint) { 541 ClassInfo callerClassInfo = JavaClassInfo.getClassInfo(m_targetInstance.getClass()); 542 ClassInfo calleeClassInfo = AsmClassInfo.getClassInfo(emittedJoinPoint.getCalleeClassName(), m_targetInstance.getClass().getClassLoader()); 543 544 if (!expression.getAdvisedClassFilterExpression().match(new ExpressionContext(pointcutType, calleeClassInfo, callerClassInfo))) 546 { 547 return false; 548 } 549 550 final ReflectionInfo reflectionInfo; 552 final PointcutType joinPointType; 553 switch (emittedJoinPoint.getJoinPointType()) { 554 case JoinPointType.STATIC_INITIALIZATION_INT: 555 reflectionInfo = calleeClassInfo.staticInitializer(); 556 joinPointType = PointcutType.STATIC_INITIALIZATION; 557 break; 558 case JoinPointType.METHOD_EXECUTION_INT: 559 reflectionInfo = calleeClassInfo.getMethod(emittedJoinPoint.getJoinPointHash()); 560 joinPointType = PointcutType.EXECUTION; 561 break; 562 case JoinPointType.METHOD_CALL_INT: 563 reflectionInfo = calleeClassInfo.getMethod(emittedJoinPoint.getJoinPointHash()); 564 joinPointType = PointcutType.CALL; 565 break; 566 case JoinPointType.FIELD_GET_INT: 567 reflectionInfo = calleeClassInfo.getField(emittedJoinPoint.getJoinPointHash()); 568 joinPointType = PointcutType.GET; 569 break; 570 case JoinPointType.FIELD_SET_INT: 571 reflectionInfo = calleeClassInfo.getField(emittedJoinPoint.getJoinPointHash()); 572 joinPointType = PointcutType.SET; 573 break; 574 case JoinPointType.CONSTRUCTOR_EXECUTION_INT: 575 reflectionInfo = calleeClassInfo.getConstructor(emittedJoinPoint.getJoinPointHash()); 576 joinPointType = PointcutType.EXECUTION; 577 break; 578 case JoinPointType.CONSTRUCTOR_CALL_INT: 579 reflectionInfo = calleeClassInfo.getConstructor(emittedJoinPoint.getJoinPointHash()); 580 joinPointType = PointcutType.CALL; 581 break; 582 case JoinPointType.HANDLER_INT: 583 reflectionInfo = calleeClassInfo; 584 joinPointType = PointcutType.HANDLER; 585 break; 586 default: 587 throw new RuntimeException ("Joinpoint type not supported: " + emittedJoinPoint.getJoinPointType()); 588 } 589 590 final ReflectionInfo withinInfo; 592 if (TransformationConstants.CLINIT_METHOD_NAME.equals(emittedJoinPoint.getCallerMethodName())) { 593 withinInfo = callerClassInfo.staticInitializer(); 594 } else if (TransformationConstants.INIT_METHOD_NAME.equals(emittedJoinPoint.getCallerMethodName())) { 595 withinInfo = callerClassInfo.getConstructor(AsmHelper.calculateConstructorHash( 596 emittedJoinPoint.getCallerMethodDesc() 597 )); 598 } else { 599 withinInfo = 600 callerClassInfo.getMethod(AsmHelper.calculateMethodHash(emittedJoinPoint.getCallerMethodName(), 601 emittedJoinPoint.getCallerMethodDesc()) 602 ); 603 } 604 605 if (pointcutType != PointcutType.WITHIN && pointcutType != joinPointType) { 607 return false; 608 } 609 610 return expression.getExpression().match(new ExpressionContext(pointcutType, reflectionInfo, withinInfo)); 611 } 612 } 613 | Popular Tags |