openwebbeans-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From strub...@apache.org
Subject svn commit: r1445630 - in /openwebbeans/trunk/webbeans-impl/src: main/java/org/apache/webbeans/proxy/ test/java/org/apache/webbeans/newtests/interceptors/factory/
Date Wed, 13 Feb 2013 14:44:55 GMT
Author: struberg
Date: Wed Feb 13 14:44:55 2013
New Revision: 1445630

URL: http://svn.apache.org/r1445630
Log:
OWB-344 add proxy support for protected methods 

Added:
    openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/ProtectedUsageBean.java
Modified:
    openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/AbstractProxyFactory.java
    openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java
    openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/NormalScopeProxyFactory.java
    openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/NormalScopeProxyFactoryTest.java

Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/AbstractProxyFactory.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/AbstractProxyFactory.java?rev=1445630&r1=1445629&r2=1445630&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/AbstractProxyFactory.java
(original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/AbstractProxyFactory.java
Wed Feb 13 14:44:55 2013
@@ -619,4 +619,80 @@ public abstract class AbstractProxyFacto
         });
     }
 
+    /**
+     * Create an Object[] parameter which contains all the parameters of the currently invoked
method
+     * and store this array for use in the call stack.
+     * @param mv
+     * @param parameterTypes
+     */
+    protected void pushMethodParameterArray(MethodVisitor mv, Class<?>[] parameterTypes)
+    {
+        // 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++;
+            }
+        }
+    }
+
+    /**
+     * 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
+     */
+    protected 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('.', '/'));
+    }
+
+
 }

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=1445630&r1=1445629&r2=1445630&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
Wed Feb 13 14:44:55 2013
@@ -437,6 +437,7 @@ public class InterceptorDecoratorProxyFa
 
         final Label l4 = new Label();
         mv.visitLabel(l4);
+
         mv.visitVarInsn(Opcodes.ALOAD, 0);
 
         // get the invocationHandler field from this class
@@ -451,47 +452,10 @@ public class InterceptorDecoratorProxyFa
         // and now load the Method from the array
         mv.visitInsn(Opcodes.AALOAD);
 
-        // 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);
+        // prepare the parameter array as Object[] and store it on the stack
+        pushMethodParameterArray(mv, parameterTypes);
 
-                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, Type.getInternalName(InterceptorHandler.class),
"invoke",
@@ -570,29 +534,4 @@ 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('.', '/'));
-    }
-
-
 }

Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/NormalScopeProxyFactory.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/NormalScopeProxyFactory.java?rev=1445630&r1=1445629&r2=1445630&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/NormalScopeProxyFactory.java
(original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/NormalScopeProxyFactory.java
Wed Feb 13 14:44:55 2013
@@ -350,7 +350,16 @@ public class NormalScopeProxyFactory ext
                                               Class<?> classToProxy, Method[] interceptedMethods)
             throws ProxyGenerationException
     {
-        //X TODO invoke protected methods via reflection
+        if (interceptedMethods == null)
+        {
+            return;
+        }
+
+        for (int i = 0; i < interceptedMethods.length; i++)
+        {
+            Method proxiedMethod = interceptedMethods[i];
+            generateDelegationMethod(cw, proxiedMethod, i, classToProxy, proxyClassFileName);
+        }
     }
 
     @Override
@@ -413,5 +422,96 @@ public class NormalScopeProxyFactory ext
 
     }
 
+    private void generateDelegationMethod(ClassWriter cw, Method method, int methodIndex,
Class<?> classToProxy, String proxyClassFileName)
+    {
+        final Class<?> returnType = method.getReturnType();
+        final Class<?>[] parameterTypes = method.getParameterTypes();
+        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();
+
+
+        mv.visitVarInsn(Opcodes.ALOAD, 0);
+
+        // add the Method from the static array as first parameter
+        mv.visitFieldInsn(Opcodes.GETSTATIC, proxyClassFileName, FIELD_PROTECTED_METHODS,
Type.getDescriptor(Method[].class));
+
+        // push the methodIndex of the current method
+        mv.visitIntInsn(Opcodes.BIPUSH, methodIndex);
+
+        // and now load the Method from the array
+        mv.visitInsn(Opcodes.AALOAD);
+
+
+        // now invoke the get() on the contextual instance Provider<T>
+        mv.visitVarInsn(Opcodes.ALOAD, 0);
+        mv.visitFieldInsn(Opcodes.GETFIELD, proxyClassFileName, FIELD_INSTANCE_PROVIDER,
Type.getDescriptor(Provider.class));
+
+        // invoke the get() method on the Provider
+        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type.getInternalName(Provider.class),
"get", "()Ljava/lang/Object;");
+
+
+        // prepare the parameter array as Object[] and store it on the stack
+        pushMethodParameterArray(mv, parameterTypes);
+
+
+        // this invokes NormalScopeProxyFactory.delegateProtectedMethod
+        mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(NormalScopeProxyFactory.class),
"delegateProtectedMethod",
+                "(Ljava/lang/reflect/Method;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
+
+        // cast the result
+        mv.visitTypeInsn(Opcodes.CHECKCAST, getCastType(returnType));
+
+        //X temporary
+        //X mv.visitInsn(Opcodes.ACONST_NULL);
+
+
+        if (returnType.isPrimitive() && (!Void.TYPE.equals(returnType)))
+        {
+            // get the primitive value
+            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, getWrapperType(returnType), getPrimitiveMethod(returnType),
+                    "()" + Type.getDescriptor(returnType));
+        }
+
+        mv.visitInsn(getReturnInsn(returnType));
+
+        // finish this method
+        mv.visitMaxs(0, 0);
+        mv.visitEnd();
+    }
+
+
+
+    /**
+     * This method get invoked via generated ASM code.
+     * It delegates to the underlying Method so we don't need to do
+     * all the reflection stuff in our generated bytecode.
+     *
+     * @see #generateDelegationMethod(org.apache.xbean.asm.ClassWriter, java.lang.reflect.Method,
int, Class, String)
+     */
+    @SuppressWarnings("unused")
+    public static Object delegateProtectedMethod(Method method, Object instance, Object[]
params)
+    {
+        try
+        {
+            if (!method.isAccessible())
+            {
+                method.setAccessible(true);
+            }
+            return method.invoke(instance, params);
+        }
+        catch (InvocationTargetException ite)
+        {
+            throw ExceptionUtil.throwAsRuntimeException(ite.getCause());
+        }
+        catch (Exception e)
+        {
+            throw ExceptionUtil.throwAsRuntimeException(e);
+        }
+    }
 
 }

Modified: openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/NormalScopeProxyFactoryTest.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/NormalScopeProxyFactoryTest.java?rev=1445630&r1=1445629&r2=1445630&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/NormalScopeProxyFactoryTest.java
(original)
+++ openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/NormalScopeProxyFactoryTest.java
Wed Feb 13 14:44:55 2013
@@ -78,6 +78,23 @@ public class NormalScopeProxyFactoryTest
     }
 
 
+    /**
+     * Test if protected and package scope methods are proxied as well.
+     * @throws Exception
+     */
+    @Test
+    public void testProtectedMethod() throws Exception
+    {
+        startContainer(ProtectedUsageBean.class);
+
+        ProtectedUsageBean protectedUsage = getInstance(ProtectedUsageBean.class);
+        Assert.assertNotNull(protectedUsage);
+
+        Assert.assertEquals(42, protectedUsage.getPackageMeaningOfLife());
+        Assert.assertEquals(42, protectedUsage.getProtectedMeaningOfLife());
+        Assert.assertEquals(Integer.valueOf(42), protectedUsage.getProtectedIntegerMeaningOfLife());
+    }
+
     public static class TestContextualInstanceProvider<T> implements Provider<T>
     {
         private T instance;

Added: openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/ProtectedUsageBean.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/ProtectedUsageBean.java?rev=1445630&view=auto
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/ProtectedUsageBean.java
(added)
+++ openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/ProtectedUsageBean.java
Wed Feb 13 14:44:55 2013
@@ -0,0 +1,51 @@
+/*
+ * 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.newtests.interceptors.factory;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.RequestScoped;
+
+@RequestScoped
+public class ProtectedUsageBean
+{
+    private int meaningOfLife;
+
+    @PostConstruct
+    private void init()
+    {
+        meaningOfLife = 42;
+    }
+
+    protected int getProtectedMeaningOfLife()
+    {
+        return meaningOfLife;
+    }
+
+    protected Integer getProtectedIntegerMeaningOfLife()
+    {
+        return Integer.valueOf(meaningOfLife);
+    }
+
+    int getPackageMeaningOfLife()
+    {
+        return meaningOfLife;
+    }
+
+
+}



Mime
View raw message