Handling resources loading in OSGI environment Conflicts: components/camel-schematron/src/main/java/org/apache/camel/component/schematron/SchematronEndpoint.java
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/a840245a Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/a840245a Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/a840245a Branch: refs/heads/camel-2.15.x Commit: a840245a2c20a79edbe7a7629106be8c355cb974 Parents: 88e6aac Author: Ayache Khettar <aya...@zotix-consulting.co.uk> Authored: Tue Jun 2 09:18:07 2015 +0100 Committer: Claus Ibsen <davscl...@apache.org> Committed: Fri Jun 5 08:21:59 2015 +0200 ---------------------------------------------------------------------- .../schematron/SchematronEndpoint.java | 36 ++++++++++++++++---- .../schematron/constant/Constants.java | 3 ++ .../processor/ClassPathURIResolver.java | 4 ++- .../schematron/processor/TemplatesFactory.java | 27 ++++----------- .../schematron/SchematronProducerTest.java | 18 ++++++---- .../processor/SchematronProcessorTest.java | 10 ++++-- .../processor/TemplatesFactoryTest.java | 10 +++--- 7 files changed, 66 insertions(+), 42 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/a840245a/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 9c2a213..8af4b13 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 @@ -19,11 +19,14 @@ package org.apache.camel.component.schematron; import java.io.File; import java.io.InputStream; import javax.xml.transform.Templates; +import javax.xml.transform.TransformerFactory; import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.component.schematron.constant.Constants; import org.apache.camel.component.schematron.exception.SchematronConfigException; +import org.apache.camel.component.schematron.processor.ClassPathURIResolver; import org.apache.camel.component.schematron.processor.TemplatesFactory; import org.apache.camel.impl.DefaultEndpoint; import org.apache.camel.spi.Metadata; @@ -34,6 +37,9 @@ import org.apache.camel.util.ResourceHelper; import org.apache.commons.io.FileUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static org.apache.camel.component.schematron.constant.Constants.LINE_NUMBERING; +import static org.apache.camel.component.schematron.constant.Constants.SAXON_TRANSFORMER_FACTORY_CLASS_NAME; + /** * Schematron Endpoint. @@ -41,7 +47,9 @@ import org.slf4j.LoggerFactory; @UriEndpoint(scheme = "schematron", title = "Schematron", syntax = "schematron:path", producerOnly = true, label = "validation") public class SchematronEndpoint extends DefaultEndpoint { - private Logger logger = LoggerFactory.getLogger(SchematronEndpoint.class); + private Logger LOG = LoggerFactory.getLogger(SchematronEndpoint.class); + + private TransformerFactory transformerFactory; @UriPath @Metadata(required = "true") private String path; @@ -108,25 +116,39 @@ public class SchematronEndpoint extends DefaultEndpoint { protected void doStart() throws Exception { super.doStart(); + + if (transformerFactory == null) { + createTransformerFactory(); + } + if (rules == null) { try { // Attempt to read the schematron rules from the class path first. - logger.debug("Reading schematron rules from class path {}", path); + LOG.debug("Reading schematron rules from class path {}", path); InputStream schRules = ResourceHelper.resolveMandatoryResourceAsInputStream(getCamelContext().getClassResolver(), path); - rules = TemplatesFactory.newInstance().newTemplates(schRules); + rules = TemplatesFactory.newInstance().getTemplates(schRules, transformerFactory); } catch (Exception e) { // Attempts from the file system. - logger.debug("Schamatron rules not found in class path, attempting file system {}", path); + LOG.debug("Schamatron rules not found in class path, attempting file system {}", path); InputStream schRules = FileUtils.openInputStream(new File(path)); - rules = TemplatesFactory.newInstance().newTemplates(schRules); + rules = TemplatesFactory.newInstance().getTemplates(schRules, transformerFactory); } // rules not found in class path nor in file system. if (rules == null) { - logger.warn("Schematron rules not found {}", path); - throw new SchematronConfigException("Failed to load rules: " + path); + LOG.error("Failed to load schematron rules {}", path); + throw new SchematronConfigException("Failed to load schematron rules: " + path); } } + } + private void createTransformerFactory() throws ClassNotFoundException { + // provide the class loader of this component to work in OSGi environments + Class<?> factoryClass = getCamelContext().getClassResolver().resolveMandatoryClass(SAXON_TRANSFORMER_FACTORY_CLASS_NAME, + SchematronComponent.class.getClassLoader()); + LOG.debug("Using TransformerFactoryClass {}", factoryClass); + transformerFactory = (TransformerFactory) getCamelContext().getInjector().newInstance(factoryClass); + transformerFactory.setURIResolver(new ClassPathURIResolver(Constants.SCHEMATRON_TEMPLATES_ROOT_DIR)); + transformerFactory.setAttribute(LINE_NUMBERING, true); } } http://git-wip-us.apache.org/repos/asf/camel/blob/a840245a/components/camel-schematron/src/main/java/org/apache/camel/component/schematron/constant/Constants.java ---------------------------------------------------------------------- diff --git a/components/camel-schematron/src/main/java/org/apache/camel/component/schematron/constant/Constants.java b/components/camel-schematron/src/main/java/org/apache/camel/component/schematron/constant/Constants.java index bd3f07a..75e9a7e 100644 --- a/components/camel-schematron/src/main/java/org/apache/camel/component/schematron/constant/Constants.java +++ b/components/camel-schematron/src/main/java/org/apache/camel/component/schematron/constant/Constants.java @@ -29,6 +29,9 @@ public final class Constants { public static final String FAILED = "FAILED"; public static final String SUCCESS = "SUCCESS"; public static final String SCHEMATRON_TEMPLATES_ROOT_DIR = "iso-schematron-xslt2"; + public static final String SAXON_TRANSFORMER_FACTORY_CLASS_NAME = "net.sf.saxon.TransformerFactoryImpl"; + public static final String LINE_NUMBERING = "http://saxon.sf.net/feature/linenumbering"; + private Constants() { throw new IllegalStateException("Utility class should not be instantiated"); http://git-wip-us.apache.org/repos/asf/camel/blob/a840245a/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 6fa2941..135026b 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 @@ -20,6 +20,7 @@ import javax.xml.transform.Source; import javax.xml.transform.TransformerException; import javax.xml.transform.URIResolver; import javax.xml.transform.stream.StreamSource; +import java.io.*; /** @@ -40,6 +41,7 @@ public class ClassPathURIResolver implements URIResolver { @Override public Source resolve(String href, String base) throws TransformerException { - return new StreamSource(ClassLoader.getSystemResourceAsStream(rulesDir.concat("/").concat(href))); + return new StreamSource(ClassPathURIResolver.class.getClassLoader() + .getResourceAsStream(rulesDir.concat(File.separator).concat(href))); } } http://git-wip-us.apache.org/repos/asf/camel/blob/a840245a/components/camel-schematron/src/main/java/org/apache/camel/component/schematron/processor/TemplatesFactory.java ---------------------------------------------------------------------- diff --git a/components/camel-schematron/src/main/java/org/apache/camel/component/schematron/processor/TemplatesFactory.java b/components/camel-schematron/src/main/java/org/apache/camel/component/schematron/processor/TemplatesFactory.java index 3e47150..6a9aab3 100644 --- a/components/camel-schematron/src/main/java/org/apache/camel/component/schematron/processor/TemplatesFactory.java +++ b/components/camel-schematron/src/main/java/org/apache/camel/component/schematron/processor/TemplatesFactory.java @@ -16,7 +16,7 @@ */ package org.apache.camel.component.schematron.processor; -import java.io.File; + import java.io.InputStream; import javax.xml.transform.Source; @@ -35,13 +35,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; - /** * Class generating Templates for a given schematron rules */ public final class TemplatesFactory { - private static final String LINE_NUMBERING = "http://saxon.sf.net/feature/linenumbering"; + private static final TemplatesFactory INSTANCE = new TemplatesFactory(); private static final String[] PIPELINE = new String[]{"iso_dsdl_include.xsl", "iso_abstract_expand.xsl", "iso_svrl_for_xslt2.xsl"}; private Logger logger = LoggerFactory.getLogger(TemplatesFactory.class); @@ -57,34 +56,22 @@ public final class TemplatesFactory { } /** - * Returns an instance of compiled schematron templates. - * - * @return - */ - public Templates newTemplates(final InputStream rules) { - - TransformerFactory fac = TransformerFactory.newInstance(); - fac.setURIResolver(new ClassPathURIResolver(Constants.SCHEMATRON_TEMPLATES_ROOT_DIR)); - fac.setAttribute(LINE_NUMBERING, true); - return getTemplates(rules, fac); - } - - /** * Generate the schematron template for given rule. * * @param rules the schematron rules * @param fac the transformer factory. * @return schematron template. */ - private Templates getTemplates(InputStream rules, TransformerFactory fac) { + public Templates getTemplates(final InputStream rules, final TransformerFactory fac) { Node node = null; Source source = new StreamSource(rules); try { for (String template : PIPELINE) { - Source xsl = new StreamSource(ClassLoader.getSystemResourceAsStream(Constants.SCHEMATRON_TEMPLATES_ROOT_DIR - .concat("/").concat(template))); - Transformer t = fac.newTransformer(xsl); + String path = Constants.SCHEMATRON_TEMPLATES_ROOT_DIR + .concat("/").concat(template); + InputStream xsl = this.getClass().getClassLoader().getResourceAsStream(path); + Transformer t = fac.newTransformer(new StreamSource(xsl)); DOMResult result = new DOMResult(); t.transform(source, result); source = new DOMSource(node = result.getNode()); http://git-wip-us.apache.org/repos/asf/camel/blob/a840245a/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 6694503..925d334 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 @@ -17,10 +17,13 @@ package org.apache.camel.component.schematron; import javax.xml.transform.Templates; +import javax.xml.transform.TransformerFactory; +import net.sf.saxon.TransformerFactoryImpl; import org.apache.camel.Exchange; import org.apache.camel.ExchangePattern; import org.apache.camel.component.schematron.constant.Constants; +import org.apache.camel.component.schematron.processor.ClassPathURIResolver; import org.apache.camel.component.schematron.processor.TemplatesFactory; import org.apache.camel.impl.DefaultExchange; import org.apache.camel.test.junit4.CamelTestSupport; @@ -29,7 +32,7 @@ import org.junit.Test; /** * Schematron Producer Unit Test. - * + * */ public class SchematronProducerTest extends CamelTestSupport { @@ -38,8 +41,10 @@ public class SchematronProducerTest extends CamelTestSupport { @BeforeClass public static void setUP() { SchematronEndpoint endpoint = new SchematronEndpoint(); - Templates templates = TemplatesFactory.newInstance().newTemplates(ClassLoader. - getSystemResourceAsStream("sch/schematron-1.sch")); + TransformerFactory fac = new TransformerFactoryImpl(); + fac.setURIResolver(new ClassPathURIResolver(Constants.SCHEMATRON_TEMPLATES_ROOT_DIR)); + Templates templates = TemplatesFactory.newInstance().getTemplates(ClassLoader. + getSystemResourceAsStream("sch/schematron-1.sch"), fac); endpoint.setRules(templates); producer = new SchematronProducer(endpoint); } @@ -54,20 +59,19 @@ public class SchematronProducerTest extends CamelTestSupport { // assert assertTrue(exc.getOut().getHeader(Constants.VALIDATION_STATUS).equals(Constants.SUCCESS)); - assertNotNull("We should get the report here.", exc.getOut().getHeader(Constants.VALIDATION_REPORT)); } @Test public void testProcessInValidXML() throws Exception { - Exchange exc = new DefaultExchange(context, ExchangePattern.InOnly); + Exchange exc = new DefaultExchange(context, ExchangePattern.InOut); exc.getIn().setBody(ClassLoader.getSystemResourceAsStream("xml/article-2.xml")); // process xml payload producer.process(exc); // assert - assertTrue("The validation status should be failed.", exc.getIn().getHeader(Constants.VALIDATION_STATUS).equals(Constants.FAILED)); - assertNotNull("We should get the report here.", exc.getIn().getHeader(Constants.VALIDATION_REPORT)); + assertTrue(exc.getOut().getHeader(Constants.VALIDATION_STATUS).equals(Constants.FAILED)); + } } http://git-wip-us.apache.org/repos/asf/camel/blob/a840245a/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 78b42d7..a0b551d 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 @@ -17,7 +17,10 @@ package org.apache.camel.component.schematron.processor; import javax.xml.transform.Templates; +import javax.xml.transform.TransformerFactory; +import net.sf.saxon.TransformerFactoryImpl; +import org.apache.camel.component.schematron.constant.Constants; import org.apache.camel.component.schematron.util.Utils; import org.apache.commons.io.IOUtils; import org.junit.Test; @@ -38,7 +41,7 @@ public class SchematronProcessorTest { String payload = IOUtils.toString(ClassLoader.getSystemResourceAsStream("xml/article-1.xml")); logger.info("Validating payload: {}", payload); - + // validate String result = getProcessor("sch/schematron-1.sch").validate(payload); logger.info("Schematron Report: {}", result); @@ -59,7 +62,6 @@ public class SchematronProcessorTest { assertEquals("A chapter should have a title", Utils.evaluate("//svrl:failed-assert/svrl:text", result)); assertEquals("'chapter' element has more than one title present", Utils.evaluate("//svrl:successful-report/svrl:text", result).trim()); - } /** @@ -69,7 +71,9 @@ public class SchematronProcessorTest { * @return */ private SchematronProcessor getProcessor(final String schematron) { - Templates rules = TemplatesFactory.newInstance().newTemplates(ClassLoader.getSystemResourceAsStream(schematron)); + TransformerFactory factory = new TransformerFactoryImpl(); + factory.setURIResolver(new ClassPathURIResolver(Constants.SCHEMATRON_TEMPLATES_ROOT_DIR)); + Templates rules = TemplatesFactory.newInstance().getTemplates(ClassLoader.getSystemResourceAsStream(schematron), factory); return SchematronProcessorFactory.newScehamtronEngine(rules); } } http://git-wip-us.apache.org/repos/asf/camel/blob/a840245a/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 e302740..a8e1271 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 @@ -17,7 +17,10 @@ package org.apache.camel.component.schematron.processor; import javax.xml.transform.Templates; +import javax.xml.transform.TransformerFactory; +import net.sf.saxon.TransformerFactoryImpl; +import org.apache.camel.component.schematron.constant.Constants; import org.junit.Assert; import org.junit.Test; @@ -31,12 +34,11 @@ public class TemplatesFactoryTest { @Test public void testInstantiateAnInstanceOfTemplates() throws Exception { - - TemplatesFactory fac = TemplatesFactory.newInstance(); - Templates templates = fac.newTemplates(ClassLoader.getSystemResourceAsStream(rules)); + TransformerFactory factory = new TransformerFactoryImpl(); + factory.setURIResolver(new ClassPathURIResolver(Constants.SCHEMATRON_TEMPLATES_ROOT_DIR)); + Templates templates = fac.getTemplates(ClassLoader.getSystemResourceAsStream(rules), factory); Assert.assertNotNull(templates); - } }