Repository: camel Updated Branches: refs/heads/master 4d02c89bf -> d19e01ffa
Fix for CAMEL-8287 Allows a user to supply a custom URIResolver to be used to resolve imports in his/her schematron rules files. Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/ffb4b1cd Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/ffb4b1cd Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/ffb4b1cd Branch: refs/heads/master Commit: ffb4b1cd22f27767f320fcec5de13dd6aec27916 Parents: 4d02c89 Author: Johan MoÌreÌn <johan.mo...@kb.se> Authored: Mon Aug 15 15:14:27 2016 +0200 Committer: Johan MoÌreÌn <johan.mo...@kb.se> Committed: Mon Aug 15 15:14:27 2016 +0200 ---------------------------------------------------------------------- .../src/main/docs/schematron.adoc | 5 ++- .../schematron/SchematronEndpoint.java | 18 +++++++++- .../processor/ClassPathURIResolver.java | 21 ++++++++--- .../schematron/SchematronProducerTest.java | 2 +- .../processor/SchematronProcessorTest.java | 32 ++++++++++++++--- .../processor/TemplatesFactoryTest.java | 2 +- .../resources/custom-resolver/title-rules.sch | 20 +++++++++++ .../src/test/resources/sch/schematron-3.sch | 37 ++++++++++++++++++++ .../src/test/resources/xml/article-3.xml | 31 ++++++++++++++++ 9 files changed, 156 insertions(+), 12 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/ffb4b1cd/components/camel-schematron/src/main/docs/schematron.adoc ---------------------------------------------------------------------- diff --git a/components/camel-schematron/src/main/docs/schematron.adoc b/components/camel-schematron/src/main/docs/schematron.adoc index d456a5b..4974ee6 100644 --- a/components/camel-schematron/src/main/docs/schematron.adoc +++ b/components/camel-schematron/src/main/docs/schematron.adoc @@ -39,8 +39,9 @@ The Schematron component has no options. + // endpoint options: START -The Schematron component supports 5 endpoint options which are listed below: +The Schematron component supports 6 endpoint options which are listed below: {% raw %} [width="100%",cols="2s,1,1m,1m,5",options="header"] @@ -49,6 +50,7 @@ The Schematron component supports 5 endpoint options which are listed below: | path | producer | | String | *Required* The path to the schematron rules file. Can either be in class path or location in the file system. | abort | producer | false | boolean | Flag to abort the route and throw a schematron validation exception. | rules | producer | | Templates | To use the given schematron rules instead of loading from the path +| uriResolver | producer | | URIResolver | Set the URIResolver to be used for resolving schematron includes in the rules file. | exchangePattern | advanced | InOnly | ExchangePattern | Sets the default exchange pattern when creating an exchange | synchronous | advanced | false | boolean | Sets whether synchronous processing should be strictly used or Camel is allowed to use asynchronous processing (if supported). |======================================================================= @@ -56,6 +58,7 @@ The Schematron component supports 5 endpoint options which are listed below: // endpoint options: END + [[Schematron-Headers]] Headers ^^^^^^^ http://git-wip-us.apache.org/repos/asf/camel/blob/ffb4b1cd/components/camel-schematron/src/main/java/org/apache/camel/component/schematron/SchematronEndpoint.java ---------------------------------------------------------------------- diff --git a/components/camel-schematron/src/main/java/org/apache/camel/component/schematron/SchematronEndpoint.java b/components/camel-schematron/src/main/java/org/apache/camel/component/schematron/SchematronEndpoint.java index 1f1a92c..17e1414 100644 --- a/components/camel-schematron/src/main/java/org/apache/camel/component/schematron/SchematronEndpoint.java +++ b/components/camel-schematron/src/main/java/org/apache/camel/component/schematron/SchematronEndpoint.java @@ -21,6 +21,7 @@ import java.io.FileNotFoundException; import java.io.InputStream; import javax.xml.transform.Templates; import javax.xml.transform.TransformerFactory; +import javax.xml.transform.URIResolver; import org.apache.camel.Consumer; import org.apache.camel.Processor; @@ -59,6 +60,9 @@ public class SchematronEndpoint extends DefaultEndpoint { @UriParam private Templates rules; + @UriParam + private URIResolver uriResolver; + public SchematronEndpoint() { } @@ -116,6 +120,18 @@ public class SchematronEndpoint extends DefaultEndpoint { this.rules = rules; } + /** + * Set the {@link URIResolver} to be used for resolving schematron includes in the rules file. + */ + public void setUriResolver(URIResolver uriResolver) { + this.uriResolver = uriResolver; + } + + public URIResolver getUriResolver() { + return uriResolver; + } + + @Override protected void doStart() throws Exception { super.doStart(); @@ -157,7 +173,7 @@ public class SchematronEndpoint extends DefaultEndpoint { LOG.debug("Using TransformerFactoryClass {}", factoryClass); transformerFactory = getCamelContext().getInjector().newInstance(factoryClass); - transformerFactory.setURIResolver(new ClassPathURIResolver(Constants.SCHEMATRON_TEMPLATES_ROOT_DIR)); + transformerFactory.setURIResolver(new ClassPathURIResolver(Constants.SCHEMATRON_TEMPLATES_ROOT_DIR, this.uriResolver)); transformerFactory.setAttribute(LINE_NUMBERING, true); } http://git-wip-us.apache.org/repos/asf/camel/blob/ffb4b1cd/components/camel-schematron/src/main/java/org/apache/camel/component/schematron/processor/ClassPathURIResolver.java ---------------------------------------------------------------------- diff --git a/components/camel-schematron/src/main/java/org/apache/camel/component/schematron/processor/ClassPathURIResolver.java b/components/camel-schematron/src/main/java/org/apache/camel/component/schematron/processor/ClassPathURIResolver.java index ddc1725..86c9bed 100644 --- a/components/camel-schematron/src/main/java/org/apache/camel/component/schematron/processor/ClassPathURIResolver.java +++ b/components/camel-schematron/src/main/java/org/apache/camel/component/schematron/processor/ClassPathURIResolver.java @@ -17,6 +17,7 @@ package org.apache.camel.component.schematron.processor; import java.io.File; +import java.io.InputStream; import javax.xml.transform.Source; import javax.xml.transform.TransformerException; import javax.xml.transform.URIResolver; @@ -28,17 +29,29 @@ import javax.xml.transform.stream.StreamSource; public class ClassPathURIResolver implements URIResolver { private final String rulesDir; + private final URIResolver clientUriResolver; /** - * Constructor setter for rules directory path. + * Constructor setter for rules directory path, and the fallback URIResolver used + * for schematron includes. */ - public ClassPathURIResolver(final String rulesDir) { + public ClassPathURIResolver(final String rulesDir, URIResolver clientUriResolver) { this.rulesDir = rulesDir; + this.clientUriResolver = clientUriResolver; } @Override public Source resolve(String href, String base) throws TransformerException { - return new StreamSource(ClassPathURIResolver.class.getClassLoader() - .getResourceAsStream(rulesDir.concat("/").concat(href))); + InputStream stream = ClassPathURIResolver.class.getClassLoader() + .getResourceAsStream(rulesDir.concat(File.separator).concat(href)); + if (stream != null) { + return new StreamSource(stream); + } else { + if (clientUriResolver != null) { + return clientUriResolver.resolve(href, base); + } else { + return new StreamSource(stream); + } + } } } http://git-wip-us.apache.org/repos/asf/camel/blob/ffb4b1cd/components/camel-schematron/src/test/java/org/apache/camel/component/schematron/SchematronProducerTest.java ---------------------------------------------------------------------- diff --git a/components/camel-schematron/src/test/java/org/apache/camel/component/schematron/SchematronProducerTest.java b/components/camel-schematron/src/test/java/org/apache/camel/component/schematron/SchematronProducerTest.java index 925d334..588f0cd 100644 --- a/components/camel-schematron/src/test/java/org/apache/camel/component/schematron/SchematronProducerTest.java +++ b/components/camel-schematron/src/test/java/org/apache/camel/component/schematron/SchematronProducerTest.java @@ -42,7 +42,7 @@ public class SchematronProducerTest extends CamelTestSupport { public static void setUP() { SchematronEndpoint endpoint = new SchematronEndpoint(); TransformerFactory fac = new TransformerFactoryImpl(); - fac.setURIResolver(new ClassPathURIResolver(Constants.SCHEMATRON_TEMPLATES_ROOT_DIR)); + fac.setURIResolver(new ClassPathURIResolver(Constants.SCHEMATRON_TEMPLATES_ROOT_DIR, endpoint.getUriResolver())); Templates templates = TemplatesFactory.newInstance().getTemplates(ClassLoader. getSystemResourceAsStream("sch/schematron-1.sch"), fac); endpoint.setRules(templates); http://git-wip-us.apache.org/repos/asf/camel/blob/ffb4b1cd/components/camel-schematron/src/test/java/org/apache/camel/component/schematron/processor/SchematronProcessorTest.java ---------------------------------------------------------------------- diff --git a/components/camel-schematron/src/test/java/org/apache/camel/component/schematron/processor/SchematronProcessorTest.java b/components/camel-schematron/src/test/java/org/apache/camel/component/schematron/processor/SchematronProcessorTest.java index a0b551d..40eae9b 100644 --- a/components/camel-schematron/src/test/java/org/apache/camel/component/schematron/processor/SchematronProcessorTest.java +++ b/components/camel-schematron/src/test/java/org/apache/camel/component/schematron/processor/SchematronProcessorTest.java @@ -16,8 +16,12 @@ */ package org.apache.camel.component.schematron.processor; +import javax.xml.transform.Source; import javax.xml.transform.Templates; +import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; +import javax.xml.transform.URIResolver; +import javax.xml.transform.stream.StreamSource; import net.sf.saxon.TransformerFactoryImpl; import org.apache.camel.component.schematron.constant.Constants; @@ -43,7 +47,7 @@ public class SchematronProcessorTest { logger.info("Validating payload: {}", payload); // validate - String result = getProcessor("sch/schematron-1.sch").validate(payload); + String result = getProcessor("sch/schematron-1.sch", null).validate(payload); logger.info("Schematron Report: {}", result); assertEquals(0, Integer.valueOf(Utils.evaluate("count(//svrl:failed-assert)", result)).intValue()); assertEquals(0, Integer.valueOf(Utils.evaluate("count(//svrl:successful-report)", result)).intValue()); @@ -51,12 +55,24 @@ public class SchematronProcessorTest { } @Test + public void testInvalidXMLWithClientResolver() throws Exception { + String payload = IOUtils.toString(ClassLoader.getSystemResourceAsStream("xml/article-3.xml")); + logger.info("Validating payload: {}", payload); + + // validate + String result = getProcessor("sch/schematron-3.sch", new ClientUriResolver()).validate(payload); + logger.info("Schematron Report: {}", result); + assertEquals("A title should be at least two characters", Utils.evaluate("//svrl:failed-assert/svrl:text", result)); + assertEquals(0, Integer.valueOf(Utils.evaluate("count(//svrl:successful-report)", result)).intValue()); + } + + @Test public void testInValidXML() throws Exception { String payload = IOUtils.toString(ClassLoader.getSystemResourceAsStream("xml/article-2.xml")); logger.info("Validating payload: {}", payload); // validate - String result = getProcessor("sch/schematron-2.sch").validate(payload); + String result = getProcessor("sch/schematron-2.sch", null).validate(payload); logger.info("Schematron Report: {}", result); // should throw two assertions because of the missing chapters in the XML. assertEquals("A chapter should have a title", Utils.evaluate("//svrl:failed-assert/svrl:text", result)); @@ -68,12 +84,20 @@ public class SchematronProcessorTest { * Returns schematron processor * * @param schematron + * @param clientResolver * @return */ - private SchematronProcessor getProcessor(final String schematron) { + private SchematronProcessor getProcessor(final String schematron, final URIResolver clientResolver) { TransformerFactory factory = new TransformerFactoryImpl(); - factory.setURIResolver(new ClassPathURIResolver(Constants.SCHEMATRON_TEMPLATES_ROOT_DIR)); + factory.setURIResolver(new ClassPathURIResolver(Constants.SCHEMATRON_TEMPLATES_ROOT_DIR, clientResolver)); Templates rules = TemplatesFactory.newInstance().getTemplates(ClassLoader.getSystemResourceAsStream(schematron), factory); return SchematronProcessorFactory.newScehamtronEngine(rules); } + + class ClientUriResolver implements URIResolver { + @Override + public Source resolve(String href, String base) throws TransformerException { + return new StreamSource(ClientUriResolver.class.getClassLoader().getResourceAsStream("custom-resolver/".concat(href))); + } + } } http://git-wip-us.apache.org/repos/asf/camel/blob/ffb4b1cd/components/camel-schematron/src/test/java/org/apache/camel/component/schematron/processor/TemplatesFactoryTest.java ---------------------------------------------------------------------- diff --git a/components/camel-schematron/src/test/java/org/apache/camel/component/schematron/processor/TemplatesFactoryTest.java b/components/camel-schematron/src/test/java/org/apache/camel/component/schematron/processor/TemplatesFactoryTest.java index a8e1271..d166a15 100644 --- a/components/camel-schematron/src/test/java/org/apache/camel/component/schematron/processor/TemplatesFactoryTest.java +++ b/components/camel-schematron/src/test/java/org/apache/camel/component/schematron/processor/TemplatesFactoryTest.java @@ -36,7 +36,7 @@ public class TemplatesFactoryTest { public void testInstantiateAnInstanceOfTemplates() throws Exception { TemplatesFactory fac = TemplatesFactory.newInstance(); TransformerFactory factory = new TransformerFactoryImpl(); - factory.setURIResolver(new ClassPathURIResolver(Constants.SCHEMATRON_TEMPLATES_ROOT_DIR)); + factory.setURIResolver(new ClassPathURIResolver(Constants.SCHEMATRON_TEMPLATES_ROOT_DIR, null)); Templates templates = fac.getTemplates(ClassLoader.getSystemResourceAsStream(rules), factory); Assert.assertNotNull(templates); http://git-wip-us.apache.org/repos/asf/camel/blob/ffb4b1cd/components/camel-schematron/src/test/resources/custom-resolver/title-rules.sch ---------------------------------------------------------------------- diff --git a/components/camel-schematron/src/test/resources/custom-resolver/title-rules.sch b/components/camel-schematron/src/test/resources/custom-resolver/title-rules.sch new file mode 100644 index 0000000..adc6525 --- /dev/null +++ b/components/camel-schematron/src/test/resources/custom-resolver/title-rules.sch @@ -0,0 +1,20 @@ +<?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. +--> +<sch:rule context="title" xmlns:sch="http://purl.oclc.org/dsdl/schematron"> + <sch:assert test="string-length(.) >= 2">A title should be at least two characters</sch:assert> +</sch:rule> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/ffb4b1cd/components/camel-schematron/src/test/resources/sch/schematron-3.sch ---------------------------------------------------------------------- diff --git a/components/camel-schematron/src/test/resources/sch/schematron-3.sch b/components/camel-schematron/src/test/resources/sch/schematron-3.sch new file mode 100644 index 0000000..9914768 --- /dev/null +++ b/components/camel-schematron/src/test/resources/sch/schematron-3.sch @@ -0,0 +1,37 @@ +<?xml version="1.0"?> +<!-- + 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. +--> +<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron" + queryBinding="xslt2"> + + <sch:title>Sample Schematron using XPath 2.0</sch:title> + <sch:ns prefix="p" uri="http://www.apache.org/camel/schematron"/> + <sch:ns prefix="xs" uri="http://www.w3.org/2001/XMLSchema"/> + + <!-- Your constraints go here --> + <sch:pattern> + <sch:include href="title-rules.sch"/> + <sch:rule context="chapter"> + <sch:let name="numOfTitles" value="count(title)"/> + <sch:assert test="title">A chapter should have a title</sch:assert> + <sch:report test="count(title) > 1"> + 'chapter' element has more than one title present + </sch:report> + </sch:rule> + </sch:pattern> + +</sch:schema> http://git-wip-us.apache.org/repos/asf/camel/blob/ffb4b1cd/components/camel-schematron/src/test/resources/xml/article-3.xml ---------------------------------------------------------------------- diff --git a/components/camel-schematron/src/test/resources/xml/article-3.xml b/components/camel-schematron/src/test/resources/xml/article-3.xml new file mode 100644 index 0000000..8d1910b --- /dev/null +++ b/components/camel-schematron/src/test/resources/xml/article-3.xml @@ -0,0 +1,31 @@ +<?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. +--> +<doc> + <chapter id="c1"> + <title>chapter title</title> + <para>Chapter content</para> + </chapter> + <chapter id="c2"> + <title>chapter 2 title</title> + <para>Content</para> + </chapter> + <chapter id="c3"> + <title>T</title> + <para>Chapter 3 content</para> + </chapter> +</doc> \ No newline at end of file