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