Skip to content

Instantly share code, notes, and snippets.

@cescoffier
Created January 30, 2012 16:09
Show Gist options
  • Save cescoffier/1705176 to your computer and use it in GitHub Desktop.
Save cescoffier/1705176 to your computer and use it in GitHub Desktop.
private void generateMethodHeader(int access, String name, String desc, String signature, String[] exceptions, List<AnnotationDescriptor> annotations, Map<Integer, List<AnnotationDescriptor>> paramAnnotations) {
GeneratorAdapter mv = new GeneratorAdapter(cv.visitMethod(access, name, desc, signature, exceptions), access, name, desc);
mv.visitCode();
Type returnType = Type.getReturnType(desc);
// Compute result and exception stack location
// We also compute the actual Thread stack, when it requires the returned object.
int result = -1;
List<Object> stack = new ArrayList<Object>();
stack.add(m_owner);
if (returnType.getSort() != Type.VOID) {
// The method returns something
result = mv.newLocal(returnType);
switch (returnType.getSort()) {
case Type.INT:
case Type.CHAR:
case Type.BOOLEAN:
case Type.BYTE:
stack.add(Opcodes.INTEGER);
break;
case Type.DOUBLE:
stack.add(Opcodes.DOUBLE);
break;
case Type.FLOAT:
stack.add(Opcodes.FLOAT);
break;
case Type.LONG:
stack.add(Opcodes.LONG);
break;
case Type.OBJECT:
case Type.ARRAY:
stack.add(returnType.getInternalName().toString());
break;
}
}
int exception = mv.newLocal(Type.getType(Throwable.class));
Label l0 = new Label();
Label l1 = new Label();
Label l2 = new Label();
mv.visitTryCatchBlock(l0, l1, l2, "java/lang/Throwable");
// Not intercepted method:
mv.visitFrame(Opcodes.F_NEW, 1, new Object[]{m_owner}, 0, new Object[]{});
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, m_owner, generateMethodFlag(name, desc), "Z");
mv.visitJumpInsn(IFNE, l0);
mv.visitVarInsn(ALOAD, 0);
mv.loadArgs();
mv.visitMethodInsn(INVOKESPECIAL, m_owner, PREFIX + name, desc);
mv.visitInsn(returnType.getOpcode(IRETURN));
// end of the non intercepted method invocation.
// Beginning of the try / catch clause
mv.visitLabel(l0);
mv.visitFrame(Opcodes.F_NEW, 1, new Object[]{m_owner}, 0, new Object[]{});
// onEntry call
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, m_owner, IM_FIELD, "Lorg/apache/felix/ipojo/InstanceManager;");
mv.visitVarInsn(ALOAD, 0);
mv.visitLdcInsn(generateMethodId(name, desc));
mv.loadArgArray();
mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", ENTRY, "(Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;)V");
// End of onEntry call
mv.visitVarInsn(ALOAD, 0);
// Actual call of the method
// Do not allow argument modification : just reload arguments.
mv.loadArgs();
mv.visitMethodInsn(INVOKESPECIAL, m_owner, PREFIX + name, desc);
if (returnType.getSort() != Type.VOID) {
mv.visitVarInsn(returnType.getOpcode(ISTORE), result);
}
// End of the actual call of the method
// onExit call
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, m_owner, IM_FIELD, "Lorg/apache/felix/ipojo/InstanceManager;");
mv.visitVarInsn(ALOAD, 0);
mv.visitLdcInsn(generateMethodId(name, desc));
if (returnType.getSort() != Type.VOID) {
mv.visitVarInsn(returnType.getOpcode(ILOAD), result);
mv.box(returnType);
} else {
mv.visitInsn(ACONST_NULL);
}
mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", EXIT, "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V");
// enf of the onExit call
mv.visitLabel(l1);
Label l7 = new Label();
mv.visitJumpInsn(GOTO, l7);
// Catch clause
mv.visitLabel(l2);
mv.visitFrame(Opcodes.F_NEW, stack.size(), stack.toArray(new Object[0]), 1, new Object[]{"java/lang/Throwable"});
mv.visitVarInsn(ASTORE, exception);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, m_owner, IM_FIELD, "Lorg/apache/felix/ipojo/InstanceManager;");
mv.visitVarInsn(ALOAD, 0);
mv.visitLdcInsn(generateMethodId(name, desc));
mv.visitVarInsn(ALOAD, exception);
mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", ERROR, "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Throwable;)V");
mv.visitVarInsn(ALOAD, exception);
mv.visitInsn(ATHROW);
// Enf ot the catch clause.
// End of the method (just return)
mv.visitLabel(l7);
if (returnType.getSort() != Type.VOID) {
mv.visitFrame(Opcodes.F_NEW, stack.size(), stack.toArray(new Object[0]), 0, new Object[]{});
mv.visitVarInsn(returnType.getOpcode(ILOAD), result);
} else {
mv.visitFrame(Opcodes.F_NEW, 1, new Object[]{m_owner}, 0, new Object[]{});
}
mv.visitInsn(returnType.getOpcode(IRETURN));
// ----- Move Annotations ---
// Move annotations
if (annotations != null) {
for (int i = 0; i < annotations.size(); i++) {
AnnotationDescriptor ad = annotations.get(i);
ad.visitAnnotation(mv);
}
}
// Move parameter annotations
if (paramAnnotations != null && !paramAnnotations.isEmpty()) {
Iterator<Integer> ids = paramAnnotations.keySet().iterator();
while (ids.hasNext()) {
Integer id = ids.next();
List<AnnotationDescriptor> ads = paramAnnotations.get(id);
for (int i = 0; i < ads.size(); i++) {
AnnotationDescriptor ad = ads.get(i);
ad.visitParameterAnnotation(id.intValue(), mv);
}
}
}
mv.visitMaxs(0, 0);
mv.visitEnd();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment