private void generateInvokeEntryPoint( GenScope scope, InstructionList il, InstructionFactory ifact, String transformationName, String entryPointName, LocalVariableGen lvg) { // Configure the transformation il.append(InstructionFactory.DUP); il.append( ifact.createInvoke( DefaultTypes.IdcTransformation.getClassName(), "configure_", Type.VOID, new Type[] {}, Constants.INVOKEVIRTUAL)); // TODO: Configure the models properly, not as I'm doing directly in instantiateTransformation // directly // Put the params into the stack and invoke, but first check the type of the transformation // object ObjectType transformationType = new ObjectType(transformationName); il.append(ifact.createCheckCast(transformationType)); // [Transformation, param1, ..., paramN] EList<Variable> params = this.getEntryPointParameters(); Type[] types = new Type[params.size()]; int i = 0; for (Variable variable : params) { scope.loadVariable(variable, il); types[i++] = Type.OBJECT; } il.append( ifact.createInvoke( transformationType.getClassName(), entryPointName, Type.OBJECT, types, Constants.INVOKEVIRTUAL)); il.append(new ASTORE(lvg.getIndex())); }
/** * 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(); }