1 8 package org.codehaus.aspectwerkz.joinpoint.management; 9 10 import java.util.ArrayList ; 11 import java.util.Collection ; 12 import java.util.Iterator ; 13 import java.util.List ; 14 import java.util.Map ; 15 import java.util.Set ; 16 import java.util.WeakHashMap ; 17 18 import org.codehaus.aspectwerkz.aspect.AdviceInfo; 19 import org.codehaus.aspectwerkz.aspect.AdviceType; 20 import org.codehaus.aspectwerkz.definition.AdviceDefinition; 21 import org.codehaus.aspectwerkz.definition.AspectDefinition; 22 import org.codehaus.aspectwerkz.definition.SystemDefinition; 23 import org.codehaus.aspectwerkz.definition.SystemDefinitionContainer; 24 import org.codehaus.aspectwerkz.definition.Virtual; 25 import org.codehaus.aspectwerkz.expression.ArgsIndexVisitor; 26 import org.codehaus.aspectwerkz.expression.ExpressionContext; 27 import org.codehaus.aspectwerkz.expression.ExpressionInfo; 28 import org.codehaus.aspectwerkz.expression.PointcutType; 29 import org.codehaus.aspectwerkz.joinpoint.ConstructorSignature; 30 import org.codehaus.aspectwerkz.joinpoint.EnclosingStaticJoinPoint; 31 import org.codehaus.aspectwerkz.joinpoint.JoinPoint; 32 import org.codehaus.aspectwerkz.joinpoint.MethodSignature; 33 import org.codehaus.aspectwerkz.joinpoint.Signature; 34 import org.codehaus.aspectwerkz.joinpoint.StaticJoinPoint; 35 import org.codehaus.aspectwerkz.joinpoint.impl.EnclosingStaticJoinPointImpl; 36 import org.codehaus.aspectwerkz.reflect.ClassInfo; 37 import org.codehaus.aspectwerkz.reflect.ClassInfoHelper; 38 import org.codehaus.aspectwerkz.reflect.MethodInfo; 39 import org.codehaus.aspectwerkz.reflect.ReflectionInfo; 40 import org.codehaus.aspectwerkz.reflect.impl.asm.AsmClassInfo; 41 import org.codehaus.aspectwerkz.reflect.impl.java.JavaClassInfo; 42 import org.codehaus.aspectwerkz.transform.TransformationConstants; 43 import org.codehaus.aspectwerkz.transform.inlining.AsmHelper; 44 import org.codehaus.aspectwerkz.transform.inlining.AspectModelManager; 45 import org.codehaus.aspectwerkz.transform.inlining.EmittedJoinPoint; 46 import org.codehaus.aspectwerkz.transform.inlining.compiler.CompilationInfo; 47 import org.codehaus.aspectwerkz.transform.inlining.compiler.JoinPointFactory; 48 import org.codehaus.aspectwerkz.transform.inlining.spi.AspectModel; 49 import org.codehaus.aspectwerkz.util.ContextClassLoader; 50 import org.codehaus.aspectwerkz.util.Strings; 51 import org.objectweb.asm.Type; 52 53 61 public class JoinPointManager { 62 78 public static void loadJoinPoint(final int joinPointType, 79 final Class callerClass, 80 final String callerMethodName, 81 final String callerMethodDesc, 82 final int callerMethodModifiers, 83 final String calleeClassName, 84 final String calleeMemberName, 85 final String calleeMemberDesc, 86 final int calleeMemberModifiers, 87 final int joinPointHash, 88 final String joinPointClassName) { 89 Class calleeClass = null; 90 try { 91 if (calleeClassName != null) { 92 calleeClass = Class.forName(calleeClassName.replace('/', '.'), false, callerClass.getClassLoader()); 93 } 94 } catch (ClassNotFoundException calleeNotFound) { 95 throw new RuntimeException ( 96 "callee class [" + calleeClassName + "] can not be found in class loader [" + 97 callerClass.getClassLoader() + 98 "]" 99 ); 100 } 101 102 final ClassLoader classLoader = callerClass.getClassLoader(); 105 boolean generateJoinPoint = false; 106 try { 107 if (calleeClass == null) { 108 throw new RuntimeException ("callee class [" + calleeClassName + "] is NULL"); 109 } 110 ContextClassLoader.forName(classLoader, joinPointClassName.replace('/', '.')); 111 } catch (ClassNotFoundException e) { 112 generateJoinPoint = true; 113 } 114 if (!generateJoinPoint) { 115 return; 116 } 117 118 final CompiledJoinPoint compiledJoinPoint = compileJoinPoint( 119 joinPointType, 120 callerClass, 121 callerMethodName, 122 callerMethodDesc, 123 callerMethodModifiers, 124 calleeClassName, 125 calleeMemberName, 126 calleeMemberDesc, 127 calleeMemberModifiers, 128 joinPointHash, 129 joinPointClassName, 130 calleeClass, 131 classLoader 132 ); 133 134 Class jpClass = JoinPointFactory.attachToClassLoader( 135 joinPointClassName, classLoader, compiledJoinPoint.bytecode 136 ); 137 JoinPointFactory.addCompilationInfo(jpClass, compiledJoinPoint.compilationInfo); 138 } 139 140 160 public static CompiledJoinPoint compileJoinPoint(final int joinPointType, 161 final Class callerClass, 162 final String callerMethodName, 163 final String callerMethodDesc, 164 final int callerMethodModifiers, 165 final String calleeClassName, 166 final String calleeMemberName, 167 final String calleeMemberDesc, 168 final int calleeMemberModifiers, 169 final int joinPointHash, 170 final String joinPointClassName, 171 final Class calleeClass, 172 final ClassLoader loader) { 173 174 ClassInfo calleeClassInfo = JavaClassInfo.getClassInfo(calleeClass); 175 176 final ReflectionInfo reflectionInfo; 178 final PointcutType pointcutType; 179 switch (joinPointType) { 180 case JoinPointType.STATIC_INITIALIZATION_INT: 181 reflectionInfo = calleeClassInfo.staticInitializer(); 182 pointcutType = PointcutType.STATIC_INITIALIZATION; 183 break; 184 case JoinPointType.METHOD_EXECUTION_INT: 185 reflectionInfo = calleeClassInfo.getMethod(joinPointHash); 186 pointcutType = PointcutType.EXECUTION; 187 break; 188 case JoinPointType.METHOD_CALL_INT: 189 reflectionInfo = calleeClassInfo.getMethod(joinPointHash); 190 pointcutType = PointcutType.CALL; 191 break; 192 case JoinPointType.FIELD_GET_INT: 193 reflectionInfo = calleeClassInfo.getField(joinPointHash); 194 pointcutType = PointcutType.GET; 195 break; 196 case JoinPointType.FIELD_SET_INT: 197 reflectionInfo = calleeClassInfo.getField(joinPointHash); 198 pointcutType = PointcutType.SET; 199 break; 200 case JoinPointType.CONSTRUCTOR_EXECUTION_INT: 201 reflectionInfo = calleeClassInfo.getConstructor(joinPointHash); 202 pointcutType = PointcutType.EXECUTION; 203 break; 204 case JoinPointType.CONSTRUCTOR_CALL_INT: 205 reflectionInfo = calleeClassInfo.getConstructor(joinPointHash); 206 pointcutType = PointcutType.CALL; 207 break; 208 case JoinPointType.HANDLER_INT: 209 reflectionInfo = calleeClassInfo; 210 pointcutType = PointcutType.HANDLER; 211 break; 212 default: 213 throw new RuntimeException ("Joinpoint type not supported: " + joinPointType); 214 } 215 216 final ClassInfo callerClassInfo = JavaClassInfo.getClassInfo(callerClass); 218 final ReflectionInfo withinInfo; 219 if (TransformationConstants.CLINIT_METHOD_NAME.equals(callerMethodName)) { 220 withinInfo = callerClassInfo.staticInitializer(); 221 } else if (TransformationConstants.INIT_METHOD_NAME.equals(callerMethodName)) { 222 withinInfo = callerClassInfo.getConstructor(AsmHelper.calculateConstructorHash(callerMethodDesc)); 223 } else { 224 withinInfo = 225 callerClassInfo.getMethod(AsmHelper.calculateMethodHash(callerMethodName, callerMethodDesc)); 226 } 227 228 final ExpressionContext ctx = new ExpressionContext(pointcutType, reflectionInfo, withinInfo); 230 final AdviceInfoContainer adviceContainer = getAdviceInfoContainerForJoinPoint( 231 ctx, loader 232 ); 233 final EmittedJoinPoint emittedJoinPoint = new EmittedJoinPoint( 234 joinPointType, 235 callerClass.getName(), 236 callerMethodName, 237 callerMethodDesc, 238 callerMethodModifiers, 239 calleeClass.getName(), 240 calleeMemberName, 241 calleeMemberDesc, 242 calleeMemberModifiers, 243 joinPointHash, 244 joinPointClassName, 245 EmittedJoinPoint.NO_LINE_NUMBER 246 ); 247 final CompilationInfo.Model compilationModel = new CompilationInfo.Model( 248 emittedJoinPoint, adviceContainer, callerClassInfo 249 ); 250 251 return new CompiledJoinPoint(compilationModel); 252 } 253 254 257 public static class CompiledJoinPoint { 258 public byte[] bytecode; 259 public CompilationInfo compilationInfo; 260 261 public CompiledJoinPoint(CompilationInfo.Model model) { 262 bytecode = JoinPointFactory.compileJoinPoint(model); 263 compilationInfo = new CompilationInfo(model); 264 } 265 } 266 267 274 public static AdviceInfoContainer getAdviceInfoContainerForJoinPoint(final ExpressionContext expressionContext, 275 final ClassLoader loader) { 276 final List beforeAdvices = new ArrayList (); 277 final List aroundAdvices = new ArrayList (); 278 final List afterFinallyAdvices = new ArrayList (); 279 final List afterReturningAdvices = new ArrayList (); 280 final List afterThrowingAdvices = new ArrayList (); 281 282 final Set systemDefinitions = SystemDefinitionContainer.getDefinitionsFor(loader); 283 284 for (Iterator iterator = systemDefinitions.iterator(); iterator.hasNext();) { 285 SystemDefinition systemDefinition = (SystemDefinition) iterator.next(); 286 Collection aspects = systemDefinition.getAspectDefinitions(); 287 for (Iterator iterator1 = aspects.iterator(); iterator1.hasNext();) { 288 AspectDefinition aspectDefinition = (AspectDefinition) iterator1.next(); 289 if (aspectDefinition.getName().equals(Virtual.class.getName())) { 290 continue; 291 } 292 293 for (Iterator iterator2 = aspectDefinition.getAdviceDefinitions().iterator(); iterator2.hasNext();) { 295 AdviceDefinition adviceDefinition = (AdviceDefinition) iterator2.next(); 296 final ExpressionInfo expressionInfo = adviceDefinition.getExpressionInfo(); 297 if (expressionInfo == null) { 298 continue; 299 } 300 if (expressionInfo.getExpression().match(expressionContext)) { 301 expressionContext.resetRuntimeState(); 304 ArgsIndexVisitor.updateContextForRuntimeInformation( 305 expressionInfo, 306 expressionContext, 307 loader 308 ); 309 314 final MethodInfo adviceMethodInfo = adviceDefinition.getMethodInfo(); 316 final AdviceInfo adviceInfo = new AdviceInfo( 317 aspectDefinition.getQualifiedName(), 318 aspectDefinition.getClassName(), 319 aspectDefinition.getDeploymentModel(), 320 adviceMethodInfo.getName(), 321 AsmHelper.getMethodDescriptor(adviceMethodInfo), 322 AsmHelper.getArgumentTypes(adviceMethodInfo), 323 adviceDefinition.getType(), 324 adviceDefinition.getSpecialArgumentType(), 325 adviceDefinition.getName(), 326 expressionContext.m_targetWithRuntimeCheck, 327 expressionInfo, 328 expressionContext, 329 adviceDefinition 330 ); 331 332 setMethodArgumentIndexes(expressionInfo, expressionContext, adviceInfo, loader); 333 334 if (AdviceType.BEFORE.equals(adviceDefinition.getType())) { 335 beforeAdvices.add(adviceInfo); 336 } else if (AdviceType.AROUND.equals(adviceDefinition.getType())) { 337 aroundAdvices.add(adviceInfo); 338 } else if (AdviceType.AFTER_FINALLY.equals(adviceDefinition.getType())) { 339 afterFinallyAdvices.add(adviceInfo); 340 } else if (AdviceType.AFTER_RETURNING.equals(adviceDefinition.getType())) { 341 afterReturningAdvices.add(adviceInfo); 342 } else if (AdviceType.AFTER_THROWING.equals(adviceDefinition.getType())) { 343 afterThrowingAdvices.add(adviceInfo); 344 } else if (AdviceType.AFTER.equals(adviceDefinition.getType())) { 345 afterFinallyAdvices.add(adviceInfo); } 347 } 348 } 349 } 350 } 351 352 final AdviceInfoContainer adviceInfoContainer = new AdviceInfoContainer( 353 aroundAdvices, 354 beforeAdvices, 355 afterFinallyAdvices, 356 afterReturningAdvices, 357 afterThrowingAdvices 358 ); 359 return adviceInfoContainer; 360 } 361 362 368 public static String [] getParameterNames(final String adviceName) { 369 int paren = adviceName.indexOf('('); 370 List paramNames = new ArrayList (); 371 if (paren > 0) { 372 String params = adviceName.substring(paren + 1, adviceName.lastIndexOf(')')).trim(); 373 String [] javaParameters = Strings.splitString(params, ","); 374 for (int i = 0; i < javaParameters.length; i++) { 375 String javaParameter = Strings.replaceSubString(javaParameters[i], " ", " ").trim(); 376 String [] paramInfo = Strings.splitString(javaParameter, " "); 377 if (paramInfo.length == 2) { 379 paramNames.add(paramInfo[1]); 380 } else { 381 paramNames.add("anonymous_" + i); 382 } 383 } 384 } 385 String [] paramNamesArray = new String [paramNames.size()]; 386 int index = 0; 387 for (Iterator it = paramNames.iterator(); it.hasNext(); index++) { 388 paramNamesArray[index] = (String ) it.next(); 389 } 390 return paramNamesArray; 391 } 392 393 404 private static void setMethodArgumentIndexes(final ExpressionInfo expressionInfo, 405 final ExpressionContext ctx, 406 final AdviceInfo adviceInfo, 407 final ClassLoader loader) { 408 String [] adviceArgNames = getParameterNames(adviceInfo.getName()); 410 411 int[] adviceToTargetArgs = new int[adviceInfo.getMethodParameterTypes().length]; 413 for (int k = 0; k < adviceArgNames.length; k++) { 414 String adviceArgName = adviceArgNames[k]; 415 int exprArgIndex = expressionInfo.getArgumentIndex(adviceArgName); 416 if (exprArgIndex >= 0 && ctx.m_exprIndexToTargetIndex.containsKey(adviceArgName)) { 417 adviceToTargetArgs[k] = ctx.m_exprIndexToTargetIndex.get(adviceArgName); 418 } else { 419 final Type type = adviceInfo.getMethodParameterTypes()[k]; 422 if (isJoinPoint(type)) { 423 adviceToTargetArgs[k] = AdviceInfo.JOINPOINT_ARG; 424 } else if (isStaticJoinPoint(type)) { 425 adviceToTargetArgs[k] = AdviceInfo.STATIC_JOINPOINT_ARG; 426 } else if (isTarget(adviceArgName, ctx)) { 427 adviceToTargetArgs[k] = AdviceInfo.TARGET_ARG; 428 } else if (isThis(adviceArgName, ctx)) { 429 adviceToTargetArgs[k] = AdviceInfo.THIS_ARG; 430 } else if (isSpecialArgument(adviceArgName, expressionInfo)) { 431 adviceToTargetArgs[k] = AdviceInfo.SPECIAL_ARGUMENT; 432 } else if (isCustomJointPoint(type, loader)) { 433 adviceToTargetArgs[k] = AdviceInfo.CUSTOM_JOIN_POINT_ARG; 434 } else { 435 throw new Error ( 436 "Unbound advice parameter at index " + k + 437 " in " + adviceInfo.getMethodName() + 438 adviceInfo.getMethodSignature() + 439 " named " + 440 adviceArgName 441 ); 442 } 443 } 444 } 445 446 if (adviceArgNames.length == 0) { 448 AspectDefinition aspectDef = adviceInfo.getAdviceDefinition().getAspectDefinition(); 449 Type[] adviceArgTypes = adviceInfo.getMethodParameterTypes(); 450 for (int i = 0; i < adviceArgTypes.length; i++) { 451 452 if (aspectDef.isAspectWerkzAspect()) { 453 if (isJoinPoint(adviceArgTypes[i])) { 454 adviceToTargetArgs[i] = AdviceInfo.JOINPOINT_ARG; 455 } else if (isStaticJoinPoint(adviceArgTypes[i])) { 456 adviceToTargetArgs[i] = AdviceInfo.STATIC_JOINPOINT_ARG; 457 } else { 458 throw new Error ( 459 "Unbound unnamed advice parameter at index " + i + 460 " in " + adviceInfo.getMethodSignature() 461 ); 462 } 463 } else { 464 final AspectModel aspectModel = AspectModelManager.getModelFor(aspectDef.getAspectModel()); 465 final String superClassName = aspectModel.getAroundClosureClassInfo().getSuperClassName(); 466 final String [] interfaces = aspectModel.getAroundClosureClassInfo().getInterfaceNames(); 467 final String [] classNames = new String [interfaces.length + 1]; 468 classNames[0] = superClassName; 469 for (int j = 1; j < interfaces.length + 1; j++) { 470 classNames[j] = interfaces[j - 1]; 471 } 472 473 final Type argType = adviceArgTypes[i]; 474 if (isValidAroundClosureType(argType, classNames)) { 475 adviceToTargetArgs[i] = AdviceInfo.VALID_NON_AW_AROUND_CLOSURE_TYPE; 476 } else if (isSpecialArgumentType(argType, adviceInfo)) { 477 adviceToTargetArgs[i] = AdviceInfo.SPECIAL_ARGUMENT; 478 } else { 479 } 480 } 481 } 482 } 483 484 adviceInfo.setMethodToArgIndexes(adviceToTargetArgs); 485 } 486 487 private static boolean isSpecialArgumentType(final Type argType, final AdviceInfo adviceInfo) { 488 final String specialArgumentTypeDesc = adviceInfo.getSpecialArgumentTypeDesc(); 489 return specialArgumentTypeDesc != null && specialArgumentTypeDesc.equals(argType.getDescriptor()); 490 } 491 492 private static boolean isValidAroundClosureType(final Type argType, final String [] closureTypeNames) { 493 for (int i = 0; i < closureTypeNames.length; i++) { 494 final String closureTypeName = closureTypeNames[i]; 495 if (closureTypeName != null && closureTypeName.equals(argType.getInternalName())) { 496 return true; 497 } 498 } 499 return false; 500 } 501 502 private static boolean isJoinPoint(final Type type) { 503 return Type.getType(JoinPoint.class).getDescriptor().equals(type.getDescriptor()); 504 } 505 506 private static boolean isStaticJoinPoint(final Type type) { 507 return Type.getType(StaticJoinPoint.class).getDescriptor().equals(type.getDescriptor()); 508 } 509 510 private static boolean isTarget(final String adviceArgName, final ExpressionContext ctx) { 511 return adviceArgName.equals(ctx.m_targetBoundedName); 512 } 513 514 private static boolean isThis(final String adviceArgName, final ExpressionContext ctx) { 515 return adviceArgName.equals(ctx.m_thisBoundedName); 516 } 517 518 private static boolean isSpecialArgument(final String adviceArgName, final ExpressionInfo expressionInfo) { 519 return adviceArgName.equals(expressionInfo.getSpecialArgumentName()); 520 } 521 522 private static boolean isCustomJointPoint(final Type type, final ClassLoader loader) { 523 ClassInfo classInfo = AsmClassInfo.getClassInfo(type.getClassName(), loader); 524 return ClassInfoHelper.implementsInterface(classInfo, ExpressionInfo.JOINPOINT_CLASS_NAME) || 525 ClassInfoHelper.implementsInterface(classInfo, ExpressionInfo.STATIC_JOINPOINT_CLASS_NAME); 526 } 527 } | Popular Tags |