private void createSelectMethod(Method selectMethod) {
Class<?> returnType = selectMethod.getReturnType();
Method executeMethod = EjbSelect.getSelectMethod(returnType);
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, selectMethod.getName(), Type.getMethodDescriptor(selectMethod), null, getExceptionTypes(selectMethod));
mv.visitCode();
// push deploymentInfo
mv.visitFieldInsn(GETSTATIC, implClassName, "deploymentInfo", "Ljava/lang/Object;");
// push method signature
mv.visitLdcInsn(getSelectMethodSignature(selectMethod));
// push return type, but only if the executeMethod is not going to be for void or
// one of the primitives.
if (!returnType.isPrimitive()) {
mv.visitLdcInsn(returnType.getName());
}
// new Object[]
mv.visitIntInsn(BIPUSH, selectMethod.getParameterTypes().length);
mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
// object[i] = arg${i}
int i = 0;
for (Class<?> parameterType : selectMethod.getParameterTypes()) {
// push arguement i on stack
mv.visitInsn(DUP);
bipush(mv, i);
mv.visitVarInsn(Type.getType(parameterType).getOpcode(ILOAD), i + 1);
// convert argument on stack to an Object
Convert.toObjectFrom(mv, parameterType);
// store it into the array
mv.visitInsn(AASTORE);
if (long.class.equals(parameterType) || double.class.equals(parameterType)) {
// longs and doubles are double wide
i = i + 2;
} else {
i++;
}
}
// EjbSelect.execute_xxxx(deploymentInfo, signature, [returnType.] args[]);
mv.visitMethodInsn(INVOKESTATIC,
Type.getInternalName(executeMethod.getDeclaringClass()),
executeMethod.getName(),
Type.getMethodDescriptor(executeMethod));
// if this is a void type, we just return. Otherwise, the return type
// needs to match the type returned from the method call
if (!Void.TYPE.equals(returnType)) {
// if this is a non-primitive return type, then the returned
// object will need to be cast to the appropriate return type for
// the verifier. The primitive types all have the proper type on the
// stack already
if (!returnType.isPrimitive()) {
// convert return type
Convert.fromObjectTo(mv, returnType);
}
// And generate the appropriate return for the type
mv.visitInsn(Type.getReturnType(selectMethod).getOpcode(IRETURN));
} else {
// void return is just a RETURN.
mv.visitInsn(RETURN);
}
// close method
mv.visitMaxs(0, 0);
mv.visitEnd();
}