This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-spring-boot.git
The following commit(s) were added to refs/heads/main by this push:
new b2a9fd0c2f8 CAMEL-18038 - add tests in camel-validator-starter (#551)
b2a9fd0c2f8 is described below
commit b2a9fd0c2f8076f3d3bec6ef7c2f745f4e920b1c
Author: Federico Mariani <[email protected]>
AuthorDate: Mon May 2 20:40:16 2022 +0200
CAMEL-18038 - add tests in camel-validator-starter (#551)
---
components-starter/camel-validator-starter/pom.xml | 11 +
.../component/validator/ContextTestSupport.java | 146 +++++++++++++
.../validator/CustomSchemaFactoryFeatureTest.java | 65 ++++++
.../validator/FileValidatorRouteTest.java | 104 +++++++++
.../component/validator/ValidatorBeanCallTest.java | 90 ++++++++
.../validator/ValidatorDtdAccessAbstractTest.java | 84 ++++++++
.../validator/ValidatorDtdAccessOffTest.java | 85 ++++++++
.../validator/ValidatorDtdAccessOnTest.java | 91 ++++++++
.../ValidatorEndpointClearCachedSchemaTest.java | 156 ++++++++++++++
.../validator/ValidatorIllegalImportTest.java | 90 ++++++++
.../ValidatorIncludeEncodingRouteTest.java | 91 ++++++++
.../ValidatorIncludeRelativeRouteTest.java | 84 ++++++++
.../validator/ValidatorIncludeRouteTest.java | 159 ++++++++++++++
.../validator/ValidatorLazyStartProducerTest.java | 86 ++++++++
.../ValidatorResourceResolverFactoryTest.java | 223 +++++++++++++++++++
.../component/validator/ValidatorRootPathTest.java | 76 +++++++
.../component/validator/ValidatorRouteTest.java | 236 +++++++++++++++++++++
.../ValidatorWithResourceResolverRouteTest.java | 109 ++++++++++
.../validation/CatalogLSResourceResolver.java | 177 ++++++++++++++++
.../org/apache/camel/urlhandler/pd/Handler.java | 85 ++++++++
.../src/test/resources/jndi-example.properties | 24 +++
.../camel/component/validator/BroadcastMonitor.xsd | 58 +++++
.../component/validator/BroadcastMonitorFixed.xsd | 57 +++++
.../apache/camel/component/validator/catalog.cat | 2 +
.../apache/camel/component/validator/health.xsd | 32 +++
.../apache/camel/component/validator/person.xsd | 38 ++++
.../camel/component/validator/report-base.xsd | 48 +++++
.../apache/camel/component/validator/report.xsd | 36 ++++
.../apache/camel/component/validator/schema.xsd | 35 +++
.../apache/camel/component/validator/sentence.xsd | 28 +++
.../org/apache/camel/component/validator/text.xsd | 31 +++
.../camel/component/validator/unsecuredSchema.xsd | 34 +++
.../camel/component/validator/xsds/customer.xsd | 30 +++
.../validator/xsds/health/common/common.xsd | 32 +++
.../component/validator/xsds/health/health.xsd | 37 ++++
.../component/validator/xsds/health/type1.xsd | 28 +++
.../camel/component/validator/xsds/order.xsd | 34 +++
.../camel/component/validator/xsds/person.xsd | 40 ++++
.../camel/component/validator/xsds/product.xsd | 46 ++++
.../camel/component/validator/xsds/type2.xsd | 25 +++
.../src/test/resources/report-base.xsd | 48 +++++
.../src/test/resources/report.xsd | 36 ++++
42 files changed, 3027 insertions(+)
diff --git a/components-starter/camel-validator-starter/pom.xml
b/components-starter/camel-validator-starter/pom.xml
index f20ba907434..eb7ef68f585 100644
--- a/components-starter/camel-validator-starter/pom.xml
+++ b/components-starter/camel-validator-starter/pom.xml
@@ -39,6 +39,17 @@
<artifactId>camel-validator</artifactId>
<version>${camel-version}</version>
</dependency>
+ <dependency>
+ <groupId>org.awaitility</groupId>
+ <artifactId>awaitility</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>xml-resolver</groupId>
+ <artifactId>xml-resolver</artifactId>
+ <version>${xml-resolver-version}</version>
+ <scope>test</scope>
+ </dependency>
<!--START OF GENERATED CODE-->
<dependency>
<groupId>org.apache.camel.springboot</groupId>
diff --git
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ContextTestSupport.java
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ContextTestSupport.java
new file mode 100644
index 00000000000..cd5b178d9ac
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ContextTestSupport.java
@@ -0,0 +1,146 @@
+/*
+ * 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.validator;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.NotifyBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class ContextTestSupport {
+
+ protected MockEndpoint validEndpoint;
+ protected MockEndpoint finallyEndpoint;
+ protected MockEndpoint invalidEndpoint;
+
+ protected volatile NotifyBuilder oneExchangeDone;
+
+ @Autowired
+ protected CamelContext context;
+
+ @Autowired
+ protected ProducerTemplate template;
+
+ protected boolean testDirectoryCleaned;
+
+ @AfterEach
+ public void tearDown() throws Exception {
+ testDirectoryCleaned = false;
+ }
+
+ protected Path testFile(String dir) {
+ return testDirectory().resolve(dir);
+ }
+
+ protected String fileUri() {
+ return "file:" + testDirectory();
+ }
+
+ protected String fileUri(String query) {
+ return "file:" + testDirectory() + (query.startsWith("?") ? ""
: "/") + query;
+ }
+
+ protected Path testDirectory(String dir, boolean create) {
+ Path f = testDirectory().resolve(dir);
+ if (create) {
+ try {
+ Files.createDirectories(f);
+ } catch (IOException e) {
+ throw new IllegalStateException("Unable to
create test directory: " + dir, e);
+ }
+ }
+ return f;
+ }
+
+ protected Path testDirectory() {
+ return testDirectory(false);
+ }
+
+ protected Path testDirectory(boolean create) {
+ Class<?> testClass = getClass();
+ if (create) {
+ deleteTestDirectory();
+ }
+ return testDirectory(testClass, create);
+ }
+
+ public static Path testDirectory(Class<?> testClass, boolean create) {
+ Path dir = Paths.get("target", "data",
testClass.getSimpleName());
+ if (create) {
+ try {
+ Files.createDirectories(dir);
+ } catch (IOException e) {
+ throw new IllegalStateException("Unable to
create test directory: " + dir, e);
+ }
+ }
+ return dir;
+ }
+
+ public void deleteTestDirectory() {
+ if (!testDirectoryCleaned) {
+ deleteDirectory(testDirectory().toFile());
+ testDirectoryCleaned = true;
+ }
+ }
+
+ public static void deleteDirectory(String file) {
+ deleteDirectory(new File(file));
+ }
+
+ /**
+ * Recursively delete a directory, useful to zapping test data
+ *
+ * @param file the directory to be deleted
+ */
+ public static void deleteDirectory(File file) {
+ if (file.isDirectory()) {
+ File[] files = file.listFiles();
+ if (files != null) {
+ for (File child : files) {
+ deleteDirectory(child);
+ }
+ }
+ }
+
+ file.delete();
+ }
+
+ protected NotifyBuilder event() {
+ return new NotifyBuilder(context);
+ }
+
+ public static <T> T assertIsInstanceOf(Class<T> expectedType, Object
value) {
+ Assertions.assertNotNull(value, "Expected an instance of type:
" + expectedType.getName() + " but was null");
+ assertTrue(expectedType.isInstance(value), "object should be a
" + expectedType.getName() + " but was: " + value
+ + " with type: " + value.getClass().getName());
+ return expectedType.cast(value);
+ }
+
+}
diff --git
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/CustomSchemaFactoryFeatureTest.java
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/CustomSchemaFactoryFeatureTest.java
new file mode 100644
index 00000000000..5dd131d5cb3
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/CustomSchemaFactoryFeatureTest.java
@@ -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.camel.component.validator;
+
+import javax.xml.XMLConstants;
+import javax.xml.validation.SchemaFactory;
+
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+ classes = {
+ CamelAutoConfiguration.class,
+ CustomSchemaFactoryFeatureTest.class,
+
CustomSchemaFactoryFeatureTest.TestConfiguration.class
+ }
+)
+public class CustomSchemaFactoryFeatureTest extends ContextTestSupport {
+
+ // just inject the SchemaFactory as we want
+ @Test
+ public void testCustomSchemaFactory() throws Exception {
+ ValidatorComponent v = new ValidatorComponent();
+ v.setCamelContext(context);
+ v.init();
+
v.createEndpoint("validator:org/apache/camel/component/validator/unsecuredSchema.xsd?schemaFactory=#mySchemaFactory");
+ }
+
+ @Configuration
+ class TestConfiguration {
+
+ @Bean
+ public SchemaFactory mySchemaFactory() throws
SAXNotSupportedException, SAXNotRecognizedException {
+ SchemaFactory mySchemaFactory =
SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+
mySchemaFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false);
+
+ return mySchemaFactory;
+ }
+ }
+}
diff --git
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/FileValidatorRouteTest.java
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/FileValidatorRouteTest.java
new file mode 100644
index 00000000000..6405ae7295e
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/FileValidatorRouteTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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.validator;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.ValidationException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.apache.camel.util.FileUtil;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+ classes = {
+ CamelAutoConfiguration.class,
+ FileValidatorRouteTest.class
+ }
+)
+public class FileValidatorRouteTest extends ContextTestSupport {
+
+ @Test
+ public void testValidMessage() throws Exception {
+ validEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+
+ template.sendBodyAndHeader(fileUri(),
+ "<mail
xmlns='http://foo.com/bar'><subject>Hey</subject><body>Hello
world!</body></mail>", Exchange.FILE_NAME,
+ "valid.xml");
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint,
finallyEndpoint);
+
+ // should be able to delete the file
+ oneExchangeDone.matchesWaitTime();
+ assertTrue(FileUtil.deleteFile(testFile("valid.xml").toFile()),
+ "Should be able to delete the file");
+ }
+
+ @Test
+ public void testInvalidMessage() throws Exception {
+ invalidEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+
+ template.sendBodyAndHeader(fileUri(),
+ "<mail xmlns='http://foo.com/bar'><body>Hello
world!</body></mail>", Exchange.FILE_NAME, "invalid.xml");
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint,
finallyEndpoint);
+
+ // should be able to delete the file
+ oneExchangeDone.matchesWaitTime();
+ assertTrue(FileUtil.deleteFile(testFile("invalid.xml").toFile()),
+ "Should be able to delete the file");
+ }
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ deleteTestDirectory();
+ validEndpoint = context.getEndpoint("mock:valid", MockEndpoint.class);
+ invalidEndpoint = context.getEndpoint("mock:invalid",
MockEndpoint.class);
+ finallyEndpoint = context.getEndpoint("mock:finally",
MockEndpoint.class);
+
+ validEndpoint.reset();
+ invalidEndpoint.reset();
+ finallyEndpoint.reset();
+
+ oneExchangeDone = event().whenDone(1).create();
+ }
+
+ @Bean
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from(fileUri("?noop=true")).doTry()
+
.to("validator:org/apache/camel/component/validator/schema.xsd").to("mock:valid")
+
.doCatch(ValidationException.class).to("mock:invalid").doFinally().to("mock:finally").end();
+ }
+ };
+ }
+
+}
diff --git
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorBeanCallTest.java
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorBeanCallTest.java
new file mode 100644
index 00000000000..a9e9e1b68b3
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorBeanCallTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.validator;
+
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+ classes = {
+ CamelAutoConfiguration.class,
+ ValidatorBeanCallTest.class
+ }
+)
+public class ValidatorBeanCallTest extends ContextTestSupport {
+
+ @Test
+ public void testCallBean() throws Exception {
+ validEndpoint.expectedMessageCount(1);
+ invalidEndpoint.expectedMessageCount(0);
+
+ template
+ .sendBody("direct:rootPath",
+ "<report xmlns='http://foo.com/report'
xmlns:rb='http://foo.com/report-base'><author><rb:name>Knuth</rb:name></author><content><rb:chapter><rb:subject></rb:subject>"
+ +
"<rb:abstract></rb:abstract><rb:body></rb:body></rb:chapter></content></report>");
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint);
+ }
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ deleteTestDirectory();
+ validEndpoint = context.getEndpoint("mock:valid", MockEndpoint.class);
+ invalidEndpoint = context.getEndpoint("mock:invalid",
MockEndpoint.class);
+
+ validEndpoint.reset();
+ invalidEndpoint.reset();
+ }
+
+ @Bean
+ public MyValidatorBean myBean() {
+ return new MyValidatorBean();
+ }
+
+ @Bean
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+
from("direct:rootPath").to("validator:bean:myBean.loadFile").to("mock:valid");
+ }
+ };
+ }
+
+ public static class MyValidatorBean {
+
+ public InputStream loadFile() throws Exception {
+ return
Files.newInputStream(Paths.get("src/test/resources/report.xsd"));
+ }
+
+ }
+}
diff --git
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessAbstractTest.java
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessAbstractTest.java
new file mode 100644
index 00000000000..d2f228e4b85
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessAbstractTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.validator;
+
+import org.apache.camel.ValidationException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.support.processor.validation.SchemaReader;
+
+import org.junit.jupiter.api.BeforeEach;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.net.UnknownHostException;
+
+public abstract class ValidatorDtdAccessAbstractTest extends
ContextTestSupport {
+
+ protected MockEndpoint finallyEndpoint;
+ protected MockEndpoint invalidEndpoint;
+ protected MockEndpoint unknownHostExceptionEndpoint;
+ protected MockEndpoint validEndpoint;
+
+ protected String payloud = getPayloudPart("Hello world!");
+
+ protected String ssrfPayloud = "<!DOCTYPE roottag PUBLIC
\"-//VSR//PENTEST//EN\" \"http://notex.isting/test\">\n" + payloud;
+
+ protected String xxePayloud
+ = "<!DOCTYPE updateProfile [<!ENTITY file SYSTEM
\"http://notex.istinghost/test\">]>\n" + getPayloudPart("&file;");
+
+ private String getPayloudPart(String bodyValue) {
+ return "<mail xmlns='http://foo.com/bar'><subject>Hey</subject><body>"
+ bodyValue + "</body></mail>";
+ }
+
+ protected abstract boolean accessExternalDTD();
+
+ @Configuration
+ class TestConfiguration {
+ @Bean
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+
+ @Override
+ public void configure() throws Exception {
+ if(accessExternalDTD()) {
+
getContext().getGlobalOptions().put(SchemaReader.ACCESS_EXTERNAL_DTD, "true");
+ }
+
from("direct:start").doTry().to("validator:org/apache/camel/component/validator/schema.xsd").to("mock:valid")
+
.doCatch(ValidationException.class).to("mock:invalid")
+
.doCatch(UnknownHostException.class).to("mock:unknownHostException").doFinally().to("mock:finally")
+ .end();
+ }
+ };
+ }
+ }
+
+ @BeforeEach
+ public void before() {
+ validEndpoint = context.getEndpoint("mock:valid", MockEndpoint.class);
+ invalidEndpoint = context.getEndpoint("mock:invalid",
MockEndpoint.class);
+ finallyEndpoint = context.getEndpoint("mock:finally",
MockEndpoint.class);
+ unknownHostExceptionEndpoint =
context.getEndpoint("mock:unknownHostException", MockEndpoint.class);
+
+ validEndpoint.reset();
+ invalidEndpoint.reset();
+ finallyEndpoint.reset();
+ unknownHostExceptionEndpoint.reset();
+ }
+
+}
diff --git
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessOffTest.java
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessOffTest.java
new file mode 100644
index 00000000000..7b0d2437c26
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessOffTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.validator;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.net.UnknownHostException;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.camel.ValidationException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.support.processor.validation.SchemaReader;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+ classes = {
+ CamelAutoConfiguration.class,
+ ValidatorDtdAccessOffTest.class,
+ ValidatorDtdAccessAbstractTest.TestConfiguration.class
+ }
+)
+public class ValidatorDtdAccessOffTest extends ValidatorDtdAccessAbstractTest {
+
+ /** Tests that no external DTD call is executed for StringSource. */
+ @Test
+ public void testInvalidMessageWithExternalDTDStringSource() throws
Exception {
+ invalidEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+
+ template.sendBody("direct:start", ssrfPayloud);
+
+ MockEndpoint.assertIsSatisfied(validEndpoint,
unknownHostExceptionEndpoint, finallyEndpoint);
+ }
+
+ /** Tests that external DTD call is not executed for StreamSource. */
+ @Test
+ public void testInvalidMessageWithExternalDTDStreamSource() throws
Exception {
+ invalidEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+ InputStream is = new
ByteArrayInputStream(ssrfPayloud.getBytes(StandardCharsets.UTF_8));
+ template.sendBody("direct:start", is);
+
+ MockEndpoint.assertIsSatisfied(validEndpoint,
unknownHostExceptionEndpoint, finallyEndpoint);
+ }
+
+ /** Tests that XXE is not possible for StreamSource. */
+ @Test
+ public void testInvalidMessageXXESourceStream() throws Exception {
+ invalidEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+ InputStream is = new
ByteArrayInputStream(xxePayloud.getBytes(StandardCharsets.UTF_8));
+ template.sendBody("direct:start", is);
+
+ MockEndpoint.assertIsSatisfied(validEndpoint,
unknownHostExceptionEndpoint, finallyEndpoint);
+ }
+
+ @Override
+ protected boolean accessExternalDTD() {
+ return false;
+ }
+}
diff --git
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessOnTest.java
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessOnTest.java
new file mode 100644
index 00000000000..ac370aabba4
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessOnTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.validator;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.net.UnknownHostException;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.camel.ValidationException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.support.processor.validation.SchemaReader;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+ classes = {
+ CamelAutoConfiguration.class,
+ ValidatorDtdAccessOnTest.class,
+ ValidatorDtdAccessAbstractTest.TestConfiguration.class
+ }
+)
+public class ValidatorDtdAccessOnTest extends ValidatorDtdAccessAbstractTest {
+
+ /**
+ * Tests that external DTD call is executed for StringSource by expecting
an UnkonwHostException.
+ */
+ @Test
+ public void testInvalidMessageWithExternalDTDStringSource() throws
Exception {
+ unknownHostExceptionEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+
+ template.sendBody("direct:start", ssrfPayloud);
+
+ MockEndpoint.assertIsSatisfied(validEndpoint,
unknownHostExceptionEndpoint, finallyEndpoint);
+ }
+
+ /**
+ * Tests that external DTD call is executed for StreamSourceby expecting
an UnknownHostException.
+ */
+ @Test
+ public void testInvalidMessageWithExternalDTDStreamSource() throws
Exception {
+ unknownHostExceptionEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+ InputStream is = new
ByteArrayInputStream(ssrfPayloud.getBytes(StandardCharsets.UTF_8));
+ template.sendBody("direct:start", is);
+
+ MockEndpoint.assertIsSatisfied(validEndpoint,
unknownHostExceptionEndpoint, finallyEndpoint);
+ }
+
+ /**
+ * Tests that XXE is possible for StreamSource by expecting an
UnkonwHostException.
+ */
+ @Test
+ public void testInvalidMessageXXESourceStream() throws Exception {
+ unknownHostExceptionEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+ InputStream is = new
ByteArrayInputStream(xxePayloud.getBytes(StandardCharsets.UTF_8));
+ template.sendBody("direct:start", is);
+
+ MockEndpoint.assertIsSatisfied(validEndpoint,
unknownHostExceptionEndpoint, finallyEndpoint);
+ }
+
+ @Override
+ protected boolean accessExternalDTD() {
+ return true;
+ }
+}
diff --git
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorEndpointClearCachedSchemaTest.java
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorEndpointClearCachedSchemaTest.java
new file mode 100644
index 00000000000..d1a86703744
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorEndpointClearCachedSchemaTest.java
@@ -0,0 +1,156 @@
+/*
+ * 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.validator;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Endpoint;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.engine.DefaultResourceLoader;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.apache.camel.urlhandler.pd.Handler;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+/**
+ * Tests whether the ValidatorEndpoint.clearCachedSchema() can be executed
when several sender threads are running.
+ */
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+ classes = {
+ CamelAutoConfiguration.class,
+ ValidatorEndpointClearCachedSchemaTest.class
+ }
+)
+public class ValidatorEndpointClearCachedSchemaTest extends ContextTestSupport
{
+
+ private static final Logger LOG =
LoggerFactory.getLogger(ValidatorEndpointClearCachedSchemaTest.class);
+
+ @Test
+ public void testClearCachedSchema() throws Exception {
+
+ MockEndpoint mock = context.getEndpoint("mock:result",
MockEndpoint.class);
+
+ // send with 5 sender threads in parallel and call clear cache in
+ // between
+ ExecutorService senderPool = Executors.newFixedThreadPool(5);
+ ExecutorService executorClearCache = Executors.newFixedThreadPool(1);
+ for (int i = 0; i < 5; i++) {
+ senderPool.execute(new Sender());
+ if (i == 2) {
+ /*
+ * The clear cache thread calls xsdEndpoint.clearCachedSchema
+ */
+ executorClearCache.execute(new ClearCache());
+ }
+ }
+
+ senderPool.shutdown();
+ executorClearCache.shutdown();
+
+ senderPool.awaitTermination(4, TimeUnit.SECONDS);
+
+ // expect at least 5 correct sent messages, the messages sent before
+ // the clearCacheSchema method is called will fail with a validation
+ // error and will nor result in an exchange
+ mock.expectedMinimumMessageCount(5);
+ mock.assertIsSatisfied();
+ }
+
+ @Bean
+ protected RouteBuilder createRouteBuilder() throws Exception {
+
context.getRegistry().bind(DefaultResourceLoader.RESOURCE_LOADER_KEY_PREFIX +
"pd", new Handler());
+
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+
from("direct:start").to("validator:pd:somefile.xsd").convertBodyTo(String.class).to("log:after")
+ .to("mock:result");
+
+ }
+ };
+ }
+
+ private class Sender implements Runnable {
+
+ private final String message = "<?xml version=\"1.0\"
encoding=\"UTF-8\"?>" + //
+ "<p:TestMessage
xmlns:p=\"http://apache.camel.org/test\">" + //
+
"<MessageContent>MessageContent</MessageContent>" + //
+ "</p:TestMessage>";
+
+ private final byte[] messageBytes =
message.getBytes(StandardCharsets.UTF_8);
+
+ @Override
+ public void run() {
+ // send up to 5 messages
+ for (int j = 0; j < 5; j++) {
+ try {
+ Thread.sleep(300);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ template.sendBody("direct:start", messageBytes);
+ }
+ }
+
+ }
+
+ private class ClearCache implements Runnable {
+
+ @Override
+ public void run() {
+ try {
+ // start later after the first sender
+ // threads are running
+ Thread.sleep(200);
+ clearCachedSchema();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ }
+
+ private void clearCachedSchema() throws Exception {
+ CamelContext context = this.context;
+ if (context == null) {
+ return;
+ }
+ Collection<Endpoint> endpoints = context.getEndpoints();
+ for (Endpoint endpoint : endpoints) {
+ LOG.info("Endpoint URI: " + endpoint.getEndpointUri());
+ if (endpoint.getEndpointUri().startsWith("validator:")) {
+ ValidatorEndpoint xsltEndpoint = (ValidatorEndpoint) endpoint;
+ xsltEndpoint.clearCachedSchema();
+ LOG.info("schema cache cleared");
+ }
+ }
+ }
+
+}
diff --git
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorIllegalImportTest.java
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorIllegalImportTest.java
new file mode 100644
index 00000000000..afc2b3f4b48
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorIllegalImportTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.validator;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.annotation.DirtiesContext;
+
+/**
+ *
+ */
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+ classes = {
+ CamelAutoConfiguration.class,
+ ValidatorIllegalImportTest.class
+ }
+)
+public class ValidatorIllegalImportTest extends ContextTestSupport {
+
+ private final String broadCastEvent
+ = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
+ "<BroadcastMonitor> "
+ + "<updated>2012-03-01T03:46:26</updated>"
+ + "<stationName>P7 Mix</stationName>" + "<Current>" +
"<startTime>2012-03-01T03:46:26</startTime>"
+ + "<itemId>1000736343:8505553</itemId>"
+ + "<titleId>785173</titleId>" +
"<itemCode>9004342-0101</itemCode>" + "<itemReference></itemReference>"
+ + "<titleName>Part Of Me</titleName>" + "<artistName>Katy
Perry</artistName>" + "<albumName></albumName>"
+ + "</Current>" + "<Next>"
+ + "<startTime>2012-03-01T03:50:00</startTime>" +
"<itemId>1000736343:8505554</itemId>"
+ + "<titleId>780319</titleId>"
+ + "<itemCode>2318050-0101</itemCode>" +
"<itemReference></itemReference>" + "<titleName>Fine</titleName>"
+ + "<artistName>Whitney Houston</artistName>" +
"<albumName></albumName>" + "</Next>" + "</BroadcastMonitor>";
+
+ @Test
+ public void testOk() throws Exception {
+ context.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+
from("direct:test").to("validator:org/apache/camel/component/validator/BroadcastMonitorFixed.xsd")
+ .to("mock:result");
+ }
+ });
+
+ MockEndpoint mock = context.getEndpoint("mock:result",
MockEndpoint.class);
+ mock.expectedMessageCount(1);
+ template.sendBody("direct:test", broadCastEvent);
+ mock.assertIsSatisfied();
+ }
+
+ @Test
+ public void testIllegalImport() throws Exception {
+ try {
+ context.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+
from("direct:test").to("validator:org/apache/camel/component/validator/BroadcastMonitor.xsd").to("mock:result");
+ }
+ });
+ fail("Should have thrown exception");
+ } catch (Exception e) {
+ IllegalArgumentException iae =
assertIsInstanceOf(IllegalArgumentException.class, e.getCause().getCause());
+ assertTrue(iae.getMessage().startsWith(
+ "Resource:
org/apache/camel/component/validator/BroadcastMonitor.xsd refers an invalid
resource without SystemId."));
+ }
+ }
+}
diff --git
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorIncludeEncodingRouteTest.java
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorIncludeEncodingRouteTest.java
new file mode 100644
index 00000000000..91b74016de0
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorIncludeEncodingRouteTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.validator;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+/**
+ *
+ */
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+ classes = {
+ CamelAutoConfiguration.class,
+ ValidatorIncludeEncodingRouteTest.class
+ }
+)
+public class ValidatorIncludeEncodingRouteTest extends ContextTestSupport {
+
+ protected MockEndpoint validEndpoint;
+ protected MockEndpoint finallyEndpoint;
+ protected MockEndpoint invalidEndpoint;
+
+ @Test
+ public void testValidMessage() throws Exception {
+ validEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+
+ String body = "<t:text xmlns:t=\"org.text\">\n" + "
<t:sentence>J'aime les cam\u00E9lid\u00E9s</t:sentence>\n"
+ + "</t:text>";
+
+ template.sendBody("direct:start", body);
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint,
finallyEndpoint);
+ }
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ validEndpoint = context.getEndpoint("mock:valid", MockEndpoint.class);
+ invalidEndpoint = context.getEndpoint("mock:invalid",
MockEndpoint.class);
+ finallyEndpoint = context.getEndpoint("mock:finally",
MockEndpoint.class);
+
+ validEndpoint.reset();
+ invalidEndpoint.reset();
+ finallyEndpoint.reset();
+ }
+
+ @Bean
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+
from("direct:start").doTry().to("validator:org/apache/camel/component/validator/text.xsd").to("mock:valid")
+ .doCatch(NumberFormatException.class)
+ .process(new Processor() {
+ @Override
+ public void process(Exchange exchange) throws
Exception {
+ System.err.println("helo " +
exchange.getException());
+ }
+
}).to("mock:invalid").doFinally().to("mock:finally").end();
+ }
+ };
+ }
+
+}
diff --git
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorIncludeRelativeRouteTest.java
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorIncludeRelativeRouteTest.java
new file mode 100644
index 00000000000..929ef1dc31f
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorIncludeRelativeRouteTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.validator;
+
+import org.apache.camel.ValidationException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+ classes = {
+ CamelAutoConfiguration.class,
+ ValidatorIncludeRelativeRouteTest.class
+ }
+)
+public class ValidatorIncludeRelativeRouteTest extends
ValidatorIncludeRouteTest {
+
+ @Override
+ @Test
+ public void testValidMessage() throws Exception {
+ validEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+
+ String body
+ = "<p:person user=\"james\" xmlns:p=\"org.person\"
xmlns:h=\"org.health.check.person\" xmlns:c=\"org.health.check.common\">\n"
+ + " <p:firstName>James</p:firstName>\n" + "
<p:lastName>Strachan</p:lastName>\n"
+ + " <p:city>London</p:city>\n" + " <h:health>\n"
+ + " <h:lastCheck>2011-12-23</h:lastCheck>\n" + "
<h:status>OK</h:status>\n"
+ + " <c:commonElement>" + " <c:element1/>"
+ + " <c:element2/>" + " </c:commonElement>" + "
</h:health>\n" + "</p:person>";
+
+ template.sendBody("direct:start", body);
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint,
finallyEndpoint);
+ }
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ validEndpoint = context.getEndpoint("mock:valid", MockEndpoint.class);
+ invalidEndpoint = context.getEndpoint("mock:invalid",
MockEndpoint.class);
+ finallyEndpoint = context.getEndpoint("mock:finally",
MockEndpoint.class);
+
+ validEndpoint.reset();
+ invalidEndpoint.reset();
+ finallyEndpoint.reset();
+ }
+
+ @Bean
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+
from("direct:start").doTry().to("validator:org/apache/camel/component/validator/xsds/person.xsd")
+ .to("mock:valid").doCatch(ValidationException.class)
+
.to("mock:invalid").doFinally().to("mock:finally").end();
+ }
+ };
+ }
+
+}
diff --git
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorIncludeRouteTest.java
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorIncludeRouteTest.java
new file mode 100644
index 00000000000..e553c5ad087
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorIncludeRouteTest.java
@@ -0,0 +1,159 @@
+/*
+ * 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.validator;
+
+import org.apache.camel.ValidationException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+/**
+ *
+ */
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+ classes = {
+ CamelAutoConfiguration.class,
+ ValidatorIncludeRouteTest.class
+ }
+)
+public class ValidatorIncludeRouteTest extends ContextTestSupport {
+
+ protected MockEndpoint validEndpoint;
+ protected MockEndpoint finallyEndpoint;
+ protected MockEndpoint invalidEndpoint;
+
+ @Test
+ public void testValidMessage() throws Exception {
+ validEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+
+ String body = "<p:person user=\"james\" xmlns:p=\"org.person\"
xmlns:h=\"org.health.check.person\">\n"
+ + " <p:firstName>James</p:firstName>\n"
+ + " <p:lastName>Strachan</p:lastName>\n" + "
<p:city>London</p:city>\n" + " <h:health>\n"
+ + " <h:lastCheck>2011-12-23</h:lastCheck>\n"
+ + " <h:status>OK</h:status>\n" + " </h:health>\n"
+ "</p:person>";
+
+ template.sendBody("direct:start", body);
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint,
finallyEndpoint);
+ }
+
+ @Test
+ public void testValidMessageNoHealth() throws Exception {
+ validEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+
+ String body = "<p:person user=\"hiram\" xmlns:p=\"org.person\"
xmlns:h=\"org.health.check.person\">\n"
+ + " <p:firstName>Hiram</p:firstName>\n"
+ + " <p:lastName>Chirino</p:lastName>\n" + "
<p:city>Tampa</p:city>\n" + "</p:person>";
+
+ template.sendBody("direct:start", body);
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint,
finallyEndpoint);
+ }
+
+ @Test
+ public void testValidMessageNoHealthNoNamespace() throws Exception {
+ validEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+
+ String body = "<p:person user=\"hiram\" xmlns:p=\"org.person\">\n" +
" <p:firstName>Hiram</p:firstName>\n"
+ + " <p:lastName>Chirino</p:lastName>\n"
+ + " <p:city>Tampa</p:city>\n" + "</p:person>";
+
+ template.sendBody("direct:start", body);
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint,
finallyEndpoint);
+ }
+
+ @Test
+ public void testInvalidMessage() throws Exception {
+ invalidEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+
+ String body = "<p:person user=\"james\" xmlns:p=\"org.person\"
xmlns:h=\"org.health.check.person\">\n"
+ + " <p:firstName>James</p:firstName>\n"
+ + " <p:lastName>Strachan</p:lastName>\n" + "
<p:city>London</p:city>\n" + " <h:health>\n"
+ + " <h:lastCheck>2011-12-23</h:lastCheck>\n"
+ + " </h:health>\n" + "</p:person>";
+
+ template.sendBody("direct:start", body);
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint,
finallyEndpoint);
+ }
+
+ @Test
+ public void testInvalidMessageNoHealth() throws Exception {
+ invalidEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+
+ String body = "<p:person user=\"james\" xmlns:p=\"org.person\"
xmlns:h=\"org.health.check.person\">\n"
+ + " <p:firstName>James</p:firstName>\n"
+ + " <p:lastName>Strachan</p:lastName>\n" +
"</p:person>";
+
+ template.sendBody("direct:start", body);
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint,
finallyEndpoint);
+ }
+
+ @Test
+ public void testInvalidMessageNoHealthNoNamespace() throws Exception {
+ invalidEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+
+ String body = "<p:person user=\"james\" xmlns:p=\"org.person\">\n" + "
<p:firstName>James</p:firstName>\n"
+ + " <p:lastName>Strachan</p:lastName>\n" +
"</p:person>";
+
+ template.sendBody("direct:start", body);
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint,
finallyEndpoint);
+ }
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ validEndpoint = context.getEndpoint("mock:valid", MockEndpoint.class);
+ invalidEndpoint = context.getEndpoint("mock:invalid",
MockEndpoint.class);
+ finallyEndpoint = context.getEndpoint("mock:finally",
MockEndpoint.class);
+
+ validEndpoint.reset();
+ invalidEndpoint.reset();
+ finallyEndpoint.reset();
+ }
+
+ @Bean
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+
from("direct:start").doTry().to("validator:org/apache/camel/component/validator/person.xsd").to("mock:valid")
+ .doCatch(ValidationException.class).to("mock:invalid")
+ .doFinally().to("mock:finally").end();
+ }
+ };
+ }
+
+}
diff --git
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorLazyStartProducerTest.java
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorLazyStartProducerTest.java
new file mode 100644
index 00000000000..1d564c36310
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorLazyStartProducerTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.validator;
+
+import java.io.FileNotFoundException;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.fail;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+ classes = {
+ CamelAutoConfiguration.class,
+ ValidatorLazyStartProducerTest.class
+ }
+)
+public class ValidatorLazyStartProducerTest extends ContextTestSupport {
+
+ @Test
+ public void testLazyStartProducerFail() throws Exception {
+ MockEndpoint mock = context.getEndpoint("mock:result",
MockEndpoint.class);
+ mock.reset();
+ mock.expectedMessageCount(0);
+
+ try {
+ template.sendBody("direct:fail",
+ "<mail
xmlns='http://foo.com/bar'><subject>Hey</subject><body>Hello
world!</body></mail>");
+ fail("Should throw exception");
+ } catch (Exception e) {
+ assertIsInstanceOf(FileNotFoundException.class, e.getCause());
+ }
+
+ mock.assertIsSatisfied();
+ }
+
+ @Test
+ public void testLazyStartProducerOk() throws Exception {
+ MockEndpoint mock = context.getEndpoint("mock:result",
MockEndpoint.class);
+ mock.reset();
+ mock.expectedMessageCount(1);
+
+ template.sendBody("direct:ok",
+ "<mail
xmlns='http://foo.com/bar'><subject>Hey</subject><body>Hello
world!</body></mail>");
+
+ mock.assertIsSatisfied();
+ }
+
+ @Bean
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+
from("direct:fail").to("validator:org/apache/camel/component/validator/unknown.xsd?lazyStartProducer=true")
+ .to("mock:result");
+
+
from("direct:ok").to("validator:org/apache/camel/component/validator/schema.xsd?lazyStartProducer=true")
+ .to("mock:result");
+ }
+ };
+ }
+}
diff --git
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorResourceResolverFactoryTest.java
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorResourceResolverFactoryTest.java
new file mode 100644
index 00000000000..b8286647b09
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorResourceResolverFactoryTest.java
@@ -0,0 +1,223 @@
+/*
+ * 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.validator;
+
+import java.io.InputStream;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+import org.w3c.dom.ls.LSInput;
+import org.w3c.dom.ls.LSResourceResolver;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.model.language.ConstantExpression;
+import org.apache.camel.model.language.SimpleExpression;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import static org.awaitility.Awaitility.await;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+ classes = {
+ CamelAutoConfiguration.class,
+ ValidatorResourceResolverFactoryTest.class
+ }
+)
+public class ValidatorResourceResolverFactoryTest extends ContextTestSupport {
+
+ private static Context jndiContext;
+
+ @Test
+ public void testConfigurationOnEndpoint() throws Exception {
+ // ensure that validator from test method
"testConfigurationOnComponent"
+ // is unbind
+ jndiContext.unbind("validator");
+
+ String directStart = "direct:start";
+ String endpointUri
+ =
"validator:org/apache/camel/component/validator/xsds/person.xsd?resourceResolverFactory=#resourceResolverFactory";
+
+ execute(directStart, endpointUri);
+ }
+
+ @Test
+ public void testConfigurationOnComponent() throws Exception {
+ // set resource resolver factory on component
+ ValidatorComponent validatorComponent = new ValidatorComponent();
+ validatorComponent.setResourceResolverFactory(new
ResourceResolverFactoryImpl());
+ jndiContext.bind("validator", validatorComponent);
+
+ String directStart = "direct:startComponent";
+ String endpointUri =
"customValidator:org/apache/camel/component/validator/xsds/person.xsd";
+ execute(directStart, endpointUri);
+
+ }
+
+ @Bean
+ public ValidatorComponent customValidator() {
+ ValidatorComponent validatorComponent = new ValidatorComponent();
+ validatorComponent.setResourceResolverFactory(new
ResourceResolverFactoryImpl());
+
+ return validatorComponent;
+ }
+
+ void execute(String directStart, String endpointUri) throws
InterruptedException {
+ MockEndpoint endEndpoint = context.getEndpoint("mock:end",
MockEndpoint.class);
+ endEndpoint.reset();
+ endEndpoint.expectedMessageCount(1);
+
+ final String body
+ = "<p:person user=\"james\" xmlns:p=\"org.person\"
xmlns:h=\"org.health.check.person\" xmlns:c=\"org.health.check.common\">\n" //
+ + " <p:firstName>James</p:firstName>\n" //
+ + " <p:lastName>Strachan</p:lastName>\n" //
+ + " <p:city>London</p:city>\n" //
+ + " <h:health>\n"//
+ + " <h:lastCheck>2011-12-23</h:lastCheck>\n" //
+ + " <h:status>OK</h:status>\n" //
+ + " <c:commonElement>" //
+ + " <c:element1/>" //
+ + " <c:element2/>" //
+ + " </c:commonElement>" //
+ + " </h:health>\n" //
+ + "</p:person>";
+
+ template.sendBody(directStart, body);
+
+ // wait until endpoint is resolved
+ await().atMost(1, TimeUnit.SECONDS).until(() ->
context.getEndpoint(endpointUri, ValidatorEndpoint.class) != null);
+
+ MockEndpoint.assertIsSatisfied(endEndpoint);
+
+ ValidatorEndpoint validatorEndpoint = context.getEndpoint(endpointUri,
ValidatorEndpoint.class);
+ assertNotNull(validatorEndpoint);
+ CustomResourceResolver resolver = (CustomResourceResolver)
validatorEndpoint.getResourceResolver();
+
+ Set<String> uris = resolver.getResolvedResourceUris();
+ checkResourceUri(uris, "../type2.xsd");
+ checkResourceUri(uris, "health/health.xsd");
+ checkResourceUri(uris, "type1.xsd");
+ checkResourceUri(uris, "common/common.xsd");
+ }
+
+ void checkResourceUri(Set<String> uris, String resourceUri) {
+ assertTrue(uris.contains(resourceUri), "Missing resource uri " +
resourceUri + " in resolved resource URI set");
+ }
+
+// @Override
+// protected Registry createRegistry() throws Exception {
+// jndiContext = createJndiContext();
+// jndiContext.bind("resourceResolverFactory", new
ResourceResolverFactoryImpl());
+// return new DefaultRegistry(new JndiBeanRepository(jndiContext));
+//
+// }
+
+ public static Context createInitialContext() throws Exception {
+ try (InputStream in =
ValidatorResourceResolverFactoryTest.class.getClassLoader().getResourceAsStream("jndi-example.properties");)
{
+ assertNotNull(in, "Cannot find jndi-example.properties on the
classpath!");
+ Properties properties = new Properties();
+ properties.load(in);
+ return new InitialContext(new Hashtable<>(properties));
+ }
+ }
+
+ @Bean
+ public ResourceResolverFactoryImpl resourceResolverFactory() {
+ return new ResourceResolverFactoryImpl();
+ }
+
+ @BeforeAll
+ public static void beforeAll() throws Exception {
+ jndiContext = createInitialContext();
+ jndiContext.bind("resourceResolverFactory", new
ResourceResolverFactoryImpl());
+ }
+
+ @Bean
+ protected RouteBuilder routeBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start")
+ .setHeader("xsd_file", new
ConstantExpression("org/apache/camel/component/validator/xsds/person.xsd"))
+ .recipientList(new SimpleExpression(
+
"validator:${header.xsd_file}?resourceResolverFactory=#resourceResolverFactory"))
+ .to("mock:end");
+ }
+ };
+ }
+
+ @Bean
+ protected RouteBuilder routeBuilderComponent() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:startComponent")
+ .setHeader("xsd_file", new
ConstantExpression("org/apache/camel/component/validator/xsds/person.xsd"))
+ .recipientList(new
SimpleExpression("customValidator:${header.xsd_file}")).to("mock:end");
+ }
+ };
+ }
+
+ static class ResourceResolverFactoryImpl implements
ValidatorResourceResolverFactory {
+
+ @Override
+ public LSResourceResolver createResourceResolver(CamelContext
camelContext, String rootResourceUri) {
+ return new CustomResourceResolver(camelContext, rootResourceUri);
+ }
+
+ }
+
+ /** Custom resource resolver which collects all resolved resource URIs. */
+ static class CustomResourceResolver extends DefaultLSResourceResolver {
+
+ private final Set<String> resolvedRsourceUris = new HashSet<>();
+
+ CustomResourceResolver(CamelContext camelContext, String resourceUri) {
+ super(camelContext, resourceUri);
+ }
+
+ public Set<String> getResolvedResourceUris() {
+ return resolvedRsourceUris;
+ }
+
+ @Override
+ public LSInput resolveResource(String type, String namespaceURI,
String publicId, String systemId, String baseURI) {
+ LSInput result = super.resolveResource(type, namespaceURI,
publicId, systemId, baseURI);
+ resolvedRsourceUris.add(systemId);
+ return result;
+ }
+
+ }
+
+}
diff --git
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorRootPathTest.java
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorRootPathTest.java
new file mode 100644
index 00000000000..d867e60bd73
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorRootPathTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.validator;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+ classes = {
+ CamelAutoConfiguration.class,
+ ValidatorRootPathTest.class
+ }
+)
+public class ValidatorRootPathTest extends ContextTestSupport {
+
+ protected MockEndpoint validEndpoint;
+ protected MockEndpoint invalidEndpoint;
+
+ @Test
+ public void testRootPath() throws Exception {
+ validEndpoint.expectedMessageCount(1);
+ invalidEndpoint.expectedMessageCount(0);
+
+ template
+ .sendBody("direct:rootPath",
+ "<report xmlns='http://foo.com/report'
xmlns:rb='http://foo.com/report-base'><author><rb:name>Knuth</rb:name></author><content><rb:chapter><rb:subject></rb:subject>"
+ +
"<rb:abstract></rb:abstract><rb:body></rb:body></rb:chapter></content></report>");
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint);
+ }
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ validEndpoint = context.getEndpoint("mock:valid", MockEndpoint.class);
+ invalidEndpoint = context.getEndpoint("mock:invalid",
MockEndpoint.class);
+
+ validEndpoint.reset();
+ invalidEndpoint.reset();
+ }
+
+ @Bean
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+
from("direct:rootPath").to("validator:report.xsd").to("mock:valid");
+ }
+ };
+ }
+
+}
diff --git
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorRouteTest.java
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorRouteTest.java
new file mode 100644
index 00000000000..9f54a605493
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorRouteTest.java
@@ -0,0 +1,236 @@
+/*
+ * 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.validator;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.ValidationException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import
org.apache.camel.support.processor.validation.NoXmlHeaderValidationException;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+ classes = {
+ CamelAutoConfiguration.class,
+ ValidatorRouteTest.class
+ }
+)
+public class ValidatorRouteTest extends ContextTestSupport {
+
+ @Autowired
+ private ProducerTemplate template;
+
+ @Autowired
+ private CamelContext context;
+
+ @Test
+ public void testValidMessage() throws Exception {
+ validEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+
+ template.sendBody("direct:start",
+ "<mail
xmlns='http://foo.com/bar'><subject>Hey</subject><body>Hello
world!</body></mail>");
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint,
finallyEndpoint);
+ }
+
+ @Test
+ 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);
+ }
+
+ @Test
+ public void testInvalidMessage() throws Exception {
+ invalidEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+
+ template.sendBody("direct:start", "<mail
xmlns='http://foo.com/bar'><body>Hello world!</body></mail>");
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint,
finallyEndpoint);
+ }
+
+ @Test
+ 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);
+ }
+
+ @Test
+ public void testNullHeaderNoFail() throws Exception {
+ validEndpoint.expectedMessageCount(1);
+
+ template.sendBodyAndHeader("direct:startNullHeaderNoFail", null,
"headerToValidate", null);
+
+ MockEndpoint.assertIsSatisfied(validEndpoint);
+ }
+
+ @Test
+ public void testNullHeader() throws Exception {
+ validEndpoint.setExpectedMessageCount(0);
+
+ Exchange in =
context.getEndpoint("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(out.isFailed(), "Should be failed");
+ boolean b = exception instanceof NoXmlHeaderValidationException;
+ assertTrue(b, "Exception should be correct type");
+ assertTrue(exception.getMessage().contains("headerToValidate"),
"Exception should mention missing header");
+ }
+
+ @Test
+ public void testInvalideBytesMessage() throws Exception {
+ invalidEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+
+ template.sendBody("direct:start", "<mail
xmlns='http://foo.com/bar'><body>Hello world!</body></mail>".getBytes());
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint,
finallyEndpoint);
+ }
+
+ @Test
+ 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);
+ }
+
+ @Test
+ public void testUseNotASharedSchema() throws Exception {
+ validEndpoint.expectedMessageCount(1);
+
+ template.sendBody("direct:useNotASharedSchema",
+ "<mail
xmlns='http://foo.com/bar'><subject>Hey</subject><body>Hello
world!</body></mail>");
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint,
finallyEndpoint);
+ }
+
+ @Test
+ public void testConcurrentUseNotASharedSchema() throws Exception {
+ validEndpoint.expectedMessageCount(10);
+ // latch for the 10 exchanges we expect
+ final CountDownLatch latch = new CountDownLatch(10);
+ // setup a task executor to be able send the messages in parallel
+ ExecutorService executor = Executors.newCachedThreadPool();
+ for (int i = 0; i < 10; i++) {
+ executor.execute(new Runnable() {
+ public void run() {
+ template.requestBody("direct:useNotASharedSchema",
+ "<mail
xmlns='http://foo.com/bar'><subject>Hey</subject><body>Hello
world!</body></mail>");
+ latch.countDown();
+ }
+ });
+ }
+
+ try {
+ // wait for test completion, timeout after 30 sec to let other unit
+ // test run to not wait forever
+ assertTrue(latch.await(30000L, TimeUnit.MILLISECONDS));
+ assertEquals(0, latch.getCount(), "Latch should be zero");
+ } finally {
+ executor.shutdown();
+ }
+ MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint,
finallyEndpoint);
+ }
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ validEndpoint = context.getEndpoint("mock:valid", MockEndpoint.class);
+ invalidEndpoint = context.getEndpoint("mock:invalid",
MockEndpoint.class);
+ finallyEndpoint = context.getEndpoint("mock:finally",
MockEndpoint.class);
+ }
+
+ @AfterEach
+ public void reset() {
+ validEndpoint.reset();
+ invalidEndpoint.reset();
+ finallyEndpoint.reset();
+ }
+
+ @Bean
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+
from("direct:start").doTry().to("validator:org/apache/camel/component/validator/schema.xsd").to("mock:valid")
+ .doCatch(ValidationException.class).to("mock:invalid")
+ .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");
+
+ from("direct:useNotASharedSchema")
+
.to("validator:org/apache/camel/component/validator/schema.xsd?useSharedSchema=false").to("mock:valid");
+ }
+ };
+ }
+
+}
diff --git
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorWithResourceResolverRouteTest.java
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorWithResourceResolverRouteTest.java
new file mode 100644
index 00000000000..fc3654cd2ce
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorWithResourceResolverRouteTest.java
@@ -0,0 +1,109 @@
+/*
+ * 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.validator;
+
+import java.net.URL;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+import org.w3c.dom.ls.LSResourceResolver;
+
+import org.apache.camel.ValidationException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.processor.validation.CatalogLSResourceResolver;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.support.ResourceHelper;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.apache.xml.resolver.CatalogManager;
+import org.apache.xml.resolver.tools.CatalogResolver;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+ classes = {
+ CamelAutoConfiguration.class,
+ ValidatorWithResourceResolverRouteTest.class
+ }
+)
+public class ValidatorWithResourceResolverRouteTest extends ContextTestSupport
{
+
+ protected MockEndpoint validEndpoint;
+ protected MockEndpoint finallyEndpoint;
+ protected MockEndpoint invalidEndpoint;
+
+ @Test
+ public void testValidMessage() throws Exception {
+ validEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+ invalidEndpoint.expectedMessageCount(0);
+ template
+ .sendBody("direct:start",
+ "<report xmlns='http://foo.com/report'
xmlns:rb='http://foo.com/report-base'><author><rb:name>Knuth</rb:name></author><content><rb:chapter><rb:subject></rb:subject>"
+ +
"<rb:abstract></rb:abstract><rb:body></rb:body></rb:chapter></content></report>");
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint,
finallyEndpoint);
+ }
+
+ @Test
+ public void testInvalidMessage() throws Exception {
+ validEndpoint.expectedMessageCount(0);
+ invalidEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+
+ template.sendBody("direct:start",
+ "<report xmlns='http://foo.com/report'
xmlns:rb='http://foo.com/report-base'><author><rb:name>Knuth</rb:name></author></report>");
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint,
finallyEndpoint);
+ }
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ validEndpoint = context.getEndpoint("mock:valid", MockEndpoint.class);
+ invalidEndpoint = context.getEndpoint("mock:invalid",
MockEndpoint.class);
+ finallyEndpoint = context.getEndpoint("mock:finally",
MockEndpoint.class);
+
+ validEndpoint.reset();
+ invalidEndpoint.reset();
+ finallyEndpoint.reset();
+ }
+
+ @Bean
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ // we have to do it here, because we need the context created first
+ CatalogManager.getStaticManager().setIgnoreMissingProperties(true);
+ CatalogResolver catalogResolver = new CatalogResolver(true);
+ URL catalogUrl = ResourceHelper.resolveMandatoryResourceAsUrl(context,
+ "org/apache/camel/component/validator/catalog.cat");
+ catalogResolver.getCatalog().parseCatalog(catalogUrl);
+ LSResourceResolver resourceResolver = new
CatalogLSResourceResolver(catalogResolver);
+ context.getRegistry().bind("resourceResolver", resourceResolver);
+
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start").doTry()
+
.to("validator:org/apache/camel/component/validator/report.xsd?resourceResolver=#resourceResolver")
+ .to("mock:valid")
+
.doCatch(ValidationException.class).to("mock:invalid").doFinally().to("mock:finally").end();
+ }
+ };
+ }
+}
diff --git
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/processor/validation/CatalogLSResourceResolver.java
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/processor/validation/CatalogLSResourceResolver.java
new file mode 100644
index 00000000000..a4edce20c37
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/processor/validation/CatalogLSResourceResolver.java
@@ -0,0 +1,177 @@
+/*
+ * 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 java.io.InputStream;
+import java.io.Reader;
+
+import org.w3c.dom.ls.LSInput;
+import org.w3c.dom.ls.LSResourceResolver;
+
+import org.xml.sax.InputSource;
+
+import org.apache.xml.resolver.tools.CatalogResolver;
+
+public class CatalogLSResourceResolver implements LSResourceResolver {
+
+ CatalogResolver catalogResolver;
+
+ public CatalogLSResourceResolver() {
+ }
+
+ public CatalogLSResourceResolver(CatalogResolver catalogResolver) {
+ this.catalogResolver = catalogResolver;
+ }
+
+ public CatalogResolver getCatalogResolver() {
+ return catalogResolver;
+ }
+
+ public void setCatalogResolver(CatalogResolver catalogResolver) {
+ this.catalogResolver = catalogResolver;
+ }
+
+ @Override
+ public LSInput resolveResource(String type, String namespaceURI, String
publicId, String systemId, String baseURI) {
+ return new LSInputSource(namespaceURI, publicId, systemId,
baseURI);
+ }
+
+ class LSInputSource implements LSInput {
+ private InputSource inputSource;
+ private String publicId;
+ private String systemId;
+ private String baseURI;
+
+ LSInputSource(String namespaceURI, String publicId, String
systemId, String baseURI) {
+ if (publicId == null) {
+ publicId = namespaceURI;
+ }
+
+ this.publicId = publicId;
+ this.systemId = systemId;
+ this.baseURI = baseURI;
+
+ if (catalogResolver == null) {
+ throw new
IllegalStateException("catalogResolver must be provided");
+ }
+
+ this.inputSource =
catalogResolver.resolveEntity(publicId, systemId);
+ }
+
+ @Override
+ public Reader getCharacterStream() {
+ return null;
+ }
+
+ @Override
+ public void setCharacterStream(Reader characterStream) {
+ // noop
+ }
+
+ @Override
+ public InputStream getByteStream() {
+ return inputSource != null ?
inputSource.getByteStream() : null;
+ }
+
+ @Override
+ public void setByteStream(InputStream byteStream) {
+ if (inputSource != null) {
+ inputSource.setByteStream(byteStream);
+ }
+ }
+
+ @Override
+ public String getStringData() {
+ return null;
+ }
+
+ @Override
+ public void setStringData(String stringData) {
+ // noop
+ }
+
+ @Override
+ public String getSystemId() {
+ if (inputSource != null) {
+ return inputSource.getSystemId();
+ }
+
+ return systemId;
+ }
+
+ @Override
+ public void setSystemId(String systemId) {
+ if (inputSource != null) {
+ inputSource.setSystemId(systemId);
+ }
+ }
+
+ @Override
+ public String getPublicId() {
+ if (inputSource != null) {
+ return inputSource.getPublicId();
+ }
+
+ return publicId;
+ }
+
+ @Override
+ public void setPublicId(String publicId) {
+ if (inputSource != null) {
+ inputSource.setPublicId(publicId);
+ } else {
+ this.publicId = publicId;
+ }
+ }
+
+ @Override
+ public String getBaseURI() {
+ return baseURI;
+ }
+
+ @Override
+ public void setBaseURI(String baseURI) {
+ // noop
+ }
+
+ @Override
+ public String getEncoding() {
+ if (inputSource != null) {
+ return inputSource.getEncoding();
+ }
+
+ return null;
+ }
+
+ @Override
+ public void setEncoding(String encoding) {
+ if (inputSource != null) {
+ inputSource.setEncoding(encoding);
+ }
+ }
+
+ @Override
+ public boolean getCertifiedText() {
+ return true;
+ }
+
+ @Override
+ public void setCertifiedText(boolean certifiedText) {
+ // noop
+ }
+ }
+}
diff --git
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/urlhandler/pd/Handler.java
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/urlhandler/pd/Handler.java
new file mode 100644
index 00000000000..6ab9168970c
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/urlhandler/pd/Handler.java
@@ -0,0 +1,85 @@
+/*
+ * 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.urlhandler.pd;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.camel.spi.Resource;
+import org.apache.camel.support.ResourceResolverSupport;
+import org.apache.camel.support.ResourceSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Class to simulate a change of the XSD document. During the first call of
the resource a XSD is returned which does
+ * not fit to the XML document. In the second call a XSD fitting to the XML
document is returned. Used in
+ * org.apache.camel.component.validator.ValidatorEndpointClearCachedSchemaTest
+ */
+public class Handler extends ResourceResolverSupport {
+ private static final Logger LOG =
LoggerFactory.getLogger(Handler.class);
+
+ // wrong element name will cause the validation to fail
+ private static final String XSD_TEMPLATE_1 = "<?xml version=\"1.0\"
encoding=\"UTF-8\"?>\n" +
+ "<xsd:schema
targetNamespace=\"http://apache.camel.org/test\" " +
+ " xmlns=\"http://apache.camel.org/test\" " +
+ "
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" +
+ " <xsd:complexType name=\"TestMessage\">" +
+ " <xsd:sequence>" +
+ " <xsd:element name=\"Content\"
type=\"xsd:string\" />" +
+ " </xsd:sequence>" +
+ " <xsd:attribute name=\"attr\"
type=\"xsd:string\" default=\"xsd1\"/>" +
+ " </xsd:complexType>" +
+ " <xsd:element name=\"TestMessage\"
type=\"TestMessage\" />" +
+ "</xsd:schema>";
+
+ // correct element name, the validation will be corerct
+ private static final String XSD_TEMPLATE_2 =
XSD_TEMPLATE_1.replace("\"Content\"", "\"MessageContent\"");
+
+ private final AtomicInteger counter;
+
+ public Handler() {
+ super("pd");
+
+ this.counter = new AtomicInteger();
+ }
+
+ @Override
+ protected Resource createResource(String location, String remaining) {
+ return new ResourceSupport("mem", location) {
+ @Override
+ public boolean exists() {
+ return true;
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ if (counter.getAndIncrement() == 0) {
+ LOG.info("resolved XSD1");
+ return new
ByteArrayInputStream(XSD_TEMPLATE_1.getBytes(StandardCharsets.UTF_8));
+ } else {
+ LOG.info("resolved XSD2");
+
+ return new
ByteArrayInputStream(XSD_TEMPLATE_2.getBytes(StandardCharsets.UTF_8));
+ }
+ }
+ };
+ }
+}
diff --git
a/components-starter/camel-validator-starter/src/test/resources/jndi-example.properties
b/components-starter/camel-validator-starter/src/test/resources/jndi-example.properties
new file mode 100644
index 00000000000..3807dfc1e3d
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/resources/jndi-example.properties
@@ -0,0 +1,24 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+# START SNIPPET: jndi
+
+java.naming.factory.initial =
org.apache.camel.support.jndi.CamelInitialContextFactory
+
+# the following properties will be copied into the context
+foo = bar
+
+# END SNIPPET: jndi
diff --git
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/BroadcastMonitor.xsd
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/BroadcastMonitor.xsd
new file mode 100755
index 00000000000..a88a315bab7
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/BroadcastMonitor.xsd
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
+ <xs:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xs:element name="BroadcastMonitor">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="updated" type="xs:dateTime"
maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="stationName" type="xs:string"
maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="Current">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="startTime"
type="xs:dateTime" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="itemId"
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="titleId"
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="itemCode"
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element
name="itemReference" type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="titleName"
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="artistName"
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="albumName"
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Next">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="startTime"
type="xs:dateTime" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="itemId"
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="titleId"
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="itemCode"
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element
name="itemReference" type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="titleName"
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="artistName"
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="albumName"
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
\ No newline at end of file
diff --git
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/BroadcastMonitorFixed.xsd
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/BroadcastMonitorFixed.xsd
new file mode 100755
index 00000000000..5f5785faeb5
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/BroadcastMonitorFixed.xsd
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
+ <xs:element name="BroadcastMonitor">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="updated" type="xs:dateTime"
maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="stationName" type="xs:string"
maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="Current">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="startTime"
type="xs:dateTime" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="itemId"
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="titleId"
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="itemCode"
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element
name="itemReference" type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="titleName"
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="artistName"
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="albumName"
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Next">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="startTime"
type="xs:dateTime" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="itemId"
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="titleId"
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="itemCode"
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element
name="itemReference" type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="titleName"
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="artistName"
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ <xs:element name="albumName"
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
\ No newline at end of file
diff --git
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/catalog.cat
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/catalog.cat
new file mode 100644
index 00000000000..4a86ac6050c
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/catalog.cat
@@ -0,0 +1,2 @@
+PUBLIC "http://foo.com/report" "report.xsd"
+PUBLIC "http://foo.com/report-base" "report-base.xsd"
diff --git
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/health.xsd
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/health.xsd
new file mode 100644
index 00000000000..c6e29f1599c
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/health.xsd
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<xs:schema
+ attributeFormDefault="unqualified"
+ elementFormDefault="qualified"
+ targetNamespace="org.health.check.person"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:element name="health" type="org:healthType"
xmlns:org="org.health.check.person"/>
+ <xs:complexType name="healthType">
+ <xs:sequence>
+ <xs:element type="xs:string" name="lastCheck"/>
+ <xs:element type="xs:string" name="status"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/person.xsd
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/person.xsd
new file mode 100644
index 00000000000..d9256a3b12d
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/person.xsd
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<xs:schema attributeFormDefault="unqualified"
+ elementFormDefault="qualified"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:p="org.person"
+ targetNamespace="org.person"
+ xmlns:h="org.health.check.person">
+ <xs:import schemaLocation="health.xsd"
namespace="org.health.check.person"/>
+ <xs:element name="person" type="p:personType">
+</xs:element>
+<xs:complexType name="personType">
+ <xs:sequence>
+ <xs:element type="xs:string" name="firstName"/>
+ <xs:element type="xs:string" name="lastName"/>
+ <xs:element type="xs:string" name="city"/>
+ <xs:element ref="h:health" maxOccurs="1" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute type="xs:string" name="user"/>
+</xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/report-base.xsd
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/report-base.xsd
new file mode 100644
index 00000000000..d01ca831e67
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/report-base.xsd
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+ 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.
+
+-->
+<xs:schema elementFormDefault="qualified" version="1.0"
+ targetNamespace="http://foo.com/report-base"
+ xmlns:tns="http://foo.com/report-base"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+
+ <xs:element name="content" type="tns:content" />
+
+ <xs:complexType name="content">
+ <xs:sequence>
+ <xs:element name="chapter" type="tns:chapter"
maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="chapter">
+ <xs:sequence>
+ <xs:element name="subject" type="xs:string"/>
+ <xs:element name="abstract" type="xs:string"/>
+ <xs:element name="body" type="xs:string"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="person">
+ <xs:sequence>
+ <xs:element name="name" type="xs:string"/>
+ <xs:element name="email" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/report.xsd
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/report.xsd
new file mode 100644
index 00000000000..1ca8c386425
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/report.xsd
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+ 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.
+
+-->
+<xs:schema elementFormDefault="qualified" version="1.0"
+ targetNamespace="http://foo.com/report"
+ xmlns:rb="http://foo.com/report-base"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ <xs:import namespace="http://foo.com/report-base"
schemaLocation="http://foo.com/report-base.xsd" />
+
+ <xs:element name="report">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="author" type="rb:person" maxOccurs="unbounded" />
+ <xs:element name="content" type="rb:content" />
+ <xs:any namespace="##any" processContents="lax" minOccurs="0"
maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
diff --git
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/schema.xsd
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/schema.xsd
new file mode 100644
index 00000000000..11ea3a6cb15
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/schema.xsd
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+ 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.
+
+-->
+<xs:schema elementFormDefault="qualified" version="1.0"
+ targetNamespace="http://foo.com/bar"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+
+ <xs:element name="mail">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="subject" type="xs:string"/>
+ <xs:element name="body" type="xs:string"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+</xs:schema>
+
diff --git
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/sentence.xsd
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/sentence.xsd
new file mode 100644
index 00000000000..29662697905
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/sentence.xsd
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+
+ 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.
+
+-->
+<xs:schema attributeFormDefault="unqualified"
+ elementFormDefault="qualified" targetNamespace="org.text.sentence"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:simpleType name="sentence">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[a-zA-Zé' ]*" />
+ </xs:restriction>
+ </xs:simpleType>
+</xs:schema>
\ No newline at end of file
diff --git
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/text.xsd
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/text.xsd
new file mode 100644
index 00000000000..8cdbb14faad
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/text.xsd
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+
+ 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.
+
+-->
+<xs:schema attributeFormDefault="unqualified"
+ elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:p="org.text" targetNamespace="org.text"
xmlns:s="org.text.sentence">
+ <xs:import schemaLocation="sentence.xsd" namespace="org.text.sentence"
/>
+ <xs:element name="text" type="p:textType">
+ </xs:element>
+ <xs:complexType name="textType">
+ <xs:sequence>
+ <xs:element type="s:sentence" name="sentence"
minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/unsecuredSchema.xsd
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/unsecuredSchema.xsd
new file mode 100644
index 00000000000..8e21fe5f4f9
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/unsecuredSchema.xsd
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+ 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.
+
+-->
+<xs:schema elementFormDefault="qualified" version="1.0"
+ targetNamespace="http://foo.com/bar"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ <xs:element name="mail">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="subject" type="xs:string" minOccurs="1"
maxOccurs="999999999" />
+ <xs:element name="body" type="xs:string"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+</xs:schema>
+
diff --git
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/customer.xsd
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/customer.xsd
new file mode 100644
index 00000000000..73f4c1775c5
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/customer.xsd
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:complexType name="CustomerType">
+ <xs:sequence>
+ <xs:element name="name" type="CustNameType"/>
+ <xs:element name="number" type="xs:integer"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="CustNameType">
+ <xs:restriction base="xs:string"/>
+ </xs:simpleType>
+</xs:schema>
\ No newline at end of file
diff --git
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/health/common/common.xsd
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/health/common/common.xsd
new file mode 100644
index 00000000000..8156d768f8b
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/health/common/common.xsd
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<xs:schema
+ attributeFormDefault="unqualified"
+ elementFormDefault="qualified"
+ targetNamespace="org.health.check.common"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:element name="commonElement" type="common:commonType"
xmlns:common="org.health.check.common"/>
+ <xs:complexType name="commonType">
+ <xs:sequence>
+ <xs:element type="xs:string" name="element1"/>
+ <xs:element type="xs:string" name="element2"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/health/health.xsd
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/health/health.xsd
new file mode 100644
index 00000000000..01113757743
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/health/health.xsd
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<xs:schema
+ attributeFormDefault="unqualified"
+ elementFormDefault="qualified"
+ targetNamespace="org.health.check.person"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:common="org.health.check.common">
+ <xs:import schemaLocation="type1.xsd" namespace="org.health.check.type1" />
+ <xs:import schemaLocation="common/common.xsd"
namespace="org.health.check.common"/>
+ <xs:element name="health" type="org:healthType"
xmlns:org="org.health.check.person"/>
+
+ <xs:complexType name="healthType">
+ <xs:sequence>
+ <xs:element type="xs:string" name="lastCheck"/>
+ <xs:element type="xs:string" name="status"/>
+ <xs:element ref="common:commonElement" maxOccurs="1"
minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/health/type1.xsd
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/health/type1.xsd
new file mode 100644
index 00000000000..79e45d8c3b3
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/health/type1.xsd
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<xs:schema
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ elementFormDefault="qualified"
+ targetNamespace="org.health.check.type1">
+
+ <xs:import schemaLocation="../type2.xsd"
namespace="org.health.check.type2"/>
+ <xs:import schemaLocation="common/common.xsd"
namespace="org.health.check.common"/>
+
+</xs:schema>
\ No newline at end of file
diff --git
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/order.xsd
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/order.xsd
new file mode 100644
index 00000000000..543e608d578
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/order.xsd
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ targetNamespace="http://example.org/ord"
+ xmlns="http://example.org/ord"
+ xmlns:prod="http://example.org/prod">
+ <xs:include
schemaLocation="https://raw.githubusercontent.com/apache/camel/main/core/camel-core/src/test/resources/org/apache/camel/component/validator/xsds/customer.xsd"/>
+ <xs:import namespace="http://example.org/prod"
+
schemaLocation="https://raw.githubusercontent.com/apache/camel/main/core/camel-core/src/test/resources/org/apache/camel/component/validator/xsds/product.xsd"/>
+ <xs:element name="order" type="OrderType"/>
+ <xs:complexType name="OrderType">
+ <xs:sequence>
+ <xs:element name="customer" type="CustomerType"/>
+ <xs:element name="items" type="prod:ItemsType"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/person.xsd
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/person.xsd
new file mode 100644
index 00000000000..8f6757b56d9
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/person.xsd
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<xs:schema attributeFormDefault="unqualified"
+ elementFormDefault="qualified"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:p="org.person"
+ targetNamespace="org.person"
+ xmlns:h="org.health.check.person">
+ <xs:import schemaLocation="health/health.xsd"
namespace="org.health.check.person"/>
+ <xs:import schemaLocation="health/common/common.xsd"
namespace="org.health.check.common"/>
+ <xs:import schemaLocation="health/type1.xsd"
namespace="org.health.check.type1" />
+ <xs:element name="person" type="p:personType">
+</xs:element>
+<xs:complexType name="personType">
+ <xs:sequence>
+ <xs:element type="xs:string" name="firstName"/>
+ <xs:element type="xs:string" name="lastName"/>
+ <xs:element type="xs:string" name="city"/>
+ <xs:element ref="h:health" maxOccurs="1" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute type="xs:string" name="user"/>
+</xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/product.xsd
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/product.xsd
new file mode 100644
index 00000000000..a9946303f2a
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/product.xsd
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns="http://example.org/prod"
+ targetNamespace="http://example.org/prod">
+ <xs:complexType name="ItemsType">
+ <xs:sequence>
+ <xs:element name="product" type="ProductType"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ProductType">
+ <xs:sequence>
+ <xs:element name="number" type="xs:integer"/>
+ <xs:element name="name" type="xs:string"/>
+ <xs:element name="size" type="SizeType"/>
+ <xs:element name="color" type="ColorType"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="SizeType">
+ <xs:simpleContent>
+ <xs:extension base="xs:integer">
+ <xs:attribute name="system" type="xs:string"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="ColorType">
+ <xs:attribute name="value" type="xs:string"/>
+ </xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/type2.xsd
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/type2.xsd
new file mode 100644
index 00000000000..f227ac06dff
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/type2.xsd
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<xs:schema
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ elementFormDefault="qualified"
+ targetNamespace="org.health.check.type2">
+
+</xs:schema>
\ No newline at end of file
diff --git
a/components-starter/camel-validator-starter/src/test/resources/report-base.xsd
b/components-starter/camel-validator-starter/src/test/resources/report-base.xsd
new file mode 100644
index 00000000000..d01ca831e67
--- /dev/null
+++
b/components-starter/camel-validator-starter/src/test/resources/report-base.xsd
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+ 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.
+
+-->
+<xs:schema elementFormDefault="qualified" version="1.0"
+ targetNamespace="http://foo.com/report-base"
+ xmlns:tns="http://foo.com/report-base"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+
+ <xs:element name="content" type="tns:content" />
+
+ <xs:complexType name="content">
+ <xs:sequence>
+ <xs:element name="chapter" type="tns:chapter"
maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="chapter">
+ <xs:sequence>
+ <xs:element name="subject" type="xs:string"/>
+ <xs:element name="abstract" type="xs:string"/>
+ <xs:element name="body" type="xs:string"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="person">
+ <xs:sequence>
+ <xs:element name="name" type="xs:string"/>
+ <xs:element name="email" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git
a/components-starter/camel-validator-starter/src/test/resources/report.xsd
b/components-starter/camel-validator-starter/src/test/resources/report.xsd
new file mode 100644
index 00000000000..320865ad167
--- /dev/null
+++ b/components-starter/camel-validator-starter/src/test/resources/report.xsd
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+ 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.
+
+-->
+<xs:schema elementFormDefault="qualified" version="1.0"
+ targetNamespace="http://foo.com/report"
+ xmlns:rb="http://foo.com/report-base"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ <xs:import namespace="http://foo.com/report-base"
schemaLocation="report-base.xsd"/>
+
+ <xs:element name="report">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="author" type="rb:person" maxOccurs="unbounded"/>
+ <xs:element name="content" type="rb:content"/>
+ <xs:any namespace="##any" processContents="lax" minOccurs="0"
maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
\ No newline at end of file