View Javadoc

    1   /***************************************************************************************
    2    * Copyright (c) Jonas BonŽr, Alexandre Vasseur. All rights reserved.                 *
    3    * http://aspectwerkz.codehaus.org                                                    *
    4    * ---------------------------------------------------------------------------------- *
    5    * The software in this package is published under the terms of the LGPL license      *
    6    * a copy of which has been included with this distribution in the license.txt file.  *
    7    **************************************************************************************/
    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  /***
    54   * Manages the join point compilation, loading and instantiation for the target classes.
    55   * This implementation relies on the SystemDefinitionContainer.
    56   *
    57   * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
    58   * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
    59   * @author <a href="mailto:the_mindstorm@evolva.ro">Alex Popescu</a>
    60   */
    61  public class JoinPointManager {
    62      /***
    63       * Ensures that the specific joinPoint class for the given target class and joinPoint info is generated. This call
    64       * is added to the weaved class as a "clinit" block
    65       *
    66       * @param joinPointType
    67       * @param callerClass
    68       * @param callerMethodName
    69       * @param callerMethodDesc
    70       * @param callerMethodModifiers
    71       * @param calleeClassName
    72       * @param calleeMemberName
    73       * @param calleeMemberDesc
    74       * @param calleeMemberModifiers
    75       * @param joinPointHash
    76       * @param joinPointClassName
    77       */
    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         // check if the JP is already loaded
    103         // this can occurs if user packaged its JIT classes, or if we are using multiweaving
    104         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     /***
    141      * Compile a new joinpoint
    142      *
    143      * @param joinPointType
    144      * @param callerClass
    145      * @param callerMethodName
    146      * @param callerMethodDesc
    147      * @param callerMethodModifiers
    148      * @param calleeClassName
    149      * @param calleeMemberName
    150      * @param calleeMemberDesc
    151      * @param calleeMemberModifiers
    152      * @param joinPointHash
    153      * @param joinPointClassName
    154      * @param calleeClass
    155      * @param loader the loader that hosts the definitions, and from where caller, callee and aspect are visible.
    156      * At runtime it is exactly callerClass.getClassLoader() but in offline mode and genjp, it can happen to be
    157      * different when weaved class also exists in the compilation classpath.
    158      * @return
    159      */
    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         // create the callee info
    177         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         // create the caller info
    217         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         // get the compilation model
    229         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     /***
    255      * A compiled joinpoint is tied to a compilation model at a given time
    256      */
    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     /***
    268      * Retrieves the advice info wrapped up in a struct.
    269      *
    270      * @param expressionContext
    271      * @param loader
    272      * @return the advice info
    273      */
    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                 //TODO - do we care about non bounded pointcut ?
    294                 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                         // compute the target method to advice method arguments map, and grab information about this
    302                         // and target bindings
    303                         expressionContext.resetRuntimeState();
    304                         ArgsIndexVisitor.updateContextForRuntimeInformation(
    305                                 expressionInfo,
    306                                 expressionContext,
    307                                 loader
    308                         );
    309                         // Note that the expressionContext dynamic information updated here should only be used
    310                         // in the scope of this code block, since at the next iteration, the data will be
    311                         // updated for another advice binding
    312                         // [hence see setMethodArgumentIndexes below]
    313
    314                         // create a lightweight representation of the bounded advices to pass to the compiler
    315                         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);//special case for "after only"
    346                         }
    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     /***
    363      * Get the parameter names from a "method declaration" signature like pc(type a, type2 b) => 0:a, 1:b
    364      *
    365      * @param adviceName
    366      * @return the parameter names
    367      */
    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                 // handles XML def where name is optional
    378                 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     /***
    394      * Sets the advice argument indexes map.
    395      * <p/>
    396      * Each advice arg is mapped to wether a system entity like StaticJoinPoint, Rtti, this, target etc thru a specific index
    397      * (see AdviceInfo), or to one of the advised member arguments (thru args(..) binding).
    398      *
    399      * @param expressionInfo
    400      * @param ctx
    401      * @param adviceInfo
    402      * @param loader
    403      */
    404     private static void setMethodArgumentIndexes(final ExpressionInfo expressionInfo,
    405                                                  final ExpressionContext ctx,
    406                                                  final AdviceInfo adviceInfo,
    407                                                  final ClassLoader loader) {
    408         // grab the parameters names
    409         String[] adviceArgNames = getParameterNames(adviceInfo.getName());
    410
    411         // map them from the ctx info
    412         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                 // does not appears to be an argument of the advised target
    420                 // It can be StaticJP / JP / This binding / Target binding
    421                 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         // support for old style advices in XML whose name does not contain the call signature
    447         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 }