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