Beispiel #1
0
  /**
   * Visits the methods.
   *
   * @param access
   * @param name
   * @param desc
   * @param signature
   * @param exceptions
   * @return
   */
  public MethodVisitor visitMethod(
      final int access,
      final String name,
      final String desc,
      final String signature,
      final String[] exceptions) {

    if (INIT_METHOD_NAME.equals(name)
        || CLINIT_METHOD_NAME.equals(name)
        || name.startsWith(ASPECTWERKZ_PREFIX)
        || name.startsWith(SYNTHETIC_MEMBER_PREFIX)
        || name.startsWith(WRAPPER_METHOD_PREFIX)
        || (AdvisableImpl.ADD_ADVICE_METHOD_NAME.equals(name)
            && AdvisableImpl.ADD_ADVICE_METHOD_DESC.equals(desc))
        || (AdvisableImpl.REMOVE_ADVICE_METHOD_NAME.equals(name)
            && AdvisableImpl.REMOVE_ADVICE_METHOD_DESC.equals(desc))) {
      return cv.visitMethod(access, name, desc, signature, exceptions);
    }

    int hash = AsmHelper.calculateMethodHash(name, desc);
    MethodInfo methodInfo = m_classInfo.getMethod(hash);
    if (methodInfo == null) {
      System.err.println(
          "AW::WARNING "
              + "metadata structure could not be build for method ["
              + m_classInfo.getName().replace('/', '.')
              + '.'
              + name
              + ':'
              + desc
              + ']');
      // bail out
      return cv.visitMethod(access, name, desc, signature, exceptions);
    }

    ExpressionContext ctx = new ExpressionContext(PointcutType.EXECUTION, methodInfo, methodInfo);

    if (methodFilter(m_ctx.getDefinitions(), ctx, methodInfo)) {
      return cv.visitMethod(access, name, desc, signature, exceptions);
    } else {
      String prefixedOriginalName =
          TransformationUtil.getPrefixedOriginalMethodName(name, m_declaringTypeName);
      if (m_addedMethods.contains(
          AlreadyAddedMethodAdapter.getMethodKey(prefixedOriginalName, desc))) {
        return cv.visitMethod(access, name, desc, signature, exceptions);
      }

      m_ctx.markAsAdvised();

      // create the proxy for the original method
      final MethodVisitor proxyMethod =
          createProxyMethod(access, name, desc, signature, exceptions, methodInfo);

      int modifiers = ACC_SYNTHETIC;
      if (Modifier.isStatic(access)) {
        modifiers |= ACC_STATIC;
      }
      // prefix the original method and make sure we copy method annotations to the proxyMethod
      // while keeping the body for the prefixed method
      return new MethodAdapter(
          cv.visitMethod(modifiers, prefixedOriginalName, desc, signature, exceptions)) {
        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
          return new AsmCopyAdapter.CopyAnnotationAdapter(
              super.visitAnnotation(desc, visible), proxyMethod.visitAnnotation(desc, visible));
        }

        public AnnotationVisitor visitParameterAnnotation(
            int parameter, String desc, boolean visible) {
          return new AsmCopyAdapter.CopyAnnotationAdapter(
              super.visitParameterAnnotation(parameter, desc, visible),
              proxyMethod.visitParameterAnnotation(parameter, desc, visible));
        }

        public void visitAttribute(Attribute attr) {
          super.visitAttribute(attr);
          proxyMethod.visitAttribute(attr);
        }
      };
    }
  }
Beispiel #2
0
  /**
   * Creates the "proxy method", e.g. the method that has the same name and signature as the
   * original method but a completely other implementation.
   *
   * @param access
   * @param name
   * @param desc
   * @param signature
   * @param exceptions
   * @param methodInfo
   * @return the method visitor
   */
  private MethodVisitor createProxyMethod(
      final int access,
      final String name,
      final String desc,
      final String signature,
      final String[] exceptions,
      final MethodInfo methodInfo) {
    MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);

    // load "this" ie callee if target method is not static
    if (!Modifier.isStatic(access)) {
      mv.visitVarInsn(ALOAD, 0);
    }
    // load args
    AsmHelper.loadArgumentTypes(mv, Type.getArgumentTypes(desc), Modifier.isStatic(access));
    // load "this" ie caller or null if method is static
    if (Modifier.isStatic(access)) {
      mv.visitInsn(ACONST_NULL);
    } else {
      mv.visitVarInsn(ALOAD, 0);
    }

    int joinPointHash = AsmHelper.calculateMethodHash(name, desc);
    String joinPointClassName =
        TransformationUtil.getJoinPointClassName(
            m_declaringTypeName,
            name,
            desc,
            m_declaringTypeName,
            JoinPointType.METHOD_EXECUTION_INT,
            joinPointHash);

    // TODO: should we provide some sort of option to do JITgen when weaving instead of when loading
    // ?
    // use case: offline full packaging and alike

    mv.visitMethodInsn(
        INVOKESTATIC,
        joinPointClassName,
        INVOKE_METHOD_NAME,
        TransformationUtil.getInvokeSignatureForCodeJoinPoints(
            access, desc, m_declaringTypeName, m_declaringTypeName));

    AsmHelper.addReturnStatement(mv, Type.getReturnType(desc));
    mv.visitMaxs(0, 0);

    // emit the joinpoint
    m_ctx.addEmittedJoinPoint(
        new EmittedJoinPoint(
            JoinPointType.METHOD_EXECUTION_INT,
            m_declaringTypeName,
            name,
            desc,
            access,
            m_declaringTypeName,
            name,
            desc,
            access,
            joinPointHash,
            joinPointClassName,
            EmittedJoinPoint.NO_LINE_NUMBER));

    return mv;
  }