You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by fo...@apache.org on 2016/02/08 14:22:29 UTC

camel git commit: CAMEL-9572: Validator: support custom resource resolver factory

Repository: camel
Updated Branches:
  refs/heads/master 092f16ebc -> 03b5c2943


CAMEL-9572: Validator: support custom resource resolver factory

support for custom resource resolvers which depend on the resource URI
of the endpoint and which works also for dynamic endpoints

Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/03b5c294
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/03b5c294
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/03b5c294

Branch: refs/heads/master
Commit: 03b5c29436a80cf8681ddf514dcaa313e2b105b0
Parents: 092f16e
Author: Franz Forsthofer <fr...@sap.com>
Authored: Sat Feb 6 15:58:35 2016 +0100
Committer: Franz Forsthofer <fr...@sap.com>
Committed: Mon Feb 8 14:20:49 2016 +0100

----------------------------------------------------------------------
 ...DefaultValidatorResourceResolverFactory.java |  34 ++++
 .../component/validator/ValidatorComponent.java |  23 +++
 .../component/validator/ValidatorEndpoint.java  |  26 ++-
 .../ValidatorResourceResolverFactory.java       |  50 ++++++
 .../ValidatorResourceResolverFactoryTest.java   | 164 +++++++++++++++++++
 5 files changed, 294 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/03b5c294/camel-core/src/main/java/org/apache/camel/component/validator/DefaultValidatorResourceResolverFactory.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/validator/DefaultValidatorResourceResolverFactory.java b/camel-core/src/main/java/org/apache/camel/component/validator/DefaultValidatorResourceResolverFactory.java
new file mode 100644
index 0000000..ac06bd1
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/validator/DefaultValidatorResourceResolverFactory.java
@@ -0,0 +1,34 @@
+/**
+ * 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.w3c.dom.ls.LSResourceResolver;
+
+import org.apache.camel.CamelContext;
+
+/**
+ * Default resource rsolver factory which instantiates the default resource
+ * rsolver ({@link DefaultLSResourceResolver}).
+ */
+public class DefaultValidatorResourceResolverFactory implements ValidatorResourceResolverFactory {
+
+    @Override
+    public LSResourceResolver createResourceResolver(CamelContext camelContext, String rootResourceUri) {
+        return new DefaultLSResourceResolver(camelContext, rootResourceUri);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/03b5c294/camel-core/src/main/java/org/apache/camel/component/validator/ValidatorComponent.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/validator/ValidatorComponent.java b/camel-core/src/main/java/org/apache/camel/component/validator/ValidatorComponent.java
index 07e038a..6756530 100644
--- a/camel-core/src/main/java/org/apache/camel/component/validator/ValidatorComponent.java
+++ b/camel-core/src/main/java/org/apache/camel/component/validator/ValidatorComponent.java
@@ -20,6 +20,7 @@ import java.util.Map;
 
 import org.apache.camel.Endpoint;
 import org.apache.camel.impl.UriEndpointComponent;
+import org.apache.camel.spi.Metadata;
 
 /**
  * The <a href="http://camel.apache.org/validation.html">Validator Component</a> is for validating XML against a schema
@@ -28,6 +29,9 @@ import org.apache.camel.impl.UriEndpointComponent;
  */
 public class ValidatorComponent extends UriEndpointComponent {
 
+    @Metadata(label = "advanced", description = "To use a custom LSResourceResolver which depends on a dynamic endpoint resource URI")
+    private ValidatorResourceResolverFactory resourceResolverFactory;
+    
     public ValidatorComponent() {
         this(ValidatorEndpoint.class);
     }
@@ -36,8 +40,27 @@ public class ValidatorComponent extends UriEndpointComponent {
         super(endpointClass);
     }
 
+    public ValidatorResourceResolverFactory getResourceResolverFactory() {
+        return resourceResolverFactory;
+    }
+
+    public void setResourceResolverFactory(ValidatorResourceResolverFactory resourceResolverFactory) {
+        this.resourceResolverFactory = resourceResolverFactory;
+    }
+
     protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
         ValidatorEndpoint endpoint = new ValidatorEndpoint(uri, this, remaining);
+        // lookup custom resolver to use
+        ValidatorResourceResolverFactory resolverFactory = resolveAndRemoveReferenceParameter(parameters, "resourceResolverFactory", ValidatorResourceResolverFactory.class);
+        if (resolverFactory == null) {
+            // not in endpoint then use component specific resource resolver factory
+            resolverFactory = getResourceResolverFactory();
+        }
+        if (resolverFactory == null) {
+            // fallback to use a Camel default resource resolver factory
+            resolverFactory = new DefaultValidatorResourceResolverFactory();
+        }
+        endpoint.setResourceResolverFactory(resolverFactory);
         setProperties(endpoint, parameters);
         return endpoint;
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/03b5c294/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 6b04a8c..8cd175e 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
@@ -69,8 +69,11 @@ public class ValidatorEndpoint extends DefaultEndpoint {
     @UriParam(defaultValue = "true", label = "advanced",
             description = "Whether the Schema instance should be shared or not. This option is introduced to work around a JDK 1.6.x bug. Xerces should not have this issue.")
     private boolean useSharedSchema = true;
-    @UriParam(label = "advanced", description = "To use a custom LSResourceResolver")
+    @UriParam(label = "advanced", description = "To use a custom LSResourceResolver.  Do not use together with resourceResolverFactory")
     private LSResourceResolver resourceResolver;
+    @UriParam(label = "advanced", description = "To use a custom LSResourceResolver which depends on a dynamic endpoint resource URI. " + //
+    "The default resource resolver factory resturns a resource resolver which can read files from the class path and file system. Do not use together with resourceResolver.")
+    private ValidatorResourceResolverFactory resourceResolverFactory;
     @UriParam(defaultValue = "true", description = "Whether to fail if no body exists.")
     private boolean failOnNullBody = true;
     @UriParam(defaultValue = "true", description = "Whether to fail if no header exists when validating against a header.")
@@ -110,8 +113,13 @@ public class ValidatorEndpoint extends DefaultEndpoint {
         if (!schemaReaderConfigured) {
             if (resourceResolver != null) {
                 schemaReader.setResourceResolver(resourceResolver);
+            } else if (resourceResolverFactory != null) {
+                // 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 DefaultLSResourceResolver(getCamelContext(), resourceUri));
+                schemaReader.setResourceResolver(new DefaultValidatorResourceResolverFactory().createResourceResolver(getCamelContext(), resourceUri));
             }
             schemaReader.setSchemaLanguage(getSchemaLanguage());
             schemaReader.setSchemaFactory(getSchemaFactory());
@@ -241,12 +249,24 @@ public class ValidatorEndpoint extends DefaultEndpoint {
     }
 
     /**
-     * To use a custom LSResourceResolver
+     * To use a custom LSResourceResolver. See also {@link #setResourceResolverFactory(ValidatorResourceResolverFactory)}
      */
     public void setResourceResolver(LSResourceResolver resourceResolver) {
         this.resourceResolver = resourceResolver;
     }
 
+    public ValidatorResourceResolverFactory getResourceResolverFactory() {
+        return resourceResolverFactory;
+    }
+
+    /** For creating a resource resolver which depends on the endpoint resource URI. 
+     * Must not be used in combination with method {@link #setResourceResolver(LSResourceResolver). 
+     * If not set then {@link DefaultValidatorResourceResolverFactory} is used 
+     */
+    public void setResourceResolverFactory(ValidatorResourceResolverFactory resourceResolverFactory) {
+        this.resourceResolverFactory = resourceResolverFactory;
+    }
+
     public boolean isFailOnNullBody() {
         return failOnNullBody;
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/03b5c294/camel-core/src/main/java/org/apache/camel/component/validator/ValidatorResourceResolverFactory.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/validator/ValidatorResourceResolverFactory.java b/camel-core/src/main/java/org/apache/camel/component/validator/ValidatorResourceResolverFactory.java
new file mode 100644
index 0000000..8004e72
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/component/validator/ValidatorResourceResolverFactory.java
@@ -0,0 +1,50 @@
+/**
+ * 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.w3c.dom.ls.LSResourceResolver;
+
+import org.apache.camel.CamelContext;
+
+/**
+ * Can be used to create custom resource resolver for the validator endpoint.
+ * This interface is useful, if the custom resource resolver depends on the
+ * resource URI specified in the validator endpoint. The resource URI of the
+ * endpoint can be even dynamic, like in the following example:
+ * 
+ * <pre>
+ * {@code <camel:recipientList>} 
+ * {@code      <camel:simple>}validator:${header.XSD_FILE}?resourceResolverFactory=#resourceResolverFactory{@code</camel:simple>}
+ * {@code </camel:recipientList>}
+ * </pre>
+ * 
+ * The dynamic resource URI given in ${header.XSD_FILE} will be past as
+ * rootResourceUri parameter in the method
+ * {@link #createResourceResolver(CamelContext, String)}
+ */
+public interface ValidatorResourceResolverFactory {
+
+    /**
+     * Method is called during the creation of a validator endpoint.
+     * 
+     * @param camelContext camel context
+     * @param rootResourceUri resource URI specified in the endpoint URI
+     * @return resource resolver
+     */
+    LSResourceResolver createResourceResolver(CamelContext camelContext, String rootResourceUri);
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/03b5c294/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorResourceResolverFactoryTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorResourceResolverFactoryTest.java b/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorResourceResolverFactoryTest.java
new file mode 100644
index 0000000..b55aad7
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorResourceResolverFactoryTest.java
@@ -0,0 +1,164 @@
+/**
+ * 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.HashSet;
+import java.util.Set;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.JndiRegistry;
+import org.apache.camel.model.language.ConstantExpression;
+import org.apache.camel.model.language.SimpleExpression;
+import org.junit.Assert;
+import org.w3c.dom.ls.LSInput;
+import org.w3c.dom.ls.LSResourceResolver;
+
+public class ValidatorResourceResolverFactoryTest extends ContextTestSupport {
+
+    private JndiRegistry registry;
+
+    public void testConfigurationOnEndpoint() throws Exception {
+        // ensure that validator from test method "testConfigurationOnComponent"
+        // is unbind
+        registry.getContext().unbind("validator");
+
+        String directStart = "direct:start";
+        String endpointUri = "validator:org/apache/camel/component/validator/xsds/person.xsd?resourceResolverFactory=#resourceResolverFactory";
+
+        execute(directStart, endpointUri);
+    }
+
+    public void testConfigurationOnComponent() throws Exception {
+        // set resource resolver factory on component
+        ValidatorComponent validatorComponent = new ValidatorComponent();
+        validatorComponent.setResourceResolverFactory(new ResourceResolverFactoryImpl());
+        registry.bind("validator", validatorComponent);
+
+        String directStart = "direct:startComponent";
+        String endpointUri = "validator:org/apache/camel/component/validator/xsds/person.xsd";
+        execute(directStart, endpointUri);
+
+    }
+
+    void execute(String directStart, String endpointUri) throws InterruptedException {
+        MockEndpoint endEndpoint = resolveMandatoryEndpoint("mock:end", MockEndpoint.class);
+        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);
+
+        // fetch dynamic endpoint
+        ValidatorEndpoint validatorEndpoint = null;
+        for (int i = 0; i < 5; i++) {
+            validatorEndpoint = resolveMandatoryEndpoint(endpointUri, ValidatorEndpoint.class);
+            if (validatorEndpoint != null) {
+                break;
+            }
+            // wait until endpoint is resolved
+            Thread.sleep(50);
+        }
+        MockEndpoint.assertIsSatisfied(endEndpoint);
+        Assert.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) {
+        Assert.assertTrue("Missing resource uri " + resourceUri + " in resolved resource URI set", uris.contains(resourceUri));
+    }
+
+    @Override
+    protected JndiRegistry createRegistry() throws Exception {
+        registry = super.createRegistry();
+        registry.bind("resourceResolverFactory", new ResourceResolverFactoryImpl());
+        return registry;
+
+    }
+
+    @Override
+    protected RouteBuilder[] createRouteBuilders() throws Exception {
+        return new RouteBuilder[] {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");
+            }
+
+        }, 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("validator:${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;
+        }
+
+    }
+
+}