Example #1
0
  private static CtMethod delegator0(CtMethod delegate, CtClass declaring)
      throws CannotCompileException, NotFoundException {
    MethodInfo deleInfo = delegate.getMethodInfo2();
    String methodName = deleInfo.getName();
    String desc = deleInfo.getDescriptor();
    ConstPool cp = declaring.getClassFile2().getConstPool();
    MethodInfo minfo = new MethodInfo(cp, methodName, desc);
    minfo.setAccessFlags(deleInfo.getAccessFlags());

    ExceptionsAttribute eattr = deleInfo.getExceptionsAttribute();
    if (eattr != null) minfo.setExceptionsAttribute((ExceptionsAttribute) eattr.copy(cp, null));

    Bytecode code = new Bytecode(cp, 0, 0);
    boolean isStatic = Modifier.isStatic(delegate.getModifiers());
    CtClass deleClass = delegate.getDeclaringClass();
    CtClass[] params = delegate.getParameterTypes();
    int s;
    if (isStatic) {
      s = code.addLoadParameters(params, 0);
      code.addInvokestatic(deleClass, methodName, desc);
    } else {
      code.addLoad(0, deleClass);
      s = code.addLoadParameters(params, 1);
      code.addInvokespecial(deleClass, methodName, desc);
    }

    code.addReturn(delegate.getReturnType());
    code.setMaxLocals(++s);
    code.setMaxStack(s < 2 ? 2 : s); // for a 2-word return value
    minfo.setCodeAttribute(code.toCodeAttribute());
    return new CtMethod(minfo, declaring);
  }
  /**
   * add a bogus constructor call to a bytecode sequence so a constructor can pass bytecode
   * validation
   *
   * @param bytecode
   */
  public static boolean addBogusConstructorCall(ClassFile file, Bytecode code) {
    MethodInfo constructorToCall = null;
    for (Object meth : file.getMethods()) {
      MethodInfo m = (MethodInfo) meth;
      if (m.getName().equals("<init>")) {
        constructorToCall = m;
        break;
      }
    }
    if (constructorToCall == null) {
      return false;
    }
    // push this onto the stack
    code.add(Bytecode.ALOAD_0);

    String[] params =
        DescriptorUtils.descriptorStringToParameterArray(constructorToCall.getDescriptor());
    for (String p : params) {
      // int char short boolean byte
      if (p.equals("I") || p.equals("C") || p.equals("S") || p.equals("Z") || p.equals("B")) {
        // push integer 0
        code.add(Opcode.ICONST_0);
      }
      // long
      else if (p.equals("J")) {
        code.add(Opcode.LCONST_0);
      }
      // double
      else if (p.equals("D")) {
        code.add(Opcode.DCONST_0);
      }
      // float
      else if (p.equals("F")) {
        code.add(Opcode.FCONST_0);
      }
      // arrays and reference types
      else {
        code.add(Opcode.ACONST_NULL);
      }
    }
    // all our args should be pushed onto the stack, call the constructor
    code.addInvokespecial(file.getName(), "<init>", constructorToCall.getDescriptor());
    code.add(Opcode.RETURN);
    return true;
  }
  /**
   * When creates the delegate initializer code when the delegate is injected into a method.
   *
   * <p>super initializer method is called first, and then _initMH is called
   *
   * @param file
   * @param intializerMethodInfo
   * @param delegateParameterPosition
   * @return
   */
  private Bytecode createDelegateInitializerCode(
      ClassFile file, MethodInformation intializerMethodInfo, int delegateParameterPosition) {
    Bytecode b = new Bytecode(file.getConstPool());
    // we need to push all the pareters on the stack to call the corresponding
    // superclass arguments
    b.addAload(0); // load this
    int localVariables = 1;
    int actualDelegateParamterPosition = 0;
    for (int i = 0; i < intializerMethodInfo.getMethod().getParameterTypes().length; ++i) {
      if (i == delegateParameterPosition) {
        // figure out the actual position of the delegate in the local
        // variables
        actualDelegateParamterPosition = localVariables;
      }
      Class<?> type = intializerMethodInfo.getMethod().getParameterTypes()[i];
      BytecodeUtils.addLoadInstruction(
          b, DescriptorUtils.classToStringRepresentation(type), localVariables);
      if (type == long.class || type == double.class) {
        localVariables = localVariables + 2;
      } else {
        localVariables++;
      }
    }
    b.addInvokespecial(
        file.getSuperclass(), intializerMethodInfo.getName(), intializerMethodInfo.getDescriptor());
    // if this method returns a value it is now sitting on top of the stack
    // we will leave it there are return it later

    // now we need to call _initMH
    b.addAload(0); // load this
    b.addAload(actualDelegateParamterPosition); // load the delegate
    b.addInvokevirtual(file.getName(), "_initMH", "(Ljava/lang/Object;)V");
    // return the object from the top of the stack that we got from calling
    // the superclass method earlier
    BytecodeUtils.addReturnInstruction(b, intializerMethodInfo.getReturnType());
    b.setMaxLocals(localVariables);
    return b;
  }
  /** Add a method to a class that simply delegates to the parent implementation of the method */
  public static void addDelegatingMethod(ClassFile file, MethodData mData)
      throws BadBytecode, DuplicateMemberException {
    MethodInfo m =
        new MethodInfo(file.getConstPool(), mData.getMethodName(), mData.getDescriptor());
    m.setAccessFlags(mData.getAccessFlags());
    Bytecode code = new Bytecode(file.getConstPool());

    String[] params = DescriptorUtils.descriptorStringToParameterArray(mData.getDescriptor());
    code.add(Opcode.ALOAD_0); // push this
    int count = 1; // zero is the this pointer
    int maxLocals = 1;
    for (String p : params) {
      // int char short boolean byte
      if (p.equals("I") || p.equals("C") || p.equals("S") || p.equals("Z") || p.equals("B")) {
        // push integer 0
        code.addIload(count);
        maxLocals++;
      }
      // long
      else if (p.equals("J")) {
        code.addLload(count);
        maxLocals += 2;
        count++;
      }
      // double
      else if (p.equals("D")) {
        code.addDload(count);
        maxLocals += 2;
        count++;
      }
      // float
      else if (p.equals("F")) {
        code.addFload(count);
        maxLocals++;
      }
      // arrays and reference types
      else {
        code.addAload(count);
        maxLocals++;
      }
      count++;
    }
    code.addInvokespecial(file.getSuperclass(), mData.getMethodName(), mData.getDescriptor());
    String p = DescriptorUtils.getReturnTypeInJvmFormat(mData.getDescriptor());
    // int char short boolean byte
    if (p.equals("I") || p.equals("C") || p.equals("S") || p.equals("Z") || p.equals("B")) {
      code.add(Opcode.IRETURN);
    }
    // long
    else if (p.equals("J")) {
      code.add(Opcode.LRETURN);
    }
    // double
    else if (p.equals("D")) {
      code.add(Opcode.DRETURN);
    }
    // float
    else if (p.equals("F")) {
      code.add(Opcode.FRETURN);
    }
    // void
    else if (p.equals("V")) {
      code.add(Opcode.RETURN);
    }
    // arrays and reference types
    else {
      code.add(Opcode.ARETURN);
    }
    CodeAttribute ca = code.toCodeAttribute();
    ca.computeMaxStack();
    ca.setMaxLocals(maxLocals);
    m.setCodeAttribute(ca);
    file.addMethod(m);
  }