Author: davsclaus
Date: Tue Feb 19 19:38:04 2013
New Revision: 1447881
URL: http://svn.apache.org/r1447881
Log:
CAMEL-6047: Added headerName option to validator component. Thanks to Laurynas
Lubys for the patch.
Added:
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/validation/NoXmlHeaderValidationException.java
Modified:
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/validation/ValidatingProcessor.java
camel/trunk/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorRouteTest.java
Added:
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/validation/NoXmlHeaderValidationException.java
URL:
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/validation/NoXmlHeaderValidationException.java?rev=1447881&view=auto
==============================================================================
---
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/validation/NoXmlHeaderValidationException.java
(added)
+++
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/validation/NoXmlHeaderValidationException.java
Tue Feb 19 19:38:04 2013
@@ -0,0 +1,37 @@
+/**
+ * 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.processor.validation;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.ValidationException;
+
+/**
+ * An exception thrown if the XML header is not available on the inbound
message
+ *
+ * @version
+ */
+public class NoXmlHeaderValidationException extends ValidationException {
+ private static final long serialVersionUID = 4502520681354358599L;
+
+ public NoXmlHeaderValidationException(Exchange exchange, String header) {
+ super(exchange, "XML header \"" + header + "\" could not be found on
the input message");
+ }
+
+ public NoXmlHeaderValidationException(Exchange exchange, String header,
Throwable cause) {
+ super("XML header \"" + header + "\" could not found on the input
message", exchange, cause);
+ }
+}
Modified:
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/validation/ValidatingProcessor.java
URL:
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/validation/ValidatingProcessor.java?rev=1447881&r1=1447880&r2=1447881&view=diff
==============================================================================
---
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/validation/ValidatingProcessor.java
(original)
+++
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/validation/ValidatingProcessor.java
Tue Feb 19 19:38:04 2013
@@ -55,8 +55,6 @@ import org.slf4j.LoggerFactory;
/**
* A processor which validates the XML version of the inbound message body
* against some schema either in XSD or RelaxNG
- *
- * @version
*/
public class ValidatingProcessor implements Processor {
private static final Logger LOG =
LoggerFactory.getLogger(ValidatingProcessor.class);
@@ -72,6 +70,8 @@ public class ValidatingProcessor impleme
private boolean useSharedSchema = true;
private LSResourceResolver resourceResolver;
private boolean failOnNullBody = true;
+ private boolean failOnNullHeader = true;
+ private String headerName;
public void process(Exchange exchange) throws Exception {
Schema schema;
@@ -90,19 +90,26 @@ public class ValidatingProcessor impleme
Result result = null;
// only convert to input stream if really needed
if (isInputStreamNeeded(exchange)) {
- is = exchange.getIn().getBody(InputStream.class);
+ is = getContentToValidate(exchange, InputStream.class);
if (is != null) {
source = getSource(exchange, is);
}
} else {
- Object body = exchange.getIn().getBody();
- if (body != null) {
- source = getSource(exchange, body);
+ Object content = getContentToValidate(exchange);
+ if (content != null) {
+ source = getSource(exchange, content);
}
}
- if (source == null && isFailOnNullBody()) {
- throw new NoXmlBodyValidationException(exchange);
+ if (shouldUseHeader()) {
+ if (source == null && isFailOnNullHeader()) {
+ throw new NoXmlHeaderValidationException(exchange,
+ headerName);
+ }
+ } else {
+ if (source == null && isFailOnNullBody()) {
+ throw new NoXmlBodyValidationException(exchange);
+ }
}
if (source instanceof DOMSource) {
@@ -129,8 +136,8 @@ public class ValidatingProcessor impleme
} catch (SAXParseException e) {
// can be thrown for non well formed XML
throw new SchemaValidationException(exchange, schema,
Collections.singletonList(e),
- Collections.<SAXParseException> emptyList(),
- Collections.<SAXParseException> emptyList());
+ Collections.<SAXParseException>emptyList(),
+ Collections.<SAXParseException>emptyList());
}
}
} finally {
@@ -138,6 +145,26 @@ public class ValidatingProcessor impleme
}
}
+ private Object getContentToValidate(Exchange exchange) {
+ if (shouldUseHeader()) {
+ return exchange.getIn().getHeader(headerName);
+ } else {
+ return exchange.getIn().getBody();
+ }
+ }
+
+ private <T> T getContentToValidate(Exchange exchange, Class<T> clazz) {
+ if (shouldUseHeader()) {
+ return exchange.getIn().getHeader(headerName, clazz);
+ } else {
+ return exchange.getIn().getBody(clazz);
+ }
+ }
+
+ private boolean shouldUseHeader() {
+ return headerName != null;
+ }
+
public void loadSchema() throws Exception {
// force loading of schema
schema = createSchema();
@@ -250,6 +277,22 @@ public class ValidatingProcessor impleme
this.failOnNullBody = failOnNullBody;
}
+ public boolean isFailOnNullHeader() {
+ return failOnNullHeader;
+ }
+
+ public void setFailOnNullHeader(boolean failOnNullHeader) {
+ this.failOnNullHeader = failOnNullHeader;
+ }
+
+ public String getHeaderName() {
+ return headerName;
+ }
+
+ public void setHeaderName(String headerName) {
+ this.headerName = headerName;
+ }
+
// Implementation methods
// -----------------------------------------------------------------------
@@ -280,31 +323,31 @@ public class ValidatingProcessor impleme
}
/**
- * Checks whether we need an {@link InputStream} to access the message
body.
+ * Checks whether we need an {@link InputStream} to access the message
body or header.
* <p/>
- * Depending on the content in the message body, we may not need to convert
+ * Depending on the content in the message body or 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 to {@link Source} afterwards.
*/
protected boolean isInputStreamNeeded(Exchange exchange) {
- Object body = exchange.getIn().getBody();
- if (body == null) {
+ Object content = getContentToValidate(exchange);
+ if (content == null) {
return false;
}
- if (body instanceof InputStream) {
+ if (content instanceof InputStream) {
return true;
- } else if (body instanceof Source) {
+ } else if (content instanceof Source) {
return false;
- } else if (body instanceof String) {
+ } else if (content instanceof String) {
return false;
- } else if (body instanceof byte[]) {
+ } else if (content instanceof byte[]) {
return false;
- } else if (body instanceof Node) {
+ } else if (content instanceof Node) {
return false;
- } else if
(exchange.getContext().getTypeConverterRegistry().lookup(Source.class,
body.getClass()) != null) {
+ } else if
(exchange.getContext().getTypeConverterRegistry().lookup(Source.class,
content.getClass()) != null) {
//there is a direct and hopefully optimized converter to Source
return false;
}
@@ -313,48 +356,48 @@ public class ValidatingProcessor impleme
}
/**
- * Converts the inbound body to a {@link Source}, if the body is
<b>not</b> already a {@link Source}.
+ * Converts the inbound body or header to a {@link Source}, if it is
<b>not</b> already a {@link Source}.
* <p/>
* This implementation will prefer to source in the following order:
* <ul>
- * <li>DOM - DOM if explicit configured to use DOM</li>
- * <li>SAX - SAX as 2nd choice</li>
- * <li>Stream - Stream as 3rd choice</li>
- * <li>DOM - DOM as 4th choice</li>
+ * <li>DOM - DOM if explicit configured to use DOM</li>
+ * <li>SAX - SAX as 2nd choice</li>
+ * <li>Stream - Stream as 3rd choice</li>
+ * <li>DOM - DOM as 4th choice</li>
* </ul>
*/
- protected Source getSource(Exchange exchange, Object body) {
+ protected Source getSource(Exchange exchange, Object content) {
if (isUseDom()) {
// force DOM
- return
exchange.getContext().getTypeConverter().tryConvertTo(DOMSource.class,
exchange, body);
+ return
exchange.getContext().getTypeConverter().tryConvertTo(DOMSource.class,
exchange, content);
}
- // body may already be a source
- if (body instanceof Source) {
- return (Source) body;
+ // body or header may already be a source
+ if (content instanceof Source) {
+ return (Source) content;
}
Source source = null;
- if (body instanceof InputStream) {
- return new StreamSource((InputStream)body);
+ if (content instanceof InputStream) {
+ return new StreamSource((InputStream) content);
}
- if (body != null) {
- TypeConverter tc =
exchange.getContext().getTypeConverterRegistry().lookup(Source.class,
body.getClass());
+ if (content != null) {
+ TypeConverter tc =
exchange.getContext().getTypeConverterRegistry().lookup(Source.class,
content.getClass());
if (tc != null) {
- source = tc.convertTo(Source.class, exchange, body);
+ source = tc.convertTo(Source.class, exchange, content);
}
}
if (source == null) {
// then try SAX
- source =
exchange.getContext().getTypeConverter().tryConvertTo(SAXSource.class,
exchange, body);
+ source =
exchange.getContext().getTypeConverter().tryConvertTo(SAXSource.class,
exchange, content);
}
if (source == null) {
// then try stream
- source =
exchange.getContext().getTypeConverter().tryConvertTo(StreamSource.class,
exchange, body);
+ source =
exchange.getContext().getTypeConverter().tryConvertTo(StreamSource.class,
exchange, content);
}
if (source == null) {
// and fallback to DOM
- source =
exchange.getContext().getTypeConverter().tryConvertTo(DOMSource.class,
exchange, body);
+ source =
exchange.getContext().getTypeConverter().tryConvertTo(DOMSource.class,
exchange, content);
}
if (source == null) {
if (isFailOnNullBody()) {
Modified:
camel/trunk/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorRouteTest.java
URL:
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorRouteTest.java?rev=1447881&r1=1447880&r2=1447881&view=diff
==============================================================================
---
camel/trunk/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorRouteTest.java
(original)
+++
camel/trunk/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorRouteTest.java
Tue Feb 19 19:38:04 2013
@@ -17,9 +17,12 @@
package org.apache.camel.component.validator;
import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
import org.apache.camel.ValidationException;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.processor.validation.NoXmlHeaderValidationException;
/**
*
@@ -40,6 +43,18 @@ public class ValidatorRouteTest extends
MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint,
finallyEndpoint);
}
+ public void testValidMessageInHeader() throws Exception {
+ validEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+
+ template.sendBodyAndHeader("direct:startHeaders",
+ null,
+ "headerToValidate",
+ "<mail
xmlns='http://foo.com/bar'><subject>Hey</subject><body>Hello
world!</body></mail>");
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint,
finallyEndpoint);
+ }
+
public void testInvalidMessage() throws Exception {
invalidEndpoint.expectedMessageCount(1);
finallyEndpoint.expectedMessageCount(1);
@@ -49,7 +64,45 @@ public class ValidatorRouteTest extends
MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint,
finallyEndpoint);
}
-
+
+ public void testInvalidMessageInHeader() throws Exception {
+ invalidEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+
+ template.sendBodyAndHeader("direct:startHeaders",
+ null,
+ "headerToValidate",
+ "<mail xmlns='http://foo.com/bar'><body>Hello
world!</body></mail>");
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint,
finallyEndpoint);
+ }
+
+ public void testNullHeaderNoFail() throws Exception {
+ validEndpoint.expectedMessageCount(1);
+
+ template.sendBodyAndHeader("direct:startNullHeaderNoFail", null,
"headerToValidate", null);
+
+ MockEndpoint.assertIsSatisfied(validEndpoint);
+ }
+
+ public void testNullHeader() throws Exception {
+ validEndpoint.setExpectedMessageCount(0);
+
+ Exchange in =
resolveMandatoryEndpoint("direct:startNoHeaderException").createExchange(ExchangePattern.InOut);
+
+ in.getIn().setBody(null);
+ in.getIn().setHeader("headerToValidate", null);
+
+ Exchange out = template.send("direct:startNoHeaderException", in);
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint,
finallyEndpoint);
+
+ Exception exception = out.getException();
+ assertTrue("Should be failed", out.isFailed());
+ assertTrue("Exception should be correct type", exception instanceof
NoXmlHeaderValidationException);
+ assertTrue("Exception should mention missing header",
exception.getMessage().contains("headerToValidate"));
+ }
+
public void testInvalideBytesMessage() throws Exception {
invalidEndpoint.expectedMessageCount(1);
finallyEndpoint.expectedMessageCount(1);
@@ -60,6 +113,18 @@ public class ValidatorRouteTest extends
MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint,
finallyEndpoint);
}
+ public void testInvalidBytesMessageInHeader() throws Exception {
+ invalidEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+
+ template.sendBodyAndHeader("direct:startHeaders",
+ null,
+ "headerToValidate",
+ "<mail xmlns='http://foo.com/bar'><body>Hello
world!</body></mail>".getBytes());
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint,
finallyEndpoint);
+ }
+
@Override
protected void setUp() throws Exception {
super.setUp();
@@ -83,6 +148,24 @@ public class ValidatorRouteTest extends
.doFinally()
.to("mock:finally")
.end();
+
+ from("direct:startHeaders")
+ .doTry()
+
.to("validator:org/apache/camel/component/validator/schema.xsd?headerName=headerToValidate")
+ .to("mock:valid")
+ .doCatch(ValidationException.class)
+ .to("mock:invalid")
+ .doFinally()
+ .to("mock:finally")
+ .end();
+
+ from("direct:startNoHeaderException")
+
.to("validator:org/apache/camel/component/validator/schema.xsd?headerName=headerToValidate")
+ .to("mock:valid");
+
+ from("direct:startNullHeaderNoFail")
+
.to("validator:org/apache/camel/component/validator/schema.xsd?headerName=headerToValidate&failOnNullHeader=false")
+ .to("mock:valid");
}
};
}