Author: struberg
Date: Mon Dec 31 19:58:18 2012
New Revision: 1427235
URL: http://svn.apache.org/viewvc?rev=1427235&view=rev
Log:
OWB-344 move method resolving out of the proxy creation
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
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=1427235&r1=1427234&r2=1427235&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
Mon Dec 31 19:58:18 2012
@@ -24,12 +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.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import org.apache.webbeans.config.WebBeansContext;
import org.objectweb.asm.ClassWriter;
@@ -143,12 +138,7 @@ public class InterceptorDecoratorProxyFa
createConstructor(cw, proxyClassFileName, classToProxy, classFileName);
- //X TODO filter out clone() and handle it seperately?
- Map<String, List<Method>> methodMap =
getNonPrivateMethods(classToProxy);
-
- //X TODO select all non-intercepted and non-decorated methods
-
- delegateNonInterceptedMethods(cw, proxyClassFileName, classToProxy,
classFileName, methodMap);
+ delegateNonInterceptedMethods(cw, proxyClassFileName, classToProxy,
classFileName, nonInterceptedMethods);
@@ -210,126 +200,52 @@ public class InterceptorDecoratorProxyFa
}
}
-
/**
- * @deprecated move this method to some other place. The proxy should get
the list of methods from outside.
- * Otherwise we would drag in business logic into the purely
technical interceptor code.
+ * Directly delegate all non intercepted nor decorated methods to the
internal instance.
+ *
+ * @param noninterceptedMethods all methods which are neither intercepted
nor decorated
*/
- private Map<String, List<Method>> getNonPrivateMethods(Class<?> clazz)
+ private static void delegateNonInterceptedMethods(ClassWriter cw, String
proxyClassFileName, Class<?> classToProxy, String classFileName,
+ List<Method>
noninterceptedMethods)
{
- Map<String, List<Method>> methodMap = new HashMap<String,
List<Method>>();
-
- while (clazz != null)
+ for (Method proxiedMethod : noninterceptedMethods)
{
- for (Method method : clazz.getDeclaredMethods())
- {
- final int modifiers = method.getModifiers();
+ String methodDescriptor = Type.getMethodDescriptor(proxiedMethod);
- if (Modifier.isFinal(modifiers) ||
Modifier.isPrivate(modifiers) ||
- Modifier.isStatic(modifiers) ||
Modifier.isAbstract(modifiers) ||
- Modifier.isNative(modifiers)) //X TODO deal with proxying
native methods (clone) later
- {
- continue;
- }
-
- if ("finalize".equals(method.getName()))
- {
- // we do not proxy finalize()
- 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
- {
- // method is not overridden, so add it
- methods.add(method);
- }
- }
+ //X TODO handle generic exception types?
+ Class[] exceptionTypes = proxiedMethod.getExceptionTypes();
+ String[] exceptionTypeNames = new String[exceptionTypes.length];
+ for (int i = 0; i < exceptionTypes.length; i++)
+ {
+ exceptionTypeNames[i] =
Type.getType(exceptionTypes[i]).getInternalName();
}
- clazz = clazz.getSuperclass();
- }
+ MethodVisitor mv = cw.visitMethod(proxiedMethod.getModifiers(),
proxiedMethod.getName(), methodDescriptor, null, exceptionTypeNames);
- return methodMap;
- }
+ // fill method body
+ mv.visitCode();
- /**
- * @deprecated see explanation in {@link #getNonPrivateMethods(Class)}
- */
- private boolean isOverridden(final List<Method> methods, final Method
method)
- {
- for (final Method m : methods)
- {
- if (Arrays.equals(m.getParameterTypes(),
method.getParameterTypes()))
- {
- return true;
- }
- }
- return false;
- }
+ // load the delegate variable
+ mv.visitVarInsn(Opcodes.ALOAD, 0);
+ mv.visitFieldInsn(Opcodes.GETFIELD, proxyClassFileName,
FIELD_PROXIED_INSTANCE, Type.getDescriptor(classToProxy));
- /**
- * Directly delegate all non intercepted nor decorated methods to the
internal instance.
- *
- * @param noninterceptedMethods all methods which are neither intercepted
nor decorated
- */
- private static void delegateNonInterceptedMethods(ClassWriter cw, String
proxyClassFileName, Class<?> classToProxy, String classFileName,
- Map<String,
List<Method>> noninterceptedMethods)
- {
- for (List<Method> methodsPerName : noninterceptedMethods.values())
- {
- for (Method proxiedMethod : methodsPerName)
+ int offset = 1;
+ for (Class<?> aClass : proxiedMethod.getParameterTypes())
{
- String methodDescriptor =
Type.getMethodDescriptor(proxiedMethod);
-
- //X TODO handle generic exception types?
- Class[] exceptionTypes = proxiedMethod.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);
-
- // fill method body
- mv.visitCode();
-
- // load the delegate variable
- mv.visitVarInsn(Opcodes.ALOAD, 0);
- mv.visitFieldInsn(Opcodes.GETFIELD, proxyClassFileName,
FIELD_PROXIED_INSTANCE, Type.getDescriptor(classToProxy));
-
- int offset = 1;
- for (Class<?> aClass : proxiedMethod.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 type = Type.getType(aClass);
+ mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), offset);
+ offset += type.getSize();
+ }
- final Type returnType =
Type.getType(proxiedMethod.getReturnType());
- mv.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
+ final Type declaringClass =
Type.getType(proxiedMethod.getDeclaringClass());
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
declaringClass.getInternalName(), proxiedMethod.getName(), methodDescriptor);
- mv.visitMaxs(-1, -1);
+ final Type returnType =
Type.getType(proxiedMethod.getReturnType());
+ mv.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
- mv.visitEnd();
+ mv.visitMaxs(-1, -1);
- }
+ mv.visitEnd();
}
}
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=1427235&r1=1427234&r2=1427235&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
Mon Dec 31 19:58:18 2012
@@ -253,6 +253,83 @@ public final class ClassUtil
}
private static volatile Set<String> objectMethodNames= null;
+ /**
+ * collect all non-private, non-static and non-abstract methods from the
given class.
+ * This method removes any overloaded methods from the list automatically.
+ *
+ * The returned Map contains the methods divided by the methodName as key
in the map
+ * following all the methods with the same methodName in a List.
+ *
+ * Note: we filter out the {@link Object#finalize()} method as users must
not deal with it
+ */
+ public static List<Method> getNonPrivateMethods(Class<?> clazz)
+ {
+ Map<String, List<Method>> methodMap = new HashMap<String,
List<Method>>();
+ List<Method> allMethods = new ArrayList<Method>(10);
+
+ while (clazz != null)
+ {
+ for (Method method : clazz.getDeclaredMethods())
+ {
+ final int modifiers = method.getModifiers();
+
+ if (Modifier.isFinal(modifiers) ||
Modifier.isPrivate(modifiers) ||
+ Modifier.isStatic(modifiers) ||
Modifier.isAbstract(modifiers))
+ {
+ continue;
+ }
+
+ if ("finalize".equals(method.getName()))
+ {
+ // we do not proxy finalize()
+ 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
+ {
+ // method is not overridden, so add it
+ methods.add(method);
+ allMethods.add(method);
+ }
+ }
+ }
+
+ clazz = clazz.getSuperclass();
+ }
+
+ return allMethods;
+ }
+
+ /**
+ * Check if the method is already defined in a subclass
+ * @param methods
+ * @param method
+ */
+ private static boolean isOverridden(final List<Method> methods, final
Method method)
+ {
+ for (final Method m : methods)
+ {
+ if (Arrays.equals(m.getParameterTypes(),
method.getParameterTypes()))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* Checks if the given method if from Object.class
@@ -1148,7 +1225,7 @@ public final class ClassUtil
}
/**
- * Learn whether <code>superClassMethod</code> is overridden by
<code>subClassMethod</code>.
+ * Check whether <code>superClassMethod</code> is overridden by
<code>subClassMethod</code>.
* @param subClassMethod potentially overriding
* @param superClassMethod potentially overridden
* @return true if overridden
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=1427235&r1=1427234&r2=1427235&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
Mon Dec 31 19:58:18 2012
@@ -19,13 +19,16 @@
package org.apache.webbeans.newtests.interceptors.factory;
import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.List;
import org.apache.webbeans.newtests.AbstractUnitTest;
import
org.apache.webbeans.newtests.interceptors.factory.beans.ClassInterceptedClass;
import org.apache.webbeans.proxy.InterceptorDecoratorProxyFactory;
+import org.apache.webbeans.util.ClassUtil;
import org.junit.Assert;
import org.junit.Test;
@@ -46,7 +49,9 @@ public class InterceptorDecoratorProxyFa
ClassLoader classLoader = this.getClass().getClassLoader();
- Class<ClassInterceptedClass> proxyClass =
pf.createProxyClass(classLoader, ClassInterceptedClass.class, null, null);
+ 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);