use of org.apache.webbeans.exception.ProxyGenerationException in project openwebbeans by apache.
the class InterceptorDecoratorProxyFactory method generateInterceptorHandledMethod.
private void generateInterceptorHandledMethod(ClassWriter cw, Method method, int methodIndex, Class<?> classToProxy, String proxyClassFileName) throws ProxyGenerationException {
if ("<init>".equals(method.getName())) {
return;
}
if (isIgnoredMethod(method)) {
return;
}
Class<?> returnType = method.getReturnType();
Class<?>[] parameterTypes = method.getParameterTypes();
Class<?>[] exceptionTypes = method.getExceptionTypes();
int modifiers = method.getModifiers();
if (Modifier.isFinal(modifiers) || Modifier.isStatic(modifiers)) {
throw new WebBeansConfigurationException("It's not possible to proxy a final or static method: " + classToProxy.getName() + " " + method.getName());
}
// push the method definition
int modifier = modifiers & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED | Opcodes.ACC_VARARGS);
MethodVisitor mv = cw.visitMethod(modifier, method.getName(), Type.getMethodDescriptor(method), null, null);
mv.visitCode();
// push try/catch block, to catch declared exceptions, and to catch java.lang.Throwable
Label l0 = new Label();
Label l1 = new Label();
Label l2 = new Label();
if (exceptionTypes.length > 0) {
mv.visitTryCatchBlock(l0, l1, l2, "java/lang/reflect/InvocationTargetException");
}
// push try code
mv.visitLabel(l0);
String classNameToOverride = method.getDeclaringClass().getName().replace('.', '/');
mv.visitLdcInsn(Type.getType("L" + classNameToOverride + ";"));
// the following code generates the bytecode for this line of Java:
// Method method = <proxy>.class.getMethod("add", new Class[] { <array of function argument classes> });
// get the method name to invoke, and push to stack
mv.visitLdcInsn(method.getName());
// create the Class[]
createArrayDefinition(mv, parameterTypes.length, Class.class);
int length = 1;
// push parameters into array
for (int i = 0; i < parameterTypes.length; i++) {
// keep copy of array on stack
mv.visitInsn(Opcodes.DUP);
Class<?> parameterType = parameterTypes[i];
// push number onto stack
pushIntOntoStack(mv, i);
if (parameterType.isPrimitive()) {
String wrapperType = getWrapperType(parameterType);
mv.visitFieldInsn(Opcodes.GETSTATIC, wrapperType, "TYPE", "Ljava/lang/Class;");
} else {
mv.visitLdcInsn(Type.getType(parameterType));
}
mv.visitInsn(Opcodes.AASTORE);
if (Long.TYPE.equals(parameterType) || Double.TYPE.equals(parameterType)) {
length += 2;
} else {
length++;
}
}
// the following code generates bytecode equivalent to:
// return ((<returntype>) invocationHandler.invoke(this, {methodIndex}, new Object[] { <function arguments }))[.<primitive>Value()];
Label l4 = new Label();
mv.visitLabel(l4);
mv.visitVarInsn(Opcodes.ALOAD, 0);
// get the invocationHandler field from this class
mv.visitFieldInsn(Opcodes.GETFIELD, proxyClassFileName, FIELD_INTERCEPTOR_HANDLER, Type.getDescriptor(InterceptorHandler.class));
// add the Method from the static array as first parameter
mv.visitFieldInsn(Opcodes.GETSTATIC, proxyClassFileName, FIELD_INTERCEPTED_METHODS, Type.getDescriptor(Method[].class));
// push the methodIndex of the current method
if (methodIndex < 128) {
mv.visitIntInsn(Opcodes.BIPUSH, methodIndex);
} else if (methodIndex < 32267) {
// for methods > 127 we need to push a short number as index
mv.visitIntInsn(Opcodes.SIPUSH, methodIndex);
} else {
throw new ProxyGenerationException("Sorry, we only support Classes with 2^15 methods...");
}
// and now load the Method from the array
mv.visitInsn(Opcodes.AALOAD);
// prepare the parameter array as Object[] and store it on the stack
pushMethodParameterArray(mv, parameterTypes);
// invoke the invocationHandler
mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type.getInternalName(InterceptorHandler.class), "invoke", "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;", true);
// 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), false);
}
// push return
mv.visitLabel(l1);
if (!Void.TYPE.equals(returnType)) {
mv.visitInsn(getReturnInsn(returnType));
} else {
mv.visitInsn(Opcodes.POP);
mv.visitInsn(Opcodes.RETURN);
}
// catch InvocationTargetException
if (exceptionTypes.length > 0) {
mv.visitLabel(l2);
mv.visitVarInsn(Opcodes.ASTORE, length);
Label l5 = new Label();
mv.visitLabel(l5);
for (int i = 0; i < exceptionTypes.length; i++) {
Class<?> exceptionType = exceptionTypes[i];
mv.visitLdcInsn(Type.getType("L" + exceptionType.getCanonicalName().replace('.', '/') + ";"));
mv.visitVarInsn(Opcodes.ALOAD, length);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/InvocationTargetException", "getCause", "()Ljava/lang/Throwable;", false);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z", false);
Label l6 = new Label();
mv.visitJumpInsn(Opcodes.IFEQ, l6);
Label l7 = new Label();
mv.visitLabel(l7);
mv.visitVarInsn(Opcodes.ALOAD, length);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/InvocationTargetException", "getCause", "()Ljava/lang/Throwable;", false);
mv.visitTypeInsn(Opcodes.CHECKCAST, getCastType(exceptionType));
mv.visitInsn(Opcodes.ATHROW);
mv.visitLabel(l6);
if (i == (exceptionTypes.length - 1)) {
mv.visitTypeInsn(Opcodes.NEW, "java/lang/reflect/UndeclaredThrowableException");
mv.visitInsn(Opcodes.DUP);
mv.visitVarInsn(Opcodes.ALOAD, length);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/reflect/UndeclaredThrowableException", "<init>", "(Ljava/lang/Throwable;)V", false);
mv.visitInsn(Opcodes.ATHROW);
}
}
}
// finish this method
mv.visitMaxs(0, 0);
mv.visitEnd();
}
use of org.apache.webbeans.exception.ProxyGenerationException in project openwebbeans by apache.
the class InterceptorDecoratorProxyFactory method createProxyClass.
private <T> Class<T> createProxyClass(ClassLoader classLoader, Class<T> classToProxy, Method[] interceptedMethods, Method[] nonInterceptedMethods) throws ProxyGenerationException {
String proxyClassName = getUnusedProxyClassName(classLoader, (classToProxy.getSigners() != null ? getSignedClassProxyName(classToProxy) : classToProxy.getName()) + "$$OwbInterceptProxy", interceptedMethods, nonInterceptedMethods);
Class<T> clazz = createProxyClass(classLoader, proxyClassName, classToProxy, interceptedMethods, nonInterceptedMethods);
try {
Field interceptedMethodsField = clazz.getDeclaredField(FIELD_INTERCEPTED_METHODS);
interceptedMethodsField.setAccessible(true);
interceptedMethodsField.set(null, interceptedMethods);
} catch (Exception e) {
throw new ProxyGenerationException(e);
}
return clazz;
}
use of org.apache.webbeans.exception.ProxyGenerationException in project openwebbeans by apache.
the class NormalScopeProxyFactory method createProxyInstance.
public <T> T createProxyInstance(Class<T> proxyClass, Provider provider) throws ProxyGenerationException {
try {
T proxy = newInstance(proxyClass);
Field delegateField = proxy.getClass().getDeclaredField(FIELD_INSTANCE_PROVIDER);
delegateField.setAccessible(true);
delegateField.set(proxy, provider);
return proxy;
} catch (Exception e) {
throw new ProxyGenerationException(e);
}
}
use of org.apache.webbeans.exception.ProxyGenerationException in project openwebbeans by apache.
the class NormalScopeProxyFactory method createProxyClass.
/**
* @param classLoader to use for creating the class in
* @param classToProxy the class for which a subclass will get generated
* @param <T>
* @return the proxy class
*/
public <T> Class<T> createProxyClass(ClassLoader classLoader, Class<T> classToProxy) throws ProxyGenerationException {
Method[] nonInterceptedMethods;
Method[] interceptedMethods = null;
if (classToProxy.isInterface()) {
nonInterceptedMethods = classToProxy.getMethods();
} else {
List<Method> methods = new ArrayList<>();
List<Method> protectedMethods = new ArrayList<>();
for (Method method : ClassUtil.getNonPrivateMethods(classToProxy, true)) {
if (unproxyableMethod(method)) {
continue;
}
if (Modifier.isProtected(method.getModifiers())) {
protectedMethods.add(method);
} else {
methods.add(method);
}
}
nonInterceptedMethods = methods.toArray(new Method[methods.size()]);
interceptedMethods = protectedMethods.toArray(new Method[protectedMethods.size()]);
}
String proxyClassName = getUnusedProxyClassName(classLoader, (classToProxy.getSigners() != null ? getSignedClassProxyName(classToProxy) : classToProxy.getName()) + "$$OwbNormalScopeProxy", interceptedMethods, nonInterceptedMethods);
Class<T> clazz = createProxyClass(classLoader, proxyClassName, classToProxy, interceptedMethods, nonInterceptedMethods);
if (interceptedMethods != null && interceptedMethods.length > 0) {
try {
Field protectedMethodsField = clazz.getDeclaredField(FIELD_PROTECTED_METHODS);
protectedMethodsField.setAccessible(true);
protectedMethodsField.set(null, interceptedMethods);
} catch (Exception e) {
throw new ProxyGenerationException(e);
}
}
return clazz;
}
use of org.apache.webbeans.exception.ProxyGenerationException in project openwebbeans by apache.
the class NormalScopeProxyFactory method createConstructor.
@Override
protected void createConstructor(ClassWriter cw, String proxyClassFileName, Class<?> classToProxy, String classFileName, Constructor<?> ignored) throws ProxyGenerationException {
try {
Constructor superDefaultCt;
String parentClassFileName;
if (classToProxy.isInterface()) {
parentClassFileName = Type.getInternalName(Object.class);
superDefaultCt = Object.class.getConstructor(null);
} else {
parentClassFileName = classFileName;
superDefaultCt = classToProxy.getDeclaredConstructor(null);
}
String descriptor = Type.getConstructorDescriptor(superDefaultCt);
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", descriptor, null, null);
mv.visitCode();
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, parentClassFileName, "<init>", descriptor, false);
// the instance provider field
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitInsn(Opcodes.ACONST_NULL);
mv.visitFieldInsn(Opcodes.PUTFIELD, proxyClassFileName, FIELD_INSTANCE_PROVIDER, Type.getDescriptor(Provider.class));
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(-1, -1);
mv.visitEnd();
} catch (NoSuchMethodException e) {
throw new ProxyGenerationException(e);
}
}
Aggregations