You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwebbeans.apache.org by st...@apache.org on 2013/01/01 07:10:28 UTC

svn commit: r1427310 - in /openwebbeans/trunk/webbeans-impl/src: main/java/org/apache/webbeans/proxy/ main/java/org/apache/webbeans/util/ test/java/org/apache/webbeans/newtests/interceptors/factory/ test/java/org/apache/webbeans/newtests/interceptors/f...

Author: struberg
Date: Tue Jan  1 06:10:27 2013
New Revision: 1427310

URL: http://svn.apache.org/viewvc?rev=1427310&view=rev
Log:
OWB-344 improve return value handling

Modified:
    openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java
    openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/util/ClassUtil.java
    openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/InterceptorDecoratorProxyFactoryTest.java
    openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/beans/ClassInterceptedClass.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=1427310&r1=1427309&r2=1427310&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 06:10:27 2013
@@ -24,6 +24,7 @@ import java.lang.reflect.Field;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 import java.util.List;
 
 import org.apache.webbeans.config.WebBeansContext;
@@ -138,13 +139,15 @@ public class InterceptorDecoratorProxyFa
         createConstructor(cw, proxyClassFileName, classToProxy, classFileName);
 
 
-        delegateNonInterceptedMethods(cw, proxyClassFileName, classToProxy, classFileName, nonInterceptedMethods);
-
-
-
-        //X TODO invoke all
+        if (nonInterceptedMethods != null)
+        {
+            delegateNonInterceptedMethods(cw, proxyClassFileName, classToProxy, classFileName, nonInterceptedMethods);
+        }
 
-        //X TODO continue;
+        if (interceptedMethods != null)
+        {
+            delegateInterceptedMethods(cw, proxyClassFileName, classToProxy, classFileName, interceptedMethods);
+        }
 
         return cw.toByteArray();
     }
@@ -205,22 +208,31 @@ public class InterceptorDecoratorProxyFa
      *
      * @param noninterceptedMethods all methods which are neither intercepted nor decorated
      */
-    private static void delegateNonInterceptedMethods(ClassWriter cw, String proxyClassFileName, Class<?> classToProxy, String classFileName,
-                                                      List<Method> noninterceptedMethods)
+    private void delegateNonInterceptedMethods(ClassWriter cw, String proxyClassFileName, Class<?> classToProxy, String classFileName,
+                                               List<Method> noninterceptedMethods)
     {
-        for (Method proxiedMethod : noninterceptedMethods)
+        for (Method delegatedMethod : noninterceptedMethods)
         {
-            String methodDescriptor = Type.getMethodDescriptor(proxiedMethod);
+            int modifiers = delegatedMethod.getModifiers();
+
+            if (unproxyableMethod(delegatedMethod))
+            {
+                continue;
+            }
+
+            String methodDescriptor = Type.getMethodDescriptor(delegatedMethod);
 
             //X TODO handle generic exception types?
-            Class[] exceptionTypes = proxiedMethod.getExceptionTypes();
+            Class[] exceptionTypes = delegatedMethod.getExceptionTypes();
             String[] exceptionTypeNames = new String[exceptionTypes.length];
             for (int i = 0; i < exceptionTypes.length; i++)
             {
                 exceptionTypeNames[i] = Type.getType(exceptionTypes[i]).getInternalName();
             }
 
-            MethodVisitor mv = cw.visitMethod(proxiedMethod.getModifiers(), proxiedMethod.getName(), methodDescriptor, null, exceptionTypeNames);
+            int targetModifiers = delegatedMethod.getModifiers() & (Modifier.PROTECTED | Modifier.PUBLIC);
+
+            MethodVisitor mv = cw.visitMethod(targetModifiers, delegatedMethod.getName(), methodDescriptor, null, exceptionTypeNames);
 
             // fill method body
             mv.visitCode();
@@ -230,18 +242,17 @@ public class InterceptorDecoratorProxyFa
             mv.visitFieldInsn(Opcodes.GETFIELD, proxyClassFileName, FIELD_PROXIED_INSTANCE, Type.getDescriptor(classToProxy));
 
             int offset = 1;
-            for (Class<?> aClass : proxiedMethod.getParameterTypes())
+            for (Class<?> aClass : delegatedMethod.getParameterTypes())
             {
                 final Type type = Type.getType(aClass);
                 mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), offset);
                 offset += type.getSize();
             }
 
-            final Type declaringClass = Type.getType(proxiedMethod.getDeclaringClass());
-            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, declaringClass.getInternalName(), proxiedMethod.getName(), methodDescriptor);
+            final Type declaringClass = Type.getType(delegatedMethod.getDeclaringClass());
+            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, declaringClass.getInternalName(), delegatedMethod.getName(), methodDescriptor);
 
-            final Type returnType = Type.getType(proxiedMethod.getReturnType());
-            mv.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
+            generateReturn(mv, delegatedMethod);
 
             mv.visitMaxs(-1, -1);
 
@@ -249,6 +260,81 @@ public class InterceptorDecoratorProxyFa
         }
     }
 
+    private boolean unproxyableMethod(Method delegatedMethod)
+    {
+        int modifiers = delegatedMethod.getModifiers();
+
+        //X TODO how to deal with native functions?
+        return (modifiers & (Modifier.PRIVATE | Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL | Modifier.NATIVE)) > 0 ||
+               "finalize".equals(delegatedMethod.getName());
+    }
+
+    private void delegateInterceptedMethods(ClassWriter cw, String proxyClassFileName, Class<?> classToProxy, String classFileName,
+                                            List<Method> interceptedMethods)
+    {
+        for (Method proxiedMethod : interceptedMethods)
+        {
+
+        }
+    }
+
+
+    private void generateReturn(MethodVisitor mv, Method delegatedMethod)
+    {
+        final Class<?> returnType = delegatedMethod.getReturnType();
+        mv.visitInsn(getReturnInsn(returnType));
+    }
+
+    /**
+     * Gets the appropriate bytecode instruction for RETURN, according to what type we need to return
+     *
+     * @param type Type the needs to be returned
+     * @return The matching bytecode instruction
+     */
+    private int getReturnInsn(final Class<?> type)
+    {
+        if (type.isPrimitive())
+        {
+            if (Void.TYPE.equals(type))
+            {
+                return Opcodes.RETURN;
+            }
+            if (Integer.TYPE.equals(type))
+            {
+                return Opcodes.IRETURN;
+            }
+            else if (Boolean.TYPE.equals(type))
+            {
+                return Opcodes.IRETURN;
+            }
+            else if (Character.TYPE.equals(type))
+            {
+                return Opcodes.IRETURN;
+            }
+            else if (Byte.TYPE.equals(type))
+            {
+                return Opcodes.IRETURN;
+            }
+            else if (Short.TYPE.equals(type))
+            {
+                return Opcodes.IRETURN;
+            }
+            else if (Float.TYPE.equals(type))
+            {
+                return Opcodes.FRETURN;
+            }
+            else if (Long.TYPE.equals(type))
+            {
+                return Opcodes.LRETURN;
+            }
+            else if (Double.TYPE.equals(type))
+            {
+                return Opcodes.DRETURN;
+            }
+        }
+
+        return Opcodes.ARETURN;
+    }
 
     /**
      * The 'defineClass' method on the ClassLoader is protected, thus we need to invoke it via reflection.

Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/util/ClassUtil.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/util/ClassUtil.java?rev=1427310&r1=1427309&r2=1427310&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/util/ClassUtil.java (original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/util/ClassUtil.java Tue Jan  1 06:10:27 2013
@@ -290,6 +290,7 @@ public final class ClassUtil
                 {
                     methods = new ArrayList<Method>();
                     methods.add(method);
+                    allMethods.add(method);
                     methodMap.put(method.getName(), methods);
                 }
                 else

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=1427310&r1=1427309&r2=1427310&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 06:10:27 2013
@@ -20,6 +20,8 @@ package org.apache.webbeans.newtests.int
 
 import java.lang.reflect.Field;
 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;
@@ -47,14 +49,36 @@ public class InterceptorDecoratorProxyFa
 
         InterceptorDecoratorProxyFactory pf = new InterceptorDecoratorProxyFactory(getWebBeansContext());
 
-        ClassLoader classLoader = this.getClass().getClassLoader();
+        // 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);
 
-        ClassInterceptedClass proxy = pf.createProxyInstance(proxyClass, new ClassInterceptedClass(), 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());
+            }
+        }
+*/
+
+        ClassInterceptedClass internalInstance = new ClassInterceptedClass();
+        internalInstance.init();
+
+        ClassInterceptedClass proxy = pf.createProxyInstance(proxyClass, internalInstance, null);
         Assert.assertNotNull(proxy);
 
         // we need to get the field from the proxy via reflection
@@ -69,7 +93,9 @@ public class InterceptorDecoratorProxyFa
         proxy.setMeaningOfLife(42);
 
         Assert.assertEquals(42, proxy.getMeaningOfLife());
-
+        Assert.assertEquals(internalInstance.getFloat(), proxy.getFloat(), 0f);
+        Assert.assertEquals('c', proxy.getChar());
+        Assert.assertEquals(internalInstance, proxy.getSelf());
 
         shutDownContainer();
     }

Modified: openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/beans/ClassInterceptedClass.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/beans/ClassInterceptedClass.java?rev=1427310&r1=1427309&r2=1427310&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/beans/ClassInterceptedClass.java (original)
+++ openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/beans/ClassInterceptedClass.java Tue Jan  1 06:10:27 2013
@@ -29,12 +29,20 @@ public class ClassInterceptedClass
     private boolean defaultCtInvoked = false;
 
     private int meaningOfLife;
+    private float f;
+    private char c;
 
     public ClassInterceptedClass()
     {
         defaultCtInvoked = true;
     }
 
+    public void init()
+    {
+        f = 2.4f;
+        c = 'c';
+    }
+
     public int getMeaningOfLife()
     {
         System.out.println("answering the question about life, the universe and everything!");
@@ -47,4 +55,19 @@ public class ClassInterceptedClass
         this.meaningOfLife = meaningOfLife;
     }
 
+    public float getFloat()
+    {
+        return f;
+    }
+
+    public ClassInterceptedClass getSelf()
+    {
+        return this;
+    }
+
+    public char getChar()
+    {
+        return c;
+    }
+
 }