Author: dblevins
Date: Fri Aug 10 07:15:53 2012
New Revision: 1371584
URL: http://svn.apache.org/viewvc?rev=1371584&view=rev
Log:
Small refactoring and code cleanup
OPENEJB-1885 Simply EJB Proxy Code
Modified:
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/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=1371584&r1=1371583&r2=1371584&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
Fri Aug 10 07:15:53 2012
@@ -17,7 +17,6 @@
package org.apache.openejb.util.proxy;
import org.apache.xbean.asm.ClassWriter;
-import org.apache.xbean.asm.FieldVisitor;
import org.apache.xbean.asm.Label;
import org.apache.xbean.asm.MethodVisitor;
import org.apache.xbean.asm.Opcodes;
@@ -45,102 +44,17 @@ public class LocalBeanProxyGeneratorImpl
static final String BUSSINESS_HANDLER_NAME = "businessHandler";
static final String NON_BUSINESS_HANDLER_NAME = "nonBusinessHandler";
- // 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;
+ public Object constructProxy(final Class clazz, final
java.lang.reflect.InvocationHandler handler) throws IllegalStateException {
+ final Object instance = Unsafe.allocateInstance(clazz);
- static {
- final Class<?> unsafeClass;
- try {
- unsafeClass = AccessController.doPrivileged(new
PrivilegedAction<Class<?>>() {
- public Class<?> run() {
- try {
- return
Thread.currentThread().getContextClassLoader().loadClass("sun.misc.Unsafe");
- } catch (Exception e) {
- try {
- return
ClassLoader.getSystemClassLoader().loadClass("sun.misc.Unsafe");
- } catch (ClassNotFoundException e1) {
- throw new IllegalStateException("Cannot get
sun.misc.Unsafe", e);
- }
- }
- }
- });
- } catch (Exception e) {
- throw new IllegalStateException("Cannot get sun.misc.Unsafe
class", e);
- }
-
- unsafe = AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- try {
- Field field = unsafeClass.getDeclaredField("theUnsafe");
- field.setAccessible(true);
- return field.get(null);
- } catch (Exception e) {
- throw new IllegalStateException("Cannot get
sun.misc.Unsafe", e);
- }
- }
- });
- 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 {
- Method mtd = unsafeClass.getDeclaredMethod("defineClass",
String.class, byte[].class, int.class, int.class, ClassLoader.class,
ProtectionDomain.class);
- mtd.setAccessible(true);
- return mtd;
- } catch (Exception e) {
- throw new IllegalStateException("Cannot get
sun.misc.Unsafe.defineClass", e);
- }
- }
- });
- }
-
- 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);
+ Unsafe.setValue(getDeclaredField(clazz, BUSSINESS_HANDLER_NAME),
instance, handler);
+ Unsafe.setValue(getDeclaredField(clazz, NON_BUSINESS_HANDLER_NAME),
instance, NON_BUSINESS_HANDLER);
return instance;
}
- private Field getDeclaredField(Class clazz, final String fieldName) {
+ private static Field getDeclaredField(final Class clazz, final String
fieldName) {
try {
return clazz.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
@@ -149,52 +63,24 @@ public class LocalBeanProxyGeneratorImpl
}
}
- 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());
+ public Class createProxy(final Class<?> clsToProxy, final ClassLoader cl) {
+ final String proxyName = generateProxyName(clsToProxy.getName());
return createProxy(clsToProxy, proxyName, cl);
}
- private static String generateProxyName(String clsName) {
+ private static String generateProxyName(final String clsName) {
return clsName + "$LocalBeanProxy";
}
- public static boolean isLocalBean(Class<?> clazz) {
+ public static boolean isLocalBean(final Class<?> clazz) {
if (clazz.getSuperclass() == null) {
return false;
}
return
clazz.getName().equals(LocalBeanProxyGeneratorImpl.generateProxyName(clazz.getSuperclass().getName()));
}
- private Class createProxy(Class<?> clsToProxy, String proxyName,
ClassLoader cl) {
- String clsName = proxyName.replaceAll("\\.", "/");
+ private Class createProxy(final Class<?> clsToProxy, final String
proxyName, final ClassLoader cl) {
+ final String clsName = proxyName.replace('.', '/');
try {
return cl.loadClass(proxyName);
@@ -208,47 +94,45 @@ public class LocalBeanProxyGeneratorImpl
}
try {
- byte[] proxyBytes = generateProxy(clsToProxy, clsName);
- return (Class<?>) defineClass.invoke(unsafe, proxyName,
proxyBytes, 0, proxyBytes.length, clsToProxy.getClassLoader(),
clsToProxy.getProtectionDomain());
+ final byte[] proxyBytes = generateProxy(clsToProxy, clsName);
+ return Unsafe.defineClass(clsToProxy, proxyName, proxyBytes);
} catch (Exception e) {
throw new InternalError(e.toString());
}
}
}
- private byte[] generateProxy(Class<?> clsToProxy, String proxyName) throws
ProxyGenerationException {
- ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
- FieldVisitor fv;
- MethodVisitor mv;
+ private byte[] generateProxy(final Class<?> classToProxy, final String
proxyName) throws ProxyGenerationException {
+ final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
- String clsToOverride = clsToProxy.getName().replaceAll("\\.", "/");
- String proxyClassName = proxyName.replaceAll("\\.", "/");
+ final String proxyClassFileName = proxyName.replace('.', '/');
+ final String classFileName = classToProxy.getName().replace('.', '/');
// push class signature
- cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, proxyClassName, null,
clsToOverride, SERIALIZABLE);
- cw.visitSource(clsToOverride + ".java", null);
+ cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, proxyClassFileName, null,
classFileName, SERIALIZABLE);
+ cw.visitSource(classFileName + ".java", null);
// push InvocationHandler fields
- fv = cw.visitField(ACC_FINAL + ACC_PRIVATE, BUSSINESS_HANDLER_NAME,
"Ljava/lang/reflect/InvocationHandler;", null, null);
- fv.visitEnd();
- fv = cw.visitField(ACC_FINAL + ACC_PRIVATE, NON_BUSINESS_HANDLER_NAME,
"Ljava/lang/reflect/InvocationHandler;", null, null);
- fv.visitEnd();
-
- Map<String, List<Method>> methodMap = getNonPrivateMethods(new
Class[]{clsToProxy});
-
- for (Map.Entry<String, List<Method>> entry : methodMap.entrySet()) {
- for (Method method : entry.getValue()) {
- String name = method.getName();
- int modifiers = method.getModifiers();
- if (Modifier.isPublic(modifiers) ||
- (method.getParameterTypes().length == 0 &&
- ("finalize".equals(name) ||
"clone".equals(name)))) {
+ cw.visitField(ACC_FINAL + ACC_PRIVATE, BUSSINESS_HANDLER_NAME,
"Ljava/lang/reflect/InvocationHandler;", null, null).visitEnd();
+ cw.visitField(ACC_FINAL + ACC_PRIVATE, NON_BUSINESS_HANDLER_NAME,
"Ljava/lang/reflect/InvocationHandler;", null, null).visitEnd();
+
+ final Map<String, List<Method>> methodMap =
getNonPrivateMethods(classToProxy);
+
+ // Iterate over the public methods
+ for (final Map.Entry<String, List<Method>> entry :
methodMap.entrySet()) {
+
+ for (final Method method : entry.getValue()) {
+ final String name = method.getName();
+
+ if (Modifier.isPublic(method.getModifiers())
+ || (method.getParameterTypes().length == 0 &&
("finalize".equals(name)
+ || "clone".equals(name)))) {
// forward invocations of any public methods or
// finalize/clone methods to businessHandler
- processMethod(cw, method, proxyClassName,
BUSSINESS_HANDLER_NAME);
+ processMethod(cw, method, proxyClassFileName,
BUSSINESS_HANDLER_NAME);
} else {
// forward invocations of any other methods to
nonBusinessHandler
- processMethod(cw, method, proxyClassName,
NON_BUSINESS_HANDLER_NAME);
+ processMethod(cw, method, proxyClassFileName,
NON_BUSINESS_HANDLER_NAME);
}
}
}
@@ -261,44 +145,42 @@ public class LocalBeanProxyGeneratorImpl
* that are not final or static. The returned map includes the inherited
methods
* and ensures that overridden methods are included once.
*/
- private Map<String, List<Method>> getNonPrivateMethods(Class<?>[] classes)
{
- Map<String, List<Method>> methodMap = new HashMap<String,
List<Method>>();
+ private Map<String, List<Method>> getNonPrivateMethods(Class<?> clazz) {
+ final Map<String, List<Method>> methodMap = new HashMap<String,
List<Method>>();
- for (int i = 0; i < classes.length; i++) {
- Class<?> clazz = classes[i];
-
- while (clazz != null) {
- for (Method method : clazz.getDeclaredMethods()) {
- int modifiers = method.getModifiers();
- if (Modifier.isFinal(modifiers) ||
- Modifier.isPrivate(modifiers) ||
- Modifier.isStatic(modifiers)) {
- continue;
- }
-
- List<Method> methods = methodMap.get(method.getName());
- if (methods == null) {
- methods = new ArrayList<Method>();
- methods.add(method);
- methodMap.put(method.getName(), methods);
+ while (clazz != null) {
+ for (Method method : clazz.getDeclaredMethods()) {
+ final int modifiers = method.getModifiers();
+
+ if (Modifier.isFinal(modifiers)
+ || Modifier.isPrivate(modifiers)
+ || Modifier.isStatic(modifiers)) {
+ continue;
+ }
+
+ List<Method> methods = methodMap.get(method.getName());
+ if (methods == null) {
+ methods = new ArrayList<Method>();
+ methods.add(method);
+ methodMap.put(method.getName(), methods);
+ } else {
+ if (isOverridden(methods, method)) {
+ // method is overridden in superclass, so do nothing
} else {
- if (isOverridden(methods, method)) {
- // method is overridden in superclass, so do
nothing
- } else {
- // method is not overridden, so add it
- methods.add(method);
- }
+ // method is not overridden, so add it
+ methods.add(method);
}
}
-
- clazz = clazz.getSuperclass();
}
+
+ clazz = clazz.getSuperclass();
}
+
return methodMap;
}
- private boolean isOverridden(List<Method> methods, Method method) {
- for (Method m : methods) {
+ private boolean isOverridden(final List<Method> methods, final Method
method) {
+ for (final Method m : methods) {
if (Arrays.equals(m.getParameterTypes(),
method.getParameterTypes())) {
return true;
}
@@ -306,15 +188,15 @@ public class LocalBeanProxyGeneratorImpl
return false;
}
- private void processMethod(ClassWriter cw, Method method, String
proxyName, String handlerName) throws ProxyGenerationException {
+ private void processMethod(final ClassWriter cw, final Method method,
final String proxyName, final String handlerName) throws
ProxyGenerationException {
if ("<init>".equals(method.getName())) {
return;
}
- Class<?> returnType = method.getReturnType();
- Class<?>[] parameterTypes = method.getParameterTypes();
- Class<?>[] exceptionTypes = method.getExceptionTypes();
- int modifiers = method.getModifiers();
+ 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 = 0;
@@ -323,25 +205,23 @@ public class LocalBeanProxyGeneratorImpl
} else if (Modifier.isProtected(modifiers)) {
modifier = ACC_PROTECTED;
}
- MethodVisitor mv = cw.visitMethod(modifier, method.getName(),
getMethodSignatureAsString(returnType, parameterTypes), null, null);
+
+ final MethodVisitor mv = cw.visitMethod(modifier, method.getName(),
getMethodSignatureAsString(returnType, parameterTypes), null, null);
mv.visitCode();
// push try/catch block, to catch declared exceptions, and to catch
java.lang.Throwable
- Label l0 = new Label();
- Label l1 = new Label();
- Label l2 = new Label();
- Label l3 = new Label();
+ 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");
}
-// mv.visitTryCatchBlock(l0, l1, l3, "java/lang/Throwable");
-
// push try code
mv.visitLabel(l0);
- String clsToOverride =
method.getDeclaringClass().getName().replaceAll("\\.", "/");
- mv.visitLdcInsn(Type.getType("L" + clsToOverride + ";"));
+ 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> });
@@ -359,7 +239,7 @@ public class LocalBeanProxyGeneratorImpl
// keep copy of array on stack
mv.visitInsn(DUP);
- Class<?> parameterType = parameterTypes[i];
+ final Class<?> parameterType = parameterTypes[i];
// push number onto stack
pushIntOntoStack(mv, i);
@@ -389,7 +269,7 @@ public class LocalBeanProxyGeneratorImpl
// the following code generates bytecode equivalent to:
// return ((<returntype>) invocationHandler.invoke(this, method, new
Object[] { <function arguments }))[.<primitive>Value()];
- Label l4 = new Label();
+ final Label l4 = new Label();
mv.visitLabel(l4);
mv.visitVarInsn(ALOAD, 0);
@@ -413,7 +293,7 @@ public class LocalBeanProxyGeneratorImpl
// keep copy of array on stack
mv.visitInsn(DUP);
- Class<?> parameterType = parameterTypes[i];
+ final Class<?> parameterType = parameterTypes[i];
// push number onto stack
pushIntOntoStack(mv, i);
@@ -461,24 +341,28 @@ public class LocalBeanProxyGeneratorImpl
if (exceptionTypes.length > 0) {
mv.visitLabel(l2);
mv.visitVarInsn(ASTORE, length);
- Label l5 = new Label();
+
+ final Label l5 = new Label();
mv.visitLabel(l5);
for (int i = 0; i < exceptionTypes.length; i++) {
- Class<?> exceptionType = exceptionTypes[i];
+ final Class<?> exceptionType = exceptionTypes[i];
- mv.visitLdcInsn(Type.getType("L" +
exceptionType.getCanonicalName().replaceAll("\\.", "/") + ";"));
+ mv.visitLdcInsn(Type.getType("L" +
exceptionType.getCanonicalName().replace('.', '/') + ";"));
mv.visitVarInsn(ALOAD, length);
mv.visitMethodInsn(INVOKEVIRTUAL,
"java/lang/reflect/InvocationTargetException", "getCause",
"()Ljava/lang/Throwable;");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object",
"getClass", "()Ljava/lang/Class;");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object",
"equals", "(Ljava/lang/Object;)Z");
- Label l6 = new Label();
+
+ final Label l6 = new Label();
mv.visitJumpInsn(IFEQ, l6);
- Label l7 = new Label();
+
+ final Label l7 = new Label();
mv.visitLabel(l7);
+
mv.visitVarInsn(ALOAD, length);
mv.visitMethodInsn(INVOKEVIRTUAL,
"java/lang/reflect/InvocationTargetException", "getCause",
"()Ljava/lang/Throwable;");
- mv.visitTypeInsn(CHECKCAST,
exceptionType.getCanonicalName().replaceAll("\\.", "/"));
+ mv.visitTypeInsn(CHECKCAST,
exceptionType.getCanonicalName().replace('.', '/'));
mv.visitInsn(ATHROW);
mv.visitLabel(l6);
@@ -502,7 +386,7 @@ public class LocalBeanProxyGeneratorImpl
* @param type Type the needs to be returned
* @return The matching bytecode instruction
*/
- private int getReturnInsn(Class<?> type) {
+ private int getReturnInsn(final Class<?> type) {
if (type.isPrimitive()) {
if (Integer.TYPE.equals(type)) {
return IRETURN;
@@ -532,7 +416,7 @@ public class LocalBeanProxyGeneratorImpl
* @param type Type to load
* @return Bytecode instruction to use
*/
- private int getVarInsn(Class<?> type) {
+ private int getVarInsn(final Class<?> type) {
if (type.isPrimitive()) {
if (Integer.TYPE.equals(type)) {
return ILOAD;
@@ -561,7 +445,7 @@ public class LocalBeanProxyGeneratorImpl
* @param type Type whose primitive method we want to lookup
* @return The name of the method to use
*/
- private String getPrimitiveMethod(Class<?> type) {
+ private String getPrimitiveMethod(final Class<?> type) {
if (Integer.TYPE.equals(type)) {
return "intValue";
} else if (Boolean.TYPE.equals(type)) {
@@ -588,7 +472,7 @@ public class LocalBeanProxyGeneratorImpl
* @param returnType The type to cast to with CHECKCAST
* @return CHECKCAST parameter
*/
- String getCastType(Class<?> returnType) {
+ String getCastType(final Class<?> returnType) {
if (returnType.isPrimitive()) {
return getWrapperType(returnType);
} else {
@@ -601,25 +485,25 @@ public class LocalBeanProxyGeneratorImpl
* @param type
* @return
*/
- private String getWrapperType(Class<?> type) {
+ private String getWrapperType(final Class<?> type) {
if (Integer.TYPE.equals(type)) {
- return Integer.class.getCanonicalName().replaceAll("\\.", "/");
+ return Integer.class.getCanonicalName().replace('.', '/');
} else if (Boolean.TYPE.equals(type)) {
- return Boolean.class.getCanonicalName().replaceAll("\\.", "/");
+ return Boolean.class.getCanonicalName().replace('.', '/');
} else if (Character.TYPE.equals(type)) {
- return Character.class.getCanonicalName().replaceAll("\\.", "/");
+ return Character.class.getCanonicalName().replace('.', '/');
} else if (Byte.TYPE.equals(type)) {
- return Byte.class.getCanonicalName().replaceAll("\\.", "/");
+ return Byte.class.getCanonicalName().replace('.', '/');
} else if (Short.TYPE.equals(type)) {
- return Short.class.getCanonicalName().replaceAll("\\.", "/");
+ return Short.class.getCanonicalName().replace('.', '/');
} else if (Float.TYPE.equals(type)) {
- return Float.class.getCanonicalName().replaceAll("\\.", "/");
+ return Float.class.getCanonicalName().replace('.', '/');
} else if (Long.TYPE.equals(type)) {
- return Long.class.getCanonicalName().replaceAll("\\.", "/");
+ return Long.class.getCanonicalName().replace('.', '/');
} else if (Double.TYPE.equals(type)) {
- return Double.class.getCanonicalName().replaceAll("\\.", "/");
+ return Double.class.getCanonicalName().replace('.', '/');
} else if (Void.TYPE.equals(type)) {
- return Void.class.getCanonicalName().replaceAll("\\.", "/");
+ return Void.class.getCanonicalName().replace('.', '/');
}
throw new IllegalStateException("Type: " + type.getCanonicalName() + "
is not a primitive type");
@@ -630,7 +514,7 @@ public class LocalBeanProxyGeneratorImpl
* @param mv
* @param i
*/
- private void pushIntOntoStack(MethodVisitor mv, int i) {
+ private void pushIntOntoStack(final MethodVisitor mv, final int i) {
if (i == 0) {
mv.visitInsn(ICONST_0);
} else if (i == 1) {
@@ -659,7 +543,7 @@ public class LocalBeanProxyGeneratorImpl
* @param type Type of array to create
* @throws ProxyGenerationException
*/
- private void createArrayDefinition(MethodVisitor mv, int size, Class<?>
type) 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) {
@@ -668,12 +552,12 @@ public class LocalBeanProxyGeneratorImpl
pushIntOntoStack(mv, size);
- mv.visitTypeInsn(ANEWARRAY, type.getCanonicalName().replaceAll("\\.",
"/"));
+ mv.visitTypeInsn(ANEWARRAY, type.getCanonicalName().replace('.', '/'));
}
- String getMethodSignatureAsString(Class<?> returnType, Class<?>[]
parameterTypes) {
- StringBuilder builder = new StringBuilder();
+ String getMethodSignatureAsString(final Class<?> returnType, final
Class<?>[] parameterTypes) {
+ final StringBuilder builder = new StringBuilder();
builder.append("(");
for (Class<?> parameterType : parameterTypes) {
builder.append(getAsmTypeAsString(parameterType, true));
@@ -690,7 +574,7 @@ public class LocalBeanProxyGeneratorImpl
* @param type
* @return
*/
- private String getPrimitiveLetter(Class<?> type) {
+ private String getPrimitiveLetter(final Class<?> type) {
if (Integer.TYPE.equals(type)) {
return "I";
} else if (Void.TYPE.equals(type)) {
@@ -720,38 +604,158 @@ public class LocalBeanProxyGeneratorImpl
* @param wrap True if a non-array object should be wrapped with L and ; -
e.g. Ljava/lang/Integer;
* @return String to use for ASM
*/
- public String getAsmTypeAsString(Class<?> parameterType, boolean wrap) {
+ public String getAsmTypeAsString(final Class<?> parameterType, final
boolean wrap) {
if (parameterType.isArray()) {
if (parameterType.getComponentType().isPrimitive()) {
- Class<?> componentType = parameterType.getComponentType();
+ final Class<?> componentType =
parameterType.getComponentType();
return "[" + getPrimitiveLetter(componentType);
} else {
return "[" +
getAsmTypeAsString(parameterType.getComponentType(), true);
}
} else {
- if (!parameterType.isPrimitive()) {
- String clsName = parameterType.getCanonicalName();
+ if (parameterType.isPrimitive()) {
+ return getPrimitiveLetter(parameterType);
+ } else {
+ String className = parameterType.getCanonicalName();
if (parameterType.isMemberClass()) {
- int lastDot = clsName.lastIndexOf(".");
- clsName = clsName.substring(0, lastDot) + "$" +
clsName.substring(lastDot + 1);
+ int lastDot = className.lastIndexOf(".");
+ className = className.substring(0, lastDot) + "$" +
className.substring(lastDot + 1);
}
+
if (wrap) {
- return "L" + clsName.replaceAll("\\.", "/") + ";";
+ return "L" + className.replace('.', '/') + ";";
} else {
- return clsName.replaceAll("\\.", "/");
+ return className.replace('.', '/');
}
- } else {
- return getPrimitiveLetter(parameterType);
}
}
}
static class NonBusinessHandler implements
java.lang.reflect.InvocationHandler, Serializable {
- public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
+ public Object invoke(final Object proxy, final Method method, final
Object[] args) throws Throwable {
throw new EJBException("Calling non-public methods of a local bean
without any interfaces is not allowed");
}
}
+
+ /**
+ * The methods of this class model sun.misc.Unsafe which is used
reflectively
+ */
+ private static class Unsafe {
+
+ // 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;
+ try {
+ unsafeClass = AccessController.doPrivileged(new
PrivilegedAction<Class<?>>() {
+ public Class<?> run() {
+ try {
+ return
Thread.currentThread().getContextClassLoader().loadClass("sun.misc.Unsafe");
+ } catch (Exception e) {
+ try {
+ return
ClassLoader.getSystemClassLoader().loadClass("sun.misc.Unsafe");
+ } catch (ClassNotFoundException e1) {
+ throw new IllegalStateException("Cannot get
sun.misc.Unsafe", e);
+ }
+ }
+ }
+ });
+ } catch (Exception e) {
+ throw new IllegalStateException("Cannot get sun.misc.Unsafe
class", e);
+ }
+
+ unsafe = AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ try {
+ Field field = unsafeClass.getDeclaredField("theUnsafe");
+ field.setAccessible(true);
+ return field.get(null);
+ } catch (Exception e) {
+ throw new IllegalStateException("Cannot get
sun.misc.Unsafe", e);
+ }
+ }
+ });
+ 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 {
+ Method mtd = unsafeClass.getDeclaredMethod("defineClass",
String.class, byte[].class, int.class, int.class, ClassLoader.class,
ProtectionDomain.class);
+ mtd.setAccessible(true);
+ return mtd;
+ } catch (Exception e) {
+ throw new IllegalStateException("Cannot get
sun.misc.Unsafe.defineClass", e);
+ }
+ }
+ });
+ }
+ private static Object allocateInstance(final Class clazz) {
+ try {
+ return 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);
+ }
+ }
+
+ private static void setValue(final Field field, final Object object,
final Object value) {
+ final 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);
+ }
+ }
+
+ private static Class defineClass(Class<?> clsToProxy, String
proxyName, byte[] proxyBytes) throws IllegalAccessException,
InvocationTargetException {
+ return (Class<?>) defineClass.invoke(unsafe, proxyName,
proxyBytes, 0, proxyBytes.length, clsToProxy.getClassLoader(),
clsToProxy.getProtectionDomain());
+ }
+ }
}