Search in sources :

Example 1 with ProxyGenerationException

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();
}
Also used : WebBeansConfigurationException(org.apache.webbeans.exception.WebBeansConfigurationException) ProxyGenerationException(org.apache.webbeans.exception.ProxyGenerationException) Label(org.apache.xbean.asm9.Label) MethodVisitor(org.apache.xbean.asm9.MethodVisitor)

Example 2 with ProxyGenerationException

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;
}
Also used : Field(java.lang.reflect.Field) ProxyGenerationException(org.apache.webbeans.exception.ProxyGenerationException) WebBeansConfigurationException(org.apache.webbeans.exception.WebBeansConfigurationException) ProxyGenerationException(org.apache.webbeans.exception.ProxyGenerationException) ObjectStreamException(java.io.ObjectStreamException)

Example 3 with ProxyGenerationException

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);
    }
}
Also used : Field(java.lang.reflect.Field) ProxyGenerationException(org.apache.webbeans.exception.ProxyGenerationException) WebBeansConfigurationException(org.apache.webbeans.exception.WebBeansConfigurationException) ProxyGenerationException(org.apache.webbeans.exception.ProxyGenerationException) InvocationTargetException(java.lang.reflect.InvocationTargetException) ObjectStreamException(java.io.ObjectStreamException)

Example 4 with ProxyGenerationException

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;
}
Also used : Field(java.lang.reflect.Field) ProxyGenerationException(org.apache.webbeans.exception.ProxyGenerationException) ArrayList(java.util.ArrayList) Method(java.lang.reflect.Method) WebBeansConfigurationException(org.apache.webbeans.exception.WebBeansConfigurationException) ProxyGenerationException(org.apache.webbeans.exception.ProxyGenerationException) InvocationTargetException(java.lang.reflect.InvocationTargetException) ObjectStreamException(java.io.ObjectStreamException)

Example 5 with ProxyGenerationException

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);
    }
}
Also used : Constructor(java.lang.reflect.Constructor) ProxyGenerationException(org.apache.webbeans.exception.ProxyGenerationException) MethodVisitor(org.apache.xbean.asm9.MethodVisitor) Provider(javax.inject.Provider)

Aggregations

ProxyGenerationException (org.apache.webbeans.exception.ProxyGenerationException)7 Field (java.lang.reflect.Field)4 WebBeansConfigurationException (org.apache.webbeans.exception.WebBeansConfigurationException)4 ObjectStreamException (java.io.ObjectStreamException)3 MethodVisitor (org.apache.xbean.asm9.MethodVisitor)3 Constructor (java.lang.reflect.Constructor)2 InvocationTargetException (java.lang.reflect.InvocationTargetException)2 Method (java.lang.reflect.Method)1 ArrayList (java.util.ArrayList)1 AnnotatedConstructor (javax.enterprise.inject.spi.AnnotatedConstructor)1 Provider (javax.inject.Provider)1 Label (org.apache.xbean.asm9.Label)1