Author: struberg
Date: Tue Jan  1 15:55:12 2013
New Revision: 1427451

URL: http://svn.apache.org/viewvc?rev=1427451&view=rev
Log:
OWB-344 fix InvocationHandler invocation

Added:
    
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/OwbProxy.java
Modified:
    
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java
    
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/InterceptorDecoratorProxyFactoryTest.java

Modified: 
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java
URL: 
http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java?rev=1427451&r1=1427450&r2=1427451&view=diff
==============================================================================
--- 
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java
 (original)
+++ 
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java
 Tue Jan  1 15:55:12 2013
@@ -27,8 +27,8 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.List;
 
-import org.apache.webbeans.config.WebBeansContext;
 import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.Type;
@@ -44,7 +44,6 @@ import org.objectweb.asm.Type;
  *
  * This factory will create and cache the proxy classes for a given type.
  *
- *
  */
 //X TODO: clarify how serialisation works! The proxy classes might need to get 
created on deserialisation!
 public class InterceptorDecoratorProxyFactory
@@ -59,11 +58,8 @@ public class InterceptorDecoratorProxyFa
     //X TODO add caching of created proxy classes. This is needed to prevent 
class loading clashes.
     //X a generated proxy cannot easily get redefined later!
 
-    private WebBeansContext webBeansContext;
-
-    public InterceptorDecoratorProxyFactory(WebBeansContext webBeansContext)
+    public InterceptorDecoratorProxyFactory()
     {
-        this.webBeansContext = webBeansContext;
     }
 
     public <T> T createProxyInstance(Class<T> proxyClass, T instance, 
InvocationHandler interceptorDecoratorStack)
@@ -129,7 +125,7 @@ public class InterceptorDecoratorProxyFa
         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
         String classFileName = classToProxy.getName().replace('.', '/');
 
-        String[] interfaceNames = new String[]{}; //X TODO there might be some 
more in the future
+        String[] interfaceNames = new 
String[]{Type.getInternalName(OwbProxy.class)};
 
         cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER + 
Opcodes.ACC_SYNTHETIC, proxyClassFileName, null, classFileName, interfaceNames);
         cw.visitSource(classFileName + ".java", null);
@@ -141,12 +137,12 @@ public class InterceptorDecoratorProxyFa
 
         if (nonInterceptedMethods != null)
         {
-            delegateNonInterceptedMethods(cw, proxyClassFileName, 
classToProxy, classFileName, nonInterceptedMethods);
+            delegateNonInterceptedMethods(cw, proxyClassFileName, 
classToProxy, nonInterceptedMethods);
         }
 
         if (interceptedMethods != null)
         {
-            delegateInterceptedMethods(cw, proxyClassFileName, classToProxy, 
classFileName, interceptedMethods);
+            delegateInterceptedMethods(cw, proxyClassFileName, classToProxy, 
interceptedMethods);
         }
 
         return cw.toByteArray();
@@ -208,13 +204,10 @@ public class InterceptorDecoratorProxyFa
      *
      * @param noninterceptedMethods all methods which are neither intercepted 
nor decorated
      */
-    private void delegateNonInterceptedMethods(ClassWriter cw, String 
proxyClassFileName, Class<?> classToProxy, String classFileName,
-                                               List<Method> 
noninterceptedMethods)
+    private void delegateNonInterceptedMethods(ClassWriter cw, String 
proxyClassFileName, Class<?> classToProxy, List<Method> noninterceptedMethods)
     {
         for (Method delegatedMethod : noninterceptedMethods)
         {
-            int modifiers = delegatedMethod.getModifiers();
-
             if (unproxyableMethod(delegatedMethod))
             {
                 continue;
@@ -269,16 +262,281 @@ public class InterceptorDecoratorProxyFa
                "finalize".equals(delegatedMethod.getName());
     }
 
-    private void delegateInterceptedMethods(ClassWriter cw, String 
proxyClassFileName, Class<?> classToProxy, String classFileName,
-                                            List<Method> interceptedMethods)
+    private void delegateInterceptedMethods(ClassWriter cw, String 
proxyClassFileName, Class<?> classToProxy, List<Method> interceptedMethods)
+            throws ProxyGenerationException
     {
         for (Method proxiedMethod : interceptedMethods)
         {
+            generateInvocationHandlerMethod(cw, proxiedMethod, 
proxyClassFileName);
+        }
+    }
+
+    private void generateInvocationHandlerMethod(ClassWriter cw, Method 
method, String proxyName)
+            throws ProxyGenerationException
+    {
+        if ("<init>".equals(method.getName()))
+        {
+            return;
+        }
+
+        final Class<?> returnType = method.getReturnType();
+        final Class<?>[] parameterTypes = method.getParameterTypes();
+        final Class<?>[] exceptionTypes = method.getExceptionTypes();
+        final int modifiers = method.getModifiers();
+
+        // push the method definition
+        int modifier = modifiers & (Opcodes.ACC_PUBLIC | 
Opcodes.ACC_PROTECTED);
+
+        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
+        final Label l0 = new Label();
+        final Label l1 = new Label();
+        final Label l2 = new Label();
+
+        if (exceptionTypes.length > 0)
+        {
+            mv.visitTryCatchBlock(l0, l1, l2, 
"java/lang/reflect/InvocationTargetException");
+        }
+
+        // push try code
+        mv.visitLabel(l0);
+        final 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);
+
+            final 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++;
+            }
+        }
+
+        // invoke getMethod() with the method name and the array of types
+        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", 
"getDeclaredMethod",
+                
"(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;");
+
+        // store the returned method for later
+        mv.visitVarInsn(Opcodes.ASTORE, length);
+
+        // the following code generates bytecode equivalent to:
+        // return ((<returntype>) invocationHandler.invoke(this, method, new 
Object[] { <function arguments }))[.<primitive>Value()];
+
+        final Label l4 = new Label();
+        mv.visitLabel(l4);
+        mv.visitVarInsn(Opcodes.ALOAD, 0);
+
+        // get the invocationHandler field from this class
+        mv.visitFieldInsn(Opcodes.GETFIELD, proxyName, 
FIELD_INVOCATION_HANDLER, "Ljava/lang/reflect/InvocationHandler;");
+
+        // we want to pass "this" in as the first parameter
+        mv.visitVarInsn(Opcodes.ALOAD, 0);
+
+        // and the method we fetched earlier
+        mv.visitVarInsn(Opcodes.ALOAD, length);
+
+        // need to construct the array of objects passed in
+
+        // create the Object[]
+        createArrayDefinition(mv, parameterTypes.length, Object.class);
+
+        int index = 1;
+        // push parameters into array
+        for (int i = 0; i < parameterTypes.length; i++)
+        {
+            // keep copy of array on stack
+            mv.visitInsn(Opcodes.DUP);
+
+            final Class<?> parameterType = parameterTypes[i];
+
+            // push number onto stack
+            pushIntOntoStack(mv, i);
+
+            if (parameterType.isPrimitive())
+            {
+                String wrapperType = getWrapperType(parameterType);
+                mv.visitVarInsn(getVarInsn(parameterType), index);
+
+                mv.visitMethodInsn(Opcodes.INVOKESTATIC, wrapperType, 
"valueOf",
+                        "(" + Type.getDescriptor(parameterType) + ")L" + 
wrapperType + ";");
+                mv.visitInsn(Opcodes.AASTORE);
+
+                if (Long.TYPE.equals(parameterType) || 
Double.TYPE.equals(parameterType))
+                {
+                    index += 2;
+                }
+                else
+                {
+                    index++;
+                }
+            }
+            else
+            {
+                mv.visitVarInsn(Opcodes.ALOAD, index);
+                mv.visitInsn(Opcodes.AASTORE);
+                index++;
+            }
+        }
+
+        // invoke the invocationHandler
+        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, 
"java/lang/reflect/InvocationHandler", "invoke",
+                
"(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;");
+
+        // 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));
+        }
+
+        // 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);
+
+            final Label l5 = new Label();
+            mv.visitLabel(l5);
+
+            for (int i = 0; i < exceptionTypes.length; i++)
+            {
+                final 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;");
+                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", 
"getClass", "()Ljava/lang/Class;");
+                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", 
"equals", "(Ljava/lang/Object;)Z");
+
+                final Label l6 = new Label();
+                mv.visitJumpInsn(Opcodes.IFEQ, l6);
+
+                final Label l7 = new Label();
+                mv.visitLabel(l7);
+
+                mv.visitVarInsn(Opcodes.ALOAD, length);
+                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, 
"java/lang/reflect/InvocationTargetException", "getCause",
+                        "()Ljava/lang/Throwable;");
+                mv.visitTypeInsn(Opcodes.CHECKCAST, 
exceptionType.getCanonicalName().replace('.', '/'));
+                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");
+                    mv.visitInsn(Opcodes.ATHROW);
+                }
+            }
+        }
+
+        // finish this method
+        mv.visitMaxs(0, 0);
+        mv.visitEnd();
+    }
 
+    /**
+     * Returns the name of the Java method to call to get the primitive value 
from an Object - e.g. intValue for java.lang.Integer
+     *
+     * @param type Type whose primitive method we want to lookup
+     * @return The name of the method to use
+     */
+    private String getPrimitiveMethod(final Class<?> type)
+    {
+        if (Integer.TYPE.equals(type))
+        {
+            return "intValue";
+        }
+        else if (Boolean.TYPE.equals(type))
+        {
+            return "booleanValue";
+        }
+        else if (Character.TYPE.equals(type))
+        {
+            return "charValue";
         }
+        else if (Byte.TYPE.equals(type))
+        {
+            return "byteValue";
+        }
+        else if (Short.TYPE.equals(type))
+        {
+            return "shortValue";
+        }
+        else if (Float.TYPE.equals(type))
+        {
+            return "floatValue";
+        }
+        else if (Long.TYPE.equals(type))
+        {
+            return "longValue";
+        }
+        else if (Double.TYPE.equals(type))
+        {
+            return "doubleValue";
+        }
+
+        throw new IllegalStateException("Type: " + type.getCanonicalName() + " 
is not a primitive type");
     }
 
 
+
     private void generateReturn(MethodVisitor mv, Method delegatedMethod)
     {
         final Class<?> returnType = delegatedMethod.getReturnType();
@@ -286,6 +544,165 @@ public class InterceptorDecoratorProxyFa
     }
 
     /**
+     * pushes an array of the specified size to the method visitor. The 
generated bytecode will leave
+     * the new array at the top of the stack.
+     *
+     * @param mv   MethodVisitor to use
+     * @param size Size of the array to create
+     * @param type Type of array to create
+     * @throws ProxyGenerationException
+     */
+    private void createArrayDefinition(final MethodVisitor mv, final int size, 
final Class<?> type)
+            throws ProxyGenerationException
+    {
+        // create a new array of java.lang.class (2)
+
+        if (size < 0)
+        {
+            throw new ProxyGenerationException("Array size cannot be less than 
zero");
+        }
+
+        pushIntOntoStack(mv, size);
+
+        mv.visitTypeInsn(Opcodes.ANEWARRAY, 
type.getCanonicalName().replace('.', '/'));
+    }
+
+    /**
+     * @return the wrapper type for a primitive, e.g. java.lang.Integer for int
+     */
+    private String getWrapperType(final Class<?> type)
+    {
+        if (Integer.TYPE.equals(type))
+        {
+            return Integer.class.getCanonicalName().replace('.', '/');
+        }
+        else if (Boolean.TYPE.equals(type))
+        {
+            return Boolean.class.getCanonicalName().replace('.', '/');
+        }
+        else if (Character.TYPE.equals(type))
+        {
+            return Character.class.getCanonicalName().replace('.', '/');
+        }
+        else if (Byte.TYPE.equals(type))
+        {
+            return Byte.class.getCanonicalName().replace('.', '/');
+        }
+        else if (Short.TYPE.equals(type))
+        {
+            return Short.class.getCanonicalName().replace('.', '/');
+        }
+        else if (Float.TYPE.equals(type))
+        {
+            return Float.class.getCanonicalName().replace('.', '/');
+        }
+        else if (Long.TYPE.equals(type))
+        {
+            return Long.class.getCanonicalName().replace('.', '/');
+        }
+        else if (Double.TYPE.equals(type))
+        {
+            return Double.class.getCanonicalName().replace('.', '/');
+        }
+        else if (Void.TYPE.equals(type))
+        {
+            return Void.class.getCanonicalName().replace('.', '/');
+        }
+
+        throw new IllegalStateException("Type: " + type.getCanonicalName() + " 
is not a primitive type");
+    }
+
+    /**
+     * Returns the appropriate bytecode instruction to load a value from a 
variable to the stack
+     *
+     * @param type Type to load
+     * @return Bytecode instruction to use
+     */
+    private int getVarInsn(final Class<?> type)
+    {
+        if (type.isPrimitive())
+        {
+            if (Integer.TYPE.equals(type))
+            {
+                return Opcodes.ILOAD;
+            }
+            else if (Boolean.TYPE.equals(type))
+            {
+                return Opcodes.ILOAD;
+            }
+            else if (Character.TYPE.equals(type))
+            {
+                return Opcodes.ILOAD;
+            }
+            else if (Byte.TYPE.equals(type))
+            {
+                return Opcodes.ILOAD;
+            }
+            else if (Short.TYPE.equals(type))
+            {
+                return Opcodes.ILOAD;
+            }
+            else if (Float.TYPE.equals(type))
+            {
+                return Opcodes.FLOAD;
+            }
+            else if (Long.TYPE.equals(type))
+            {
+                return Opcodes.LLOAD;
+            }
+            else if (Double.TYPE.equals(type))
+            {
+                return Opcodes.DLOAD;
+            }
+        }
+
+        throw new IllegalStateException("Type: " + type.getCanonicalName() + " 
is not a primitive type");
+    }
+
+    /**
+     * Invokes the most appropriate bytecode instruction to put a number on 
the stack
+     *
+     * @param mv
+     * @param i
+     */
+    private void pushIntOntoStack(final MethodVisitor mv, final int i)
+    {
+        if (i == 0)
+        {
+            mv.visitInsn(Opcodes.ICONST_0);
+        }
+        else if (i == 1)
+        {
+            mv.visitInsn(Opcodes.ICONST_1);
+        }
+        else if (i == 2)
+        {
+            mv.visitInsn(Opcodes.ICONST_2);
+        }
+        else if (i == 3)
+        {
+            mv.visitInsn(Opcodes.ICONST_3);
+        }
+        else if (i == 4)
+        {
+            mv.visitInsn(Opcodes.ICONST_4);
+        }
+        else if (i == 5)
+        {
+            mv.visitInsn(Opcodes.ICONST_5);
+        }
+        else if (i > 5 && i <= 255)
+        {
+            mv.visitIntInsn(Opcodes.BIPUSH, i);
+        }
+        else
+        {
+            mv.visitIntInsn(Opcodes.SIPUSH, i);
+        }
+    }
+
+
+    /**
      * Gets the appropriate bytecode instruction for RETURN, according to what 
type we need to return
      *
      * @param type Type the needs to be returned
@@ -337,6 +754,24 @@ public class InterceptorDecoratorProxyFa
     }
 
     /**
+     * Gets the string to use for CHECKCAST instruction, returning the correct 
value for any type, including primitives and arrays
+     *
+     * @param returnType The type to cast to with CHECKCAST
+     * @return CHECKCAST parameter
+     */
+    private String getCastType(final Class<?> returnType)
+    {
+        if (returnType.isPrimitive())
+        {
+            return getWrapperType(returnType);
+        }
+        else
+        {
+            return Type.getInternalName(returnType);
+        }
+    }
+
+    /**
      * The 'defineClass' method on the ClassLoader is protected, thus we need 
to invoke it via reflection.
      * @return the Class which got loaded in the classloader
      */

Added: 
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/OwbProxy.java
URL: 
http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/OwbProxy.java?rev=1427451&view=auto
==============================================================================
--- 
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/OwbProxy.java
 (added)
+++ 
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/OwbProxy.java
 Tue Jan  1 15:55:12 2013
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.webbeans.proxy;
+
+/**
+ * Marker Interface for all OpenWebBeans Proxies.
+ */
+public interface OwbProxy
+{
+}

Modified: 
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/InterceptorDecoratorProxyFactoryTest.java
URL: 
http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/InterceptorDecoratorProxyFactoryTest.java?rev=1427451&r1=1427450&r2=1427451&view=diff
==============================================================================
--- 
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/InterceptorDecoratorProxyFactoryTest.java
 (original)
+++ 
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/InterceptorDecoratorProxyFactoryTest.java
 Tue Jan  1 15:55:12 2013
@@ -19,17 +19,18 @@
 package org.apache.webbeans.newtests.interceptors.factory;
 
 import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.List;
 
 import org.apache.webbeans.newtests.AbstractUnitTest;
 import 
org.apache.webbeans.newtests.interceptors.factory.beans.ClassInterceptedClass;
 import org.apache.webbeans.proxy.InterceptorDecoratorProxyFactory;
 
+import org.apache.webbeans.proxy.OwbProxy;
 import org.apache.webbeans.util.ClassUtil;
 import org.junit.Assert;
 import org.junit.Test;
@@ -44,41 +45,31 @@ public class InterceptorDecoratorProxyFa
     @Test
     public void textSimpleProxyCreation() throws Exception
     {
+/*X not needed so far
         Collection<Class<?>> beanClasses = new ArrayList<Class<?>>();
         startContainer(beanClasses, null);
+*/
 
-        InterceptorDecoratorProxyFactory pf = new 
InterceptorDecoratorProxyFactory(getWebBeansContext());
+        InterceptorDecoratorProxyFactory pf = new 
InterceptorDecoratorProxyFactory();
 
         // we take a fresh URLClassLoader to not blur the test classpath with 
synthetic classes.
         ClassLoader classLoader = new URLClassLoader(new URL[0]);
 
         List<Method> methods = 
ClassUtil.getNonPrivateMethods(ClassInterceptedClass.class);
 
-        Class<ClassInterceptedClass> proxyClass = 
pf.createProxyClass(classLoader, ClassInterceptedClass.class, null, methods);
-        Assert.assertNotNull(proxyClass);
+        List<Method> interceptedMethods = methods;
+        List<Method> nonInterceptedMethods = null;
 
-/*X
-        for (Method m : methods)
-        {
-            List<Method> ms = new ArrayList<Method>();
-            ms.add(m);
 
-            try
-            {
-                Class<ClassInterceptedClass> pc = pf.createProxyClass(cl, 
ClassInterceptedClass.class, null, ms);
-                Assert.assertNotNull(pc);
-            }
-            catch (Exception e)
-            {
-                System.out.println("hab die sau :) " + m.toString());
-            }
-        }
-*/
+        Class<ClassInterceptedClass> proxyClass = 
pf.createProxyClass(classLoader, ClassInterceptedClass.class, 
interceptedMethods, nonInterceptedMethods);
+        Assert.assertNotNull(proxyClass);
 
         ClassInterceptedClass internalInstance = new ClassInterceptedClass();
         internalInstance.init();
 
-        ClassInterceptedClass proxy = pf.createProxyInstance(proxyClass, 
internalInstance, null);
+        TestInvocationHandler testInvocationHandler = new 
TestInvocationHandler(internalInstance);
+
+        ClassInterceptedClass proxy = pf.createProxyInstance(proxyClass, 
internalInstance, testInvocationHandler);
         Assert.assertNotNull(proxy);
 
         // we need to get the field from the proxy via reflection
@@ -86,10 +77,11 @@ public class InterceptorDecoratorProxyFa
         Field field = 
proxy.getClass().getSuperclass().getDeclaredField("defaultCtInvoked");
         Assert.assertNotNull(field);
         field.setAccessible(true);
-
         Boolean isDefaultCtInvoked = (Boolean) field.get(proxy);
         Assert.assertTrue(isDefaultCtInvoked);
 
+        Assert.assertTrue(proxy instanceof OwbProxy);
+
         proxy.setMeaningOfLife(42);
 
         Assert.assertEquals(42, proxy.getMeaningOfLife());
@@ -97,6 +89,28 @@ public class InterceptorDecoratorProxyFa
         Assert.assertEquals('c', proxy.getChar());
         Assert.assertEquals(internalInstance, proxy.getSelf());
 
-        shutDownContainer();
+        //X shutDownContainer();
+    }
+
+    public static class TestInvocationHandler implements InvocationHandler
+    {
+        public List<String> invokedMethodNames = new ArrayList<String>();
+
+        private final Object instance;
+
+        public TestInvocationHandler(Object instance)
+        {
+            this.instance = instance;
+        }
+
+        @Override
+        public Object invoke(Object proxy, Method method, Object[] args) 
throws Throwable
+        {
+            invokedMethodNames.add(method.getName());
+
+            System.out.println("TestInvocationHandler got properly invoked for 
method " + method.getName());
+
+            return method.invoke(instance, args);
+        }
     }
 }


Reply via email to