You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by jc...@apache.org on 2008/04/10 03:44:28 UTC

svn commit: r646613 - in /commons/proper/proxy/branches/version-2.0-work/src: main/java/org/apache/commons/proxy/invoker/recorder/InvocationRecorder.java test/java/org/apache/commons/proxy/invoker/recorder/TestInvocationRecorder.java

Author: jcarman
Date: Wed Apr  9 18:44:24 2008
New Revision: 646613

URL: http://svn.apache.org/viewvc?rev=646613&view=rev
Log:
Now supports genericized method recording.

Modified:
    commons/proper/proxy/branches/version-2.0-work/src/main/java/org/apache/commons/proxy/invoker/recorder/InvocationRecorder.java
    commons/proper/proxy/branches/version-2.0-work/src/test/java/org/apache/commons/proxy/invoker/recorder/TestInvocationRecorder.java

Modified: commons/proper/proxy/branches/version-2.0-work/src/main/java/org/apache/commons/proxy/invoker/recorder/InvocationRecorder.java
URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/src/main/java/org/apache/commons/proxy/invoker/recorder/InvocationRecorder.java?rev=646613&r1=646612&r2=646613&view=diff
==============================================================================
--- commons/proper/proxy/branches/version-2.0-work/src/main/java/org/apache/commons/proxy/invoker/recorder/InvocationRecorder.java (original)
+++ commons/proper/proxy/branches/version-2.0-work/src/main/java/org/apache/commons/proxy/invoker/recorder/InvocationRecorder.java Wed Apr  9 18:44:24 2008
@@ -22,6 +22,9 @@
 import org.apache.commons.proxy.ProxyUtils;
 
 import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -45,24 +48,79 @@
 
     public <T> T proxy( Class<T> type )
     {
-        if(proxyFactory.canProxy(type))
+        return proxy(type, type);
+    }
+
+    public <T> T proxy( Type genericType, Class<T> type )
+    {
+        if( proxyFactory.canProxy(type) )
         {
-            return proxyFactory.createInvokerProxy(new InvocationRecorderInvoker(), type);
+            return proxyFactory.createInvokerProxy(new InvocationRecorderInvoker(genericType), type);
         }
         return ProxyUtils.nullValue(type);
     }
 
     private class InvocationRecorderInvoker implements Invoker
     {
+        private final Type targetType;
+
+        private InvocationRecorderInvoker( Type targetType )
+        {
+            this.targetType = targetType;
+        }
+
+        @SuppressWarnings("unchecked")
         public Object invoke( Object o, Method method, Object[] args ) throws Throwable
         {
             recordedInvocations.add(new RecordedInvocation(method, args));
-            return proxy(method.getReturnType());
+            final Class returnType = getReturnType(targetType, method);
+            return proxy(method.getGenericReturnType(), returnType);
         }
     }
 
     public void reset()
     {
         recordedInvocations.clear();
+    }
+
+    public static Class getReturnType( Type enclosingType, Method method ) throws Exception
+    {
+        Type returnType = method.getGenericReturnType();
+        if( returnType instanceof Class )
+        {
+            return ( Class ) returnType;
+        }
+        else if( returnType instanceof TypeVariable )
+        {
+            return resolveVariable(enclosingType, ( TypeVariable ) returnType);
+        }
+        else if( returnType instanceof ParameterizedType )
+        {
+            return ( Class ) ( ( ParameterizedType ) returnType ).getRawType();
+        }
+        return null;
+    }
+
+    public static Class resolveVariable( Type enclosingType, TypeVariable typeVar ) throws Exception
+    {
+        if( enclosingType instanceof ParameterizedType )
+        {
+            ParameterizedType pt = ( ParameterizedType ) enclosingType;
+            final Class rawType = ( Class ) pt.getRawType();
+            TypeVariable[] typeParameters = rawType.getTypeParameters();
+            for( int i = 0; i < typeParameters.length; i++ )
+            {
+                TypeVariable typeParameter = typeParameters[i];
+                if( typeParameter == typeVar )
+                {
+                    return ( Class ) pt.getActualTypeArguments()[i];
+                }
+            }
+        }
+        else if( enclosingType instanceof Class )
+        {
+            return resolveVariable(( ( Class ) enclosingType ).getGenericSuperclass(), typeVar);
+        }
+        return null;
     }
 }

Modified: commons/proper/proxy/branches/version-2.0-work/src/test/java/org/apache/commons/proxy/invoker/recorder/TestInvocationRecorder.java
URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/src/test/java/org/apache/commons/proxy/invoker/recorder/TestInvocationRecorder.java?rev=646613&r1=646612&r2=646613&view=diff
==============================================================================
--- commons/proper/proxy/branches/version-2.0-work/src/test/java/org/apache/commons/proxy/invoker/recorder/TestInvocationRecorder.java (original)
+++ commons/proper/proxy/branches/version-2.0-work/src/test/java/org/apache/commons/proxy/invoker/recorder/TestInvocationRecorder.java Wed Apr  9 18:44:24 2008
@@ -28,7 +28,7 @@
  */
 public class TestInvocationRecorder extends AbstractTestCase
 {
-    public void testRecording() throws Exception
+    public void testNestedMethodRecording() throws Exception
     {
         InvocationRecorder recorder = new InvocationRecorder(new CglibProxyFactory());
         Person personProxy = recorder.proxy(Person.class);
@@ -40,6 +40,25 @@
         assertEquals(0, getAddressInvocation.getArguments().length);
     }
 
+    public void testNestedGenericMethodRecording() throws Exception
+    {
+        InvocationRecorder recorder = new InvocationRecorder(new CglibProxyFactory());
+        Person personProxy = recorder.proxy(Person.class);
+        assertEquals(null, personProxy.getNicknames().get(0));
+        List<RecordedInvocation> recordedInvocations = recorder.getRecordedInvocations();
+
+        assertEquals(2, recordedInvocations.size());
+        
+        RecordedInvocation invocation = recordedInvocations.get(0);
+        assertEquals(Person.class.getMethod("getNicknames"), invocation.getInvokedMethod());
+        assertEquals(0, invocation.getArguments().length);
+
+        invocation = recordedInvocations.get(1);
+        assertEquals(List.class.getMethod("get", int.class), invocation.getInvokedMethod());
+        assertEquals(1, invocation.getArguments().length);
+        assertEquals(0, invocation.getArguments()[0] );
+    }
+
     public void testProxyNonProxyableType()
     {
         InvocationRecorder recorder = new InvocationRecorder(new CglibProxyFactory());
@@ -70,6 +89,8 @@
     public static interface Person
     {
         public Address getAddress();
+
+        public List<String> getNicknames();
     }
 
     public static interface Address