in deltaspike/modules/proxy/impl-asm/src/main/java/org/apache/deltaspike/proxy/impl/AsmDeltaSpikeProxyClassGenerator.java [334:432]
private static void defineMethod(ClassWriter cw, java.lang.reflect.Method method, Type proxyType)
{
Type methodType = Type.getType(method);
ArrayList<Type> exceptionsToCatch = new ArrayList<Type>();
for (Class<?> exception : method.getExceptionTypes())
{
if (!RuntimeException.class.isAssignableFrom(exception))
{
exceptionsToCatch.add(Type.getType(exception));
}
}
// push the method definition
int modifiers = (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED) & method.getModifiers();
Method asmMethod = Method.getMethod(method);
GeneratorAdapter mg = new GeneratorAdapter(modifiers,
asmMethod,
null,
getTypes(method.getExceptionTypes()),
cw);
// copy annotations
for (Annotation annotation : method.getDeclaredAnnotations())
{
mg.visitAnnotation(Type.getDescriptor(annotation.annotationType()), true).visitEnd();
}
mg.visitCode();
Label tryBlockStart = mg.mark();
mg.loadThis();
mg.getField(proxyType, FIELDNAME_INVOCATION_HANDLER, TYPE_DELTA_SPIKE_PROXY_INVOCATION_HANDLER);
mg.loadThis();
loadCurrentMethod(mg, method, methodType);
loadArguments(mg, method, methodType);
mg.invokeVirtual(TYPE_DELTA_SPIKE_PROXY_INVOCATION_HANDLER,
Method.getMethod("Object invoke(Object, java.lang.reflect.Method, Object[])"));
// cast the result
mg.unbox(methodType.getReturnType());
// build try catch
Label tryBlockEnd = mg.mark();
// push return
mg.returnValue();
// catch runtime exceptions and rethrow it
Label rethrow = mg.mark();
mg.visitVarInsn(Opcodes.ASTORE, 1);
mg.visitVarInsn(Opcodes.ALOAD, 1);
mg.throwException();
mg.visitTryCatchBlock(tryBlockStart, tryBlockEnd, rethrow, Type.getInternalName(RuntimeException.class));
// catch checked exceptions and rethrow it
boolean throwableCatched = false;
if (!exceptionsToCatch.isEmpty())
{
rethrow = mg.mark();
mg.visitVarInsn(Opcodes.ASTORE, 1);
mg.visitVarInsn(Opcodes.ALOAD, 1);
mg.throwException();
// catch declared exceptions and rethrow it...
for (Type exceptionType : exceptionsToCatch)
{
if (exceptionType.getClassName().equals(Throwable.class.getName()))
{
throwableCatched = true;
}
mg.visitTryCatchBlock(tryBlockStart, tryBlockEnd, rethrow, exceptionType.getInternalName());
}
}
// if throwable isn't alreached cachted, catch it and wrap it with an UndeclaredThrowableException and throw it
if (!throwableCatched)
{
Type uteType = Type.getType(UndeclaredThrowableException.class);
Label wrapAndRethrow = mg.mark();
mg.visitVarInsn(Opcodes.ASTORE, 1);
mg.newInstance(uteType);
mg.dup();
mg.visitVarInsn(Opcodes.ALOAD, 1);
mg.invokeConstructor(uteType,
Method.getMethod("void <init>(java.lang.Throwable)"));
mg.throwException();
mg.visitTryCatchBlock(tryBlockStart, tryBlockEnd, wrapAndRethrow, Type.getInternalName(Throwable.class));
}
// finish the method
mg.endMethod();
mg.visitMaxs(12, 12);
mg.visitEnd();
}