Author: struberg
Date: Tue Jan 1 06:10:27 2013
New Revision: 1427310
URL: http://svn.apache.org/viewvc?rev=1427310&view=rev
Log:
OWB-344 improve return value handling
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
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/beans/ClassInterceptedClass.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=1427310&r1=1427309&r2=1427310&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
Tue Jan 1 06:10:27 2013
@@ -24,6 +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.List;
import org.apache.webbeans.config.WebBeansContext;
@@ -138,13 +139,15 @@ public class InterceptorDecoratorProxyFa
createConstructor(cw, proxyClassFileName, classToProxy, classFileName);
- delegateNonInterceptedMethods(cw, proxyClassFileName, classToProxy,
classFileName, nonInterceptedMethods);
-
-
-
- //X TODO invoke all
+ if (nonInterceptedMethods != null)
+ {
+ delegateNonInterceptedMethods(cw, proxyClassFileName,
classToProxy, classFileName, nonInterceptedMethods);
+ }
- //X TODO continue;
+ if (interceptedMethods != null)
+ {
+ delegateInterceptedMethods(cw, proxyClassFileName, classToProxy,
classFileName, interceptedMethods);
+ }
return cw.toByteArray();
}
@@ -205,22 +208,31 @@ public class InterceptorDecoratorProxyFa
*
* @param noninterceptedMethods all methods which are neither intercepted
nor decorated
*/
- private static void delegateNonInterceptedMethods(ClassWriter cw, String
proxyClassFileName, Class<?> classToProxy, String classFileName,
- List<Method>
noninterceptedMethods)
+ private void delegateNonInterceptedMethods(ClassWriter cw, String
proxyClassFileName, Class<?> classToProxy, String classFileName,
+ List<Method>
noninterceptedMethods)
{
- for (Method proxiedMethod : noninterceptedMethods)
+ for (Method delegatedMethod : noninterceptedMethods)
{
- String methodDescriptor = Type.getMethodDescriptor(proxiedMethod);
+ int modifiers = delegatedMethod.getModifiers();
+
+ if (unproxyableMethod(delegatedMethod))
+ {
+ continue;
+ }
+
+ String methodDescriptor =
Type.getMethodDescriptor(delegatedMethod);
//X TODO handle generic exception types?
- Class[] exceptionTypes = proxiedMethod.getExceptionTypes();
+ Class[] exceptionTypes = delegatedMethod.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);
+ int targetModifiers = delegatedMethod.getModifiers() &
(Modifier.PROTECTED | Modifier.PUBLIC);
+
+ MethodVisitor mv = cw.visitMethod(targetModifiers,
delegatedMethod.getName(), methodDescriptor, null, exceptionTypeNames);
// fill method body
mv.visitCode();
@@ -230,18 +242,17 @@ public class InterceptorDecoratorProxyFa
mv.visitFieldInsn(Opcodes.GETFIELD, proxyClassFileName,
FIELD_PROXIED_INSTANCE, Type.getDescriptor(classToProxy));
int offset = 1;
- for (Class<?> aClass : proxiedMethod.getParameterTypes())
+ for (Class<?> aClass : delegatedMethod.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 declaringClass =
Type.getType(delegatedMethod.getDeclaringClass());
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
declaringClass.getInternalName(), delegatedMethod.getName(), methodDescriptor);
- final Type returnType =
Type.getType(proxiedMethod.getReturnType());
- mv.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
+ generateReturn(mv, delegatedMethod);
mv.visitMaxs(-1, -1);
@@ -249,6 +260,81 @@ public class InterceptorDecoratorProxyFa
}
}
+ private boolean unproxyableMethod(Method delegatedMethod)
+ {
+ int modifiers = delegatedMethod.getModifiers();
+
+ //X TODO how to deal with native functions?
+ return (modifiers & (Modifier.PRIVATE | Modifier.ABSTRACT |
Modifier.STATIC | Modifier.FINAL | Modifier.NATIVE)) > 0 ||
+ "finalize".equals(delegatedMethod.getName());
+ }
+
+ private void delegateInterceptedMethods(ClassWriter cw, String
proxyClassFileName, Class<?> classToProxy, String classFileName,
+ List<Method> interceptedMethods)
+ {
+ for (Method proxiedMethod : interceptedMethods)
+ {
+
+ }
+ }
+
+
+ private void generateReturn(MethodVisitor mv, Method delegatedMethod)
+ {
+ final Class<?> returnType = delegatedMethod.getReturnType();
+ mv.visitInsn(getReturnInsn(returnType));
+ }
+
+ /**
+ * Gets the appropriate bytecode instruction for RETURN, according to what
type we need to return
+ *
+ * @param type Type the needs to be returned
+ * @return The matching bytecode instruction
+ */
+ private int getReturnInsn(final Class<?> type)
+ {
+ if (type.isPrimitive())
+ {
+ if (Void.TYPE.equals(type))
+ {
+ return Opcodes.RETURN;
+ }
+ if (Integer.TYPE.equals(type))
+ {
+ return Opcodes.IRETURN;
+ }
+ else if (Boolean.TYPE.equals(type))
+ {
+ return Opcodes.IRETURN;
+ }
+ else if (Character.TYPE.equals(type))
+ {
+ return Opcodes.IRETURN;
+ }
+ else if (Byte.TYPE.equals(type))
+ {
+ return Opcodes.IRETURN;
+ }
+ else if (Short.TYPE.equals(type))
+ {
+ return Opcodes.IRETURN;
+ }
+ else if (Float.TYPE.equals(type))
+ {
+ return Opcodes.FRETURN;
+ }
+ else if (Long.TYPE.equals(type))
+ {
+ return Opcodes.LRETURN;
+ }
+ else if (Double.TYPE.equals(type))
+ {
+ return Opcodes.DRETURN;
+ }
+ }
+
+ return Opcodes.ARETURN;
+ }
/**
* The 'defineClass' method on the ClassLoader is protected, thus we need
to invoke it via reflection.
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=1427310&r1=1427309&r2=1427310&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
Tue Jan 1 06:10:27 2013
@@ -290,6 +290,7 @@ public final class ClassUtil
{
methods = new ArrayList<Method>();
methods.add(method);
+ allMethods.add(method);
methodMap.put(method.getName(), methods);
}
else
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=1427310&r1=1427309&r2=1427310&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
Tue Jan 1 06:10:27 2013
@@ -20,6 +20,8 @@ package org.apache.webbeans.newtests.int
import java.lang.reflect.Field;
import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -47,14 +49,36 @@ public class InterceptorDecoratorProxyFa
InterceptorDecoratorProxyFactory pf = new
InterceptorDecoratorProxyFactory(getWebBeansContext());
- ClassLoader classLoader = this.getClass().getClassLoader();
+ // we take a fresh URLClassLoader to not blur the test classpath with
synthetic classes.
+ ClassLoader classLoader = new URLClassLoader(new URL[0]);
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);
+/*X
+ for (Method m : methods)
+ {
+ List<Method> ms = new ArrayList<Method>();
+ ms.add(m);
+
+ try
+ {
+ Class<ClassInterceptedClass> pc = pf.createProxyClass(cl,
ClassInterceptedClass.class, null, ms);
+ Assert.assertNotNull(pc);
+ }
+ catch (Exception e)
+ {
+ System.out.println("hab die sau :) " + m.toString());
+ }
+ }
+*/
+
+ ClassInterceptedClass internalInstance = new ClassInterceptedClass();
+ internalInstance.init();
+
+ ClassInterceptedClass proxy = pf.createProxyInstance(proxyClass,
internalInstance, null);
Assert.assertNotNull(proxy);
// we need to get the field from the proxy via reflection
@@ -69,7 +93,9 @@ public class InterceptorDecoratorProxyFa
proxy.setMeaningOfLife(42);
Assert.assertEquals(42, proxy.getMeaningOfLife());
-
+ Assert.assertEquals(internalInstance.getFloat(), proxy.getFloat(), 0f);
+ Assert.assertEquals('c', proxy.getChar());
+ Assert.assertEquals(internalInstance, proxy.getSelf());
shutDownContainer();
}
Modified:
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/beans/ClassInterceptedClass.java
URL:
http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/beans/ClassInterceptedClass.java?rev=1427310&r1=1427309&r2=1427310&view=diff
==============================================================================
---
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/beans/ClassInterceptedClass.java
(original)
+++
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/beans/ClassInterceptedClass.java
Tue Jan 1 06:10:27 2013
@@ -29,12 +29,20 @@ public class ClassInterceptedClass
private boolean defaultCtInvoked = false;
private int meaningOfLife;
+ private float f;
+ private char c;
public ClassInterceptedClass()
{
defaultCtInvoked = true;
}
+ public void init()
+ {
+ f = 2.4f;
+ c = 'c';
+ }
+
public int getMeaningOfLife()
{
System.out.println("answering the question about life, the universe
and everything!");
@@ -47,4 +55,19 @@ public class ClassInterceptedClass
this.meaningOfLife = meaningOfLife;
}
+ public float getFloat()
+ {
+ return f;
+ }
+
+ public ClassInterceptedClass getSelf()
+ {
+ return this;
+ }
+
+ public char getChar()
+ {
+ return c;
+ }
+
}