You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by cm...@apache.org on 2011/01/08 19:26:28 UTC

svn commit: r1056749 - in /camel/trunk/camel-core/src: main/java/org/apache/camel/ main/java/org/apache/camel/component/bean/ main/java/org/apache/camel/converter/ test/java/org/apache/camel/component/bean/ test/java/org/apache/camel/converter/

Author: cmueller
Date: Sat Jan  8 18:26:28 2011
New Revision: 1056749

URL: http://svn.apache.org/viewvc?rev=1056749&view=rev
Log:
CAMEL-3311: bean parameter binding - Add support for type option to force Camel to pick method with compatible type

Modified:
    camel/trunk/camel-core/src/main/java/org/apache/camel/Exchange.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanProcessor.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/converter/ObjectConverter.java
    camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanExplicitMethodAmbiguousTest.java
    camel/trunk/camel-core/src/test/java/org/apache/camel/converter/ObjectConverterTest.java

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/Exchange.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/Exchange.java?rev=1056749&r1=1056748&r2=1056749&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/Exchange.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/Exchange.java Sat Jan  8 18:26:28 2011
@@ -84,6 +84,7 @@ public interface Exchange {
     String BATCH_COMPLETE             = "CamelBatchComplete";
     String BEAN_METHOD_NAME           = "CamelBeanMethodName";
     String BEAN_MULTI_PARAMETER_ARRAY = "CamelBeanMultiParameterArray";
+    String BEAN_TYPE_NAME             = "CamelBeanTypeName";
     String BINDING                    = "CamelBinding";
 
     String CHARSET_NAME      = "CamelCharsetName";

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java?rev=1056749&r1=1056748&r2=1056749&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java Sat Jan  8 18:26:28 2011
@@ -129,10 +129,12 @@ public class BeanInfo {
         return null;
     }
 
+    @SuppressWarnings("rawtypes")
     public MethodInvocation createInvocation(Object pojo, Exchange exchange) throws AmbiguousMethodCallException, MethodNotFoundException {
         MethodInfo methodInfo = null;
 
         String name = exchange.getIn().getHeader(Exchange.BEAN_METHOD_NAME, String.class);
+        Class type = exchange.getIn().getHeader(Exchange.BEAN_TYPE_NAME, Class.class);
         if (name != null) {
             if (hasMethod(name)) {
                 List<MethodInfo> methods = getOperations(name);
@@ -143,7 +145,7 @@ public class BeanInfo {
                     // there are more methods with that name so we cannot decide which to use
 
                     // but first lets try to choose a method and see if that comply with the name
-                    methodInfo = chooseMethod(pojo, exchange, name);
+                    methodInfo = chooseMethod(pojo, exchange, name, type);
                     if (methodInfo == null || !name.equals(methodInfo.getMethod().getName())) {
                         throw new AmbiguousMethodCallException(exchange, methods);
                     }
@@ -154,7 +156,7 @@ public class BeanInfo {
             }
         }
         if (methodInfo == null) {
-            methodInfo = chooseMethod(pojo, exchange, name);
+            methodInfo = chooseMethod(pojo, exchange, name, null);
         }
         if (methodInfo == null) {
             methodInfo = defaultMethod;
@@ -280,7 +282,7 @@ public class BeanInfo {
         return answer;
     }
 
-    @SuppressWarnings("unchecked")
+    @SuppressWarnings({ "unchecked", "rawtypes" })
     protected MethodInfo createMethodInfo(Class clazz, Method method) {
         Class[] parameterTypes = method.getParameterTypes();
         Annotation[][] parametersAnnotations = method.getParameterAnnotations();
@@ -349,15 +351,17 @@ public class BeanInfo {
      * @param pojo the bean to invoke a method on
      * @param exchange the message exchange
      * @param name an optional name of the method that must match, use <tt>null</tt> to indicate all methods
+     * @param type an optional type of the method parameter that must match, use <tt>null</tt> to indicate all types
      * @return the method to invoke or null if no definitive method could be matched
      * @throws AmbiguousMethodCallException is thrown if cannot chose method due to ambiguous
      */
-    protected MethodInfo chooseMethod(Object pojo, Exchange exchange, String name) throws AmbiguousMethodCallException {
+    @SuppressWarnings("rawtypes")
+    protected MethodInfo chooseMethod(Object pojo, Exchange exchange, String name, Class type) throws AmbiguousMethodCallException {
         // @Handler should be select first
         // then any single method that has a custom @annotation
         // or any single method that has a match parameter type that matches the Exchange payload
         // and last then try to select the best among the rest
-
+        
         if (name != null) {
             // filter all lists to only include methods with this name
             removeNonMatchingMethods(operationsWithHandlerAnnotation, name);
@@ -369,6 +373,13 @@ public class BeanInfo {
             removeAllSetterOrGetterMethods(operationsWithCustomAnnotation);
             removeAllSetterOrGetterMethods(operationsWithBody);
         }
+        
+        if (type != null) {
+            // filter all lists to only include methods with this argument type
+            removeNonMatchingMethods(operationsWithHandlerAnnotation, type);
+            removeNonMatchingMethods(operationsWithCustomAnnotation, type);
+            removeNonMatchingMethods(operationsWithBody, type);
+        }
 
         if (operationsWithHandlerAnnotation.size() > 1) {
             // if we have more than 1 @Handler then its ambiguous
@@ -404,6 +415,7 @@ public class BeanInfo {
         return null;
     }
     
+    @SuppressWarnings("rawtypes")
     private MethodInfo chooseMethodWithMatchingBody(Exchange exchange, Collection<MethodInfo> operationList)
         throws AmbiguousMethodCallException {
         // lets see if we can find a method who's body param type matches the message body
@@ -665,6 +677,19 @@ public class BeanInfo {
             }
         }
     }
+    
+    @SuppressWarnings("rawtypes")
+    private static void removeNonMatchingMethods(List<MethodInfo> methods, Class type) {
+        Iterator<MethodInfo> it = methods.iterator();
+        while (it.hasNext()) {
+            MethodInfo info = it.next();
+            Class<?>[] parameterTypes = info.getMethod().getParameterTypes();
+            if (!(parameterTypes.length > 0 && parameterTypes[0].isAssignableFrom(type))) {
+                // type does not match so remove it
+                it.remove();
+            }
+        }
+    }
 
     private static Class<?> getTargetClass(Class<?> clazz) {
         if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) {

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanProcessor.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanProcessor.java?rev=1056749&r1=1056748&r2=1056749&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanProcessor.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanProcessor.java Sat Jan  8 18:26:28 2011
@@ -47,6 +47,8 @@ public class BeanProcessor extends Servi
     private String method;
     private BeanHolder beanHolder;
     private boolean shorthandMethod;
+    @SuppressWarnings("rawtypes")
+    private Class type;
 
     public BeanProcessor(Object pojo, BeanInfo beanInfo) {
         this(new ConstantBeanHolder(pojo, beanInfo));
@@ -74,9 +76,13 @@ public class BeanProcessor extends Servi
         AsyncProcessorHelper.process(this, exchange);
     }
 
+    @SuppressWarnings({ "unused", "rawtypes" })
     public boolean process(Exchange exchange, AsyncCallback callback) {
         // do we have an explicit method name we always should invoke
         boolean isExplicitMethod = ObjectHelper.isNotEmpty(method);
+        // do we have an explicit parameter type we should invoke if we have multiple possible
+        // methods
+        boolean isExplicitType = ObjectHelper.isNotEmpty(type);
 
         Object bean = beanHolder.getBean();
         BeanInfo beanInfo = beanHolder.getBeanInfo();
@@ -98,7 +104,7 @@ public class BeanProcessor extends Servi
         }
 
         Message in = exchange.getIn();
-
+        
         // Now it gets a bit complicated as ProxyHelper can proxy beans which we later
         // intend to invoke (for example to proxy and invoke using spring remoting).
         // and therefore the message body contains a BeanInvocation object.
@@ -122,13 +128,14 @@ public class BeanProcessor extends Servi
                 return true;
             }
         }
-
+        
         // set temporary header which is a hint for the bean info that introspect the bean
         if (in.getHeader(Exchange.BEAN_MULTI_PARAMETER_ARRAY) == null) {
             in.setHeader(Exchange.BEAN_MULTI_PARAMETER_ARRAY, isMultiParameterArray());
         }
 
         String prevMethod = null;
+        Class prevType = null;
         MethodInvocation invocation;
         if (methodObject != null) {
             invocation = beanInfo.createInvocation(methodObject, bean, exchange);
@@ -138,6 +145,10 @@ public class BeanProcessor extends Servi
                 prevMethod = in.getHeader(Exchange.BEAN_METHOD_NAME, String.class);
                 in.setHeader(Exchange.BEAN_METHOD_NAME, method);
             }
+            if (isExplicitType) {
+                prevType = in.getHeader(Exchange.BEAN_TYPE_NAME, Class.class);
+                in.setHeader(Exchange.BEAN_TYPE_NAME, type);
+            }
             try {
                 invocation = beanInfo.createInvocation(bean, exchange);
             } catch (Throwable e) {
@@ -258,6 +269,21 @@ public class BeanProcessor extends Servi
     public void setShorthandMethod(boolean shorthandMethod) {
         this.shorthandMethod = shorthandMethod;
     }
+    
+    @SuppressWarnings("rawtypes")
+    public Class getType() {
+        return type;
+    }
+
+    /**
+     * Sets the type/class name to which the body should converted before the suitable method is
+     * determined.
+     * @param type
+     */
+    @SuppressWarnings("rawtypes")
+    public void setType(Class type) {
+        this.type = type;
+    }
 
     // Implementation methods
     //-------------------------------------------------------------------------

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/converter/ObjectConverter.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/converter/ObjectConverter.java?rev=1056749&r1=1056748&r2=1056749&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/converter/ObjectConverter.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/converter/ObjectConverter.java Sat Jan  8 18:26:28 2011
@@ -65,6 +65,7 @@ public final class ObjectConverter {
     /**
      * Creates an iterator over the value
      */
+    @SuppressWarnings("rawtypes")
     @Converter
     public static Iterator iterator(Object value) {
         return ObjectHelper.createIterator(value);
@@ -106,6 +107,21 @@ public final class ObjectConverter {
     public static String fromCharArray(char[] value) {
         return new String(value);
     }
+    
+    /**
+     * Returns the converted value, or null if the value is null
+     */
+    @SuppressWarnings("rawtypes")
+    @Converter
+    public static Class toClass(Object value) {
+        if (value instanceof Class) {
+            return (Class) value;
+        } else if (value instanceof String) {
+            return ObjectHelper.loadClass((String) value);
+        } else {
+            return null;
+        }
+    }
 
     /**
      * Returns the converted value, or null if the value is null

Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanExplicitMethodAmbiguousTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanExplicitMethodAmbiguousTest.java?rev=1056749&r1=1056748&r2=1056749&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanExplicitMethodAmbiguousTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanExplicitMethodAmbiguousTest.java Sat Jan  8 18:26:28 2011
@@ -17,6 +17,7 @@
 package org.apache.camel.component.bean;
 
 import java.io.ByteArrayInputStream;
+import java.io.StringReader;
 
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.builder.RouteBuilder;
@@ -49,16 +50,36 @@ public class BeanExplicitMethodAmbiguous
         assertEquals("Bye Camel", out);
     }
     
-    public void testBeanExplicitMethodInvocationStringBody() throws Exception {
+    public void testBeanImplicitMethodInvocationStringBody() throws Exception {
         String out = template.requestBody("direct:foo", "Camel", String.class);
         assertEquals("String", out);
     }
     
-    public void testBeanExplicitMethodInvocationInputStreamBody() throws Exception {
+    public void testBeanImplicitMethodInvocationReaderBody() throws Exception {
+        String out = template.requestBody("direct:foo", new StringReader("Camel"), String.class);
+        assertEquals("Reader", out);
+    }
+    
+    public void testBeanImplicitMethodInvocationInputStreamBody() throws Exception {
         String out = template.requestBody("direct:foo", new ByteArrayInputStream("Camel".getBytes()), String.class);
         assertEquals("InputStream", out);
     }
+    
+    public void testBeanExplicitMethodInvocationString() throws Exception {
+        String out = template.requestBody("direct:explicitString", new ByteArrayInputStream("Camel".getBytes()), String.class);
+        assertEquals("String", out);
+    }
+    
+    public void testBeanExplicitMethodInvocationReader() throws Exception {
+        String out = template.requestBody("direct:explicitReader", new ByteArrayInputStream("Camel".getBytes()), String.class);
+        assertEquals("Reader", out);
+    }
 
+    public void testBeanExplicitMethodInvocationInputStream() throws Exception {
+        String out = template.requestBody("direct:explicitInputStream", "Camel", String.class);
+        assertEquals("InputStream", out);
+    }
+    
     @Override
     protected RouteBuilder createRouteBuilder() throws Exception {
         return new RouteBuilder() {
@@ -69,6 +90,12 @@ public class BeanExplicitMethodAmbiguous
                 from("direct:bye").beanRef("dummy");
                 
                 from("direct:foo").beanRef("dummy", "bar");
+                
+                from("direct:explicitString").to("bean:dummy?method=bar&type=java.lang.String");
+                
+                from("direct:explicitReader").to("bean:dummy?method=bar&type=java.io.Reader");
+                
+                from("direct:explicitInputStream").to("bean:dummy?method=bar&type=java.io.InputStream");
             }
         };
     }

Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/converter/ObjectConverterTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/converter/ObjectConverterTest.java?rev=1056749&r1=1056748&r2=1056749&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/converter/ObjectConverterTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/converter/ObjectConverterTest.java Sat Jan  8 18:26:28 2011
@@ -47,6 +47,13 @@ public class ObjectConverterTest extends
         assertEquals(Byte.valueOf("4"), ObjectConverter.toByte("4"));
         assertEquals(null, ObjectConverter.toByte(new Date()));
     }
+    
+    public void testToClass() {
+        assertEquals(String.class, ObjectConverter.toClass(String.class));
+        assertEquals(String.class, ObjectConverter.toClass("java.lang.String"));
+        assertEquals(null, ObjectConverter.toClass(new Integer(4)));
+        assertEquals(null, ObjectConverter.toClass("foo.Bar"));
+    }
 
     public void testToShort() {
         assertEquals(Short.valueOf("4"), ObjectConverter.toShort(Short.valueOf("4")));