Author: struberg
Date: Tue Jan 1 15:55:12 2013
New Revision: 1427451
URL: http://svn.apache.org/viewvc?rev=1427451&view=rev
Log:
OWB-344 fix InvocationHandler invocation
Added:
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/OwbProxy.java
Modified:
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.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=1427451&r1=1427450&r2=1427451&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 15:55:12 2013
@@ -27,8 +27,8 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
-import org.apache.webbeans.config.WebBeansContext;
import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
@@ -44,7 +44,6 @@ import org.objectweb.asm.Type;
*
* This factory will create and cache the proxy classes for a given type.
*
- *
*/
//X TODO: clarify how serialisation works! The proxy classes might need to get
created on deserialisation!
public class InterceptorDecoratorProxyFactory
@@ -59,11 +58,8 @@ public class InterceptorDecoratorProxyFa
//X TODO add caching of created proxy classes. This is needed to prevent
class loading clashes.
//X a generated proxy cannot easily get redefined later!
- private WebBeansContext webBeansContext;
-
- public InterceptorDecoratorProxyFactory(WebBeansContext webBeansContext)
+ public InterceptorDecoratorProxyFactory()
{
- this.webBeansContext = webBeansContext;
}
public <T> T createProxyInstance(Class<T> proxyClass, T instance,
InvocationHandler interceptorDecoratorStack)
@@ -129,7 +125,7 @@ public class InterceptorDecoratorProxyFa
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
String classFileName = classToProxy.getName().replace('.', '/');
- String[] interfaceNames = new String[]{}; //X TODO there might be some
more in the future
+ String[] interfaceNames = new
String[]{Type.getInternalName(OwbProxy.class)};
cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER +
Opcodes.ACC_SYNTHETIC, proxyClassFileName, null, classFileName, interfaceNames);
cw.visitSource(classFileName + ".java", null);
@@ -141,12 +137,12 @@ public class InterceptorDecoratorProxyFa
if (nonInterceptedMethods != null)
{
- delegateNonInterceptedMethods(cw, proxyClassFileName,
classToProxy, classFileName, nonInterceptedMethods);
+ delegateNonInterceptedMethods(cw, proxyClassFileName,
classToProxy, nonInterceptedMethods);
}
if (interceptedMethods != null)
{
- delegateInterceptedMethods(cw, proxyClassFileName, classToProxy,
classFileName, interceptedMethods);
+ delegateInterceptedMethods(cw, proxyClassFileName, classToProxy,
interceptedMethods);
}
return cw.toByteArray();
@@ -208,13 +204,10 @@ public class InterceptorDecoratorProxyFa
*
* @param noninterceptedMethods all methods which are neither intercepted
nor decorated
*/
- private void delegateNonInterceptedMethods(ClassWriter cw, String
proxyClassFileName, Class<?> classToProxy, String classFileName,
- List<Method>
noninterceptedMethods)
+ private void delegateNonInterceptedMethods(ClassWriter cw, String
proxyClassFileName, Class<?> classToProxy, List<Method> noninterceptedMethods)
{
for (Method delegatedMethod : noninterceptedMethods)
{
- int modifiers = delegatedMethod.getModifiers();
-
if (unproxyableMethod(delegatedMethod))
{
continue;
@@ -269,16 +262,281 @@ public class InterceptorDecoratorProxyFa
"finalize".equals(delegatedMethod.getName());
}
- private void delegateInterceptedMethods(ClassWriter cw, String
proxyClassFileName, Class<?> classToProxy, String classFileName,
- List<Method> interceptedMethods)
+ private void delegateInterceptedMethods(ClassWriter cw, String
proxyClassFileName, Class<?> classToProxy, List<Method> interceptedMethods)
+ throws ProxyGenerationException
{
for (Method proxiedMethod : interceptedMethods)
{
+ generateInvocationHandlerMethod(cw, proxiedMethod,
proxyClassFileName);
+ }
+ }
+
+ private void generateInvocationHandlerMethod(ClassWriter cw, Method
method, String proxyName)
+ throws ProxyGenerationException
+ {
+ if ("<init>".equals(method.getName()))
+ {
+ return;
+ }
+
+ 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 = modifiers & (Opcodes.ACC_PUBLIC |
Opcodes.ACC_PROTECTED);
+
+ MethodVisitor mv = cw.visitMethod(modifier, method.getName(),
Type.getMethodDescriptor(method), null, null);
+ mv.visitCode();
+
+ // push try/catch block, to catch declared exceptions, and to catch
java.lang.Throwable
+ 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");
+ }
+
+ // push try code
+ mv.visitLabel(l0);
+ 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> });
+
+ // get the method name to invoke, and push to stack
+ mv.visitLdcInsn(method.getName());
+
+ // create the Class[]
+ createArrayDefinition(mv, parameterTypes.length, Class.class);
+
+ int length = 1;
+
+ // push parameters into array
+ for (int i = 0; i < parameterTypes.length; i++)
+ {
+ // keep copy of array on stack
+ mv.visitInsn(Opcodes.DUP);
+
+ final Class<?> parameterType = parameterTypes[i];
+
+ // push number onto stack
+ pushIntOntoStack(mv, i);
+
+ if (parameterType.isPrimitive())
+ {
+ String wrapperType = getWrapperType(parameterType);
+ mv.visitFieldInsn(Opcodes.GETSTATIC, wrapperType, "TYPE",
"Ljava/lang/Class;");
+ }
+ else
+ {
+ mv.visitLdcInsn(Type.getType(parameterType));
+ }
+
+ mv.visitInsn(Opcodes.AASTORE);
+
+ if (Long.TYPE.equals(parameterType) ||
Double.TYPE.equals(parameterType))
+ {
+ length += 2;
+ }
+ else
+ {
+ length++;
+ }
+ }
+
+ // invoke getMethod() with the method name and the array of types
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class",
"getDeclaredMethod",
+
"(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;");
+
+ // store the returned method for later
+ mv.visitVarInsn(Opcodes.ASTORE, length);
+
+ // the following code generates bytecode equivalent to:
+ // return ((<returntype>) invocationHandler.invoke(this, method, new
Object[] { <function arguments }))[.<primitive>Value()];
+
+ final Label l4 = new Label();
+ mv.visitLabel(l4);
+ mv.visitVarInsn(Opcodes.ALOAD, 0);
+
+ // get the invocationHandler field from this class
+ mv.visitFieldInsn(Opcodes.GETFIELD, proxyName,
FIELD_INVOCATION_HANDLER, "Ljava/lang/reflect/InvocationHandler;");
+
+ // we want to pass "this" in as the first parameter
+ mv.visitVarInsn(Opcodes.ALOAD, 0);
+
+ // and the method we fetched earlier
+ mv.visitVarInsn(Opcodes.ALOAD, length);
+
+ // need to construct the array of objects passed in
+
+ // create the Object[]
+ createArrayDefinition(mv, parameterTypes.length, Object.class);
+
+ int index = 1;
+ // push parameters into array
+ for (int i = 0; i < parameterTypes.length; i++)
+ {
+ // keep copy of array on stack
+ mv.visitInsn(Opcodes.DUP);
+
+ final Class<?> parameterType = parameterTypes[i];
+
+ // push number onto stack
+ pushIntOntoStack(mv, i);
+
+ if (parameterType.isPrimitive())
+ {
+ String wrapperType = getWrapperType(parameterType);
+ mv.visitVarInsn(getVarInsn(parameterType), index);
+
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, wrapperType,
"valueOf",
+ "(" + Type.getDescriptor(parameterType) + ")L" +
wrapperType + ";");
+ mv.visitInsn(Opcodes.AASTORE);
+
+ if (Long.TYPE.equals(parameterType) ||
Double.TYPE.equals(parameterType))
+ {
+ index += 2;
+ }
+ else
+ {
+ index++;
+ }
+ }
+ else
+ {
+ mv.visitVarInsn(Opcodes.ALOAD, index);
+ mv.visitInsn(Opcodes.AASTORE);
+ index++;
+ }
+ }
+
+ // invoke the invocationHandler
+ mv.visitMethodInsn(Opcodes.INVOKEINTERFACE,
"java/lang/reflect/InvocationHandler", "invoke",
+
"(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;");
+
+ // cast the result
+ mv.visitTypeInsn(Opcodes.CHECKCAST, getCastType(returnType));
+
+ if (returnType.isPrimitive() && (!Void.TYPE.equals(returnType)))
+ {
+ // get the primitive value
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
getWrapperType(returnType), getPrimitiveMethod(returnType),
+ "()" + Type.getDescriptor(returnType));
+ }
+
+ // push return
+ mv.visitLabel(l1);
+ if (!Void.TYPE.equals(returnType))
+ {
+ mv.visitInsn(getReturnInsn(returnType));
+ }
+ else
+ {
+ mv.visitInsn(Opcodes.POP);
+ mv.visitInsn(Opcodes.RETURN);
+ }
+
+ // catch InvocationTargetException
+ if (exceptionTypes.length > 0)
+ {
+ mv.visitLabel(l2);
+ mv.visitVarInsn(Opcodes.ASTORE, length);
+
+ final Label l5 = new Label();
+ mv.visitLabel(l5);
+
+ for (int i = 0; i < exceptionTypes.length; i++)
+ {
+ final Class<?> exceptionType = exceptionTypes[i];
+
+ mv.visitLdcInsn(Type.getType("L" +
exceptionType.getCanonicalName().replace('.', '/') + ";"));
+ mv.visitVarInsn(Opcodes.ALOAD, length);
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
"java/lang/reflect/InvocationTargetException", "getCause",
+ "()Ljava/lang/Throwable;");
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object",
"getClass", "()Ljava/lang/Class;");
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object",
"equals", "(Ljava/lang/Object;)Z");
+
+ final Label l6 = new Label();
+ mv.visitJumpInsn(Opcodes.IFEQ, l6);
+
+ final Label l7 = new Label();
+ mv.visitLabel(l7);
+
+ mv.visitVarInsn(Opcodes.ALOAD, length);
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
"java/lang/reflect/InvocationTargetException", "getCause",
+ "()Ljava/lang/Throwable;");
+ mv.visitTypeInsn(Opcodes.CHECKCAST,
exceptionType.getCanonicalName().replace('.', '/'));
+ mv.visitInsn(Opcodes.ATHROW);
+ mv.visitLabel(l6);
+
+ if (i == (exceptionTypes.length - 1))
+ {
+ mv.visitTypeInsn(Opcodes.NEW,
"java/lang/reflect/UndeclaredThrowableException");
+ mv.visitInsn(Opcodes.DUP);
+ mv.visitVarInsn(Opcodes.ALOAD, length);
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL,
"java/lang/reflect/UndeclaredThrowableException", "<init>",
+ "(Ljava/lang/Throwable;)V");
+ mv.visitInsn(Opcodes.ATHROW);
+ }
+ }
+ }
+
+ // finish this method
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+ }
+ /**
+ * Returns the name of the Java method to call to get the primitive value
from an Object - e.g. intValue for java.lang.Integer
+ *
+ * @param type Type whose primitive method we want to lookup
+ * @return The name of the method to use
+ */
+ private String getPrimitiveMethod(final Class<?> type)
+ {
+ if (Integer.TYPE.equals(type))
+ {
+ return "intValue";
+ }
+ else if (Boolean.TYPE.equals(type))
+ {
+ return "booleanValue";
+ }
+ else if (Character.TYPE.equals(type))
+ {
+ return "charValue";
}
+ else if (Byte.TYPE.equals(type))
+ {
+ return "byteValue";
+ }
+ else if (Short.TYPE.equals(type))
+ {
+ return "shortValue";
+ }
+ else if (Float.TYPE.equals(type))
+ {
+ return "floatValue";
+ }
+ else if (Long.TYPE.equals(type))
+ {
+ return "longValue";
+ }
+ else if (Double.TYPE.equals(type))
+ {
+ return "doubleValue";
+ }
+
+ throw new IllegalStateException("Type: " + type.getCanonicalName() + "
is not a primitive type");
}
+
private void generateReturn(MethodVisitor mv, Method delegatedMethod)
{
final Class<?> returnType = delegatedMethod.getReturnType();
@@ -286,6 +544,165 @@ public class InterceptorDecoratorProxyFa
}
/**
+ * pushes an array of the specified size to the method visitor. The
generated bytecode will leave
+ * the new array at the top of the stack.
+ *
+ * @param mv MethodVisitor to use
+ * @param size Size of the array to create
+ * @param type Type of array to create
+ * @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)
+ {
+ throw new ProxyGenerationException("Array size cannot be less than
zero");
+ }
+
+ pushIntOntoStack(mv, size);
+
+ mv.visitTypeInsn(Opcodes.ANEWARRAY,
type.getCanonicalName().replace('.', '/'));
+ }
+
+ /**
+ * @return the wrapper type for a primitive, e.g. java.lang.Integer for int
+ */
+ private String getWrapperType(final Class<?> type)
+ {
+ if (Integer.TYPE.equals(type))
+ {
+ return Integer.class.getCanonicalName().replace('.', '/');
+ }
+ else if (Boolean.TYPE.equals(type))
+ {
+ return Boolean.class.getCanonicalName().replace('.', '/');
+ }
+ else if (Character.TYPE.equals(type))
+ {
+ return Character.class.getCanonicalName().replace('.', '/');
+ }
+ else if (Byte.TYPE.equals(type))
+ {
+ return Byte.class.getCanonicalName().replace('.', '/');
+ }
+ else if (Short.TYPE.equals(type))
+ {
+ return Short.class.getCanonicalName().replace('.', '/');
+ }
+ else if (Float.TYPE.equals(type))
+ {
+ return Float.class.getCanonicalName().replace('.', '/');
+ }
+ else if (Long.TYPE.equals(type))
+ {
+ return Long.class.getCanonicalName().replace('.', '/');
+ }
+ else if (Double.TYPE.equals(type))
+ {
+ return Double.class.getCanonicalName().replace('.', '/');
+ }
+ else if (Void.TYPE.equals(type))
+ {
+ return Void.class.getCanonicalName().replace('.', '/');
+ }
+
+ throw new IllegalStateException("Type: " + type.getCanonicalName() + "
is not a primitive type");
+ }
+
+ /**
+ * Returns the appropriate bytecode instruction to load a value from a
variable to the stack
+ *
+ * @param type Type to load
+ * @return Bytecode instruction to use
+ */
+ private int getVarInsn(final Class<?> type)
+ {
+ if (type.isPrimitive())
+ {
+ if (Integer.TYPE.equals(type))
+ {
+ return Opcodes.ILOAD;
+ }
+ else if (Boolean.TYPE.equals(type))
+ {
+ return Opcodes.ILOAD;
+ }
+ else if (Character.TYPE.equals(type))
+ {
+ return Opcodes.ILOAD;
+ }
+ else if (Byte.TYPE.equals(type))
+ {
+ return Opcodes.ILOAD;
+ }
+ else if (Short.TYPE.equals(type))
+ {
+ return Opcodes.ILOAD;
+ }
+ else if (Float.TYPE.equals(type))
+ {
+ return Opcodes.FLOAD;
+ }
+ else if (Long.TYPE.equals(type))
+ {
+ return Opcodes.LLOAD;
+ }
+ else if (Double.TYPE.equals(type))
+ {
+ return Opcodes.DLOAD;
+ }
+ }
+
+ throw new IllegalStateException("Type: " + type.getCanonicalName() + "
is not a primitive type");
+ }
+
+ /**
+ * Invokes the most appropriate bytecode instruction to put a number on
the stack
+ *
+ * @param mv
+ * @param i
+ */
+ private void pushIntOntoStack(final MethodVisitor mv, final int i)
+ {
+ if (i == 0)
+ {
+ mv.visitInsn(Opcodes.ICONST_0);
+ }
+ else if (i == 1)
+ {
+ mv.visitInsn(Opcodes.ICONST_1);
+ }
+ else if (i == 2)
+ {
+ mv.visitInsn(Opcodes.ICONST_2);
+ }
+ else if (i == 3)
+ {
+ mv.visitInsn(Opcodes.ICONST_3);
+ }
+ else if (i == 4)
+ {
+ mv.visitInsn(Opcodes.ICONST_4);
+ }
+ else if (i == 5)
+ {
+ mv.visitInsn(Opcodes.ICONST_5);
+ }
+ else if (i > 5 && i <= 255)
+ {
+ mv.visitIntInsn(Opcodes.BIPUSH, i);
+ }
+ else
+ {
+ mv.visitIntInsn(Opcodes.SIPUSH, i);
+ }
+ }
+
+
+ /**
* Gets the appropriate bytecode instruction for RETURN, according to what
type we need to return
*
* @param type Type the needs to be returned
@@ -337,6 +754,24 @@ public class InterceptorDecoratorProxyFa
}
/**
+ * Gets the string to use for CHECKCAST instruction, returning the correct
value for any type, including primitives and arrays
+ *
+ * @param returnType The type to cast to with CHECKCAST
+ * @return CHECKCAST parameter
+ */
+ private String getCastType(final Class<?> returnType)
+ {
+ if (returnType.isPrimitive())
+ {
+ return getWrapperType(returnType);
+ }
+ else
+ {
+ return Type.getInternalName(returnType);
+ }
+ }
+
+ /**
* The 'defineClass' method on the ClassLoader is protected, thus we need
to invoke it via reflection.
* @return the Class which got loaded in the classloader
*/
Added:
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/OwbProxy.java
URL:
http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/OwbProxy.java?rev=1427451&view=auto
==============================================================================
---
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/OwbProxy.java
(added)
+++
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/OwbProxy.java
Tue Jan 1 15:55:12 2013
@@ -0,0 +1,26 @@
+/*
+ * 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.webbeans.proxy;
+
+/**
+ * Marker Interface for all OpenWebBeans Proxies.
+ */
+public interface OwbProxy
+{
+}
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=1427451&r1=1427450&r2=1427451&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 15:55:12 2013
@@ -19,17 +19,18 @@
package org.apache.webbeans.newtests.interceptors.factory;
import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
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;
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.proxy.OwbProxy;
import org.apache.webbeans.util.ClassUtil;
import org.junit.Assert;
import org.junit.Test;
@@ -44,41 +45,31 @@ public class InterceptorDecoratorProxyFa
@Test
public void textSimpleProxyCreation() throws Exception
{
+/*X not needed so far
Collection<Class<?>> beanClasses = new ArrayList<Class<?>>();
startContainer(beanClasses, null);
+*/
- InterceptorDecoratorProxyFactory pf = new
InterceptorDecoratorProxyFactory(getWebBeansContext());
+ InterceptorDecoratorProxyFactory pf = new
InterceptorDecoratorProxyFactory();
// 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);
+ List<Method> interceptedMethods = methods;
+ List<Method> nonInterceptedMethods = 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());
- }
- }
-*/
+ Class<ClassInterceptedClass> proxyClass =
pf.createProxyClass(classLoader, ClassInterceptedClass.class,
interceptedMethods, nonInterceptedMethods);
+ Assert.assertNotNull(proxyClass);
ClassInterceptedClass internalInstance = new ClassInterceptedClass();
internalInstance.init();
- ClassInterceptedClass proxy = pf.createProxyInstance(proxyClass,
internalInstance, null);
+ TestInvocationHandler testInvocationHandler = new
TestInvocationHandler(internalInstance);
+
+ ClassInterceptedClass proxy = pf.createProxyInstance(proxyClass,
internalInstance, testInvocationHandler);
Assert.assertNotNull(proxy);
// we need to get the field from the proxy via reflection
@@ -86,10 +77,11 @@ public class InterceptorDecoratorProxyFa
Field field =
proxy.getClass().getSuperclass().getDeclaredField("defaultCtInvoked");
Assert.assertNotNull(field);
field.setAccessible(true);
-
Boolean isDefaultCtInvoked = (Boolean) field.get(proxy);
Assert.assertTrue(isDefaultCtInvoked);
+ Assert.assertTrue(proxy instanceof OwbProxy);
+
proxy.setMeaningOfLife(42);
Assert.assertEquals(42, proxy.getMeaningOfLife());
@@ -97,6 +89,28 @@ public class InterceptorDecoratorProxyFa
Assert.assertEquals('c', proxy.getChar());
Assert.assertEquals(internalInstance, proxy.getSelf());
- shutDownContainer();
+ //X shutDownContainer();
+ }
+
+ public static class TestInvocationHandler implements InvocationHandler
+ {
+ public List<String> invokedMethodNames = new ArrayList<String>();
+
+ private final Object instance;
+
+ public TestInvocationHandler(Object instance)
+ {
+ this.instance = instance;
+ }
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
+ {
+ invokedMethodNames.add(method.getName());
+
+ System.out.println("TestInvocationHandler got properly invoked for
method " + method.getName());
+
+ return method.invoke(instance, args);
+ }
}
}