1 4 package com.tc.aspectwerkz.joinpoint.management; 5 6 import com.tc.asm.Type; 7 8 import com.tc.aspectwerkz.aspect.AdviceInfo; 9 import com.tc.aspectwerkz.aspect.AdviceType; 10 import com.tc.aspectwerkz.definition.AdviceDefinition; 11 import com.tc.aspectwerkz.definition.AspectDefinition; 12 import com.tc.aspectwerkz.definition.SystemDefinition; 13 import com.tc.aspectwerkz.definition.SystemDefinitionContainer; 14 import com.tc.aspectwerkz.definition.Virtual; 15 import com.tc.aspectwerkz.joinpoint.JoinPoint; 16 import com.tc.aspectwerkz.joinpoint.StaticJoinPoint; 17 import com.tc.aspectwerkz.reflect.impl.asm.AsmClassInfo; 18 import com.tc.aspectwerkz.reflect.impl.java.JavaClassInfo; 19 import com.tc.aspectwerkz.reflect.ClassInfo; 20 import com.tc.aspectwerkz.reflect.ReflectionInfo; 21 import com.tc.aspectwerkz.reflect.MethodInfo; 22 import com.tc.aspectwerkz.reflect.ClassInfoHelper; 23 import com.tc.aspectwerkz.transform.TransformationConstants; 24 import com.tc.aspectwerkz.transform.inlining.AsmHelper; 25 import com.tc.aspectwerkz.transform.inlining.AspectModelManager; 26 import com.tc.aspectwerkz.transform.inlining.EmittedJoinPoint; 27 import com.tc.aspectwerkz.transform.inlining.compiler.CompilationInfo; 28 import com.tc.aspectwerkz.transform.inlining.compiler.CompilerHelper; 29 import com.tc.aspectwerkz.transform.inlining.spi.AspectModel; 30 import com.tc.aspectwerkz.util.ContextClassLoader; 31 import com.tc.aspectwerkz.util.Strings; 32 import com.tc.aspectwerkz.expression.PointcutType; 33 import com.tc.aspectwerkz.expression.ExpressionContext; 34 import com.tc.aspectwerkz.expression.ExpressionInfo; 35 import com.tc.aspectwerkz.expression.ArgsIndexVisitor; 36 37 import java.util.ArrayList ; 38 import java.util.Collection ; 39 import java.util.HashSet ; 40 import java.util.Iterator ; 41 import java.util.List ; 42 import java.util.Set ; 43 44 51 public class JoinPointManager { 52 53 70 public static void loadJoinPoint(final int joinPointType, final Class callerClass, final String callerMethodName, 71 final String callerMethodDesc, final int callerMethodModifiers, final String calleeClassName, 72 final String calleeMemberName, final String calleeMemberDesc, final int calleeMemberModifiers, 73 final int joinPointHash, final String joinPointClassName, final SystemDefinition systemDef) { 74 Class calleeClass = null; 75 try { 76 if (calleeClassName != null) { 77 calleeClass = Class.forName(calleeClassName.replace('/', '.'), false, callerClass.getClassLoader()); 78 } 79 } catch (ClassNotFoundException calleeNotFound) { 80 throw new RuntimeException ("callee class [" + calleeClassName + "] can not be found in class loader [" 81 + callerClass.getClassLoader() + "]"); 82 } 83 84 final ClassLoader classLoader = callerClass.getClassLoader(); 87 boolean generateJoinPoint = false; 88 try { 89 if (calleeClass == null) { throw new RuntimeException ("callee class [" + calleeClassName + "] is NULL"); } 90 ContextClassLoader.forName(classLoader, joinPointClassName.replace('/', '.')); 91 } catch (ClassNotFoundException e) { 92 generateJoinPoint = true; 93 } 94 if (!generateJoinPoint) { return; } 95 96 final CompiledJoinPoint compiledJoinPoint = 97 compileJoinPoint(joinPointType, callerClass, callerMethodName, callerMethodDesc, callerMethodModifiers, 98 calleeClassName, calleeMemberName, calleeMemberDesc, calleeMemberModifiers, joinPointHash, 99 joinPointClassName, calleeClass, classLoader, systemDef); 100 101 Class jpClass = CompilerHelper.attachToClassLoader(joinPointClassName, classLoader, compiledJoinPoint.bytecode); 102 CompilerHelper.addCompilationInfo(jpClass, compiledJoinPoint.compilationInfo); 103 } 104 105 121 public static void loadJoinPoint(final int joinPointType, final Class callerClass, final String callerMethodName, 122 final String callerMethodDesc, final int callerMethodModifiers, final String calleeClassName, 123 final String calleeMemberName, final String calleeMemberDesc, final int calleeMemberModifiers, 124 final int joinPointHash, final String joinPointClassName) { 125 loadJoinPoint(joinPointType, callerClass, callerMethodName, callerMethodDesc, callerMethodModifiers, 126 calleeClassName, calleeMemberName, calleeMemberDesc, calleeMemberModifiers, joinPointHash, joinPointClassName, 127 null); 128 } 129 130 151 public static CompiledJoinPoint compileJoinPoint(final int joinPointType, final Class callerClass, 152 final String callerMethodName, final String callerMethodDesc, final int callerMethodModifiers, 153 final String calleeClassName, final String calleeMemberName, final String calleeMemberDesc, 154 final int calleeMemberModifiers, final int joinPointHash, final String joinPointClassName, 155 final Class calleeClass, final ClassLoader loader, final SystemDefinition systemDef) { 156 157 ClassInfo calleeClassInfo = JavaClassInfo.getClassInfo(calleeClass); 158 159 final ReflectionInfo reflectionInfo; 161 final PointcutType pointcutType; 162 switch (joinPointType) { 163 case JoinPointType.STATIC_INITIALIZATION_INT: 164 reflectionInfo = calleeClassInfo.staticInitializer(); 165 pointcutType = PointcutType.STATIC_INITIALIZATION; 166 break; 167 case JoinPointType.METHOD_EXECUTION_INT: 168 reflectionInfo = calleeClassInfo.getMethod(joinPointHash); 169 pointcutType = PointcutType.EXECUTION; 170 break; 171 case JoinPointType.METHOD_CALL_INT: 172 reflectionInfo = calleeClassInfo.getMethod(joinPointHash); 173 pointcutType = PointcutType.CALL; 174 break; 175 case JoinPointType.FIELD_GET_INT: 176 reflectionInfo = calleeClassInfo.getField(joinPointHash); 177 pointcutType = PointcutType.GET; 178 break; 179 case JoinPointType.FIELD_SET_INT: 180 reflectionInfo = calleeClassInfo.getField(joinPointHash); 181 pointcutType = PointcutType.SET; 182 break; 183 case JoinPointType.CONSTRUCTOR_EXECUTION_INT: 184 reflectionInfo = calleeClassInfo.getConstructor(joinPointHash); 185 pointcutType = PointcutType.EXECUTION; 186 break; 187 case JoinPointType.CONSTRUCTOR_CALL_INT: 188 reflectionInfo = calleeClassInfo.getConstructor(joinPointHash); 189 pointcutType = PointcutType.CALL; 190 break; 191 case JoinPointType.HANDLER_INT: 192 reflectionInfo = calleeClassInfo; 193 pointcutType = PointcutType.HANDLER; 194 break; 195 default: 196 throw new RuntimeException ("Joinpoint type not supported: " + joinPointType); 197 } 198 199 final ClassInfo callerClassInfo = JavaClassInfo.getClassInfo(callerClass); 201 final ReflectionInfo withinInfo; 202 if (TransformationConstants.CLINIT_METHOD_NAME.equals(callerMethodName)) { 203 withinInfo = callerClassInfo.staticInitializer(); 204 } else if (TransformationConstants.INIT_METHOD_NAME.equals(callerMethodName)) { 205 withinInfo = callerClassInfo.getConstructor(AsmHelper.calculateConstructorHash(callerMethodDesc)); 206 } else { 207 withinInfo = callerClassInfo.getMethod(AsmHelper.calculateMethodHash(callerMethodName, callerMethodDesc)); 208 } 209 210 final ExpressionContext ctx = new ExpressionContext(pointcutType, reflectionInfo, withinInfo); 212 final AdviceInfoContainer adviceContainer = getAdviceInfoContainerForJoinPoint(ctx, loader, systemDef); 213 final EmittedJoinPoint emittedJoinPoint = 214 new EmittedJoinPoint(joinPointType, callerClass.getName(), callerMethodName, callerMethodDesc, 215 callerMethodModifiers, calleeClass.getName(), calleeMemberName, calleeMemberDesc, calleeMemberModifiers, 216 joinPointHash, joinPointClassName, EmittedJoinPoint.NO_LINE_NUMBER); 217 final CompilationInfo.Model compilationModel = 218 new CompilationInfo.Model(emittedJoinPoint, adviceContainer, callerClassInfo); 219 220 return new CompiledJoinPoint(compilationModel); 221 } 222 223 226 public static class CompiledJoinPoint { 227 public byte[] bytecode; 228 public CompilationInfo compilationInfo; 229 230 public CompiledJoinPoint(CompilationInfo.Model model) { 231 bytecode = CompilerHelper.compileJoinPoint(model); 232 compilationInfo = new CompilationInfo(model); 233 } 234 } 235 236 244 public static AdviceInfoContainer getAdviceInfoContainerForJoinPoint(final ExpressionContext expressionContext, 245 final ClassLoader loader, final SystemDefinition systemDef) { 246 final List beforeAdvices = new ArrayList (); 247 final List aroundAdvices = new ArrayList (); 248 final List afterFinallyAdvices = new ArrayList (); 249 final List afterReturningAdvices = new ArrayList (); 250 final List afterThrowingAdvices = new ArrayList (); 251 252 final Set systemDefinitions; 253 if (systemDef == null) { 254 systemDefinitions = SystemDefinitionContainer.getDefinitionsFor(loader); 255 } else { 256 systemDefinitions = new HashSet (); 257 systemDefinitions.add(systemDef); 258 } 259 264 for (Iterator iterator = systemDefinitions.iterator(); iterator.hasNext();) { 265 SystemDefinition systemDefinition = (SystemDefinition) iterator.next(); 266 Collection aspects = systemDefinition.getAspectDefinitions(); 267 for (Iterator iterator1 = aspects.iterator(); iterator1.hasNext();) { 268 AspectDefinition aspectDefinition = (AspectDefinition) iterator1.next(); 269 if (aspectDefinition.getName().equals(Virtual.class.getName())) { 270 continue; 271 } 272 273 for (Iterator iterator2 = aspectDefinition.getAdviceDefinitions().iterator(); iterator2.hasNext();) { 275 AdviceDefinition adviceDefinition = (AdviceDefinition) iterator2.next(); 276 final ExpressionInfo expressionInfo = adviceDefinition.getExpressionInfo(); 277 if (expressionInfo == null) { 278 continue; 279 } 280 try { 281 if (expressionInfo.getExpression().match(expressionContext)) { 282 expressionContext.resetRuntimeState(); 285 ArgsIndexVisitor.updateContextForRuntimeInformation(expressionInfo, expressionContext, loader); 286 291 final MethodInfo adviceMethodInfo = adviceDefinition.getMethodInfo(); 293 final AdviceInfo adviceInfo = 294 new AdviceInfo(aspectDefinition.getQualifiedName(), aspectDefinition.getClassName(), aspectDefinition 295 .getDeploymentModel(), adviceMethodInfo.getName(), AsmHelper.getMethodDescriptor(adviceMethodInfo), 296 AsmHelper.getArgumentTypes(adviceMethodInfo), adviceDefinition.getType(), adviceDefinition 297 .getSpecialArgumentType(), adviceDefinition.getName(), 298 expressionContext.m_targetWithRuntimeCheck, expressionInfo, expressionContext, adviceDefinition); 299 300 setMethodArgumentIndexes(expressionInfo, expressionContext, adviceInfo, loader); 301 302 if (AdviceType.BEFORE.equals(adviceDefinition.getType())) { 303 beforeAdvices.add(adviceInfo); 304 } else if (AdviceType.AROUND.equals(adviceDefinition.getType())) { 305 aroundAdvices.add(adviceInfo); 306 } else if (AdviceType.AFTER_FINALLY.equals(adviceDefinition.getType())) { 307 afterFinallyAdvices.add(adviceInfo); 308 } else if (AdviceType.AFTER_RETURNING.equals(adviceDefinition.getType())) { 309 afterReturningAdvices.add(adviceInfo); 310 } else if (AdviceType.AFTER_THROWING.equals(adviceDefinition.getType())) { 311 afterThrowingAdvices.add(adviceInfo); 312 } else if (AdviceType.AFTER.equals(adviceDefinition.getType())) { 313 afterFinallyAdvices.add(adviceInfo); } 315 } 316 } catch (NullPointerException e) { 317 System.out.println("-------------------------> NPE: Expression - " + expressionInfo.getExpressionString()); 318 System.out.println("-------------------------> NPE: Context - " + expressionContext.getDebugString()); 319 throw e; 320 } 321 } 322 } 323 } 324 325 final AdviceInfoContainer adviceInfoContainer = 326 new AdviceInfoContainer(aroundAdvices, beforeAdvices, afterFinallyAdvices, afterReturningAdvices, 327 afterThrowingAdvices); 328 return adviceInfoContainer; 329 } 330 331 337 public static String [] getParameterNames(final String adviceName) { 338 int paren = adviceName.indexOf('('); 339 List paramNames = new ArrayList (); 340 if (paren > 0) { 341 String params = adviceName.substring(paren + 1, adviceName.lastIndexOf(')')).trim(); 342 String [] javaParameters = Strings.splitString(params, ","); 343 for (int i = 0; i < javaParameters.length; i++) { 344 String javaParameter = Strings.replaceSubString(javaParameters[i], " ", " ").trim(); 345 String [] paramInfo = Strings.splitString(javaParameter, " "); 346 if (paramInfo.length == 2) { 348 paramNames.add(paramInfo[1]); 349 } else { 350 paramNames.add("anonymous_" + i); 351 } 352 } 353 } 354 String [] paramNamesArray = new String [paramNames.size()]; 355 int index = 0; 356 for (Iterator it = paramNames.iterator(); it.hasNext(); index++) { 357 paramNamesArray[index] = (String ) it.next(); 358 } 359 return paramNamesArray; 360 } 361 362 372 private static void setMethodArgumentIndexes(final ExpressionInfo expressionInfo, final ExpressionContext ctx, 373 final AdviceInfo adviceInfo, final ClassLoader loader) { 374 String [] adviceArgNames = getParameterNames(adviceInfo.getName()); 376 377 int[] adviceToTargetArgs = new int[adviceInfo.getMethodParameterTypes().length]; 379 for (int k = 0; k < adviceArgNames.length; k++) { 380 String adviceArgName = adviceArgNames[k]; 381 int exprArgIndex = expressionInfo.getArgumentIndex(adviceArgName); 382 if (exprArgIndex >= 0 && ctx.m_exprIndexToTargetIndex.containsKey(adviceArgName)) { 383 adviceToTargetArgs[k] = ((Integer ) ctx.m_exprIndexToTargetIndex.get(adviceArgName)).intValue(); 384 } else { 385 final Type type = adviceInfo.getMethodParameterTypes()[k]; 388 if (isJoinPoint(type)) { 389 adviceToTargetArgs[k] = AdviceInfo.JOINPOINT_ARG; 390 } else if (isStaticJoinPoint(type)) { 391 adviceToTargetArgs[k] = AdviceInfo.STATIC_JOINPOINT_ARG; 392 } else if (isTarget(adviceArgName, ctx)) { 393 adviceToTargetArgs[k] = AdviceInfo.TARGET_ARG; 394 } else if (isThis(adviceArgName, ctx)) { 395 adviceToTargetArgs[k] = AdviceInfo.THIS_ARG; 396 } else if (isSpecialArgument(adviceArgName, expressionInfo)) { 397 adviceToTargetArgs[k] = AdviceInfo.SPECIAL_ARGUMENT; 398 } else if (isCustomJointPoint(type, loader)) { 399 adviceToTargetArgs[k] = AdviceInfo.CUSTOM_JOIN_POINT_ARG; 400 } else { 401 throw new Error ("Unbound advice parameter at index " + k + " in " + adviceInfo.getMethodName() 402 + adviceInfo.getMethodSignature() + " named " + adviceArgName); 403 } 404 } 405 } 406 407 if (adviceArgNames.length == 0) { 409 AspectDefinition aspectDef = adviceInfo.getAdviceDefinition().getAspectDefinition(); 410 Type[] adviceArgTypes = adviceInfo.getMethodParameterTypes(); 411 for (int i = 0; i < adviceArgTypes.length; i++) { 412 413 if (aspectDef.isAspectWerkzAspect()) { 414 if (isJoinPoint(adviceArgTypes[i])) { 415 adviceToTargetArgs[i] = AdviceInfo.JOINPOINT_ARG; 416 } else if (isStaticJoinPoint(adviceArgTypes[i])) { 417 adviceToTargetArgs[i] = AdviceInfo.STATIC_JOINPOINT_ARG; 418 } else { 419 throw new Error ("Unbound unnamed advice parameter at index " + i + " in " + adviceInfo.getMethodSignature()); 420 } 421 } else { 422 final AspectModel aspectModel = AspectModelManager.getModelFor(aspectDef.getAspectModel()); 427 final String superClassName = aspectModel.getAroundClosureClassInfo().getSuperClassName(); 428 final String [] interfaces = aspectModel.getAroundClosureClassInfo().getInterfaceNames(); 429 final String [] classNames = new String [interfaces.length + 1]; 430 classNames[0] = superClassName; 431 for (int j = 1; j < interfaces.length + 1; j++) { 432 classNames[j] = interfaces[j - 1]; 433 } 434 435 final Type argType = adviceArgTypes[i]; 436 if (isValidAroundClosureType(argType, classNames)) { 437 adviceToTargetArgs[i] = AdviceInfo.VALID_NON_AW_AROUND_CLOSURE_TYPE; 438 } else if (isSpecialArgumentType(argType, adviceInfo)) { 439 adviceToTargetArgs[i] = AdviceInfo.SPECIAL_ARGUMENT; 440 } 441 } 442 } 443 } 444 445 adviceInfo.setMethodToArgIndexes(adviceToTargetArgs); 446 } 447 448 private static boolean isSpecialArgumentType(final Type argType, final AdviceInfo adviceInfo) { 449 final String specialArgumentTypeDesc = adviceInfo.getSpecialArgumentTypeDesc(); 450 return specialArgumentTypeDesc != null && specialArgumentTypeDesc.equals(argType.getDescriptor()); 451 } 452 453 private static boolean isValidAroundClosureType(final Type argType, final String [] closureTypeNames) { 454 for (int i = 0; i < closureTypeNames.length; i++) { 455 final String closureTypeName = closureTypeNames[i]; 456 if (closureTypeName != null && closureTypeName.equals(argType.getInternalName())) { return true; } 457 } 458 return false; 459 } 460 461 private static boolean isJoinPoint(final Type type) { 462 return Type.getType(JoinPoint.class).getDescriptor().equals(type.getDescriptor()); 463 } 464 465 private static boolean isStaticJoinPoint(final Type type) { 466 return Type.getType(StaticJoinPoint.class).getDescriptor().equals(type.getDescriptor()); 467 } 468 469 private static boolean isTarget(final String adviceArgName, final ExpressionContext ctx) { 470 return adviceArgName.equals(ctx.m_targetBoundedName); 471 } 472 473 private static boolean isThis(final String adviceArgName, final ExpressionContext ctx) { 474 return adviceArgName.equals(ctx.m_thisBoundedName); 475 } 476 477 private static boolean isSpecialArgument(final String adviceArgName, final ExpressionInfo expressionInfo) { 478 return adviceArgName.equals(expressionInfo.getSpecialArgumentName()); 479 } 480 481 private static boolean isCustomJointPoint(final Type type, final ClassLoader loader) { 482 ClassInfo classInfo = AsmClassInfo.getClassInfo(type.getClassName(), loader); 483 return ClassInfoHelper.implementsInterface(classInfo, ExpressionInfo.JOINPOINT_CLASS_NAME) 484 || ClassInfoHelper.implementsInterface(classInfo, ExpressionInfo.STATIC_JOINPOINT_CLASS_NAME); 485 } 486 } | Popular Tags |