final int modifiers = method.getModifiers();
// push the method definition
int modifier = modifiers & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED);
MethodVisitor mv = cw.visitMethod(modifier, method.getName(), Type.getMethodDescriptor(method), null, null);
mv.visitCode();
mv.visitVarInsn(Opcodes.ALOAD, 0);
// add the Method from the static array as first parameter
mv.visitFieldInsn(Opcodes.GETSTATIC, proxyClassFileName, FIELD_PROTECTED_METHODS, Type.getDescriptor(Method[].class));
// push the methodIndex of the current method
mv.visitIntInsn(Opcodes.BIPUSH, methodIndex);
// and now load the Method from the array
mv.visitInsn(Opcodes.AALOAD);
// now invoke the get() on the contextual instance Provider<T>
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitFieldInsn(Opcodes.GETFIELD, proxyClassFileName, FIELD_INSTANCE_PROVIDER, Type.getDescriptor(Provider.class));
// invoke the get() method on the Provider
mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type.getInternalName(Provider.class), "get", "()Ljava/lang/Object;");
// prepare the parameter array as Object[] and store it on the stack
pushMethodParameterArray(mv, parameterTypes);
// this invokes NormalScopeProxyFactory.delegateProtectedMethod
mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(NormalScopeProxyFactory.class), "delegateProtectedMethod",
"(Ljava/lang/reflect/Method;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
// cast the result
mv.visitTypeInsn(Opcodes.CHECKCAST, getCastType(returnType));
if (returnType.isPrimitive() && (!Void.TYPE.equals(returnType)))
{
// get the primitive value
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, getWrapperType(returnType), getPrimitiveMethod(returnType),
"()" + Type.getDescriptor(returnType));
}
mv.visitInsn(getReturnInsn(returnType));
// finish this method
mv.visitMaxs(0, 0);
mv.visitEnd();
}