You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ni...@apache.org on 2012/08/27 07:04:39 UTC

svn commit: r1377569 - in /camel/trunk/camel-core/src: main/java/org/apache/camel/builder/xml/ main/java/org/apache/camel/component/bean/ main/java/org/apache/camel/language/ test/java/org/apache/camel/component/bean/

Author: ningjiang
Date: Mon Aug 27 05:04:38 2012
New Revision: 1377569

URL: http://svn.apache.org/viewvc?rev=1377569&view=rev
Log:
CAMEL-5503 Expanding Bean Binding annotations xpatch with header value

Added:
    camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanWithXPathInjectionUsingHeaderValueTest.java
Modified:
    camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/DefaultAnnotationExpressionFactory.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/XPathAnnotationExpressionFactory.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/language/XPath.java

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java?rev=1377569&r1=1377568&r2=1377569&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java Mon Aug 27 05:04:38 2012
@@ -112,14 +112,32 @@ public class XPathBuilder implements Exp
     private XPathFunction propertiesFunction;
     private XPathFunction simpleFunction;
 
+    /**
+     * The name of the header we want to apply the XPath expression to, which when set will cause
+     * the xpath to be evaluated on the required header, otherwise it will be applied to the body
+     */
+    private String headerName;
+
+    /**
+     * @param text The XPath expression
+     */
     public XPathBuilder(String text) {
         this.text = text;
     }
 
+    /**
+     * @param text The XPath expression
+     * @return A new XPathBuilder object
+     */
     public static XPathBuilder xpath(String text) {
         return new XPathBuilder(text);
     }
 
+    /**
+     * @param text The XPath expression
+     * @param resultType The result type that the XPath expression will return.
+     * @return A new XPathBuilder object
+     */
     public static XPathBuilder xpath(String text, Class<?> resultType) {
         XPathBuilder builder = new XPathBuilder(text);
         builder.setResultType(resultType);
@@ -449,6 +467,14 @@ public class XPathBuilder implements Exp
         this.resultQName = resultQName;
     }
 
+    public String getHeaderName() {
+        return headerName;
+    }
+    
+    public void setHeaderName(String headerName) { 
+        this.headerName = headerName;
+    }
+    
     public DefaultNamespaceContext getNamespaceContext() {
         if (namespaceContext == null) {
             try {
@@ -781,14 +807,29 @@ public class XPathBuilder implements Exp
         InputStream is = null;
         try {
             Object document;
-            // only convert to input stream if really needed
-            if (isInputStreamNeeded(exchange)) {
-                is = exchange.getIn().getBody(InputStream.class);
-                document = getDocument(exchange, is);
+           
+            // Check if we need to apply the XPath expression to a header
+            if (ObjectHelper.isNotEmpty(getHeaderName())) {         
+                String headerName = getHeaderName();
+                // only convert to input stream if really needed
+                if (isInputStreamNeeded(exchange, headerName)) {
+                    is = exchange.getIn().getHeader(headerName, InputStream.class);
+                    document = getDocument(exchange, is);
+                } else {
+                    Object headerObject = exchange.getIn().getHeader(getHeaderName());
+                    document = getDocument(exchange, headerObject);
+                }
             } else {
-                Object body = exchange.getIn().getBody();
-                document = getDocument(exchange, body);
+                // only convert to input stream if really needed
+                if (isInputStreamNeeded(exchange)) {
+                    is = exchange.getIn().getBody(InputStream.class);
+                    document = getDocument(exchange, is);
+                } else {
+                    Object body = exchange.getIn().getBody();
+                    document = getDocument(exchange, body);
+                }
             }
+                    
             if (resultQName != null) {
                 if (document instanceof InputSource) {
                     InputSource inputSource = (InputSource) document;
@@ -922,14 +963,41 @@ public class XPathBuilder implements Exp
      */
     protected boolean isInputStreamNeeded(Exchange exchange) {
         Object body = exchange.getIn().getBody();
-        if (body == null) {
+        return isInputStreamNeededForObject(exchange, body);
+    }
+    
+    /**
+     * Checks whether we need an {@link InputStream} to access the message header.
+     * <p/>
+     * Depending on the content in the message header, we may not need to convert
+     * to {@link InputStream}.
+     *
+     * @param exchange the current exchange
+     * @return <tt>true</tt> to convert to {@link InputStream} beforehand converting afterwards.
+     */
+    protected boolean isInputStreamNeeded(Exchange exchange, String headerName) {
+        Object header = exchange.getIn().getHeader(headerName);
+        return isInputStreamNeededForObject(exchange, header);
+    }
+
+    /**
+     * Checks whether we need an {@link InputStream} to access this object
+     * <p/>
+     * Depending on the content in the object, we may not need to convert
+     * to {@link InputStream}.
+     *
+     * @param exchange the current exchange
+     * @return <tt>true</tt> to convert to {@link InputStream} beforehand converting afterwards.
+     */
+    protected boolean isInputStreamNeededForObject(Exchange exchange, Object obj) {
+        if (obj == null) {
             return false;
         }
 
-        if (body instanceof WrappedFile) {
-            body = ((WrappedFile<?>) body).getFile();
+        if (obj instanceof WrappedFile) {
+            obj = ((WrappedFile<?>) obj).getFile();
         }
-        if (body instanceof File) {
+        if (obj instanceof File) {
             // input stream is needed for File to avoid locking the file in case of errors etc
             return true;
         }
@@ -937,7 +1005,7 @@ public class XPathBuilder implements Exp
         // input stream is not needed otherwise
         return false;
     }
-
+    
     /**
      * Strategy method to extract the document from the exchange.
      */

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/DefaultAnnotationExpressionFactory.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/DefaultAnnotationExpressionFactory.java?rev=1377569&r1=1377568&r2=1377569&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/DefaultAnnotationExpressionFactory.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/DefaultAnnotationExpressionFactory.java Mon Aug 27 05:04:38 2012
@@ -46,16 +46,26 @@ public class DefaultAnnotationExpression
     }
 
     protected String getExpressionFromAnnotation(Annotation annotation) {
-        // let's try the 'value()' method
+        Object value = getAnnotationObjectValue(annotation, "value");
+        if (value == null) {
+            throw new IllegalArgumentException("Cannot determine the expression from the annotation: " + annotation);
+        }
+        return value.toString();
+    }
+    
+    /**
+     * @param annotation The annotation to get the value of 
+     * @param methodName The annotation name 
+     * @return The value of the annotation
+     */
+    protected Object getAnnotationObjectValue(Annotation annotation, String methodName) {        
         try {
-            Method method = annotation.getClass().getMethod("value");
+            Method method = annotation.getClass().getMethod(methodName);
             Object value = ObjectHelper.invokeMethod(method, annotation);
-            if (value == null) {
-                throw new IllegalArgumentException("Cannot determine the expression from the annotation: " + annotation);
-            }
-            return value.toString();
+            return value;
         } catch (NoSuchMethodException e) {
-            throw new IllegalArgumentException("Cannot determine the expression of the annotation: " + annotation + " as it does not have a value() method");
+            throw new IllegalArgumentException("Cannot determine the Object value of the annotation: " + annotation
+                + " as it does not have the method: " + methodName + "() method", e);
         }
     }
 }

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/XPathAnnotationExpressionFactory.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/XPathAnnotationExpressionFactory.java?rev=1377569&r1=1377568&r2=1377569&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/XPathAnnotationExpressionFactory.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/XPathAnnotationExpressionFactory.java Mon Aug 27 05:04:38 2012
@@ -17,7 +17,6 @@
 package org.apache.camel.component.bean;
 
 import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.Expression;
@@ -48,28 +47,41 @@ public class XPathAnnotationExpressionFa
             for (NamespacePrefix namespacePrefix : namespaces) {
                 builder = builder.namespace(namespacePrefix.prefix(), namespacePrefix.uri());
             }
+        }
 
+        // Set the header name that we want the XPathBuilder to apply the XPath expression to
+        String headerName = getHeaderName(annotation);
+        if (ObjectHelper.isNotEmpty(headerName)) {
+            builder.setHeaderName(headerName);
         }
+        
         return builder;
     }
 
     protected Class<?> getResultType(Annotation annotation) {
-        try {
-            Method method = annotation.getClass().getMethod("resultType");
-            Object value = ObjectHelper.invokeMethod(method, annotation);
-            return (Class<?>) value;
-        } catch (NoSuchMethodException e) {
-            throw new IllegalArgumentException("Cannot determine the annotation: " + annotation + " as it does not have an resultType() method", e);
-        }
+        return (Class<?>) getAnnotationObjectValue(annotation, "resultType");
     }
-
+    
     protected NamespacePrefix[] getExpressionNameSpacePrefix(Annotation annotation) {
+        return (NamespacePrefix[]) getAnnotationObjectValue(annotation, "namespaces");
+    }
+    
+    /**
+     * Extracts the value of the header method in the Annotation. For backwards
+     * compatibility this method will return null if the annotation's method is
+     * not found.
+     * 
+     * @return If the annotation has the method 'header' then the name of the
+     *         header we want to apply the XPath expression to. Otherwise null
+     *         will be returned
+     */
+    protected String getHeaderName(Annotation annotation) {
+        String headerValue = null;
         try {
-            Method method = annotation.getClass().getMethod("namespaces");
-            Object value = ObjectHelper.invokeMethod(method, annotation);
-            return (NamespacePrefix[]) value;
-        } catch (NoSuchMethodException e) {
-            throw new IllegalArgumentException("Cannot determine the annotation: " + annotation + " as it does not have an namespaces() method", e);
+            headerValue = (String)getAnnotationObjectValue(annotation, "header");
+        } catch (Exception e) {
+            // Do Nothing
         }
+        return headerValue;
     }
 }

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/language/XPath.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/XPath.java?rev=1377569&r1=1377568&r2=1377569&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/XPath.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/XPath.java Mon Aug 27 05:04:38 2012
@@ -35,11 +35,20 @@ import org.apache.camel.component.bean.X
 @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
 @LanguageAnnotation(language = "xpath", factory = XPathAnnotationExpressionFactory.class)
 public @interface XPath {
-    String value();
+    /**
+     * @return The XPath which will be applied
+     */
+	String value();
 
     NamespacePrefix[] namespaces() default {
     @NamespacePrefix(prefix = "soap", uri = "http://www.w3.org/2003/05/soap-envelope"),
     @NamespacePrefix(prefix = "xsd", uri = "http://www.w3.org/2001/XMLSchema")};
     
     Class<?> resultType() default Object.class;
+    
+    /**
+     * @return The name of the header we want to apply the XPath expression to.
+     * 			If this is empty then the XPath expression will be applied to the body instead.
+     */
+    String header() default "";
 }
\ No newline at end of file

Added: camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanWithXPathInjectionUsingHeaderValueTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanWithXPathInjectionUsingHeaderValueTest.java?rev=1377569&view=auto
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanWithXPathInjectionUsingHeaderValueTest.java (added)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanWithXPathInjectionUsingHeaderValueTest.java Mon Aug 27 05:04:38 2012
@@ -0,0 +1,64 @@
+/**
+ * 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.camel.component.bean;
+
+import javax.naming.Context;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Handler;
+import org.apache.camel.language.XPath;
+import org.apache.camel.util.jndi.JndiContext;
+
+/**
+ * Tests the XPath annotation 'header' value which when set will cause the XPath
+ * to be evaluated on the required header, otherwise it will be applied to the
+ * body
+ */
+public class BeanWithXPathInjectionUsingHeaderValueTest extends ContextTestSupport {
+    protected MyBean myBean = new MyBean();
+
+    public void testConstantXPathHeaders() throws Exception {
+        template.sendBodyAndHeader("bean:myBean", "<response>OK</response>",
+                                   "invoiceDetails", "<invoice><person><name>Alan</name><date>26/08/2012</date></person></invoice>");
+       
+        assertEquals("bean response:  " + myBean, "OK", myBean.response);
+        assertEquals("bean userName: " + myBean, "Alan", myBean.userName);
+        assertEquals("bean date:  " + myBean, "26/08/2012", myBean.date);
+    }
+    
+    @Override
+    protected Context createJndiContext() throws Exception {
+        JndiContext answer = new JndiContext();
+        answer.bind("myBean", myBean);
+        return answer;
+    }
+
+    public static class MyBean {
+        public String userName;
+        public String date;
+        public String response;
+
+        @Handler
+        public void handler(@XPath("//response/text()") String response,
+                            @XPath(header = "invoiceDetails", value = "//invoice/person/name/text()") String userName,
+                            @XPath(header = "invoiceDetails", value = "//invoice/person/date", resultType = String.class) String date) {
+            this.response = response;
+            this.userName = userName;
+            this.date = date;
+        }
+    }
+}
\ No newline at end of file