This is an automated email from the ASF dual-hosted git repository. ppalaga pushed a commit to branch 2.7.x in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
commit 1a6b6e4eaf383e556da8d648044224131d7d35f9 Author: Denis Istomin <[email protected]> AuthorDate: Tue Feb 8 18:16:36 2022 +0100 #3503 Add xslt.features support --- .../ROOT/pages/reference/extensions/xslt.adoc | 26 +++++++++++++++++ .../component/xslt/deployment/XsltProcessor.java | 6 ++++ .../xslt/runtime/src/main/doc/configuration.adoc | 20 +++++++++++++ .../quarkus/component/xslt/CamelXsltConfig.java | 7 +++++ .../quarkus/component/xslt/CamelXsltRecorder.java | 20 +++++++++++-- integration-tests-support/pom.xml | 1 + integration-tests-support/xslt-support/pom.xml | 31 ++++++++++++++++++++ .../camel/quarkus/test/support/xslt/Functions.java | 26 ++++------------- integration-tests/xml/pom.xml | 4 +++ .../component/xml/it/FunctionsConfiguration.java | 24 +++------------- .../quarkus/component/xml/it/XmlResource.java | 9 +++++- .../xml/src/main/resources/application.properties | 3 +- .../src/main/resources/xslt/extension-function.xsl | 33 ++++++++++++++++++++++ .../camel/quarkus/component/xml/it/XmlTest.java | 14 +++++++++ poms/bom-test/pom.xml | 5 ++++ 15 files changed, 184 insertions(+), 45 deletions(-) diff --git a/docs/modules/ROOT/pages/reference/extensions/xslt.adoc b/docs/modules/ROOT/pages/reference/extensions/xslt.adoc index 903d8e2..c065202 100644 --- a/docs/modules/ROOT/pages/reference/extensions/xslt.adoc +++ b/docs/modules/ROOT/pages/reference/extensions/xslt.adoc @@ -54,6 +54,26 @@ Scheme-less URIs are interpreted as `classpath:` URIs. Only `classpath:` URIs are supported on Quarkus. `file:`, `http:` and other kinds of URIs do not work by design. +=== Configuration +TransformerFactory features can be configured using following property: +[source,properties] +---- +quarkus.camel.xslt.features."http\://javax.xml.XMLConstants/feature/secure-processing"=false +---- +=== Extension functions support +https://xml.apache.org/xalan-j/extensions.html[Xalan's extension functions] +do work properly only when: + +1. Secure-processing is disabled +2. Functions are defined in a separate jar +3. Functions are augmented during native build phase. For example, they can be registered for reflection: +[source,java] +---- +@RegisterForReflection(targets = { my.Functions.class }) +public class FunctionsConfiguration { +} +---- + [NOTE] ==== The content of the XSLT source URIs is parsed and compiled into Java classes at build time. These Java classes are the @@ -82,6 +102,12 @@ A comma separated list of templates to compile. The package name for the generated classes. | `string` | `org.apache.camel.quarkus.component.xslt.generated` + +|icon:lock[title=Fixed at build time] [[quarkus.camel.xslt.features]]`link:#quarkus.camel.xslt.features[quarkus.camel.xslt.features]` + +TransformerFactory features. +| ``Map<String,Boolean>`` +| |=== [.configuration-legend] diff --git a/extensions/xslt/deployment/src/main/java/org/apache/camel/quarkus/component/xslt/deployment/XsltProcessor.java b/extensions/xslt/deployment/src/main/java/org/apache/camel/quarkus/component/xslt/deployment/XsltProcessor.java index 074c415..11748c9 100644 --- a/extensions/xslt/deployment/src/main/java/org/apache/camel/quarkus/component/xslt/deployment/XsltProcessor.java +++ b/extensions/xslt/deployment/src/main/java/org/apache/camel/quarkus/component/xslt/deployment/XsltProcessor.java @@ -24,6 +24,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.Set; import javax.xml.transform.TransformerException; @@ -102,6 +103,11 @@ class XsltProcessor { try { TransformerFactory tf = new XalanTransformerFactory(); + + for (Map.Entry<String, Boolean> entry : config.features.entrySet()) { + tf.setFeature(entry.getKey(), entry.getValue()); + } + tf.setAttribute("generate-translet", true); tf.setAttribute("translet-name", resolvedUri.transletClassName); tf.setAttribute("package-name", config.packageName); diff --git a/extensions/xslt/runtime/src/main/doc/configuration.adoc b/extensions/xslt/runtime/src/main/doc/configuration.adoc index 090d98b..d8783fa 100644 --- a/extensions/xslt/runtime/src/main/doc/configuration.adoc +++ b/extensions/xslt/runtime/src/main/doc/configuration.adoc @@ -11,6 +11,26 @@ Scheme-less URIs are interpreted as `classpath:` URIs. Only `classpath:` URIs are supported on Quarkus. `file:`, `http:` and other kinds of URIs do not work by design. +=== Configuration +TransformerFactory features can be configured using following property: +[source,properties] +---- +quarkus.camel.xslt.features."http\://javax.xml.XMLConstants/feature/secure-processing"=false +---- +=== Extension functions support +https://xml.apache.org/xalan-j/extensions.html[Xalan's extension functions] +do work properly only when: + +1. Secure-processing is disabled +2. Functions are defined in a separate jar +3. Functions are augmented during native build phase. For example, they can be registered for reflection: +[source,java] +---- +@RegisterForReflection(targets = { my.Functions.class }) +public class FunctionsConfiguration { +} +---- + [NOTE] ==== The content of the XSLT source URIs is parsed and compiled into Java classes at build time. These Java classes are the diff --git a/extensions/xslt/runtime/src/main/java/org/apache/camel/quarkus/component/xslt/CamelXsltConfig.java b/extensions/xslt/runtime/src/main/java/org/apache/camel/quarkus/component/xslt/CamelXsltConfig.java index ed7c684..00479f6 100644 --- a/extensions/xslt/runtime/src/main/java/org/apache/camel/quarkus/component/xslt/CamelXsltConfig.java +++ b/extensions/xslt/runtime/src/main/java/org/apache/camel/quarkus/component/xslt/CamelXsltConfig.java @@ -17,6 +17,7 @@ package org.apache.camel.quarkus.component.xslt; import java.util.List; +import java.util.Map; import java.util.Optional; import io.quarkus.runtime.annotations.ConfigItem; @@ -36,4 +37,10 @@ public class CamelXsltConfig { */ @ConfigItem(defaultValue = "org.apache.camel.quarkus.component.xslt.generated") public String packageName; + + /** + * TransformerFactory features. + */ + @ConfigItem + public Map<String, Boolean> features; } diff --git a/extensions/xslt/runtime/src/main/java/org/apache/camel/quarkus/component/xslt/CamelXsltRecorder.java b/extensions/xslt/runtime/src/main/java/org/apache/camel/quarkus/component/xslt/CamelXsltRecorder.java index b91d937..67f85cf 100644 --- a/extensions/xslt/runtime/src/main/java/org/apache/camel/quarkus/component/xslt/CamelXsltRecorder.java +++ b/extensions/xslt/runtime/src/main/java/org/apache/camel/quarkus/component/xslt/CamelXsltRecorder.java @@ -16,6 +16,9 @@ */ package org.apache.camel.quarkus.component.xslt; +import java.util.Map; + +import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import io.quarkus.runtime.RuntimeValue; @@ -27,11 +30,12 @@ import org.apache.camel.quarkus.support.xalan.XalanTransformerFactory; @Recorder public class CamelXsltRecorder { + public RuntimeValue<XsltComponent> createXsltComponent(CamelXsltConfig config, RuntimeValue<RuntimeUriResolver.Builder> uriResolverBuilder) { final RuntimeUriResolver uriResolver = uriResolverBuilder.getValue().build(); final QuarkusTransformerFactoryConfigurationStrategy strategy = new QuarkusTransformerFactoryConfigurationStrategy( - config.packageName, uriResolver); + config.packageName, config.features, uriResolver); final XsltComponent component = new XsltComponent(); component.setUriResolver(uriResolver); component.setTransformerFactoryConfigurationStrategy(strategy); @@ -52,16 +56,28 @@ public class CamelXsltRecorder { private final String packageName; private final RuntimeUriResolver uriResolver; + private final Map<String, Boolean> features; - public QuarkusTransformerFactoryConfigurationStrategy(String packageName, RuntimeUriResolver uriResolver) { + public QuarkusTransformerFactoryConfigurationStrategy(String packageName, Map<String, Boolean> features, + RuntimeUriResolver uriResolver) { this.uriResolver = uriResolver; this.packageName = packageName; + this.features = features; } @Override public void configure(TransformerFactory tf, XsltEndpoint endpoint) { final String className = uriResolver.getTransletClassName(endpoint.getResourceUri()); + for (Map.Entry<String, Boolean> entry : features.entrySet()) { + try { + tf.setFeature(entry.getKey(), entry.getValue()); + } catch (TransformerException e) { + throw new RuntimeException("Could not set TransformerFactory feature '" + + entry.getKey() + "' = " + entry.getValue(), e); + } + } + tf.setAttribute("use-classpath", true); tf.setAttribute("translet-name", className); tf.setAttribute("package-name", packageName); diff --git a/integration-tests-support/pom.xml b/integration-tests-support/pom.xml index 4aee181..6f5182e 100644 --- a/integration-tests-support/pom.xml +++ b/integration-tests-support/pom.xml @@ -50,6 +50,7 @@ <module>test-support</module> <module>mock-backend</module> <module>wiremock</module> + <module>xslt-support</module> </modules> <dependencyManagement> diff --git a/integration-tests-support/xslt-support/pom.xml b/integration-tests-support/xslt-support/pom.xml new file mode 100644 index 0000000..e69274d --- /dev/null +++ b/integration-tests-support/xslt-support/pom.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. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-integration-tests-support</artifactId> + <version>2.7.1-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>camel-quarkus-integration-tests-support-xslt</artifactId> + <name>Camel Quarkus :: Integration Tests :: Support :: XSLT</name> +</project> diff --git a/extensions/xslt/runtime/src/main/java/org/apache/camel/quarkus/component/xslt/CamelXsltConfig.java b/integration-tests-support/xslt-support/src/main/java/org/apache/camel/quarkus/test/support/xslt/Functions.java similarity index 54% copy from extensions/xslt/runtime/src/main/java/org/apache/camel/quarkus/component/xslt/CamelXsltConfig.java copy to integration-tests-support/xslt-support/src/main/java/org/apache/camel/quarkus/test/support/xslt/Functions.java index ed7c684..7cf8d34 100644 --- a/extensions/xslt/runtime/src/main/java/org/apache/camel/quarkus/component/xslt/CamelXsltConfig.java +++ b/integration-tests-support/xslt-support/src/main/java/org/apache/camel/quarkus/test/support/xslt/Functions.java @@ -14,26 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.quarkus.component.xslt; +package org.apache.camel.quarkus.test.support.xslt; -import java.util.List; -import java.util.Optional; - -import io.quarkus.runtime.annotations.ConfigItem; -import io.quarkus.runtime.annotations.ConfigPhase; -import io.quarkus.runtime.annotations.ConfigRoot; - -@ConfigRoot(name = "camel.xslt", phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED) -public class CamelXsltConfig { - /** - * A comma separated list of templates to compile. - */ - @ConfigItem - public Optional<List<String>> sources; - - /** - * The package name for the generated classes. - */ - @ConfigItem(defaultValue = "org.apache.camel.quarkus.component.xslt.generated") - public String packageName; +public class Functions { + public static String concatDash(String val1, String val2) { + return val1 + "-" + val2; + } } diff --git a/integration-tests/xml/pom.xml b/integration-tests/xml/pom.xml index 1a6adc2..12bf572 100644 --- a/integration-tests/xml/pom.xml +++ b/integration-tests/xml/pom.xml @@ -56,6 +56,10 @@ <artifactId>camel-quarkus-support-stax</artifactId> </dependency> <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-integration-tests-support-xslt</artifactId> + </dependency> + <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-resteasy</artifactId> </dependency> diff --git a/extensions/xslt/runtime/src/main/java/org/apache/camel/quarkus/component/xslt/CamelXsltConfig.java b/integration-tests/xml/src/main/java/org/apache/camel/quarkus/component/xml/it/FunctionsConfiguration.java similarity index 54% copy from extensions/xslt/runtime/src/main/java/org/apache/camel/quarkus/component/xslt/CamelXsltConfig.java copy to integration-tests/xml/src/main/java/org/apache/camel/quarkus/component/xml/it/FunctionsConfiguration.java index ed7c684..c44360c 100644 --- a/extensions/xslt/runtime/src/main/java/org/apache/camel/quarkus/component/xslt/CamelXsltConfig.java +++ b/integration-tests/xml/src/main/java/org/apache/camel/quarkus/component/xml/it/FunctionsConfiguration.java @@ -14,26 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.quarkus.component.xslt; +package org.apache.camel.quarkus.component.xml.it; -import java.util.List; -import java.util.Optional; +import io.quarkus.runtime.annotations.RegisterForReflection; -import io.quarkus.runtime.annotations.ConfigItem; -import io.quarkus.runtime.annotations.ConfigPhase; -import io.quarkus.runtime.annotations.ConfigRoot; - -@ConfigRoot(name = "camel.xslt", phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED) -public class CamelXsltConfig { - /** - * A comma separated list of templates to compile. - */ - @ConfigItem - public Optional<List<String>> sources; - - /** - * The package name for the generated classes. - */ - @ConfigItem(defaultValue = "org.apache.camel.quarkus.component.xslt.generated") - public String packageName; +@RegisterForReflection(targets = { org.apache.camel.quarkus.test.support.xslt.Functions.class }) +public class FunctionsConfiguration { } diff --git a/integration-tests/xml/src/main/java/org/apache/camel/quarkus/component/xml/it/XmlResource.java b/integration-tests/xml/src/main/java/org/apache/camel/quarkus/component/xml/it/XmlResource.java index fd1e2f4..82da7b5 100644 --- a/integration-tests/xml/src/main/java/org/apache/camel/quarkus/component/xml/it/XmlResource.java +++ b/integration-tests/xml/src/main/java/org/apache/camel/quarkus/component/xml/it/XmlResource.java @@ -57,10 +57,17 @@ public class XmlResource { @Path("/xslt") @POST @Produces(MediaType.TEXT_PLAIN) - public String classpath(String body) throws Exception { + public String classpath(String body) { return producerTemplate.requestBody("xslt:xslt/classpath-transform.xsl", body, String.class); } + @Path("/xslt-extension-function") + @POST + @Produces(MediaType.TEXT_PLAIN) + public String extensionFunction(String body) { + return producerTemplate.requestBody("xslt:xslt/extension-function.xsl", body, String.class); + } + @Path("/html-transform") @POST @Consumes(MediaType.TEXT_HTML) diff --git a/integration-tests/xml/src/main/resources/application.properties b/integration-tests/xml/src/main/resources/application.properties index 7990d8b..472d5bc 100644 --- a/integration-tests/xml/src/main/resources/application.properties +++ b/integration-tests/xml/src/main/resources/application.properties @@ -23,4 +23,5 @@ quarkus.log.category."org.apache.camel.quarkus.core.deployment".level = INFO # # Quarkus - Camel # -quarkus.camel.xslt.sources = xslt/classpath-transform.xsl,xslt/html-transform.xsl,xslt/html-to-text.xsl +quarkus.camel.xslt.sources = xslt/classpath-transform.xsl,xslt/html-transform.xsl,xslt/html-to-text.xsl,xslt/extension-function.xsl +quarkus.camel.xslt.features."http\://javax.xml.XMLConstants/feature/secure-processing" = false \ No newline at end of file diff --git a/integration-tests/xml/src/main/resources/xslt/extension-function.xsl b/integration-tests/xml/src/main/resources/xslt/extension-function.xsl new file mode 100644 index 0000000..ac97acf --- /dev/null +++ b/integration-tests/xml/src/main/resources/xslt/extension-function.xsl @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<!-- + + 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. + +--> +<xsl:stylesheet + xmlns:xsl='http://www.w3.org/1999/XSL/Transform' + xmlns:func='xalan://org.apache.camel.quarkus.test.support.xslt.Functions' + extension-element-prefixes='func' + version='1.0'> + + <xsl:output method="xml" indent="yes" encoding="ISO-8859-1"/> + + <xsl:template match="/"> + <extension-function-xsl> + <xsl:value-of select="func:concatDash(/mail/subject, /mail/body)" /> + </extension-function-xsl> + </xsl:template> +</xsl:stylesheet> diff --git a/integration-tests/xml/src/test/java/org/apache/camel/quarkus/component/xml/it/XmlTest.java b/integration-tests/xml/src/test/java/org/apache/camel/quarkus/component/xml/it/XmlTest.java index 72544e8..22d6802 100644 --- a/integration-tests/xml/src/test/java/org/apache/camel/quarkus/component/xml/it/XmlTest.java +++ b/integration-tests/xml/src/test/java/org/apache/camel/quarkus/component/xml/it/XmlTest.java @@ -60,6 +60,20 @@ class XmlTest { } @Test + public void xsltExtensionFunction() { + final String actual = RestAssured.given() + .body(BODY) + .post("/xml/xslt-extension-function") + .then() + .statusCode(200) + .extract().body().asString().trim().replaceAll(">\\s+<", "><"); + + Assertions.assertEquals( + "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><extension-function-xsl>Hey-Hello world!</extension-function-xsl>", + actual); + } + + @Test public void htmlTransform() throws Exception { String html = IOUtils.toString(getClass().getResourceAsStream("/test.html"), Charset.forName("UTF-8")); diff --git a/poms/bom-test/pom.xml b/poms/bom-test/pom.xml index 3f01043..5286c0d 100644 --- a/poms/bom-test/pom.xml +++ b/poms/bom-test/pom.xml @@ -132,6 +132,11 @@ <artifactId>camel-quarkus-integration-wiremock-support</artifactId> <version>${camel-quarkus.version}</version> </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-integration-tests-support-xslt</artifactId> + <version>${camel-quarkus.version}</version> + </dependency> <dependency> <groupId>org.apache.camel.quarkus</groupId>
