1 8 package org.codehaus.aspectwerkz.intercept; 9 10 import java.util.ArrayList ; 11 import java.util.List ; 12 import java.lang.reflect.Field ; 13 14 import gnu.trove.TIntObjectHashMap; 15 import org.codehaus.aspectwerkz.reflect.ClassInfo; 16 import org.codehaus.aspectwerkz.reflect.ReflectionInfo; 17 import org.codehaus.aspectwerkz.reflect.impl.asm.AsmClassInfo; 18 import org.codehaus.aspectwerkz.reflect.impl.java.JavaClassInfo; 19 import org.codehaus.aspectwerkz.expression.PointcutType; 20 import org.codehaus.aspectwerkz.expression.ExpressionContext; 21 import org.codehaus.aspectwerkz.expression.ExpressionInfo; 22 import org.codehaus.aspectwerkz.transform.inlining.AsmHelper; 23 import org.codehaus.aspectwerkz.transform.inlining.EmittedJoinPoint; 24 import org.codehaus.aspectwerkz.transform.TransformationConstants; 25 import org.codehaus.aspectwerkz.joinpoint.management.JoinPointType; 26 27 33 public class AdvisableImpl implements Advisable { 34 35 private static final String EXPRESSION_NAMESPACE = "___AW_ADVISABLE_AW___"; 36 37 public static final ClassInfo CLASS_INFO; 38 public static final AroundAdvice[] EMPTY_AROUND_ADVICE_ARRAY = new AroundAdvice[0]; 39 public static final BeforeAdvice[] EMPTY_BEFORE_ADVICE_ARRAY = new BeforeAdvice[0]; 40 public static final AfterAdvice[] EMPTY_AFTER_ADVICE_ARRAY = new AfterAdvice[0]; 41 public static final AfterReturningAdvice[] EMPTY_AFTER_RETURNING_ADVICE_ARRAY = new AfterReturningAdvice[0]; 42 public static final AfterThrowingAdvice[] EMPTY_AFTER_THROWING_ADVICE_ARRAY = new AfterThrowingAdvice[0]; 43 44 static { 45 final Class clazz = AdvisableImpl.class; 46 try { 47 CLASS_INFO = AsmClassInfo.getClassInfo(clazz.getName(), clazz.getClassLoader()); 48 } catch (Exception e) { 49 throw new Error ("could not create class info for [" + clazz.getName() + ']'); 50 } 51 } 52 53 private final Advisable m_targetInstance; 54 private final TIntObjectHashMap m_emittedJoinPoints; 55 56 private final TIntObjectHashMap m_aroundAdvice = new TIntObjectHashMap(); 57 private final TIntObjectHashMap m_beforeAdvice = new TIntObjectHashMap(); 58 private final TIntObjectHashMap m_afterAdvice = new TIntObjectHashMap(); 59 private final TIntObjectHashMap m_afterReturningAdvice = new TIntObjectHashMap(); 60 private final TIntObjectHashMap m_afterThrowingAdvice = new TIntObjectHashMap(); 61 62 67 public AdvisableImpl(final Object targetInstance) { 68 if (!(targetInstance instanceof Advisable)) { 69 throw new RuntimeException ( 70 "advisable mixin applied to target class that does not implement the Advisable interface" 71 ); 72 } 73 m_targetInstance = (Advisable) targetInstance; 74 75 try { 76 Field f = targetInstance.getClass().getDeclaredField("aw$emittedJoinPoints"); 77 f.setAccessible(true); 78 m_emittedJoinPoints = (TIntObjectHashMap) f.get(null); 79 } catch (Exception e) { 80 throw new RuntimeException ( 81 "advisable mixin applied to target class cannot access reflective information: " + e.toString() 82 ); 83 } 84 } 85 86 90 public void aw_addAdvice(final String pointcut, final Advice advice) { 91 addAdvice(pointcut, advice); 92 } 93 94 98 public void aw_removeAdvice(final String pointcut, final Class adviceClass) { 99 removeAdvice(pointcut, adviceClass); 100 } 101 102 106 public AroundAdvice[] aw$getAroundAdvice(final int joinPointIndex) { 107 Object advice = m_aroundAdvice.get(joinPointIndex); 108 if (advice == null) { 109 return EMPTY_AROUND_ADVICE_ARRAY; 110 } else { 111 return (AroundAdvice[]) advice; 112 } 113 } 114 115 119 public BeforeAdvice[] aw$getBeforeAdvice(final int joinPointIndex) { 120 Object advice = m_beforeAdvice.get(joinPointIndex); 121 if (advice == null) { 122 return EMPTY_BEFORE_ADVICE_ARRAY; 123 } else { 124 return (BeforeAdvice[]) advice; 125 } 126 } 127 128 132 public AfterAdvice[] aw$getAfterAdvice(final int joinPointIndex) { 133 Object advice = m_afterAdvice.get(joinPointIndex); 134 if (advice == null) { 135 return EMPTY_AFTER_ADVICE_ARRAY; 136 } else { 137 return (AfterAdvice[]) advice; 138 } 139 } 140 141 145 public AfterReturningAdvice[] aw$getAfterReturningAdvice(final int joinPointIndex) { 146 Object advice = m_afterReturningAdvice.get(joinPointIndex); 147 if (advice == null) { 148 return EMPTY_AFTER_RETURNING_ADVICE_ARRAY; 149 } else { 150 return (AfterReturningAdvice[]) advice; 151 } 152 } 153 154 158 public AfterThrowingAdvice[] aw$getAfterThrowingAdvice(final int joinPointIndex) { 159 Object advice = m_afterThrowingAdvice.get(joinPointIndex); 160 if (advice == null) { 161 return EMPTY_AFTER_THROWING_ADVICE_ARRAY; 162 } else { 163 return (AfterThrowingAdvice[]) advice; 164 } 165 } 166 167 171 private void addAdvice(final String pointcut, 172 final Advice advice) { 173 ExpressionInfo expressionInfo = new ExpressionInfo(pointcut, EXPRESSION_NAMESPACE); 174 Object [] emittedJoinPoints = m_emittedJoinPoints.getValues(); 175 for (int i = 0; i < emittedJoinPoints.length; i++) { 176 EmittedJoinPoint emittedJoinPoint = (EmittedJoinPoint) emittedJoinPoints[i]; 177 if (match(expressionInfo, PointcutType.EXECUTION, emittedJoinPoint) 178 || match(expressionInfo, PointcutType.CALL, emittedJoinPoint) 179 || match(expressionInfo, PointcutType.HANDLER, emittedJoinPoint) 180 || match(expressionInfo, PointcutType.GET, emittedJoinPoint) 181 || match(expressionInfo, PointcutType.SET, emittedJoinPoint) 182 ) { 184 int hash = emittedJoinPoint.getJoinPointClassName().hashCode(); 185 addAroundAdvice(advice, hash); 186 addBeforeAdvice(advice, hash); 187 addAfterAdvice(advice, hash); 188 addAfterReturningAdvice(advice, hash); 189 addAfterThrowingAdvice(advice, hash); 190 } 191 } 192 } 193 194 198 private void removeAdvice(final String pointcut, 199 final Class adviceClass) { 200 ExpressionInfo expressionInfo = new ExpressionInfo(pointcut, EXPRESSION_NAMESPACE); 201 Object [] emittedJoinPoints = m_emittedJoinPoints.getValues(); 202 for (int i = 0; i < emittedJoinPoints.length; i++) { 203 EmittedJoinPoint emittedJoinPoint = (EmittedJoinPoint) emittedJoinPoints[i]; 204 if (match(expressionInfo, PointcutType.EXECUTION, emittedJoinPoint) 205 || match(expressionInfo, PointcutType.CALL, emittedJoinPoint) 206 || match(expressionInfo, PointcutType.HANDLER, emittedJoinPoint) 207 || match(expressionInfo, PointcutType.GET, emittedJoinPoint) 208 || match(expressionInfo, PointcutType.SET, emittedJoinPoint) 209 ) { 211 int hash = emittedJoinPoint.getJoinPointClassName().hashCode(); 212 removeAroundAdvice(adviceClass, hash); 213 removeBeforeAdvice(adviceClass, hash); 214 removeAfterAdvice(adviceClass, hash); 215 removeAfterReturningAdvice(adviceClass, hash); 216 removeAfterThrowingAdvice(adviceClass, hash); 217 } 218 } 219 } 220 221 225 private void addAroundAdvice(final Advice advice, int joinPointHash) { 226 if (advice instanceof AroundAdvice) { 227 AroundAdvice aroundAdvice = (AroundAdvice) advice; 228 AroundAdvice[] advices; 229 AroundAdvice[] olds = aw$getAroundAdvice(joinPointHash); 230 if (olds != null) { 231 advices = new AroundAdvice[olds.length + 1]; 232 System.arraycopy(olds, 0, advices, 0, olds.length); 233 advices[advices.length - 1] = aroundAdvice; 234 } else { 235 advices = new AroundAdvice[]{aroundAdvice}; 236 } 237 m_aroundAdvice.put(joinPointHash, advices); 238 } 239 } 240 241 245 private void addBeforeAdvice(final Advice advice, int joinPointHash) { 246 if (advice instanceof BeforeAdvice) { 247 BeforeAdvice beforeAdvice = (BeforeAdvice) advice; 248 BeforeAdvice[] advices; 249 BeforeAdvice[] olds = aw$getBeforeAdvice(joinPointHash); 250 if (olds != null) { 251 advices = new BeforeAdvice[olds.length + 1]; 252 System.arraycopy(olds, 0, advices, 0, olds.length); 253 advices[advices.length - 1] = beforeAdvice; 254 } else { 255 advices = new BeforeAdvice[]{beforeAdvice}; 256 } 257 m_beforeAdvice.put(joinPointHash, advices); 258 } 259 } 260 261 265 private void addAfterAdvice(final Advice advice, int joinPointHash) { 266 if (advice instanceof AfterAdvice) { 267 AfterAdvice afterFinallyAdvice = (AfterAdvice) advice; 268 AfterAdvice[] advices; 269 AfterAdvice[] olds = aw$getAfterAdvice(joinPointHash); 270 if (olds != null) { 271 advices = new AfterAdvice[olds.length + 1]; 272 System.arraycopy(olds, 0, advices, 0, olds.length); 273 advices[advices.length - 1] = afterFinallyAdvice; 274 } else { 275 advices = new AfterAdvice[]{afterFinallyAdvice}; 276 } 277 m_afterAdvice.put(joinPointHash, advices); 278 } 279 } 280 281 285 private void addAfterReturningAdvice(final Advice advice, int joinPointHash) { 286 if (advice instanceof AfterReturningAdvice) { 287 AfterReturningAdvice afterReturningAdvice = (AfterReturningAdvice) advice; 288 AfterReturningAdvice[] advices; 289 AfterReturningAdvice[] olds = aw$getAfterReturningAdvice(joinPointHash); 290 if (olds != null) { 291 advices = new AfterReturningAdvice[olds.length + 1]; 292 System.arraycopy(olds, 0, advices, 0, olds.length); 293 advices[advices.length - 1] = afterReturningAdvice; 294 } else { 295 advices = new AfterReturningAdvice[]{afterReturningAdvice}; 296 } 297 m_afterReturningAdvice.put(joinPointHash, advices); 298 } 299 } 300 301 305 private void addAfterThrowingAdvice(final Advice advice, int joinPointHash) { 306 if (advice instanceof AfterThrowingAdvice) { 307 AfterThrowingAdvice afterThrowingAdvice = (AfterThrowingAdvice) advice; 308 AfterThrowingAdvice[] advices; 309 AfterThrowingAdvice[] olds = aw$getAfterThrowingAdvice(joinPointHash); 310 if (olds != null) { 311 advices = new AfterThrowingAdvice[olds.length + 1]; 312 System.arraycopy(olds, 0, advices, 0, olds.length); 313 advices[advices.length - 1] = afterThrowingAdvice; 314 } else { 315 advices = new AfterThrowingAdvice[]{afterThrowingAdvice}; 316 } 317 m_afterThrowingAdvice.put(joinPointHash, advices); 318 } 319 } 320 321 325 private void removeAroundAdvice(final Class adviceClass, int joinPointHash) { 326 if (isAroundAdvice(adviceClass)) { 327 AroundAdvice[] oldArray = aw$getAroundAdvice(joinPointHash); 328 if (oldArray.length == 0) { 329 } else if (oldArray.length == 1) { 330 m_aroundAdvice.put(joinPointHash, EMPTY_AROUND_ADVICE_ARRAY); 331 } else { 332 List newArrayList = new ArrayList (); 333 for (int i = 0; i < oldArray.length; i++) { 334 AroundAdvice aroundAdvice = oldArray[i]; 335 if (!aroundAdvice.getClass().equals(adviceClass)) { 336 newArrayList.add(aroundAdvice); 337 } 338 } 339 m_aroundAdvice.put( 340 joinPointHash, 341 (AroundAdvice[]) newArrayList.toArray(new AroundAdvice[newArrayList.size()]) 342 ); 343 } 344 } 345 } 346 347 351 private void removeBeforeAdvice(final Class adviceClass, int joinPointHash) { 352 if (isBeforeAdvice(adviceClass)) { 353 BeforeAdvice[] oldArray = aw$getBeforeAdvice(joinPointHash); 354 if (oldArray.length == 0) { 355 } else if (oldArray.length == 1) { 356 m_beforeAdvice.put(joinPointHash, EMPTY_BEFORE_ADVICE_ARRAY); 357 } else { 358 List newArrayList = new ArrayList (); 359 for (int i = 0; i < oldArray.length; i++) { 360 BeforeAdvice beforeAdvice = oldArray[i]; 361 if (!beforeAdvice.getClass().equals(adviceClass)) { 362 newArrayList.add(beforeAdvice); 363 } 364 } 365 m_beforeAdvice.put( 366 joinPointHash, 367 (BeforeAdvice[]) newArrayList.toArray(new BeforeAdvice[newArrayList.size()]) 368 ); 369 } 370 } 371 } 372 373 377 private void removeAfterAdvice(final Class adviceClass, int joinPointHash) { 378 if (isAfterAdvice(adviceClass)) { 379 AfterAdvice[] oldArray = aw$getAfterAdvice(joinPointHash); 380 if (oldArray.length == 0) { 381 } else if (oldArray.length == 1) { 382 m_afterAdvice.put(joinPointHash, EMPTY_AFTER_ADVICE_ARRAY); 383 } else { 384 List newArrayList = new ArrayList (); 385 for (int i = 0; i < oldArray.length; i++) { 386 AfterAdvice afterAdvice = oldArray[i]; 387 if (!afterAdvice.getClass().equals(adviceClass)) { 388 newArrayList.add(afterAdvice); 389 } 390 } 391 m_afterAdvice.put( 392 joinPointHash, 393 (AfterAdvice[]) newArrayList.toArray(new AfterAdvice[newArrayList.size()]) 394 ); 395 } 396 } 397 } 398 399 403 private void removeAfterReturningAdvice(final Class adviceClass, int joinPointHash) { 404 if (isAfterReturningAdvice(adviceClass)) { 405 AfterReturningAdvice[] oldArray = aw$getAfterReturningAdvice(joinPointHash); 406 if (oldArray.length == 0) { 407 } else if (oldArray.length == 1) { 408 m_afterReturningAdvice.put(joinPointHash, EMPTY_AFTER_RETURNING_ADVICE_ARRAY); 409 } else { 410 List newArrayList = new ArrayList (); 411 for (int i = 0; i < oldArray.length; i++) { 412 AfterReturningAdvice afterReturningAdvice = oldArray[i]; 413 if (!afterReturningAdvice.getClass().equals(adviceClass)) { 414 newArrayList.add(afterReturningAdvice); 415 } 416 } 417 m_afterReturningAdvice.put( 418 joinPointHash, 419 (AfterReturningAdvice[]) newArrayList.toArray(new AfterReturningAdvice[newArrayList.size()]) 420 ); 421 } 422 } 423 } 424 425 429 private void removeAfterThrowingAdvice(final Class adviceClass, int joinPointHash) { 430 if (isAfterThrowingAdvice(adviceClass)) { 431 AfterThrowingAdvice[] oldArray = aw$getAfterThrowingAdvice(joinPointHash); 432 if (oldArray.length == 0) { 433 } else if (oldArray.length == 1) { 434 m_afterThrowingAdvice.put(joinPointHash, EMPTY_AFTER_THROWING_ADVICE_ARRAY); 435 } else { 436 List newArrayList = new ArrayList (); 437 for (int i = 0; i < oldArray.length; i++) { 438 AfterThrowingAdvice advice = oldArray[i]; 439 if (!advice.getClass().equals(adviceClass)) { 440 newArrayList.add(advice); 441 } 442 } 443 m_afterThrowingAdvice.put( 444 joinPointHash, 445 (AfterThrowingAdvice[]) newArrayList.toArray(new AfterThrowingAdvice[newArrayList.size()]) 446 ); 447 } 448 } 449 } 450 451 private boolean isAroundAdvice(final Class adviceClass) { 452 if (adviceClass == AroundAdvice.class) { 453 return true; 454 } 455 Class [] interfaces = adviceClass.getInterfaces(); 456 for (int i = 0; i < interfaces.length; i++) { 457 Class anInterface = interfaces[i]; 458 if (anInterface == AroundAdvice.class) { 459 return true; 460 } 461 } 462 return false; 463 } 464 465 private boolean isBeforeAdvice(final Class adviceClass) { 466 if (adviceClass == BeforeAdvice.class) { 467 return true; 468 } 469 Class [] interfaces = adviceClass.getInterfaces(); 470 for (int i = 0; i < interfaces.length; i++) { 471 Class anInterface = interfaces[i]; 472 if (anInterface == BeforeAdvice.class) { 473 return true; 474 } 475 } 476 return false; 477 } 478 479 private boolean isAfterAdvice(final Class adviceClass) { 480 if (adviceClass == AfterAdvice.class) { 481 return true; 482 } 483 Class [] interfaces = adviceClass.getInterfaces(); 484 for (int i = 0; i < interfaces.length; i++) { 485 Class anInterface = interfaces[i]; 486 if (anInterface == AfterAdvice.class) { 487 return true; 488 } 489 } 490 return false; 491 } 492 493 private boolean isAfterReturningAdvice(final Class adviceClass) { 494 if (adviceClass == AfterReturningAdvice.class) { 495 return true; 496 } 497 Class [] interfaces = adviceClass.getInterfaces(); 498 for (int i = 0; i < interfaces.length; i++) { 499 Class anInterface = interfaces[i]; 500 if (anInterface == AfterReturningAdvice.class) { 501 return true; 502 } 503 } 504 return false; 505 } 506 507 private boolean isAfterThrowingAdvice(final Class adviceClass) { 508 if (adviceClass == AfterThrowingAdvice.class) { 509 return true; 510 } 511 Class [] interfaces = adviceClass.getInterfaces(); 512 for (int i = 0; i < interfaces.length; i++) { 513 Class anInterface = interfaces[i]; 514 if (anInterface == AfterThrowingAdvice.class) { 515 return true; 516 } 517 } 518 return false; 519 } 520 521 529 private boolean match(ExpressionInfo expression, PointcutType pointcutType, EmittedJoinPoint emittedJoinPoint) { 530 ClassInfo callerClassInfo = JavaClassInfo.getClassInfo(m_targetInstance.getClass()); 531 ClassInfo calleeClassInfo = AsmClassInfo.getClassInfo(emittedJoinPoint.getCalleeClassName(), m_targetInstance.getClass().getClassLoader()); 532 533 if (!expression.getAdvisedClassFilterExpression().match(new ExpressionContext(pointcutType, calleeClassInfo, callerClassInfo))) { 535 return false; 536 } 537 538 final ReflectionInfo reflectionInfo; 540 final PointcutType joinPointType; 541 switch (emittedJoinPoint.getJoinPointType()) { 542 case JoinPointType.STATIC_INITIALIZATION_INT: 543 reflectionInfo = calleeClassInfo.staticInitializer(); 544 joinPointType = PointcutType.STATIC_INITIALIZATION; 545 break; 546 case JoinPointType.METHOD_EXECUTION_INT: 547 reflectionInfo = calleeClassInfo.getMethod(emittedJoinPoint.getJoinPointHash()); 548 joinPointType = PointcutType.EXECUTION; 549 break; 550 case JoinPointType.METHOD_CALL_INT: 551 reflectionInfo = calleeClassInfo.getMethod(emittedJoinPoint.getJoinPointHash()); 552 joinPointType = PointcutType.CALL; 553 break; 554 case JoinPointType.FIELD_GET_INT: 555 reflectionInfo = calleeClassInfo.getField(emittedJoinPoint.getJoinPointHash()); 556 joinPointType = PointcutType.GET; 557 break; 558 case JoinPointType.FIELD_SET_INT: 559 reflectionInfo = calleeClassInfo.getField(emittedJoinPoint.getJoinPointHash()); 560 joinPointType = PointcutType.SET; 561 break; 562 case JoinPointType.CONSTRUCTOR_EXECUTION_INT: 563 reflectionInfo = calleeClassInfo.getConstructor(emittedJoinPoint.getJoinPointHash()); 564 joinPointType = PointcutType.EXECUTION; 565 break; 566 case JoinPointType.CONSTRUCTOR_CALL_INT: 567 reflectionInfo = calleeClassInfo.getConstructor(emittedJoinPoint.getJoinPointHash()); 568 joinPointType = PointcutType.CALL; 569 break; 570 case JoinPointType.HANDLER_INT: 571 reflectionInfo = calleeClassInfo; 572 joinPointType = PointcutType.HANDLER; 573 break; 574 default: 575 throw new RuntimeException ("Joinpoint type not supported: " + emittedJoinPoint.getJoinPointType()); 576 } 577 578 final ReflectionInfo withinInfo; 580 if (TransformationConstants.CLINIT_METHOD_NAME.equals(emittedJoinPoint.getCallerMethodName())) { 581 withinInfo = callerClassInfo.staticInitializer(); 582 } else if (TransformationConstants.INIT_METHOD_NAME.equals(emittedJoinPoint.getCallerMethodName())) { 583 withinInfo = callerClassInfo.getConstructor(AsmHelper.calculateConstructorHash( 584 emittedJoinPoint.getCallerMethodDesc() 585 )); 586 } else { 587 withinInfo = 588 callerClassInfo.getMethod(AsmHelper.calculateMethodHash(emittedJoinPoint.getCallerMethodName(), 589 emittedJoinPoint.getCallerMethodDesc()) 590 ); 591 } 592 593 if (pointcutType != PointcutType.WITHIN && pointcutType != joinPointType) { 595 return false; 596 } 597 598 return expression.getExpression().match(new ExpressionContext(pointcutType, reflectionInfo, withinInfo)); 599 } 600 } 601 | Popular Tags |