Repository: camel Updated Branches: refs/heads/master 03b5c2943 -> 8e479dfa7
CAMEL-9580: XSLT component: Support URI resolver factory - factory for creating URI resolver - usfull to create an URI resolver which is a sub-class of the default XsltUriResolver Change-Id: Idfd3b1c2b0811aa5ef1c6e43178f67dc6fe2228d Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/8e479dfa Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/8e479dfa Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/8e479dfa Branch: refs/heads/master Commit: 8e479dfa7a7e83713c2b3eb2e1145aaefd15ff6f Parents: 03b5c29 Author: Franz Forsthofer <franz.forstho...@sap.com> Authored: Mon Feb 8 16:56:24 2016 +0100 Committer: Franz Forsthofer <franz.forstho...@sap.com> Committed: Mon Feb 8 17:13:20 2016 +0100 ---------------------------------------------------------------------- .../xslt/DefaultXsltUriResolverFactory.java | 20 +++ .../camel/component/xslt/XsltComponent.java | 38 ++++- .../component/xslt/XsltUriResolverFactory.java | 50 +++++++ .../xslt/XsltUriResolverFactoryTest.java | 146 +++++++++++++++++++ 4 files changed, 249 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/8e479dfa/camel-core/src/main/java/org/apache/camel/component/xslt/DefaultXsltUriResolverFactory.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/component/xslt/DefaultXsltUriResolverFactory.java b/camel-core/src/main/java/org/apache/camel/component/xslt/DefaultXsltUriResolverFactory.java new file mode 100644 index 0000000..a6a283e --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/component/xslt/DefaultXsltUriResolverFactory.java @@ -0,0 +1,20 @@ +package org.apache.camel.component.xslt; + +import javax.xml.transform.URIResolver; + +import org.apache.camel.CamelContext; +import org.apache.camel.builder.xml.XsltUriResolver; + +/** + * Default URI resolver factory which instantiates the camel default XSLT URI + * resolver which can resolves absolute and relative URIs in the classpath and + * file system. + */ +public class DefaultXsltUriResolverFactory implements XsltUriResolverFactory { + + @Override + public URIResolver createUriResolver(CamelContext camelContext, String resourceUri) { + return new XsltUriResolver(camelContext.getClassResolver(), resourceUri); + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/8e479dfa/camel-core/src/main/java/org/apache/camel/component/xslt/XsltComponent.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/component/xslt/XsltComponent.java b/camel-core/src/main/java/org/apache/camel/component/xslt/XsltComponent.java index 3227242..0754e3b 100644 --- a/camel-core/src/main/java/org/apache/camel/component/xslt/XsltComponent.java +++ b/camel-core/src/main/java/org/apache/camel/component/xslt/XsltComponent.java @@ -37,8 +37,10 @@ public class XsltComponent extends UriEndpointComponent { @Metadata(label = "advanced") private XmlConverter xmlConverter; - @Metadata(label = "advanced") + @Metadata(label = "advanced", description="To use a custom UriResolver. Should not be used together with the option 'uriResolverFactory'.") private URIResolver uriResolver; + @Metadata(label = "advanced", description="To use a custom UriResolver which depends on a dynamic endpoint resource URI. Should not be used together with the option 'uriResolver'.") + private XsltUriResolverFactory uriResolverFactory; @Metadata(defaultValue = "true") private boolean contentCache = true; private boolean saxon; @@ -57,13 +59,29 @@ public class XsltComponent extends UriEndpointComponent { public void setXmlConverter(XmlConverter xmlConverter) { this.xmlConverter = xmlConverter; } + + + + public XsltUriResolverFactory getUriResolverFactory() { + return uriResolverFactory; + } + + /** + * To use a custom javax.xml.transform.URIResolver which depends on a dynamic endpoint resource URI or which is a subclass of {@link XsltUriResolver}. + * Do not use in combination with uriResolver. + * See also {@link #setUriResolver(URIResolver)}. + */ + public void setUriResolverFactory(XsltUriResolverFactory uriResolverFactory) { + this.uriResolverFactory = uriResolverFactory; + } public URIResolver getUriResolver() { return uriResolver; } /** - * To use a custom javax.xml.transform.URIResolver + * To use a custom javax.xml.transform.URIResolver. Do not use in combination with uriResolverFactory. + * See also {@link #setUriResolverFactory(XsltUriResolverFactory)}. */ public void setUriResolver(URIResolver uriResolver) { this.uriResolver = uriResolver; @@ -114,10 +132,20 @@ public class XsltComponent extends UriEndpointComponent { if (resolver == null) { // not in endpoint then use component specific resolver resolver = getUriResolver(); - } + } if (resolver == null) { - // fallback to use a Camel specific resolver - resolver = new XsltUriResolver(getCamelContext().getClassResolver(), remaining); + // lookup custom resolver factory to use + XsltUriResolverFactory resolverFactory = resolveAndRemoveReferenceParameter(parameters, "uriResolverFactory", XsltUriResolverFactory.class); + if (resolverFactory == null) { + // not in endpoint then use component specific resolver factory + resolverFactory = getUriResolverFactory(); + } + if (resolverFactory == null){ + // fallback to use the Default URI resolver factory + resolverFactory = new DefaultXsltUriResolverFactory(); + } + + resolver = resolverFactory.createUriResolver(getCamelContext(), remaining); } endpoint.setUriResolver(resolver); http://git-wip-us.apache.org/repos/asf/camel/blob/8e479dfa/camel-core/src/main/java/org/apache/camel/component/xslt/XsltUriResolverFactory.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/component/xslt/XsltUriResolverFactory.java b/camel-core/src/main/java/org/apache/camel/component/xslt/XsltUriResolverFactory.java new file mode 100644 index 0000000..f9209a3 --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/component/xslt/XsltUriResolverFactory.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.xslt; + +import javax.xml.transform.URIResolver; + +import org.apache.camel.CamelContext; + +/** + * Can be used to create custom URI resolver for the XSLT endpoint. This + * interface is useful, if the custom URI resolver depends on the resource URI + * specified in the XSLT endpoint. The resource URI of the endpoint can be even + * dynamic, like in the following example: + * + * <pre> + * {@code <camel:recipientList>} + * {@code <camel:simple>}xslt:${header.XSLT_FILE}?uriResolverFactory=#uriResolverFactory{@code</camel:simple>} + * {@code </camel:recipientList>} + * </pre> + * + * The dynamic resource URI given in ${header.XSLT_FILE} will be past as + * resourceUri parameter in the method + * {@link #createUriResolver(CamelContext, String)} + */ +public interface XsltUriResolverFactory { + + /** + * Method is called during the creation of a xslt endpoint. + * + * @param camelContext camel context + * @param resourceUri resource URI specified in the endpoint URI + * @return URI resolver + */ + URIResolver createUriResolver(CamelContext camelContext, String resourceUri); + +} http://git-wip-us.apache.org/repos/asf/camel/blob/8e479dfa/camel-core/src/test/java/org/apache/camel/component/xslt/XsltUriResolverFactoryTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/component/xslt/XsltUriResolverFactoryTest.java b/camel-core/src/test/java/org/apache/camel/component/xslt/XsltUriResolverFactoryTest.java new file mode 100644 index 0000000..e16fb4a --- /dev/null +++ b/camel-core/src/test/java/org/apache/camel/component/xslt/XsltUriResolverFactoryTest.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.xslt; + +import java.io.InputStream; +import java.util.HashSet; +import java.util.Set; + +import javax.xml.transform.Source; +import javax.xml.transform.TransformerException; +import javax.xml.transform.URIResolver; + +import org.apache.camel.CamelContext; +import org.apache.camel.ContextTestSupport; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.builder.xml.XsltUriResolver; +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.apache.camel.spi.ClassResolver; +import org.junit.Assert; + +/** + * + */ +public class XsltUriResolverFactoryTest extends ContextTestSupport { + + private JndiRegistry registry; + + public void testConfigurationOnEndpoint() throws Exception { + String endpointUri = "xslt:xslt/staff/staff.xsl?uriResolverFactory=#uriResolverFactory"; + String directStart = "direct:start"; + + // ensure that the URI resolver factory is not set on the component by + // the method "testConfigurationOnComponent" + registry.getContext().unbind("xslt"); + execute(endpointUri, directStart); + } + + public void testConfigurationOnComponent() throws Exception { + + XsltComponent xsltComponent = new XsltComponent(); + xsltComponent.setUriResolverFactory(new CustomXsltUriResolverFactory()); + registry.bind("xslt", xsltComponent); + + String endpointUri = "xslt:xslt/staff/staff.xsl"; + String directStart = "direct:startComponent"; + + execute(endpointUri, directStart); + } + + void execute(String endpointUri, String directStart) throws InterruptedException { + InputStream payloud = XsltUriResolverFactoryTest.class.getClassLoader().getResourceAsStream("xslt/staff/staff.xml"); + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMessageCount(1); + + sendBody(directStart, payloud); + XsltEndpoint xsltEndpoint = null; + for (int i = 0; i < 5; i++) { + xsltEndpoint = resolveMandatoryEndpoint(endpointUri, XsltEndpoint.class); + if (xsltEndpoint != null) { + break; + } + // wait until endpoint is resolved + Thread.sleep(50); + } + assertMockEndpointsSatisfied(); + assertNotNull(xsltEndpoint); + CustomXsltUriResolver resolver = (CustomXsltUriResolver)xsltEndpoint.getUriResolver(); + checkResourceUri(resolver.resolvedRsourceUris, "xslt/staff/staff.xsl"); + checkResourceUri(resolver.resolvedRsourceUris, "../common/staff_template.xsl"); + } + + @Override + protected RouteBuilder[] createRouteBuilders() throws Exception { + return new RouteBuilder[] {new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:start") // + .setHeader("xslt_file", new ConstantExpression("xslt/staff/staff.xsl")) // + .recipientList(new SimpleExpression("xslt:${header.xslt_file}?uriResolverFactory=#uriResolverFactory")) // + .to("mock:result"); + } + }, new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:startComponent") // + .setHeader("xslt_file", new ConstantExpression("xslt/staff/staff.xsl")) // + .recipientList(new SimpleExpression("xslt:${header.xslt_file}")) // + .to("mock:result"); + } + }}; + } + + @Override + protected JndiRegistry createRegistry() throws Exception { + registry = super.createRegistry(); + registry.bind("uriResolverFactory", new CustomXsltUriResolverFactory()); + return registry; + + } + + void checkResourceUri(Set<String> uris, String resourceUri) { + Assert.assertTrue("Missing resource uri " + resourceUri + " in resolved resource URI set", uris.contains(resourceUri)); + } + + static class CustomXsltUriResolverFactory implements XsltUriResolverFactory { + + @Override + public URIResolver createUriResolver(CamelContext camelContext, String resourceUri) { + return new CustomXsltUriResolver(camelContext.getClassResolver(), resourceUri); + } + + } + + static class CustomXsltUriResolver extends XsltUriResolver { + + private final Set<String> resolvedRsourceUris = new HashSet<>(); + + public CustomXsltUriResolver(ClassResolver resolver, String location) { + super(resolver, location); + } + + public Source resolve(String href, String base) throws TransformerException { + Source result = super.resolve(href, base); + resolvedRsourceUris.add(href); + return result; + } + + } +}