Repository: camel Updated Branches: refs/heads/master 792e4c6d6 -> 77e079a83
CAMEL-9572: Validator: clearSchemaCache method refactored - it is not a good idea to re-read the schema in the clearSchemaCache method. Therefore the readSchema method is moved to the SchemaReader. Now, if the schema was updated and the clearSchemaCache method is called then the re-reading is tried during the first process call. This change was especially necessary to support the case where the schema document was deleted and the clearSchemaCache was called. In this case. now no error occurs during the clearSchemaCache call, but the error "no file found" occurs during the next process call. This is the expected behavior, in the previous solution the cache would not be cleared at all and the processing would have went on. Change-Id: Ie206872875e2bddaeb036fc4dfb43ec907770787 Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/77e079a8 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/77e079a8 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/77e079a8 Branch: refs/heads/master Commit: 77e079a83861b93d39d556a76019e78cfb9389db Parents: 792e4c6 Author: Franz Forsthofer <franz.forstho...@sap.com> Authored: Tue Feb 16 14:00:39 2016 +0100 Committer: Franz Forsthofer <franz.forstho...@sap.com> Committed: Tue Feb 16 14:00:39 2016 +0100 ---------------------------------------------------------------------- .../component/validator/ValidatorEndpoint.java | 43 ++++----------- .../processor/validation/SchemaReader.java | 56 ++++++++++++++++++-- 2 files changed, 62 insertions(+), 37 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/77e079a8/camel-core/src/main/java/org/apache/camel/component/validator/ValidatorEndpoint.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/component/validator/ValidatorEndpoint.java b/camel-core/src/main/java/org/apache/camel/component/validator/ValidatorEndpoint.java index 8cd175e..163364d 100644 --- a/camel-core/src/main/java/org/apache/camel/component/validator/ValidatorEndpoint.java +++ b/camel-core/src/main/java/org/apache/camel/component/validator/ValidatorEndpoint.java @@ -16,8 +16,6 @@ */ package org.apache.camel.component.validator; -import java.io.IOException; -import java.io.InputStream; import javax.xml.XMLConstants; import javax.xml.validation.SchemaFactory; @@ -29,7 +27,6 @@ import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.api.management.ManagedOperation; import org.apache.camel.api.management.ManagedResource; -import org.apache.camel.converter.IOConverter; import org.apache.camel.impl.DefaultEndpoint; import org.apache.camel.processor.validation.DefaultValidationErrorHandler; import org.apache.camel.processor.validation.SchemaReader; @@ -39,10 +36,7 @@ import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; import org.apache.camel.spi.UriPath; -import org.apache.camel.util.IOHelper; -import org.apache.camel.util.ResourceHelper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; + /** * Validates the payload of a message using XML Schema and JAXP Validation. @@ -51,8 +45,6 @@ import org.slf4j.LoggerFactory; @UriEndpoint(scheme = "validator", title = "Validator", syntax = "validator:resourceUri", producerOnly = true, label = "core,validation") public class ValidatorEndpoint extends DefaultEndpoint { - private static final Logger LOG = LoggerFactory.getLogger(ValidatorEndpoint.class); - @UriPath(description = "URL to a local resource on the classpath, or a reference to lookup a bean in the Registry," + " or a full URL to a remote resource or resource on the file system which contains the XSD to validate against.") @Metadata(required = "true") @@ -86,25 +78,23 @@ public class ValidatorEndpoint extends DefaultEndpoint { * to be able to clear the cached schema in the schema reader. See method * {@link #clearCachedSchema}. */ - private final SchemaReader schemaReader = new SchemaReader(); + private final SchemaReader schemaReader; private volatile boolean schemaReaderConfigured; public ValidatorEndpoint() { + schemaReader = new SchemaReader(); } public ValidatorEndpoint(String endpointUri, Component component, String resourceUri) { super(endpointUri, component); this.resourceUri = resourceUri; + schemaReader = new SchemaReader(getCamelContext(), resourceUri); } @ManagedOperation(description = "Clears the cached schema, forcing to re-load the schema on next request") - public void clearCachedSchema() throws Exception { - LOG.debug("{} rereading schema resource: {}", this, resourceUri); - byte[] bytes = readSchemaResource(); - schemaReader.setSchemaAsByteArray(bytes); - - schemaReader.setSchema(null); // will cause to reload the schema from - // the set byte-array on next request + public void clearCachedSchema() { + + schemaReader.setSchema(null); // will cause to reload the schema } @Override @@ -114,9 +104,9 @@ public class ValidatorEndpoint extends DefaultEndpoint { if (resourceResolver != null) { schemaReader.setResourceResolver(resourceResolver); } else if (resourceResolverFactory != null) { + resourceResolver = resourceResolverFactory.createResourceResolver(getCamelContext(), resourceUri); // set the created resource resolver to the resourceResolver variable, so that it can // be accessed by the endpoint - resourceResolver = resourceResolverFactory.createResourceResolver(getCamelContext(), resourceUri); schemaReader.setResourceResolver(resourceResolver); } else { schemaReader.setResourceResolver(new DefaultValidatorResourceResolverFactory().createResourceResolver(getCamelContext(), resourceUri)); @@ -124,10 +114,6 @@ public class ValidatorEndpoint extends DefaultEndpoint { schemaReader.setSchemaLanguage(getSchemaLanguage()); schemaReader.setSchemaFactory(getSchemaFactory()); - byte[] bytes = readSchemaResource(); - schemaReader.setSchemaAsByteArray(bytes); - LOG.debug("{} using schema resource: {}", this, resourceUri); - // force loading of schema at create time otherwise concurrent // processing could cause thread safe issues for the // javax.xml.validation.SchemaFactory @@ -143,18 +129,7 @@ public class ValidatorEndpoint extends DefaultEndpoint { return new ValidatorProducer(this, validator); } - protected byte[] readSchemaResource() throws IOException { - InputStream is = ResourceHelper.resolveMandatoryResourceAsInputStream(getCamelContext(), resourceUri); - byte[] bytes = null; - try { - bytes = IOConverter.toBytes(is); - } finally { - // and make sure to close the input stream after the schema has been - // loaded - IOHelper.close(is); - } - return bytes; - } + @Override public Consumer createConsumer(Processor processor) throws Exception { http://git-wip-us.apache.org/repos/asf/camel/blob/77e079a8/camel-core/src/main/java/org/apache/camel/processor/validation/SchemaReader.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/processor/validation/SchemaReader.java b/camel-core/src/main/java/org/apache/camel/processor/validation/SchemaReader.java index 0fdb9e1..12abfdb 100644 --- a/camel-core/src/main/java/org/apache/camel/processor/validation/SchemaReader.java +++ b/camel-core/src/main/java/org/apache/camel/processor/validation/SchemaReader.java @@ -19,6 +19,7 @@ package org.apache.camel.processor.validation; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.net.URL; import javax.xml.XMLConstants; @@ -30,11 +31,22 @@ import javax.xml.validation.SchemaFactory; import org.w3c.dom.ls.LSResourceResolver; import org.xml.sax.SAXException; +import org.apache.camel.CamelContext; +import org.apache.camel.converter.IOConverter; +import org.apache.camel.util.IOHelper; +import org.apache.camel.util.ObjectHelper; +import org.apache.camel.util.ResourceHelper; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Reads the schema used in the processor {@link ValidatingProcessor}. Contains * the method {@link clearCachedSchema()} to force re-reading the schema. */ public class SchemaReader { + + private static final Logger LOG = LoggerFactory.getLogger(SchemaReader.class); private String schemaLanguage = XMLConstants.W3C_XML_SCHEMA_NS_URI; // must be volatile because is accessed from different threads see ValidatorEndpoint.clearCachedSchema @@ -44,8 +56,24 @@ public class SchemaReader { private volatile SchemaFactory schemaFactory; private URL schemaUrl; private File schemaFile; - private volatile byte[] schemaAsByteArray; + private byte[] schemaAsByteArray; + private final String schemaResourceUri; private LSResourceResolver resourceResolver; + + private final CamelContext camelContext; + + + public SchemaReader() { + this(null, null); + } + + /** Specify a camel context and a schema resource URI in order to read the schema via the class resolver specified in the Camel context. */ + public SchemaReader(CamelContext camelContext, String schemaResourceUri) { + ObjectHelper.notNull(camelContext, "camelContext"); + ObjectHelper.notNull(schemaResourceUri, "schemaResourceUri"); + this.camelContext = camelContext; + this.schemaResourceUri = schemaResourceUri; + } public void loadSchema() throws Exception { // force loading of schema @@ -145,7 +173,7 @@ public class SchemaReader { } protected Source createSchemaSource() throws IOException { - throw new IllegalArgumentException("You must specify either a schema, schemaFile, schemaSource or schemaUrl property"); + throw new IllegalArgumentException("You must specify either a schema, schemaFile, schemaSource, schemaUrl, or schemaUri property"); } protected Schema createSchema() throws SAXException, IOException { @@ -171,11 +199,33 @@ public class SchemaReader { return factory.newSchema(new StreamSource(new ByteArrayInputStream(schemaAsByteArray))); } } - + + if (schemaResourceUri != null) { + synchronized (this) { + bytes = readSchemaResource(); + return factory.newSchema(new StreamSource(new ByteArrayInputStream(bytes))); + } + } + Source source = getSchemaSource(); synchronized (this) { return factory.newSchema(source); } + + } + + protected byte[] readSchemaResource() throws IOException { + LOG.debug("reading schema resource: {}", schemaResourceUri); + InputStream is = ResourceHelper.resolveMandatoryResourceAsInputStream(camelContext, schemaResourceUri); + byte[] bytes = null; + try { + bytes = IOConverter.toBytes(is); + } finally { + // and make sure to close the input stream after the schema has been + // loaded + IOHelper.close(is); + } + return bytes; } }