コード例 #1
0
  /**
   * Creates a proxy method for the original method specified. This method has the same signature as
   * the original method and catches the invocation for further processing by the framework before
   * redirecting to the original method.
   *
   * @todo pass the 'class' as a Class instance not a String to the join point. Add the class field
   *     to the class using BCEL (see AdviseStaticMethodTransformer.java)
   * @param cp the ConstantPoolGen
   * @param cg the ClassGen
   * @param originalMethod the current method
   * @param factory the objectfactory
   * @param methodId the id of the current method in the lookup tabl
   * @param methodSequence the methods sequence number
   * @param accessFlags the access flags of the original method
   * @param uuid the uuid for the weave model defining the pointcut
   * @param controllerClassName the class name of the controller class to use
   * @return the proxy method
   */
  private Method createProxyMethod(
      final ConstantPoolGen cp,
      final ClassGen cg,
      final MethodGen originalMethod,
      final InstructionFactory factory,
      final int methodId,
      final int methodSequence,
      final int accessFlags,
      final String uuid,
      final String controllerClassName) {

    InstructionList il = new InstructionList();

    String joinPoint = getJoinPointName(originalMethod.getMethod(), methodSequence);

    final MethodGen method =
        new MethodGen(
            accessFlags,
            Type.getReturnType(originalMethod.getSignature()),
            Type.getArgumentTypes(originalMethod.getSignature()),
            originalMethod.getArgumentNames(),
            originalMethod.getName(),
            cg.getClassName(),
            il,
            cp);

    String[] exceptions = originalMethod.getExceptions();
    for (int i = 0; i < exceptions.length; i++) {
      method.addException(exceptions[i]);
    }

    int indexParam = 1;
    int indexStack = 0;
    int indexJoinPoint = Type.getArgumentTypes(originalMethod.getSignature()).length * 2 + 1;

    // if (threadLocal == null) {
    //    threadLocal = new SerializableThreadLocal();
    // }
    il.append(factory.createLoad(Type.OBJECT, 0));
    il.append(
        factory.createFieldAccess(
            cg.getClassName(),
            joinPoint,
            new ObjectType(TransformationUtil.THREAD_LOCAL_CLASS),
            Constants.GETFIELD));

    BranchInstruction ifNotNull = factory.createBranchInstruction(Constants.IFNONNULL, null);
    il.append(ifNotNull);
    il.append(factory.createLoad(Type.OBJECT, 0));
    il.append(factory.createNew(TransformationUtil.THREAD_LOCAL_CLASS));

    il.append(InstructionConstants.DUP);
    il.append(
        factory.createInvoke(
            TransformationUtil.THREAD_LOCAL_CLASS,
            "<init>",
            Type.VOID,
            Type.NO_ARGS,
            Constants.INVOKESPECIAL));
    il.append(
        factory.createFieldAccess(
            cg.getClassName(),
            joinPoint.toString(),
            new ObjectType(TransformationUtil.THREAD_LOCAL_CLASS),
            Constants.PUTFIELD));

    // Object joinPoint = ___jp.get();
    BranchInstruction biIfNotNull = null;
    InstructionHandle ihIfNotNull = null;

    ifNotNull.setTarget(il.append(factory.createLoad(Type.OBJECT, 0)));

    il.append(
        factory.createFieldAccess(
            cg.getClassName(),
            joinPoint.toString(),
            new ObjectType(TransformationUtil.THREAD_LOCAL_CLASS),
            Constants.GETFIELD));
    il.append(
        factory.createInvoke(
            TransformationUtil.THREAD_LOCAL_CLASS,
            "get",
            Type.OBJECT,
            Type.NO_ARGS,
            Constants.INVOKEVIRTUAL));

    il.append(factory.createStore(Type.OBJECT, indexJoinPoint));
    il.append(factory.createLoad(Type.OBJECT, indexJoinPoint));

    // if (joinPoint == null) {
    biIfNotNull = factory.createBranchInstruction(Constants.IFNONNULL, null);
    il.append(biIfNotNull);

    // joinPoint = new WeakReference(new MemberMethodJoinPoint(uuid, this, "foo.bar.Baz", 10));
    //        il.append(factory.createNew(TransformationUtil.WEAK_REFERENCE_CLASS));
    //        il.append(InstructionConstants.DUP);

    il.append(factory.createNew(TransformationUtil.MEMBER_METHOD_JOIN_POINT_CLASS));
    il.append(InstructionConstants.DUP);

    il.append(new PUSH(cp, uuid));
    il.append(factory.createLoad(Type.OBJECT, 0));
    il.append(new PUSH(cp, cg.getClassName()));
    il.append(new PUSH(cp, methodId));
    il.append(new PUSH(cp, controllerClassName));

    il.append(
        factory.createInvoke(
            TransformationUtil.MEMBER_METHOD_JOIN_POINT_CLASS,
            "<init>",
            Type.VOID,
            new Type[] {Type.STRING, Type.OBJECT, Type.STRING, Type.INT, Type.STRING},
            Constants.INVOKESPECIAL));
    il.append(factory.createStore(Type.OBJECT, indexJoinPoint));

    // threadLocal.set(joinPoint);
    il.append(factory.createLoad(Type.OBJECT, 0));
    il.append(
        factory.createFieldAccess(
            cg.getClassName(),
            joinPoint.toString(),
            new ObjectType(TransformationUtil.THREAD_LOCAL_CLASS),
            Constants.GETFIELD));
    il.append(factory.createLoad(Type.OBJECT, indexJoinPoint));
    il.append(
        factory.createInvoke(
            TransformationUtil.THREAD_LOCAL_CLASS,
            "set",
            Type.VOID,
            new Type[] {Type.OBJECT},
            Constants.INVOKEVIRTUAL));

    ihIfNotNull = il.append(factory.createLoad(Type.OBJECT, indexJoinPoint));
    indexJoinPoint += 2;

    il.append(factory.createCheckCast(TransformationUtil.MEMBER_METHOD_JOIN_POINT_TYPE));
    il.append(factory.createStore(Type.OBJECT, indexJoinPoint));

    biIfNotNull.setTarget(ihIfNotNull);

    // if we have parameters, wrap them up
    if (Type.getArgumentTypes(originalMethod.getSignature()).length != 0) {

      // create and allocate the parameters array
      il.append(new PUSH(cp, Type.getArgumentTypes(originalMethod.getSignature()).length));
      il.append(factory.createNewArray(Type.OBJECT, (short) 1));

      il.append(InstructionConstants.DUP);
      il.append(new PUSH(cp, indexStack));
      indexStack++;

      // add all the parameters, wrap the primitive types in their object counterparts
      for (int count = 0;
          count < Type.getArgumentTypes(originalMethod.getSignature()).length;
          count++) {

        String wrapperClass = null;
        BasicType type = null;
        boolean hasLongOrDouble = false;

        if (Type.getArgumentTypes(originalMethod.getSignature())[count] instanceof ObjectType
            || Type.getArgumentTypes(originalMethod.getSignature())[count] instanceof ArrayType) {
          // we have an object or an array
          il.append(factory.createLoad(Type.OBJECT, indexParam));
          il.append(InstructionConstants.AASTORE);
          indexParam++;
        } else if (Type.getArgumentTypes(originalMethod.getSignature())[count]
            instanceof ArrayType) {
          // we have an array
          il.append(factory.createLoad(Type.OBJECT, indexParam));
          il.append(InstructionConstants.AASTORE);
          indexParam++;
        } else if (Type.getArgumentTypes(originalMethod.getSignature())[count]
            instanceof BasicType) {
          hasLongOrDouble = false;
          // we have a primitive type
          if ((Type.getArgumentTypes(originalMethod.getSignature())[count]).equals(Type.LONG)) {
            wrapperClass = "java.lang.Long";
            type = Type.LONG;
            hasLongOrDouble = true;
          } else if ((Type.getArgumentTypes(originalMethod.getSignature())[count])
              .equals(Type.INT)) {
            wrapperClass = "java.lang.Integer";
            type = Type.INT;
          } else if ((Type.getArgumentTypes(originalMethod.getSignature())[count])
              .equals(Type.SHORT)) {
            wrapperClass = "java.lang.Short";
            type = Type.SHORT;
          } else if ((Type.getArgumentTypes(originalMethod.getSignature())[count])
              .equals(Type.DOUBLE)) {
            wrapperClass = "java.lang.Double";
            type = Type.DOUBLE;
            hasLongOrDouble = true;
          } else if ((Type.getArgumentTypes(originalMethod.getSignature())[count])
              .equals(Type.FLOAT)) {
            wrapperClass = "java.lang.Float";
            type = Type.FLOAT;
          } else if ((Type.getArgumentTypes(originalMethod.getSignature())[count])
              .equals(Type.CHAR)) {
            wrapperClass = "java.lang.Character";
            type = Type.CHAR;
          } else if ((Type.getArgumentTypes(originalMethod.getSignature())[count])
              .equals(Type.BYTE)) {
            wrapperClass = "java.lang.Byte";
            type = Type.BYTE;
          } else if ((Type.getArgumentTypes(originalMethod.getSignature())[count])
              .equals(Type.BOOLEAN)) {
            wrapperClass = "java.lang.Boolean";
            type = Type.BOOLEAN;
          } else {
            throw new RuntimeException(
                "unknown parameter type: "
                    + Type.getArgumentTypes(originalMethod.getSignature())[count]);
          }
          il.append(factory.createNew(wrapperClass));
          il.append(InstructionConstants.DUP);
          il.append(factory.createLoad(type, indexParam));
          il.append(
              factory.createInvoke(
                  wrapperClass, "<init>", Type.VOID, new Type[] {type}, Constants.INVOKESPECIAL));
          il.append(InstructionConstants.AASTORE);
          indexParam++;
        } // end handle basic or object type

        if (count != Type.getArgumentTypes(originalMethod.getSignature()).length - 1) {
          // if we don't have the last parameter, create the parameter on the stack
          il.append(InstructionConstants.DUP);
          il.append(new PUSH(cp, indexStack));
          indexStack++;

          // long or double needs two registers to fit
          if (hasLongOrDouble) indexParam++;
        }
      }

      // create the object array
      il.append(factory.createStore(Type.OBJECT, indexParam));

      // if threadsafe grab the newly retrieved local join point field from the stack
      il.append(factory.createLoad(Type.OBJECT, indexJoinPoint));

      // invoke joinPoint.setParameter(..)
      il.append(factory.createLoad(Type.OBJECT, indexParam));
      il.append(
          factory.createInvoke(
              TransformationUtil.MEMBER_METHOD_JOIN_POINT_CLASS,
              "setParameters",
              Type.VOID,
              new Type[] {new ArrayType(Type.OBJECT, 1)},
              Constants.INVOKEVIRTUAL));
      indexParam++;
    } // end - if parameters.length != 0

    // if threadsafe grab the newly retrieved local join point field from the stack
    il.append(factory.createLoad(Type.OBJECT, indexJoinPoint));
    il.append(
        factory.createInvoke(
            TransformationUtil.MEMBER_METHOD_JOIN_POINT_CLASS,
            "proceed",
            Type.OBJECT,
            Type.NO_ARGS,
            Constants.INVOKEVIRTUAL));

    if (!Type.getReturnType(originalMethod.getSignature()).equals(Type.VOID)) {
      // create the result from the invocation
      il.append(factory.createStore(Type.OBJECT, indexParam));
      il.append(factory.createLoad(Type.OBJECT, indexParam));

      // cast the result and return it, if the return type is a
      // primitive type, retrieve it from the wrapped object first
      // unless the return object is null (AW-100)
      if (Type.getReturnType(originalMethod.getSignature()) instanceof BasicType) {
        if (Type.getReturnType(originalMethod.getSignature()).equals(Type.VOID)) {; // skip
        } else {
          BranchInstruction ifNullBranch =
              factory.createBranchInstruction(Constants.IFNONNULL, null);
          InstructionHandle elseBranch = null;
          il.append(ifNullBranch);
          if (Type.getReturnType(originalMethod.getSignature()).equals(Type.LONG)) {
            il.append(new PUSH(cp, 0L));
            il.append(factory.createReturn(Type.LONG));
            elseBranch = il.append(factory.createLoad(Type.OBJECT, indexParam));
            il.append(factory.createCheckCast(new ObjectType("java.lang.Long")));
            il.append(
                factory.createInvoke(
                    "java.lang.Long",
                    "longValue",
                    Type.LONG,
                    Type.NO_ARGS,
                    Constants.INVOKEVIRTUAL));
          } else if (Type.getReturnType(originalMethod.getSignature()).equals(Type.INT)) {
            il.append(new PUSH(cp, 0));
            il.append(factory.createReturn(Type.INT));
            elseBranch = il.append(factory.createLoad(Type.OBJECT, indexParam));
            il.append(factory.createCheckCast(new ObjectType("java.lang.Integer")));
            il.append(
                factory.createInvoke(
                    "java.lang.Integer",
                    "intValue",
                    Type.INT,
                    Type.NO_ARGS,
                    Constants.INVOKEVIRTUAL));
          } else if (Type.getReturnType(originalMethod.getSignature()).equals(Type.SHORT)) {
            il.append(new PUSH(cp, (short) 0));
            il.append(factory.createReturn(Type.SHORT));
            elseBranch = il.append(factory.createLoad(Type.OBJECT, indexParam));
            il.append(factory.createCheckCast(new ObjectType("java.lang.Short")));
            il.append(
                factory.createInvoke(
                    "java.lang.Short",
                    "shortValue",
                    Type.SHORT,
                    Type.NO_ARGS,
                    Constants.INVOKEVIRTUAL));
          } else if (Type.getReturnType(originalMethod.getSignature()).equals(Type.DOUBLE)) {
            il.append(new PUSH(cp, 0.0d));
            il.append(factory.createReturn(Type.DOUBLE));
            elseBranch = il.append(factory.createLoad(Type.OBJECT, indexParam));
            il.append(factory.createCheckCast(new ObjectType("java.lang.Double")));
            il.append(
                factory.createInvoke(
                    "java.lang.Double",
                    "doubleValue",
                    Type.DOUBLE,
                    Type.NO_ARGS,
                    Constants.INVOKEVIRTUAL));
          } else if (Type.getReturnType(originalMethod.getSignature()).equals(Type.FLOAT)) {
            il.append(new PUSH(cp, 0.0f));
            il.append(factory.createReturn(Type.FLOAT));
            elseBranch = il.append(factory.createLoad(Type.OBJECT, indexParam));
            il.append(factory.createCheckCast(new ObjectType("java.lang.Float")));
            il.append(
                factory.createInvoke(
                    "java.lang.Float",
                    "floatValue",
                    Type.FLOAT,
                    Type.NO_ARGS,
                    Constants.INVOKEVIRTUAL));
          } else if (Type.getReturnType(originalMethod.getSignature()).equals(Type.CHAR)) {
            il.append(new PUSH(cp, '\u0000'));
            il.append(factory.createReturn(Type.CHAR));
            elseBranch = il.append(factory.createLoad(Type.OBJECT, indexParam));
            il.append(factory.createCheckCast(new ObjectType("java.lang.Character")));
            il.append(
                factory.createInvoke(
                    "java.lang.Character",
                    "charValue",
                    Type.CHAR,
                    Type.NO_ARGS,
                    Constants.INVOKEVIRTUAL));
          } else if (Type.getReturnType(originalMethod.getSignature()).equals(Type.BYTE)) {
            il.append(new PUSH(cp, (byte) 0));
            il.append(factory.createReturn(Type.BYTE));
            elseBranch = il.append(factory.createLoad(Type.OBJECT, indexParam));
            il.append(factory.createCheckCast(new ObjectType("java.lang.Byte")));
            il.append(
                factory.createInvoke(
                    "java.lang.Byte",
                    "byteValue",
                    Type.BYTE,
                    Type.NO_ARGS,
                    Constants.INVOKEVIRTUAL));
          } else if (Type.getReturnType(originalMethod.getSignature()).equals(Type.BOOLEAN)) {
            il.append(new PUSH(cp, false));
            il.append(factory.createReturn(Type.BOOLEAN));
            elseBranch = il.append(factory.createLoad(Type.OBJECT, indexParam));
            il.append(factory.createCheckCast(new ObjectType("java.lang.Boolean")));
            il.append(
                factory.createInvoke(
                    "java.lang.Boolean",
                    "booleanValue",
                    Type.BOOLEAN,
                    Type.NO_ARGS,
                    Constants.INVOKEVIRTUAL));
          } else {
            throw new Error(
                "unknown return type: " + Type.getReturnType(originalMethod.getSignature()));
          }
          ifNullBranch.setTarget(elseBranch);
        }
      } else {
        // cast the result to the right type
        il.append(
            factory.createCast(Type.OBJECT, Type.getReturnType(originalMethod.getSignature())));
      }
    }
    il.append(factory.createReturn(Type.getReturnType(originalMethod.getSignature())));

    method.setMaxStack();
    method.setMaxLocals();
    return method.getMethod();
  }