Author: dblevins
Date: Mon Aug  6 04:40:11 2012
New Revision: 1369720

URL: http://svn.apache.org/viewvc?rev=1369720&view=rev
Log:
Reworked OPENEJB-1882 so that constructors are not called when creating 
@LocalBean proxies

Added:
    
openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/ThisInConstructorTest.java
   (contents, props changed)
      - copied, changed from r1367883, 
openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/ThisInConstructorTest.java
Modified:
    
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/LocalBeanProxyFactory.java
    
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/LocalBeanProxyGeneratorImpl.java

Modified: 
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/LocalBeanProxyFactory.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/LocalBeanProxyFactory.java?rev=1369720&r1=1369719&r2=1369720&view=diff
==============================================================================
--- 
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/LocalBeanProxyFactory.java
 (original)
+++ 
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/LocalBeanProxyFactory.java
 Mon Aug  6 04:40:11 2012
@@ -16,32 +16,24 @@
  */
 package org.apache.openejb.util.proxy;
 
-import javax.ejb.EJBException;
-import java.io.Serializable;
+import org.apache.openejb.util.Debug;
+
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 
 public class LocalBeanProxyFactory {
 
-    private static final java.lang.reflect.InvocationHandler 
NON_BUSINESS_HANDLER = new NonBusinessHandler();
-
     public static Object newProxyInstance(ClassLoader cl, Class interfce, 
java.lang.reflect.InvocationHandler h) throws IllegalArgumentException {
         try {
-            final Class proxyCls = new 
LocalBeanProxyGeneratorImpl().createProxy(interfce, cl);
-            final Constructor constructor = 
proxyCls.getConstructor(java.lang.reflect.InvocationHandler.class,
-                    java.lang.reflect.InvocationHandler.class);
-            final Object object = constructor.newInstance(h, 
NON_BUSINESS_HANDLER);
+            final LocalBeanProxyGeneratorImpl generator = new 
LocalBeanProxyGeneratorImpl();
+
+            final Class proxyClass = generator.createProxy(interfce, cl);
+            final Object object = generator.constructProxy(proxyClass, h);
+
             return object;
-        } catch (NoSuchMethodException e) {
-            throw new InternalError(e.toString());
-        } catch (InstantiationException e) {
-            throw new InternalError(e.toString());
-        } catch (IllegalAccessException e) {
-            throw new InternalError(e.toString());
-        } catch (InvocationTargetException e) {
-            throw new InternalError(e.toString());
+        } catch (Throwable e) {
+            throw new InternalError(Debug.printStackTrace(e));
         }
     }
 
@@ -61,11 +53,4 @@ public class LocalBeanProxyFactory {
         }
     }
 
-    private static class NonBusinessHandler implements 
java.lang.reflect.InvocationHandler, Serializable {
-
-        public Object invoke(Object proxy, Method method, Object[] args) 
throws Throwable {
-            throw new EJBException("Calling non-public methods of a local bean 
without any interfaces is not allowed");
-        }
-
-    }
 }

Modified: 
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/LocalBeanProxyGeneratorImpl.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/LocalBeanProxyGeneratorImpl.java?rev=1369720&r1=1369719&r2=1369720&view=diff
==============================================================================
--- 
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/LocalBeanProxyGeneratorImpl.java
 (original)
+++ 
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/LocalBeanProxyGeneratorImpl.java
 Mon Aug  6 04:40:11 2012
@@ -16,8 +16,11 @@
  */
 package org.apache.openejb.util.proxy;
 
+import java.io.File;
+import java.io.IOException;
 import java.io.Serializable;
 import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.security.AccessController;
@@ -29,6 +32,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.openejb.loader.IO;
 import org.apache.xbean.asm.ClassWriter;
 import org.apache.xbean.asm.FieldVisitor;
 import org.apache.xbean.asm.Label;
@@ -36,8 +40,11 @@ import org.apache.xbean.asm.MethodVisito
 import org.apache.xbean.asm.Opcodes;
 import org.apache.xbean.asm.Type;
 
+import javax.ejb.EJBException;
+
 public class LocalBeanProxyGeneratorImpl implements LocalBeanProxyGenerator, 
Opcodes {
     private static final String[] SERIALIZABLE = new String[] { 
Serializable.class.getName().replace('.', '/') };
+    public static final java.lang.reflect.InvocationHandler 
NON_BUSINESS_HANDLER = new NonBusinessHandler();
 
     static final String BUSSINESS_HANDLER_NAME = "businessHandler";    
     static final String NON_BUSINESS_HANDLER_NAME = "nonBusinessHandler";
@@ -45,6 +52,10 @@ public class LocalBeanProxyGeneratorImpl
     // sun.misc.Unsafe
     private static final Object unsafe;
     private static final Method defineClass;
+    private static final Method allocateInstance;
+    private static final Method putObject;
+    private static final Method objectFieldOffset;
+
 
     static {
         final Class<?> unsafeClass;
@@ -77,6 +88,39 @@ public class LocalBeanProxyGeneratorImpl
                 }
             }
         });
+        allocateInstance = AccessController.doPrivileged(new 
PrivilegedAction<Method>() {
+            public Method run() {
+                try {
+                    Method mtd = 
unsafeClass.getDeclaredMethod("allocateInstance", Class.class);
+                    mtd.setAccessible(true);
+                    return mtd;
+                } catch (Exception e) {
+                    throw new IllegalStateException("Cannot get 
sun.misc.Unsafe.allocateInstance", e);
+                }
+            }
+        });
+        objectFieldOffset = AccessController.doPrivileged(new 
PrivilegedAction<Method>() {
+            public Method run() {
+                try {
+                    Method mtd = 
unsafeClass.getDeclaredMethod("objectFieldOffset", Field.class);
+                    mtd.setAccessible(true);
+                    return mtd;
+                } catch (Exception e) {
+                    throw new IllegalStateException("Cannot get 
sun.misc.Unsafe.objectFieldOffset", e);
+                }
+            }
+        });
+        putObject = AccessController.doPrivileged(new 
PrivilegedAction<Method>() {
+            public Method run() {
+                try {
+                    Method mtd = unsafeClass.getDeclaredMethod("putObject", 
Object.class, long.class, Object.class);
+                    mtd.setAccessible(true);
+                    return mtd;
+                } catch (Exception e) {
+                    throw new IllegalStateException("Cannot get 
sun.misc.Unsafe.putObject", e);
+                }
+            }
+        });
         defineClass = AccessController.doPrivileged(new 
PrivilegedAction<Method>() {
             public Method run() {
                 try {
@@ -90,6 +134,53 @@ public class LocalBeanProxyGeneratorImpl
         });
     }
 
+    public Object constructProxy(Class clazz, 
java.lang.reflect.InvocationHandler handler) throws IllegalStateException {
+
+        final Object instance = allocateInstance(clazz);
+
+        setValue(getDeclaredField(clazz, BUSSINESS_HANDLER_NAME), instance, 
handler);
+        setValue(getDeclaredField(clazz, NON_BUSINESS_HANDLER_NAME), instance, 
NON_BUSINESS_HANDLER);
+
+        return instance;
+    }
+
+    private Field getDeclaredField(Class clazz, final String fieldName) {
+        try {
+            return clazz.getDeclaredField(fieldName);
+        } catch (NoSuchFieldException e) {
+            final String message = String.format("Proxy class does not contain 
expected field \"%s\": %s", fieldName, clazz.getName());
+            throw new IllegalStateException(message, e);
+        }
+    }
+
+    private Object allocateInstance(Class clazz) {
+        final Object instance;
+        try {
+            instance = allocateInstance.invoke(unsafe, clazz);
+        } catch (IllegalAccessException e) {
+            throw new IllegalStateException("Failed to allocateInstance of 
Proxy class " + clazz.getName(), e);
+        } catch (InvocationTargetException e) {
+            Throwable throwable = e.getTargetException() != null ? 
e.getTargetException() : e;
+            throw new IllegalStateException("Failed to allocateInstance of 
Proxy class " + clazz.getName(), throwable);
+        }
+        return instance;
+    }
+
+    private void setValue(Field field, Object object, Object value) {
+        long offset;
+        try {
+            offset = (Long) objectFieldOffset.invoke(unsafe, field);
+        } catch (Exception e) {
+            throw new IllegalStateException("Failed getting offset for: 
field=" + field.getName() + "  class=" + field.getDeclaringClass().getName(), 
e);
+        }
+
+        try {
+            putObject.invoke(unsafe, object, offset, value);
+        } catch (Exception e) {
+            throw new IllegalStateException("Failed putting field=" + 
field.getName() + "  class=" + field.getDeclaringClass().getName(), e);
+        }
+    }
+
     public Class createProxy(Class<?> clsToProxy, ClassLoader cl) {
         String proxyName = generateProxyName(clsToProxy.getName());
         return createProxy(clsToProxy, proxyName, cl);
@@ -147,32 +238,6 @@ public class LocalBeanProxyGeneratorImpl
                fv = cw.visitField(ACC_FINAL + ACC_PRIVATE, 
NON_BUSINESS_HANDLER_NAME, "Ljava/lang/reflect/InvocationHandler;", null, null);
                fv.visitEnd();
                
-               // push single argument constructor
-               mv = cw.visitMethod(ACC_PUBLIC, "<init>", 
"(Ljava/lang/reflect/InvocationHandler;)V", null, null);
-               mv.visitCode();
-               mv.visitVarInsn(ALOAD, 0);
-               mv.visitVarInsn(ALOAD, 1);
-               mv.visitVarInsn(ALOAD, 1);
-               mv.visitMethodInsn(INVOKESPECIAL, proxyName, "<init>", 
"(Ljava/lang/reflect/InvocationHandler;Ljava/lang/reflect/InvocationHandler;)V");
-               mv.visitInsn(RETURN);
-               mv.visitMaxs(0, 0);
-               mv.visitEnd();
-
-               // push double argument constructor
-               mv = cw.visitMethod(ACC_PUBLIC, "<init>", 
"(Ljava/lang/reflect/InvocationHandler;Ljava/lang/reflect/InvocationHandler;)V",
 null, null);
-               mv.visitCode();
-               mv.visitVarInsn(ALOAD, 0);
-               mv.visitMethodInsn(INVOKESPECIAL, clsToOverride, "<init>", 
"()V");
-               mv.visitVarInsn(ALOAD, 0);
-               mv.visitVarInsn(ALOAD, 1);
-               mv.visitFieldInsn(PUTFIELD, proxyName, BUSSINESS_HANDLER_NAME, 
"Ljava/lang/reflect/InvocationHandler;");
-               mv.visitVarInsn(ALOAD, 0);
-               mv.visitVarInsn(ALOAD, 2);
-               mv.visitFieldInsn(PUTFIELD, proxyName, 
NON_BUSINESS_HANDLER_NAME, "Ljava/lang/reflect/InvocationHandler;");
-               mv.visitInsn(RETURN);
-               mv.visitMaxs(0, 0);
-               mv.visitEnd();
-
                Map<String, List<Method>> methodMap = getNonPrivateMethods(new 
Class[] { clsToProxy });
 
                for (Map.Entry<String, List<Method>> entry : 
methodMap.entrySet()) {
@@ -193,7 +258,12 @@ public class LocalBeanProxyGeneratorImpl
                }
                
                byte[] clsBytes = cw.toByteArray();
-               return clsBytes;
+        try {
+            IO.copy(clsBytes, new File("/tmp/foo.class"));
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return clsBytes;
        }
 
        /*
@@ -687,4 +757,11 @@ public class LocalBeanProxyGeneratorImpl
                }
        }
 
+    static class NonBusinessHandler implements 
java.lang.reflect.InvocationHandler, Serializable {
+
+        public Object invoke(Object proxy, Method method, Object[] args) 
throws Throwable {
+            throw new EJBException("Calling non-public methods of a local bean 
without any interfaces is not allowed");
+        }
+
+    }
 }

Copied: 
openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/ThisInConstructorTest.java
 (from r1367883, 
openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/ThisInConstructorTest.java)
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/ThisInConstructorTest.java?p2=openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/ThisInConstructorTest.java&p1=openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/ThisInConstructorTest.java&r1=1367883&r2=1369720&rev=1369720&view=diff
==============================================================================
--- 
openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/ThisInConstructorTest.java
 (original)
+++ 
openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/ThisInConstructorTest.java
 Mon Aug  6 04:40:11 2012
@@ -1,3 +1,19 @@
+/**
+ * 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.openejb.core.stateless;
 
 import org.apache.openejb.jee.Empty;

Propchange: 
openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/ThisInConstructorTest.java
------------------------------------------------------------------------------
--- svn:mergeinfo (added)
+++ svn:mergeinfo Mon Aug  6 04:40:11 2012
@@ -0,0 +1,6 @@
+/openejb/branches/generated-descriptors/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/ThisInConstructorTest.java:1239492,1239514,1239610,1239615
+/openejb/branches/openejb-3.1.1/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/ThisInConstructorTest.java:779593
+/openejb/branches/openejb-3.1.x/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/ThisInConstructorTest.java:945409,945448,1004381,1005322,1021880,1021903,1021955,1021961,1021965,1021975,1021979,1021990,1022375,1022393,1023096,1023116,1023125,1026527,1027696,1027724,1027739,1027754,1032856,1032866,1034030,1040222,1040250
+/openejb/branches/openejb-4.0.0/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/ThisInConstructorTest.java:1326901
+/openejb/branches/openejb-4.0.0-beta-2/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/ThisInConstructorTest.java:1227467
+/openejb/branches/openejb-jcdi/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/ThisInConstructorTest.java:984659-985270


Reply via email to