예제 #1
0
 public static void loadClass(MethodVisitor mv, int type, String typeName) {
   switch (type) {
     case 'V':
       mv.visitFieldInsn(
           GETSTATIC,
           AsmUtil.SIGNATURE_JAVA_LANG_VOID,
           "TYPE",
           AsmUtil.L_SIGNATURE_JAVA_LANG_CLASS);
       break;
     case 'B':
       mv.visitFieldInsn(
           GETSTATIC,
           AsmUtil.SIGNATURE_JAVA_LANG_BYTE,
           "TYPE",
           AsmUtil.L_SIGNATURE_JAVA_LANG_CLASS);
       break;
     case 'C':
       mv.visitFieldInsn(
           GETSTATIC,
           AsmUtil.SIGNATURE_JAVA_LANG_CHARACTER,
           "TYPE",
           AsmUtil.L_SIGNATURE_JAVA_LANG_CLASS);
       break;
     case 'S':
       mv.visitFieldInsn(
           GETSTATIC,
           AsmUtil.SIGNATURE_JAVA_LANG_SHORT,
           "TYPE",
           AsmUtil.L_SIGNATURE_JAVA_LANG_CLASS);
       break;
     case 'I':
       mv.visitFieldInsn(
           GETSTATIC,
           AsmUtil.SIGNATURE_JAVA_LANG_INTEGER,
           "TYPE",
           AsmUtil.L_SIGNATURE_JAVA_LANG_CLASS);
       break;
     case 'Z':
       mv.visitFieldInsn(
           GETSTATIC,
           AsmUtil.SIGNATURE_JAVA_LANG_BOOLEAN,
           "TYPE",
           AsmUtil.L_SIGNATURE_JAVA_LANG_CLASS);
       break;
     case 'J':
       mv.visitFieldInsn(
           GETSTATIC,
           AsmUtil.SIGNATURE_JAVA_LANG_LONG,
           "TYPE",
           AsmUtil.L_SIGNATURE_JAVA_LANG_CLASS);
       break;
     case 'F':
       mv.visitFieldInsn(
           GETSTATIC,
           AsmUtil.SIGNATURE_JAVA_LANG_FLOAT,
           "TYPE",
           AsmUtil.L_SIGNATURE_JAVA_LANG_CLASS);
       break;
     case 'D':
       mv.visitFieldInsn(
           GETSTATIC,
           AsmUtil.SIGNATURE_JAVA_LANG_DOUBLE,
           "TYPE",
           AsmUtil.L_SIGNATURE_JAVA_LANG_CLASS);
       break;
     default:
       mv.visitLdcInsn(Type.getType(typeName));
       break;
   }
 }
  /** Invoked on INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC, INVOKEINTERFACE or INVOKEDYNAMIC. */
  @Override
  public void visitMethodInsn(int opcode, String owner, String name, String desc) {

    // replace NEW.<init>
    if ((newInvokeReplacer != null) && (opcode == INVOKESPECIAL)) {
      String exOwner = owner;
      owner = newInvokeReplacer.getOwner();
      name = newInvokeReplacer.getMethodName();
      desc = changeReturnType(desc, 'L' + exOwner + ';');
      super.visitMethodInsn(INVOKESTATIC, owner, name, desc);
      newInvokeReplacer = null;
      return;
    }

    InvokeInfo invokeInfo = new InvokeInfo(owner, name, desc);

    // [*]
    // creating FooClone.<init>; inside the FOO constructor
    // replace the very first invokespecial <init> call (SUB.<init>)
    // to targets subclass with target (FOO.<init>).
    if (methodInfo.getMethodName().equals(INIT)) {
      if ((firstSuperCtorInitCalled == false)
          && (opcode == INVOKESPECIAL)
          && name.equals(INIT)
          && owner.equals(wd.nextSupername)) {
        firstSuperCtorInitCalled = true;
        owner = wd.superReference;
        super.visitMethodInsn(opcode, owner, name, desc);
        return;
      }
    }

    // detection of super calls
    if ((opcode == INVOKESPECIAL)
        && (owner.equals(wd.nextSupername) && (name.equals(INIT) == false))) {
      throw new ProxettaException(
          "Super call detected in class "
              + methodInfo.getClassname()
              + " method: "
              + methodInfo.getSignature()
              + "\nProxetta can't handle super calls due to VM limitations.");
    }

    InvokeReplacer ir = null;

    // find first matching aspect
    for (InvokeAspect aspect : aspects) {
      ir = aspect.pointcut(invokeInfo);
      if (ir != null) {
        break;
      }
    }

    if (ir == null) {
      super.visitMethodInsn(opcode, owner, name, desc);
      return;
    }

    wd.proxyApplied = true;

    String exOwner = owner;
    owner = ir.getOwner();
    name = ir.getMethodName();

    switch (opcode) {
      case INVOKEINTERFACE:
        desc = prependArgument(desc, AsmUtil.L_SIGNATURE_JAVA_LANG_OBJECT);
        break;
      case INVOKEVIRTUAL:
        desc = prependArgument(desc, AsmUtil.L_SIGNATURE_JAVA_LANG_OBJECT);
        break;
      case INVOKESTATIC:
        break;
      default:
        throw new ProxettaException("Unsupported opcode: " + opcode);
    }

    // additional arguments
    if (ir.isPassOwnerName()) {
      desc = appendArgument(desc, AsmUtil.L_SIGNATURE_JAVA_LANG_STRING);
      super.visitLdcInsn(exOwner);
    }
    if (ir.isPassMethodName()) {
      desc = appendArgument(desc, AsmUtil.L_SIGNATURE_JAVA_LANG_STRING);
      super.visitLdcInsn(methodInfo.getMethodName());
    }
    if (ir.isPassMethodSignature()) {
      desc = appendArgument(desc, AsmUtil.L_SIGNATURE_JAVA_LANG_STRING);
      super.visitLdcInsn(methodInfo.getSignature());
    }
    if (ir.isPassTargetClass()) {
      desc = appendArgument(desc, AsmUtil.L_SIGNATURE_JAVA_LANG_CLASS);
      super.mv.visitLdcInsn(Type.getType('L' + wd.superReference + ';'));
    }
    if (ir.isPassThis()) {
      desc = appendArgument(desc, AsmUtil.L_SIGNATURE_JAVA_LANG_OBJECT);
      super.mv.visitVarInsn(ALOAD, 0);
    }

    super.visitMethodInsn(INVOKESTATIC, owner, name, desc);
  }