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 2007/09/28 18:07:09 UTC

svn commit: r580396 - in /commons/sandbox/proxy/trunk/src: main/java/org/apache/commons/proxy/invoker/DuckTypingInvoker.java site/xdoc/index.xml test/java/org/apache/commons/proxy/invoker/TestDuckTypingInvoker.java

Author: jcarman
Date: Fri Sep 28 09:07:06 2007
New Revision: 580396

URL: http://svn.apache.org/viewvc?rev=580396&view=rev
Log:
SANDBOX-198: Duck Typing Invoker

Added:
    commons/sandbox/proxy/trunk/src/main/java/org/apache/commons/proxy/invoker/DuckTypingInvoker.java
    commons/sandbox/proxy/trunk/src/test/java/org/apache/commons/proxy/invoker/TestDuckTypingInvoker.java
Modified:
    commons/sandbox/proxy/trunk/src/site/xdoc/index.xml

Added: commons/sandbox/proxy/trunk/src/main/java/org/apache/commons/proxy/invoker/DuckTypingInvoker.java
URL: http://svn.apache.org/viewvc/commons/sandbox/proxy/trunk/src/main/java/org/apache/commons/proxy/invoker/DuckTypingInvoker.java?rev=580396&view=auto
==============================================================================
--- commons/sandbox/proxy/trunk/src/main/java/org/apache/commons/proxy/invoker/DuckTypingInvoker.java (added)
+++ commons/sandbox/proxy/trunk/src/main/java/org/apache/commons/proxy/invoker/DuckTypingInvoker.java Fri Sep 28 09:07:06 2007
@@ -0,0 +1,65 @@
+/*
+ * 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.commons.proxy.invoker;
+
+import org.apache.commons.proxy.Invoker;
+import org.apache.commons.proxy.ObjectProvider;
+
+import java.lang.reflect.Method;
+
+/**
+ * An invoker which supports "duck typing", meaning that it finds a matching method
+ * on the object returned from the target provider and invokes it.  This class is useful for
+ * adapting an existing class to an interface it does not implement.
+ */
+public class DuckTypingInvoker implements Invoker
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Fields
+//----------------------------------------------------------------------------------------------------------------------
+
+    private final ObjectProvider targetProvider;
+
+//----------------------------------------------------------------------------------------------------------------------
+// Constructors
+//----------------------------------------------------------------------------------------------------------------------
+
+    public DuckTypingInvoker( final ObjectProvider targetProvider )
+    {
+        this.targetProvider = targetProvider;
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// Interface Invoker
+//----------------------------------------------------------------------------------------------------------------------
+
+    public Object invoke( final Object proxy, final Method method, final Object[] arguments ) throws Throwable
+    {
+        final Object target = targetProvider.getObject();
+        final Class targetClass = target.getClass();
+        try
+        {
+            final Method targetMethod = targetClass.getMethod( method.getName(), method.getParameterTypes() );
+            return targetMethod.invoke( target, arguments );
+        }
+        catch ( NoSuchMethodException e )
+        {
+            throw new UnsupportedOperationException("Target type " + targetClass.getName() + " does not have a method matching " + method + "." );
+        }
+    }
+}

Modified: commons/sandbox/proxy/trunk/src/site/xdoc/index.xml
URL: http://svn.apache.org/viewvc/commons/sandbox/proxy/trunk/src/site/xdoc/index.xml?rev=580396&r1=580395&r2=580396&view=diff
==============================================================================
--- commons/sandbox/proxy/trunk/src/site/xdoc/index.xml (original)
+++ commons/sandbox/proxy/trunk/src/site/xdoc/index.xml Fri Sep 28 09:07:06 2007
@@ -103,6 +103,7 @@
                     <table border="0">
                       <tr><td><b>Null</b></td><td>Always returns a null (useful for the "Null Object" pattern)</td></tr>
                       <tr><td><b>Apache XML-RPC</b></td><td>Uses <a href="http://ws.apache.org/xmlrpc/">Apache XML-RPC</a> to fulfill the method invocation</td></tr>
+                        <tr><td><b>Duck Typing</b></td><td>Supports &quot;duck typing&quot; by adapting a class to an interface it does not implement.</td></tr>
                       <tr><td><b>Invocation Handler Adapter</b></td><td>Adapts the JDK <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/reflect/InvocationHandler.html">InvocationHandler</a> interface
                           to the <em>Commons Proxy</em> <a href="apidocs/org/apache/commons/proxy/Invoker.html">Invoker</a> interface.</td></tr>
                     </table>

Added: commons/sandbox/proxy/trunk/src/test/java/org/apache/commons/proxy/invoker/TestDuckTypingInvoker.java
URL: http://svn.apache.org/viewvc/commons/sandbox/proxy/trunk/src/test/java/org/apache/commons/proxy/invoker/TestDuckTypingInvoker.java?rev=580396&view=auto
==============================================================================
--- commons/sandbox/proxy/trunk/src/test/java/org/apache/commons/proxy/invoker/TestDuckTypingInvoker.java (added)
+++ commons/sandbox/proxy/trunk/src/test/java/org/apache/commons/proxy/invoker/TestDuckTypingInvoker.java Fri Sep 28 09:07:06 2007
@@ -0,0 +1,82 @@
+/*
+ * 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.commons.proxy.invoker;
+
+import junit.framework.TestCase;
+import org.apache.commons.proxy.ObjectProvider;
+import org.apache.commons.proxy.ProxyFactory;
+import org.apache.commons.proxy.provider.ConstantProvider;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.util.Comparator;
+
+/**
+ *
+ */
+public class TestDuckTypingInvoker extends TestCase
+{
+//----------------------------------------------------------------------------------------------------------------------
+// Other Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+    public void testExactSignatureMatch()
+    {
+        final ObjectProvider targetProvider = new ConstantProvider(new DuckComparator());
+        final DuckTypingInvoker invoker = new DuckTypingInvoker( targetProvider );
+        final Comparator c = ( Comparator )new ProxyFactory().createInvokerProxy( invoker, new Class[] { Comparator.class } );
+        assertEquals( 12345, c.compare( null, null ) );
+    }
+
+    public void testNoMatchingMethod()
+    {
+        final ObjectProvider targetProvider = new ConstantProvider(new DuckComparator());
+        final DuckTypingInvoker invoker = new DuckTypingInvoker( targetProvider );
+        final Externalizable externalizable = ( Externalizable )new ProxyFactory().createInvokerProxy( invoker, new Class[] {
+                Externalizable.class } );
+        try
+        {
+            externalizable.writeExternal( null );
+            fail("No matching method should be found.");
+        }
+        catch(UnsupportedOperationException e )
+        {
+            // Do nothing, expected behavior!
+        }
+        catch ( IOException e )
+        {
+            fail("No IOException should be thrown here.");
+        }
+    }
+
+//----------------------------------------------------------------------------------------------------------------------
+// Inner Classes
+//----------------------------------------------------------------------------------------------------------------------
+
+    public static class DuckComparator
+    {
+//----------------------------------------------------------------------------------------------------------------------
+// Other Methods
+//----------------------------------------------------------------------------------------------------------------------
+
+        public int compare( final Object o1, final Object o2 )
+        {
+            return 12345;
+        }
+    }
+}