* }
* }
* </pre>
*/
private void addInvocationContextProceed() {
MethodVisitor mv = getCW()
.visitMethod(ACC_PUBLIC, "proceed", "()" + JAVA_LANG_OBJECT, null, PROCEED_EXCEPTIONS);
mv.visitCode();
// interceptor++ or in fact : interceptor = interceptor + 1;
mv.visitVarInsn(ALOAD, 0);
mv.visitInsn(DUP);
mv.visitFieldInsn(GETFIELD, this.generatedClassName, "interceptor", "I");
mv.visitInsn(ICONST_1);
mv.visitInsn(IADD); // + 1
mv.visitFieldInsn(PUTFIELD, this.generatedClassName, "interceptor", "I");
// load interceptor constant to do the switch
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, this.generatedClassName, "interceptor", "I");
// Size
int sizeInterceptors = this.allInterceptors.size();
// need to add call to the original method
int switchSize = sizeInterceptors + 1;
// Build array of labels corresponding to swtich entries
Label[] switchLabels = new Label[switchSize];
for (int s = 0; s < switchSize; s++) {
switchLabels[s] = new Label();
}
// default label
Label defaultCaseLabel = new Label();
// switch
mv.visitTableSwitchInsn(1, switchSize, defaultCaseLabel, switchLabels);
// add each interceptor switch entry with a return block at the end
// ie : case 1 :
// return myInterceptor.intercept(this); // interceptor class
// or case 1 :
// return bean.intercept(this) // bean class
int index = 0;
int interceptorIndex = 0;
for (IJClassInterceptor interceptor : this.allInterceptors) {
mv.visitLabel(switchLabels[index]);
Type returnType = Type.getReturnType(interceptor.getJMethod().getDescriptor());
// interceptor on the bean
if (interceptor.getClassName().equals(this.beanClassName)) {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, this.generatedClassName, "bean", this.beanClassDesc);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, this.beanClassName,
interceptor.getJMethod().getName(), interceptor.getJMethod().getDescriptor());
// return object or null if the return type is void
returnsObject(returnType, mv);
} else { // interceptor in another class
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, this.generatedClassName, INTERCEPTOR + interceptorIndex ,
encodeClassDesc(interceptor.getClassName()));
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, interceptor.getClassName(),
interceptor.getJMethod().getName(), interceptor.getJMethod().getDescriptor());
// return object or null if the return type is void
returnsObject(returnType, mv);
interceptorIndex++;
}
index++;
}
// then, add call to original method, ie bean.businessMethod(i,j,...);
mv.visitLabel(switchLabels[index++]);
// get bean object
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, this.generatedClassName, "bean", this.beanClassDesc);
// arguments of the method
int indexArg = 0;
for (Type argType : this.methodArgsType) {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, this.generatedClassName, ARG + (indexArg++), argType.getDescriptor());
}
// Call to the renamed method only for AroundInvoke
// LifeCycle interceptors call the original method
String interceptedMethod = null;
if (this.interceptorType.equals(AROUND_INVOKE)) {
interceptedMethod = MethodRenamer.encode(this.jMethod.getName());
} else {
interceptedMethod = this.jMethod.getName();
}
mv.visitMethodInsn(INVOKEVIRTUAL, this.beanClassName, interceptedMethod, this.jMethod.getDescriptor());
Type returnType = Type.getReturnType(this.jMethod.getDescriptor());
// return object or null if the return type is void
returnsObject(returnType, mv);
// default case
mv.visitLabel(defaultCaseLabel);
mv.visitTypeInsn(NEW, "java/lang/IllegalStateException");
mv.visitInsn(DUP);
mv.visitLdcInsn("Problem in interceptors. Shouldn't go in the default case.");
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalStateException", "<init>", "(Ljava/lang/String;)V");
mv.visitInsn(ATHROW);
// end
mv.visitMaxs(0, 0);
mv.visitEnd();
}