This is an automated email from the ASF dual-hosted git repository. gnodet pushed a commit to branch backport/28160-to-camel-4.18.x in repository https://gitbox.apache.org/repos/asf/camel.git
commit 6efe769ed341479321b689918500523a7746a2a5 Author: Guillaume Nodet <[email protected]> AuthorDate: Tue Oct 27 09:01:13 2026 +0000 [backport camel-4.18.x] CAMEL-25827: camel-xslt-saxon - restrict external resource access for a Source message body --- .../org/apache/camel/catalog/components/xj.json | 4 +- .../camel/catalog/components/xslt-saxon.json | 4 +- .../META-INF/org/apache/camel/component/xj/xj.json | 4 +- .../camel/component/xslt/saxon/xslt-saxon.json | 4 +- .../saxon/SaxonXmlSourceHandlerFactoryImpl.java | 21 ++ .../xslt/saxon/XsltSaxonAggregationStrategy.java | 10 +- .../component/xslt/saxon/XsltSaxonBuilder.java | 10 + .../component/xslt/saxon/XsltSaxonComponent.java | 6 +- .../component/xslt/saxon/XsltSaxonEndpoint.java | 11 +- .../component/xslt/saxon/XsltSaxonHelper.java | 95 ++++++ .../XsltSaxonAggregationStrategyIncludeTest.java | 65 +++++ ...XsltSaxonAggregationStrategySourceBodyTest.java | 96 +++++++ .../xslt/saxon/XsltSaxonDomSourceTest.java | 320 +++++++++++++++++++++ .../saxon/XsltSaxonHelperConfigurationTest.java | 75 +++++ .../component/xslt/saxon/aggregate-included.xsl | 28 ++ .../xslt/saxon/aggregate-with-include.xsl | 38 +++ .../camel/component/xslt/saxon/dom-source-root.xsl | 38 +++ .../component/dsl/XjComponentBuilderFactory.java | 44 +-- .../dsl/XsltSaxonComponentBuilderFactory.java | 44 +-- .../endpoint/dsl/XJEndpointBuilderFactory.java | 76 ++--- .../dsl/XsltSaxonEndpointBuilderFactory.java | 76 ++--- 21 files changed, 942 insertions(+), 127 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xj.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xj.json index a8304ba98538..cd57203bdc97 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xj.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xj.json @@ -31,7 +31,7 @@ "saxonConfiguration": { "index": 4, "kind": "property", "displayName": "Saxon Configuration", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "net.sf.saxon.Configuration", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom Saxon configuration" }, "saxonConfigurationProperties": { "index": 5, "kind": "property", "displayName": "Saxon Configuration Properties", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "deprecated": false, "autowired": false, "secret": false, "description": "To set custom Saxon configuration properties" }, "saxonExtensionFunctions": { "index": 6, "kind": "property", "displayName": "Saxon Extension Functions", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Allows you to use a custom net.sf.saxon.lib.ExtensionFunctionDefinition. You would need to add camel-saxon to the classpath. The function is looked up in the registry, where you can use commas to se [...] - "secureProcessing": { "index": 7, "kind": "property", "displayName": "Secure Processing", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Feature for XML secure processing (see javax.xml.XMLConstants). This is enabled by default. However, when using Saxon Professional you may need to turn this off to allow Saxon to be able to use Java [...] + "secureProcessing": { "index": 7, "kind": "property", "displayName": "Secure Processing", "group": "security", "label": "advanced,security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "security": "insecure:dev", "insecureValue": "false", "defaultValue": true, "description": "Feature for XML secure processing (see javax.xml.XMLConstants). This is enabled by default. However, when using Saxon Professional you m [...] "transformerFactoryClass": { "index": 8, "kind": "property", "displayName": "Transformer Factory Class", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom XSLT transformer factory, specified as a FQN class name" }, "transformerFactoryConfigurationStrategy": { "index": 9, "kind": "property", "displayName": "Transformer Factory Configuration Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.xslt.TransformerFactoryConfigurationStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "A configuration strategy to apply on freshly created instances of TransformerFactory." }, "uriResolver": { "index": 10, "kind": "property", "displayName": "Uri Resolver", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.xml.transform.URIResolver", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom UriResolver. Should not be used together with the option 'uriResolverFactory'." }, @@ -61,7 +61,7 @@ "resultHandlerFactory": { "index": 14, "kind": "parameter", "displayName": "Result Handler Factory", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.xslt.ResultHandlerFactory", "deprecated": false, "autowired": false, "secret": false, "description": "Allows you to use a custom org.apache.camel.builder.xml.ResultHandlerFactory which is capable of using custom org.apache.camel.builder.xml.ResultHandler types." }, "saxonConfiguration": { "index": 15, "kind": "parameter", "displayName": "Saxon Configuration", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "net.sf.saxon.Configuration", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom Saxon configuration" }, "saxonExtensionFunctions": { "index": 16, "kind": "parameter", "displayName": "Saxon Extension Functions", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Allows you to use a custom net.sf.saxon.lib.ExtensionFunctionDefinition. You would need to add camel-saxon to the classpath. The function is looked up in the registry, where you can comma to separ [...] - "secureProcessing": { "index": 17, "kind": "parameter", "displayName": "Secure Processing", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Feature for XML secure processing (see javax.xml.XMLConstants). This is enabled by default. However, when using Saxon Professional you may need to turn this off to allow Saxon to be able to use Jav [...] + "secureProcessing": { "index": 17, "kind": "parameter", "displayName": "Secure Processing", "group": "security", "label": "advanced,security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "security": "insecure:dev", "insecureValue": "false", "defaultValue": true, "description": "Feature for XML secure processing (see javax.xml.XMLConstants). This is enabled by default. However, when using Saxon Professional you [...] "transformerFactory": { "index": 18, "kind": "parameter", "displayName": "Transformer Factory", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.xml.transform.TransformerFactory", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom XSLT transformer factory" }, "transformerFactoryClass": { "index": 19, "kind": "parameter", "displayName": "Transformer Factory Class", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom XSLT transformer factory, specified as a FQN class name" }, "transformerFactoryConfigurationStrategy": { "index": 20, "kind": "parameter", "displayName": "Transformer Factory Configuration Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.xslt.TransformerFactoryConfigurationStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "A configuration strategy to apply on freshly created instances of TransformerFactory." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xslt-saxon.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xslt-saxon.json index f6ec0a47c371..29c92468aeb0 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xslt-saxon.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xslt-saxon.json @@ -31,7 +31,7 @@ "saxonConfiguration": { "index": 4, "kind": "property", "displayName": "Saxon Configuration", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "net.sf.saxon.Configuration", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom Saxon configuration" }, "saxonConfigurationProperties": { "index": 5, "kind": "property", "displayName": "Saxon Configuration Properties", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "deprecated": false, "autowired": false, "secret": false, "description": "To set custom Saxon configuration properties" }, "saxonExtensionFunctions": { "index": 6, "kind": "property", "displayName": "Saxon Extension Functions", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Allows you to use a custom net.sf.saxon.lib.ExtensionFunctionDefinition. You would need to add camel-saxon to the classpath. The function is looked up in the registry, where you can use commas to se [...] - "secureProcessing": { "index": 7, "kind": "property", "displayName": "Secure Processing", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Feature for XML secure processing (see javax.xml.XMLConstants). This is enabled by default. However, when using Saxon Professional you may need to turn this off to allow Saxon to be able to use Java [...] + "secureProcessing": { "index": 7, "kind": "property", "displayName": "Secure Processing", "group": "security", "label": "advanced,security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "security": "insecure:dev", "insecureValue": "false", "defaultValue": true, "description": "Feature for XML secure processing (see javax.xml.XMLConstants). This is enabled by default. However, when using Saxon Professional you m [...] "transformerFactoryClass": { "index": 8, "kind": "property", "displayName": "Transformer Factory Class", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom XSLT transformer factory, specified as a FQN class name" }, "transformerFactoryConfigurationStrategy": { "index": 9, "kind": "property", "displayName": "Transformer Factory Configuration Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.xslt.TransformerFactoryConfigurationStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "A configuration strategy to apply on freshly created instances of TransformerFactory." }, "uriResolver": { "index": 10, "kind": "property", "displayName": "Uri Resolver", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.xml.transform.URIResolver", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom UriResolver. Should not be used together with the option 'uriResolverFactory'." }, @@ -60,7 +60,7 @@ "resultHandlerFactory": { "index": 13, "kind": "parameter", "displayName": "Result Handler Factory", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.xslt.ResultHandlerFactory", "deprecated": false, "autowired": false, "secret": false, "description": "Allows you to use a custom org.apache.camel.builder.xml.ResultHandlerFactory which is capable of using custom org.apache.camel.builder.xml.ResultHandler types." }, "saxonConfiguration": { "index": 14, "kind": "parameter", "displayName": "Saxon Configuration", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "net.sf.saxon.Configuration", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom Saxon configuration" }, "saxonExtensionFunctions": { "index": 15, "kind": "parameter", "displayName": "Saxon Extension Functions", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Allows you to use a custom net.sf.saxon.lib.ExtensionFunctionDefinition. You would need to add camel-saxon to the classpath. The function is looked up in the registry, where you can comma to separ [...] - "secureProcessing": { "index": 16, "kind": "parameter", "displayName": "Secure Processing", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Feature for XML secure processing (see javax.xml.XMLConstants). This is enabled by default. However, when using Saxon Professional you may need to turn this off to allow Saxon to be able to use Jav [...] + "secureProcessing": { "index": 16, "kind": "parameter", "displayName": "Secure Processing", "group": "security", "label": "advanced,security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "security": "insecure:dev", "insecureValue": "false", "defaultValue": true, "description": "Feature for XML secure processing (see javax.xml.XMLConstants). This is enabled by default. However, when using Saxon Professional you [...] "transformerFactory": { "index": 17, "kind": "parameter", "displayName": "Transformer Factory", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.xml.transform.TransformerFactory", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom XSLT transformer factory" }, "transformerFactoryClass": { "index": 18, "kind": "parameter", "displayName": "Transformer Factory Class", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom XSLT transformer factory, specified as a FQN class name" }, "transformerFactoryConfigurationStrategy": { "index": 19, "kind": "parameter", "displayName": "Transformer Factory Configuration Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.xslt.TransformerFactoryConfigurationStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "A configuration strategy to apply on freshly created instances of TransformerFactory." }, diff --git a/components/camel-xj/src/generated/resources/META-INF/org/apache/camel/component/xj/xj.json b/components/camel-xj/src/generated/resources/META-INF/org/apache/camel/component/xj/xj.json index a8304ba98538..cd57203bdc97 100644 --- a/components/camel-xj/src/generated/resources/META-INF/org/apache/camel/component/xj/xj.json +++ b/components/camel-xj/src/generated/resources/META-INF/org/apache/camel/component/xj/xj.json @@ -31,7 +31,7 @@ "saxonConfiguration": { "index": 4, "kind": "property", "displayName": "Saxon Configuration", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "net.sf.saxon.Configuration", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom Saxon configuration" }, "saxonConfigurationProperties": { "index": 5, "kind": "property", "displayName": "Saxon Configuration Properties", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "deprecated": false, "autowired": false, "secret": false, "description": "To set custom Saxon configuration properties" }, "saxonExtensionFunctions": { "index": 6, "kind": "property", "displayName": "Saxon Extension Functions", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Allows you to use a custom net.sf.saxon.lib.ExtensionFunctionDefinition. You would need to add camel-saxon to the classpath. The function is looked up in the registry, where you can use commas to se [...] - "secureProcessing": { "index": 7, "kind": "property", "displayName": "Secure Processing", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Feature for XML secure processing (see javax.xml.XMLConstants). This is enabled by default. However, when using Saxon Professional you may need to turn this off to allow Saxon to be able to use Java [...] + "secureProcessing": { "index": 7, "kind": "property", "displayName": "Secure Processing", "group": "security", "label": "advanced,security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "security": "insecure:dev", "insecureValue": "false", "defaultValue": true, "description": "Feature for XML secure processing (see javax.xml.XMLConstants). This is enabled by default. However, when using Saxon Professional you m [...] "transformerFactoryClass": { "index": 8, "kind": "property", "displayName": "Transformer Factory Class", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom XSLT transformer factory, specified as a FQN class name" }, "transformerFactoryConfigurationStrategy": { "index": 9, "kind": "property", "displayName": "Transformer Factory Configuration Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.xslt.TransformerFactoryConfigurationStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "A configuration strategy to apply on freshly created instances of TransformerFactory." }, "uriResolver": { "index": 10, "kind": "property", "displayName": "Uri Resolver", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.xml.transform.URIResolver", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom UriResolver. Should not be used together with the option 'uriResolverFactory'." }, @@ -61,7 +61,7 @@ "resultHandlerFactory": { "index": 14, "kind": "parameter", "displayName": "Result Handler Factory", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.xslt.ResultHandlerFactory", "deprecated": false, "autowired": false, "secret": false, "description": "Allows you to use a custom org.apache.camel.builder.xml.ResultHandlerFactory which is capable of using custom org.apache.camel.builder.xml.ResultHandler types." }, "saxonConfiguration": { "index": 15, "kind": "parameter", "displayName": "Saxon Configuration", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "net.sf.saxon.Configuration", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom Saxon configuration" }, "saxonExtensionFunctions": { "index": 16, "kind": "parameter", "displayName": "Saxon Extension Functions", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Allows you to use a custom net.sf.saxon.lib.ExtensionFunctionDefinition. You would need to add camel-saxon to the classpath. The function is looked up in the registry, where you can comma to separ [...] - "secureProcessing": { "index": 17, "kind": "parameter", "displayName": "Secure Processing", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Feature for XML secure processing (see javax.xml.XMLConstants). This is enabled by default. However, when using Saxon Professional you may need to turn this off to allow Saxon to be able to use Jav [...] + "secureProcessing": { "index": 17, "kind": "parameter", "displayName": "Secure Processing", "group": "security", "label": "advanced,security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "security": "insecure:dev", "insecureValue": "false", "defaultValue": true, "description": "Feature for XML secure processing (see javax.xml.XMLConstants). This is enabled by default. However, when using Saxon Professional you [...] "transformerFactory": { "index": 18, "kind": "parameter", "displayName": "Transformer Factory", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.xml.transform.TransformerFactory", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom XSLT transformer factory" }, "transformerFactoryClass": { "index": 19, "kind": "parameter", "displayName": "Transformer Factory Class", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom XSLT transformer factory, specified as a FQN class name" }, "transformerFactoryConfigurationStrategy": { "index": 20, "kind": "parameter", "displayName": "Transformer Factory Configuration Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.xslt.TransformerFactoryConfigurationStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "A configuration strategy to apply on freshly created instances of TransformerFactory." }, diff --git a/components/camel-xslt-saxon/src/generated/resources/META-INF/org/apache/camel/component/xslt/saxon/xslt-saxon.json b/components/camel-xslt-saxon/src/generated/resources/META-INF/org/apache/camel/component/xslt/saxon/xslt-saxon.json index f6ec0a47c371..29c92468aeb0 100644 --- a/components/camel-xslt-saxon/src/generated/resources/META-INF/org/apache/camel/component/xslt/saxon/xslt-saxon.json +++ b/components/camel-xslt-saxon/src/generated/resources/META-INF/org/apache/camel/component/xslt/saxon/xslt-saxon.json @@ -31,7 +31,7 @@ "saxonConfiguration": { "index": 4, "kind": "property", "displayName": "Saxon Configuration", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "net.sf.saxon.Configuration", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom Saxon configuration" }, "saxonConfigurationProperties": { "index": 5, "kind": "property", "displayName": "Saxon Configuration Properties", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "deprecated": false, "autowired": false, "secret": false, "description": "To set custom Saxon configuration properties" }, "saxonExtensionFunctions": { "index": 6, "kind": "property", "displayName": "Saxon Extension Functions", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Allows you to use a custom net.sf.saxon.lib.ExtensionFunctionDefinition. You would need to add camel-saxon to the classpath. The function is looked up in the registry, where you can use commas to se [...] - "secureProcessing": { "index": 7, "kind": "property", "displayName": "Secure Processing", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Feature for XML secure processing (see javax.xml.XMLConstants). This is enabled by default. However, when using Saxon Professional you may need to turn this off to allow Saxon to be able to use Java [...] + "secureProcessing": { "index": 7, "kind": "property", "displayName": "Secure Processing", "group": "security", "label": "advanced,security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "security": "insecure:dev", "insecureValue": "false", "defaultValue": true, "description": "Feature for XML secure processing (see javax.xml.XMLConstants). This is enabled by default. However, when using Saxon Professional you m [...] "transformerFactoryClass": { "index": 8, "kind": "property", "displayName": "Transformer Factory Class", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom XSLT transformer factory, specified as a FQN class name" }, "transformerFactoryConfigurationStrategy": { "index": 9, "kind": "property", "displayName": "Transformer Factory Configuration Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.xslt.TransformerFactoryConfigurationStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "A configuration strategy to apply on freshly created instances of TransformerFactory." }, "uriResolver": { "index": 10, "kind": "property", "displayName": "Uri Resolver", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.xml.transform.URIResolver", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom UriResolver. Should not be used together with the option 'uriResolverFactory'." }, @@ -60,7 +60,7 @@ "resultHandlerFactory": { "index": 13, "kind": "parameter", "displayName": "Result Handler Factory", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.xslt.ResultHandlerFactory", "deprecated": false, "autowired": false, "secret": false, "description": "Allows you to use a custom org.apache.camel.builder.xml.ResultHandlerFactory which is capable of using custom org.apache.camel.builder.xml.ResultHandler types." }, "saxonConfiguration": { "index": 14, "kind": "parameter", "displayName": "Saxon Configuration", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "net.sf.saxon.Configuration", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom Saxon configuration" }, "saxonExtensionFunctions": { "index": 15, "kind": "parameter", "displayName": "Saxon Extension Functions", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Allows you to use a custom net.sf.saxon.lib.ExtensionFunctionDefinition. You would need to add camel-saxon to the classpath. The function is looked up in the registry, where you can comma to separ [...] - "secureProcessing": { "index": 16, "kind": "parameter", "displayName": "Secure Processing", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Feature for XML secure processing (see javax.xml.XMLConstants). This is enabled by default. However, when using Saxon Professional you may need to turn this off to allow Saxon to be able to use Jav [...] + "secureProcessing": { "index": 16, "kind": "parameter", "displayName": "Secure Processing", "group": "security", "label": "advanced,security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "security": "insecure:dev", "insecureValue": "false", "defaultValue": true, "description": "Feature for XML secure processing (see javax.xml.XMLConstants). This is enabled by default. However, when using Saxon Professional you [...] "transformerFactory": { "index": 17, "kind": "parameter", "displayName": "Transformer Factory", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.xml.transform.TransformerFactory", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom XSLT transformer factory" }, "transformerFactoryClass": { "index": 18, "kind": "parameter", "displayName": "Transformer Factory Class", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom XSLT transformer factory, specified as a FQN class name" }, "transformerFactoryConfigurationStrategy": { "index": 19, "kind": "parameter", "displayName": "Transformer Factory Configuration Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.xslt.TransformerFactoryConfigurationStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "A configuration strategy to apply on freshly created instances of TransformerFactory." }, diff --git a/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/SaxonXmlSourceHandlerFactoryImpl.java b/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/SaxonXmlSourceHandlerFactoryImpl.java index faadda012976..2e005f2b93ee 100644 --- a/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/SaxonXmlSourceHandlerFactoryImpl.java +++ b/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/SaxonXmlSourceHandlerFactoryImpl.java @@ -36,6 +36,7 @@ public class SaxonXmlSourceHandlerFactoryImpl extends XmlSourceHandlerFactoryImp private static final Logger LOG = LoggerFactory.getLogger(SaxonXmlSourceHandlerFactoryImpl.class); private boolean useJsonBody = false; + private boolean secureProcessing = true; public boolean isUseJsonBody() { return useJsonBody; @@ -45,12 +46,32 @@ public class SaxonXmlSourceHandlerFactoryImpl extends XmlSourceHandlerFactoryImp this.useJsonBody = useJsonBody; } + public boolean isSecureProcessing() { + return secureProcessing; + } + + public void setSecureProcessing(boolean secureProcessing) { + this.secureProcessing = secureProcessing; + } + private net.sf.saxon.s9api.Processor saxonProcessor; private net.sf.saxon.s9api.XPathExecutable saxonJsonToXmlExecutable; private DocumentBuilder documentBuilder; @Override protected Source getSource(Exchange exchange, Object body) { + Source source = doGetSource(exchange, body); + if (secureProcessing) { + // A stream-based source still has to be parsed. Parse it with a reader that does not resolve references + // to external resources declared in the document, like the other body types which reach Saxon through + // Camel's StAX/SAX converters. A source that is already parsed (for example a DOMSource or a StAXSource) + // or that carries a reader the caller configured is returned as is. + source = XsltSaxonHelper.secureSource(source); + } + return source; + } + + private Source doGetSource(Exchange exchange, Object body) { // body may already be a source if (body instanceof Source) { return (Source) body; diff --git a/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonAggregationStrategy.java b/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonAggregationStrategy.java index cf86c3d4b010..d531828fb59d 100644 --- a/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonAggregationStrategy.java +++ b/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonAggregationStrategy.java @@ -19,6 +19,7 @@ package org.apache.camel.component.xslt.saxon; import javax.xml.transform.TransformerFactory; import net.sf.saxon.TransformerFactoryImpl; +import org.apache.camel.RuntimeCamelException; import org.apache.camel.component.xslt.XsltAggregationStrategy; import org.apache.camel.component.xslt.XsltBuilder; import org.apache.camel.component.xslt.XsltOutput; @@ -50,7 +51,14 @@ public class XsltSaxonAggregationStrategy extends XsltAggregationStrategy { public XsltSaxonAggregationStrategy(String xslFileLocation) { super(xslFileLocation); - setTransformerFactory(new TransformerFactoryImpl()); + TransformerFactoryImpl factory = new TransformerFactoryImpl(); + try { + XsltSaxonHelper.configureSecureProcessing(factory, true); + } catch (Exception e) { + throw new RuntimeCamelException("Cannot configure secure processing on the Saxon TransformerFactory", e); + } + XsltSaxonHelper.configureExternalAccess(factory); + setTransformerFactory(factory); } @Override diff --git a/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonBuilder.java b/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonBuilder.java index bd3c58e04028..e5b2fd193d0f 100644 --- a/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonBuilder.java +++ b/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonBuilder.java @@ -40,6 +40,7 @@ public class XsltSaxonBuilder extends XsltBuilder { private boolean allowStAX = true; private boolean useJsonBody = false; + private boolean secureProcessing = true; @Override protected Source prepareSource(Source source) { @@ -74,10 +75,19 @@ public class XsltSaxonBuilder extends XsltBuilder { this.useJsonBody = useJsonBody; } + public boolean isSecureProcessing() { + return secureProcessing; + } + + public void setSecureProcessing(boolean secureProcessing) { + this.secureProcessing = secureProcessing; + } + @Override protected XmlSourceHandlerFactoryImpl createXmlSourceHandlerFactoryImpl() { SaxonXmlSourceHandlerFactoryImpl factory = new SaxonXmlSourceHandlerFactoryImpl(); factory.setUseJsonBody(useJsonBody); + factory.setSecureProcessing(secureProcessing); return factory; } diff --git a/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonComponent.java b/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonComponent.java index e21898cc5ed7..7de498921d6e 100644 --- a/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonComponent.java +++ b/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonComponent.java @@ -39,7 +39,7 @@ public class XsltSaxonComponent extends XsltComponent { private Map<String, Object> saxonConfigurationProperties = new HashMap<>(); @Metadata(label = "advanced", javaType = "java.lang.String") private List<Object> saxonExtensionFunctions; - @Metadata(label = "advanced", defaultValue = "true") + @Metadata(label = "advanced,security", defaultValue = "true", security = "insecure:dev", insecureValue = "false") private boolean secureProcessing = true; public List<Object> getSaxonExtensionFunctions() { @@ -73,7 +73,9 @@ public class XsltSaxonComponent extends XsltComponent { /** * Feature for XML secure processing (see javax.xml.XMLConstants). This is enabled by default. However, when using - * Saxon Professional you may need to turn this off to allow Saxon to be able to use Java extension functions. + * Saxon Professional you may need to turn this off to allow Saxon to be able to use Java extension functions. Note + * that turning it off also restores the previous, unrestricted parsing of a {@code Source} message body that is + * still to be parsed, so only do so for trusted input. */ public void setSecureProcessing(boolean secureProcessing) { this.secureProcessing = secureProcessing; diff --git a/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonEndpoint.java b/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonEndpoint.java index 87b3fed7a42a..f117aa30b169 100644 --- a/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonEndpoint.java +++ b/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonEndpoint.java @@ -78,7 +78,7 @@ public class XsltSaxonEndpoint extends XsltEndpoint { private List<Object> saxonExtensionFunctions; @UriParam(displayName = "Allow StAX", defaultValue = "true") private boolean allowStAX = true; - @UriParam(label = "advanced", defaultValue = "true") + @UriParam(label = "advanced,security", defaultValue = "true", security = "insecure:dev", insecureValue = "false") private boolean secureProcessing = true; @UriParam @Metadata(firstVersion = "4.15.0", displayName = "Use JSON Body", defaultValue = "false", required = false) @@ -168,7 +168,9 @@ public class XsltSaxonEndpoint extends XsltEndpoint { /** * Feature for XML secure processing (see javax.xml.XMLConstants). This is enabled by default. However, when using - * Saxon Professional you may need to turn this off to allow Saxon to be able to use Java extension functions. + * Saxon Professional you may need to turn this off to allow Saxon to be able to use Java extension functions. Note + * that turning it off also restores the previous, unrestricted parsing of a {@code Source} message body that is + * still to be parsed, so only do so for trusted input. */ public void setSecureProcessing(boolean secureProcessing) { this.secureProcessing = secureProcessing; @@ -234,6 +236,7 @@ public class XsltSaxonEndpoint extends XsltEndpoint { LOG.debug("Using TransformerFactoryClass {}", factoryClass); factory = injector.newInstance(factoryClass); } + } if (factory instanceof TransformerFactoryImpl) { @@ -242,6 +245,9 @@ public class XsltSaxonEndpoint extends XsltEndpoint { XsltSaxonHelper.registerSaxonConfigurationProperties(tf, saxonConfigurationProperties); XsltSaxonHelper.registerSaxonExtensionFunctions(tf, saxonExtensionFunctions, secureProcessing); } + if (factory != null) { + XsltSaxonHelper.configureExternalAccess(factory); + } if (factory != null) { LOG.debug("Using TransformerFactory {}", factory); @@ -259,6 +265,7 @@ public class XsltSaxonEndpoint extends XsltEndpoint { xslt.setEntityResolver(getEntityResolver()); xslt.setAllowStAX(allowStAX); xslt.setUseJsonBody(useJsonBody); + xslt.setSecureProcessing(secureProcessing); xslt.setDeleteOutputFile(isDeleteOutputFile()); xslt.setSource(ExpressionBuilder.singleInputExpression(getSource())); diff --git a/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonHelper.java b/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonHelper.java index 0a6f3be451f9..be2257e8a0a6 100644 --- a/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonHelper.java +++ b/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonHelper.java @@ -20,10 +20,21 @@ import java.util.List; import java.util.Map; import javax.xml.XMLConstants; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.Source; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXSource; + +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; import net.sf.saxon.Configuration; import net.sf.saxon.TransformerFactoryImpl; import net.sf.saxon.lib.ExtensionFunctionDefinition; +import org.apache.camel.RuntimeCamelException; +import org.apache.camel.converter.jaxp.XMLReaderPool; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,9 +42,35 @@ final class XsltSaxonHelper { private static final Logger LOG = LoggerFactory.getLogger(XsltSaxonHelper.class); + private static final String EXTERNAL_GENERAL_ENTITIES = "http://xml.org/sax/features/external-general-entities"; + private static final String EXTERNAL_PARAMETER_ENTITIES = "http://xml.org/sax/features/external-parameter-entities"; + private static final String LOAD_EXTERNAL_DTD = "http://apache.org/xml/features/nonvalidating/load-external-dtd"; + + private static final class SecureReaderPoolHolder { + // Configured once: a SAXParserFactory on the classpath that does not recognise one of the required features fails + // on first use of the holder rather than silently degrading on every exchange. The pool hands out a + // reader for a single parse and is safe to share between threads. + static final XMLReaderPool POOL = new XMLReaderPool(createSecureSaxParserFactory()); + } + private XsltSaxonHelper() { } + private static SAXParserFactory createSecureSaxParserFactory() { + try { + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setNamespaceAware(true); + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + factory.setFeature(EXTERNAL_GENERAL_ENTITIES, false); + factory.setFeature(EXTERNAL_PARAMETER_ENTITIES, false); + factory.setFeature(LOAD_EXTERNAL_DTD, false); + return factory; + } catch (ParserConfigurationException | SAXException e) { + throw new IllegalStateException( + "Cannot configure a restricted SAXParserFactory for xslt-saxon input parsing", e); + } + } + public static void registerSaxonConfiguration(TransformerFactoryImpl factory, Configuration saxonConfiguration) { if (saxonConfiguration != null) { factory.setConfiguration(saxonConfiguration); @@ -50,6 +87,64 @@ final class XsltSaxonHelper { } } + public static void configureSecureProcessing(TransformerFactoryImpl factory, boolean secureProcessing) + throws Exception { + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, secureProcessing); + } + + /** + * Restricts the external resource access of the given factory to the empty set, so that stylesheet compilation and + * the {@code document()} function do not reach external resources. This is the same configuration the + * {@code xslt-saxon} endpoint applies to the factory it creates; it is shared so the endpoint and + * {@link XsltSaxonAggregationStrategy} cannot drift apart. + */ + public static void configureExternalAccess(TransformerFactory factory) { + try { + factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + } catch (IllegalArgumentException e) { + LOG.debug("TransformerFactory does not support {}", XMLConstants.ACCESS_EXTERNAL_DTD); + } + try { + factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); + } catch (IllegalArgumentException e) { + LOG.debug("TransformerFactory does not support {}", XMLConstants.ACCESS_EXTERNAL_STYLESHEET); + } + } + + /** + * Returns a source whose parsing does not resolve references to external resources, for an input that is still to + * be parsed. The factory's {@code ACCESS_EXTERNAL_*} attributes do not cover this parse, because the transformer + * factory has a {@link javax.xml.transform.URIResolver} installed that resolves the reference itself, so the input + * is parsed with a dedicated reader instead. + * <p> + * A {@link SAXSource} that already carries its own {@link XMLReader}, and any source that is not stream-based (for + * example a {@code DOMSource} or a {@code StAXSource}), is returned unchanged; its content has already been parsed + * or is read through a reader the caller controls. Only a stream-based source still to be parsed + * ({@code StreamSource}, including Camel's {@code StringSource}/{@code BytesSource}, or a reader-less + * {@code SAXSource}) is wrapped with the restricted reader. + */ + public static Source secureSource(Source source) { + if (source == null) { + return null; + } + if (source instanceof SAXSource saxSource && saxSource.getXMLReader() != null) { + return source; + } + InputSource inputSource = SAXSource.sourceToInputSource(source); + if (inputSource == null) { + return source; + } + try { + XMLReader xmlReader = SecureReaderPoolHolder.POOL.createXMLReader(); + return new SAXSource(xmlReader, inputSource); + } catch (ParserConfigurationException | SAXException e) { + // Fail closed: this is the security control, so do not fall back to an unrestricted parse. + throw new RuntimeCamelException( + "Cannot create a restricted XMLReader for the xslt-saxon input source", e); + } + } + + public static void registerSaxonExtensionFunctions( TransformerFactoryImpl factory, List<Object> saxonExtensionFunctions, diff --git a/components/camel-xslt-saxon/src/test/java/org/apache/camel/component/xslt/saxon/XsltSaxonAggregationStrategyIncludeTest.java b/components/camel-xslt-saxon/src/test/java/org/apache/camel/component/xslt/saxon/XsltSaxonAggregationStrategyIncludeTest.java new file mode 100644 index 000000000000..4d9ce3e05b67 --- /dev/null +++ b/components/camel-xslt-saxon/src/test/java/org/apache/camel/component/xslt/saxon/XsltSaxonAggregationStrategyIncludeTest.java @@ -0,0 +1,65 @@ +/* + * 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.saxon; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.junit6.CamelTestSupport; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Checks that an aggregation stylesheet used by {@link XsltSaxonAggregationStrategy} can still resolve an + * {@code xsl:include} from the classpath, even though the strategy now restricts external resource access + * ({@code ACCESS_EXTERNAL_STYLESHEET=""}) the same way the {@code xslt-saxon} endpoint does. The restriction targets + * resources named by the message body, not the stylesheet's own includes, which Camel resolves from the classpath. + */ +class XsltSaxonAggregationStrategyIncludeTest extends CamelTestSupport { + + @Test + void shouldResolveClasspathIncludeInAggregationStylesheet() throws Exception { + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMessageCount(1); + + template.sendBody("direct:aggregate", "<item>A</item>"); + template.sendBody("direct:aggregate", "<item>B</item>"); + + MockEndpoint.assertIsSatisfied(context); + + String body = mock.getReceivedExchanges().get(0).getIn().getBody(String.class); + assertTrue(body.contains("INCLUDED-"), + "The xsl:include from the classpath should be resolved (named template from the included stylesheet). Got: " + + body); + assertTrue(body.contains("AB"), "The aggregation should combine both bodies. Got: " + body); + } + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + from("direct:aggregate") + .aggregate(constant(true), + new XsltSaxonAggregationStrategy( + "org/apache/camel/component/xslt/saxon/aggregate-with-include.xsl")) + .completionSize(2) + .to("mock:result"); + } + }; + } +} diff --git a/components/camel-xslt-saxon/src/test/java/org/apache/camel/component/xslt/saxon/XsltSaxonAggregationStrategySourceBodyTest.java b/components/camel-xslt-saxon/src/test/java/org/apache/camel/component/xslt/saxon/XsltSaxonAggregationStrategySourceBodyTest.java new file mode 100644 index 000000000000..7fe5501b5876 --- /dev/null +++ b/components/camel-xslt-saxon/src/test/java/org/apache/camel/component/xslt/saxon/XsltSaxonAggregationStrategySourceBodyTest.java @@ -0,0 +1,96 @@ +/* + * 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.saxon; + +import java.nio.file.Files; +import java.nio.file.Path; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.junit6.CamelTestSupport; +import org.apache.camel.util.xml.StringSource; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Checks how {@link XsltSaxonAggregationStrategy} parses a message body that is already a + * {@link javax.xml.transform.Source} when it aggregates it. Such a body reaches Saxon still to be parsed, unlike the + * other body types which Camel converts first, so the strategy must parse it with the same restrictions the + * {@code xslt-saxon} endpoint applies to its own factory: a reference to a resource named by the body is not resolved + * from it, while a declaration internal to the document is still applied. + */ +class XsltSaxonAggregationStrategySourceBodyTest extends CamelTestSupport { + + @TempDir + static Path tmp; + + private static final String SENTINEL = "SENTINELFILECONTENT"; + + @Test + void shouldNotResolveSystemReferenceInAggregatedSourceBody() throws Exception { + Path file = tmp.resolve("neighbour.txt"); + Files.writeString(file, SENTINEL); + + String firstBody = "<!DOCTYPE item [<!ENTITY ref SYSTEM \"" + file.toUri() + "\">]><item>&ref;</item>"; + + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMessageCount(1); + + template.sendBody("direct:aggregate", new StringSource(firstBody)); + template.sendBody("direct:aggregate", "<item>B</item>"); + + MockEndpoint.assertIsSatisfied(context); + + String body = mock.getReceivedExchanges().get(0).getIn().getBody(String.class); + assertFalse(body.contains(SENTINEL), + "The resource named by the aggregated body must not be resolved into the result. Got: " + body); + } + + @Test + void shouldStillApplyInternalDeclarationInAggregatedSourceBody() throws Exception { + String firstBody = "<!DOCTYPE item [<!ENTITY ok \"OKVALUE\">]><item>&ok;</item>"; + + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMessageCount(1); + + template.sendBody("direct:aggregate", new StringSource(firstBody)); + template.sendBody("direct:aggregate", "<item>B</item>"); + + MockEndpoint.assertIsSatisfied(context); + + String body = mock.getReceivedExchanges().get(0).getIn().getBody(String.class); + assertTrue(body.contains("OKVALUE"), + "A declaration internal to the document should still be applied. Got: " + body); + } + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + from("direct:aggregate") + .aggregate(constant(true), + new XsltSaxonAggregationStrategy("org/apache/camel/util/toolbox/aggregate.xsl")) + .completionSize(2) + .to("mock:result"); + } + }; + } +} diff --git a/components/camel-xslt-saxon/src/test/java/org/apache/camel/component/xslt/saxon/XsltSaxonDomSourceTest.java b/components/camel-xslt-saxon/src/test/java/org/apache/camel/component/xslt/saxon/XsltSaxonDomSourceTest.java new file mode 100644 index 000000000000..11380cc47d6d --- /dev/null +++ b/components/camel-xslt-saxon/src/test/java/org/apache/camel/component/xslt/saxon/XsltSaxonDomSourceTest.java @@ -0,0 +1,320 @@ +/* + * 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.saxon; + +import java.io.StringReader; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.stream.XMLInputFactory; +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.sax.SAXSource; +import javax.xml.transform.stax.StAXSource; +import javax.xml.transform.stream.StreamSource; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.xml.sax.InputSource; + +import org.apache.camel.Exchange; +import org.apache.camel.Expression; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.builder.ExpressionBuilder; +import org.apache.camel.impl.DefaultCamelContext; +import org.apache.camel.support.DefaultExchange; +import org.apache.camel.support.TypeConverterSupport; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class XsltSaxonDomSourceTest { + + private static final String ENDPOINT = "xslt-saxon:org/apache/camel/component/xslt/saxon/dom-source-root.xsl"; + private static final String INPUT = """ + <req:Request xmlns:req="urn:request"> + <req:Header>SOURCE_SYSTEM_VALUE</req:Header> + <req:Authentication> + <req:UserName>test-user</req:UserName> + <req:Password>test-password</req:Password> + </req:Authentication> + </req:Request> + """; + + private DefaultCamelContext context; + private ProducerTemplate template; + + @BeforeEach + void setUp() throws Exception { + context = new DefaultCamelContext(); + // Force the DOM and generic Source fallback paths without depending on converter discovery order. + TypeConverterSupport converter = new TypeConverterSupport() { + @Override + public <T> T convertTo(Class<T> type, Exchange exchange, Object value) { + Payload payload = (Payload) value; + if (type == Source.class || type == payload.source.getClass() && !payload.genericSourceOnly) { + payload.conversions++; + return type.cast(payload.source); + } + return null; + } + }; + for (Class<?> type : new Class<?>[] { + Source.class, DOMSource.class, SAXSource.class, + StreamSource.class, StAXSource.class }) { + context.getTypeConverterRegistry().addTypeConverter(type, Payload.class, converter); + } + context.start(); + template = context.createProducerTemplate(); + template.start(); + } + + @AfterEach + void tearDown() throws Exception { + if (template != null) { + template.stop(); + } + if (context != null) { + context.stop(); + } + } + + @ParameterizedTest + @ValueSource(booleans = { false, true }) + void testImplicitDocumentElement(boolean genericSourceOnly) throws Exception { + Document document = parse(INPUT); + Document original = (Document) document.cloneNode(true); + Element element = document.getDocumentElement(); + DOMSource source = new DOMSource(element, "file:/payload/request.xml"); + Payload payload = new Payload(source, genericSourceOnly); + // Reuse the converter's cached DOMSource, as an Element-backed CXF payload does. + for (int i = 0; i < 3; i++) { + String result = template.requestBody(ENDPOINT, payload, String.class); + assertTrue(result.contains("<root"), result); + Document output = parse(result); + assertEquals("root", output.getDocumentElement().getNodeName()); + assertEquals("test-user", output.getElementsByTagNameNS("urn:login", "UserId").item(0).getTextContent()); + assertEquals("test-password", output.getElementsByTagNameNS("urn:login", "Password").item(0).getTextContent()); + assertEquals(1, output.getElementsByTagNameNS("urn:login", "LogIn_Input").getLength()); + assertFalse(result.contains("SOURCE_SYSTEM_VALUE"), result); + } + assertTrue(payload.conversions >= 3, "The test must use the registered DOM converter"); + assertSame(element, source.getNode()); + assertSame(document, element.getOwnerDocument()); + assertSame(document, element.getParentNode()); + assertTrue(original.isEqualNode(document), "Conversion must not modify the original DOM"); + Source prepared = getSource(payload); + assertNotSame(source, prepared); + assertSame(document, ((DOMSource) prepared).getNode()); + assertEquals(source.getSystemId(), prepared.getSystemId()); + assertEquals("file:/payload/request.xml", source.getSystemId()); + } + + @ParameterizedTest + @ValueSource(booleans = { false, true }) + void testStaxLookupReturningDomSource(boolean sourceExpression) throws Exception { + Document document = parse(INPUT); + Document original = (Document) document.cloneNode(true); + DOMSource source = new DOMSource(document.getDocumentElement(), "file:/payload/request.xml"); + GenericSourcePayload payload = new GenericSourcePayload(source); + TypeConverterSupport converter = new TypeConverterSupport() { + @Override + @SuppressWarnings("unchecked") + public <T> T convertTo(Class<T> type, Exchange exchange, Object value) { + GenericSourcePayload input = (GenericSourcePayload) value; + input.requestedType = type; + return (T) input.source; + } + }; + context.getTypeConverterRegistry().addTypeConverter(Source.class, GenericSourcePayload.class, converter); + // Pin the generic Source converter selected by the registry for a StAX request, as with CXF payloads. + context.getTypeConverterRegistry().addTypeConverter(StAXSource.class, GenericSourcePayload.class, converter); + for (int i = 0; i < 3; i++) { + String result = sourceExpression + ? template.requestBodyAndHeader( + ENDPOINT + "?source=header:payloadSource", "unused body", "payloadSource", payload, String.class) + : template.requestBody(ENDPOINT, payload, String.class); + assertSame(StAXSource.class, payload.requestedType, "Must exercise Saxon's non-null StAX conversion path"); + assertEquals("root", parse(result).getDocumentElement().getNodeName(), result); + assertFalse(result.contains("SOURCE_SYSTEM_VALUE"), result); + } + Source prepared = getSource(payload); + assertSame(document, ((DOMSource) prepared).getNode()); + assertNotSame(source, prepared); + assertEquals(source.getSystemId(), prepared.getSystemId()); + assertSame(document.getDocumentElement(), source.getNode()); + assertSame(document, source.getNode().getParentNode()); + assertTrue(original.isEqualNode(document)); + } + + @ParameterizedTest + @ValueSource(strings = { "element", "nested", "detached" }) + void testExplicitElementSource(String kind) throws Exception { + DOMSource source = elementSource(kind); + assertSame(source, getSource(source)); + assertElementContext(template.requestBody(ENDPOINT, source, String.class)); + } + + @Test + void testExplicitSourceExpression() throws Exception { + DOMSource source = elementSource("element"); + Exchange exchange = new DefaultExchange(context); + exchange.getMessage().setBody(new Payload(source, false)); + exchange.getMessage().setHeader("payloadSource", source); + Expression expression = ExpressionBuilder.headerExpression("payloadSource"); + assertSame(source, new SaxonXmlSourceHandlerFactoryImpl().getSource(exchange, expression)); + String result = template.requestBodyAndHeader( + ENDPOINT + "?source=header:payloadSource", new Payload(source, false), "payloadSource", source, String.class); + assertElementContext(result); + } + + @ParameterizedTest + @ValueSource(strings = { "nested", "detached" }) + void testImplicitSubtree(String kind) throws Exception { + DOMSource source = elementSource(kind); + Element element = (Element) source.getNode(); + Document document = element.getOwnerDocument(); + Document original = (Document) document.cloneNode(true); + var parent = element.getParentNode(); + Payload payload = new Payload(source, false); + assertSame(source, getSource(payload)); + assertElementContext(template.requestBody(ENDPOINT, payload, String.class)); + assertSame(element, source.getNode()); + assertSame(parent, element.getParentNode()); + assertSame(document, element.getOwnerDocument()); + assertTrue(original.isEqualNode(document)); + } + + @ParameterizedTest + @ValueSource(strings = { "document", "sax", "stream", "stax" }) + void testExplicitDocumentAndStreamingSources(String kind) throws Exception { + Source source = documentOrStreamingSource(kind); + assertPreparedSource(kind, getSource(source)); + String result = template.requestBody(ENDPOINT, source, String.class); + assertTrue(result.contains("<root"), result); + assertEquals("root", parse(result).getDocumentElement().getNodeName()); + } + + @ParameterizedTest + @ValueSource(strings = { "document", "sax", "stream", "stax" }) + void testImplicitDocumentAndStreamingSources(String kind) throws Exception { + Source source = documentOrStreamingSource(kind); + Payload payload = new Payload(source, false); + assertPreparedSource(kind, getSource(payload)); + String result = template.requestBody(ENDPOINT, payload, String.class); + assertEquals("root", parse(result).getDocumentElement().getNodeName()); + assertTrue(payload.conversions >= 2); + } + + @Test + void testStreamSourceUnwrappedWhenSecureProcessingDisabled() throws Exception { + XsltSaxonEndpoint endpoint = context.getEndpoint(ENDPOINT + "?secureProcessing=false", XsltSaxonEndpoint.class); + endpoint.start(); + XsltSaxonBuilder builder = (XsltSaxonBuilder) endpoint.getXslt(); + Exchange exchange = new DefaultExchange(context); + StreamSource source = new StreamSource(new StringReader(INPUT)); + exchange.getMessage().setBody(source); + assertSame(source, builder.getSourceHandlerFactory().getSource(exchange, (Expression) null)); + } + + /** + * A source that is already parsed ({@code DOMSource}) or read through a reader the caller controls + * ({@code StAXSource}) is passed through unchanged; a stream-based source still to be parsed is wrapped with a + * reader that does not resolve references to external resources. + */ + private static void assertPreparedSource(String kind, Source prepared) throws Exception { + if (kind.equals("document")) { + assertInstanceOf(DOMSource.class, prepared); + } else if (kind.equals("stax")) { + assertInstanceOf(StAXSource.class, prepared); + } else { + SAXSource saxSource = assertInstanceOf(SAXSource.class, prepared); + assertNotNull(saxSource.getXMLReader(), "A restricted reader should be installed on the source"); + assertFalse(saxSource.getXMLReader().getFeature("http://xml.org/sax/features/external-general-entities")); + } + } + + private static Source documentOrStreamingSource(String kind) throws Exception { + return switch (kind) { + case "document" -> new DOMSource(parse(INPUT)); + case "sax" -> new SAXSource(new InputSource(new StringReader(INPUT))); + case "stream" -> new StreamSource(new StringReader(INPUT)); + case "stax" -> new StAXSource(XMLInputFactory.newFactory().createXMLStreamReader(new StringReader(INPUT))); + default -> throw new IllegalArgumentException(kind); + }; + } + + private Source getSource(Object body) throws Exception { + Exchange exchange = new DefaultExchange(context); + exchange.getMessage().setBody(body); + return new SaxonXmlSourceHandlerFactoryImpl().getSource(exchange, (Expression) null); + } + + private static void assertElementContext(String result) throws Exception { + assertEquals("element-context", parse(result).getDocumentElement().getNodeName(), result); + assertFalse(result.contains("OUTSIDE_PAYLOAD"), result); + assertFalse(result.contains("UNRELATED"), result); + } + + private static DOMSource elementSource(String kind) throws Exception { + Document document = parse(INPUT); + Element element = document.getDocumentElement(); + if (kind.equals("nested")) { + document = parse("<envelope>OUTSIDE_PAYLOAD" + INPUT + "<other>UNRELATED</other></envelope>"); + element = (Element) document.getDocumentElement().getElementsByTagNameNS("urn:request", "Request").item(0); + } else if (kind.equals("detached")) { + document.removeChild(element); + } + return new DOMSource(element); + } + + private static Document parse(String xml) throws Exception { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + return factory.newDocumentBuilder().parse(new InputSource(new StringReader(xml))); + } + + private static final class GenericSourcePayload { + private final DOMSource source; + private Class<?> requestedType; + + private GenericSourcePayload(DOMSource source) { + this.source = source; + } + } + + private static final class Payload { + private final Source source; + private final boolean genericSourceOnly; + private int conversions; + + private Payload(Source source, boolean genericSourceOnly) { + this.source = source; + this.genericSourceOnly = genericSourceOnly; + } + } +} diff --git a/components/camel-xslt-saxon/src/test/java/org/apache/camel/component/xslt/saxon/XsltSaxonHelperConfigurationTest.java b/components/camel-xslt-saxon/src/test/java/org/apache/camel/component/xslt/saxon/XsltSaxonHelperConfigurationTest.java new file mode 100644 index 000000000000..2639189bdae6 --- /dev/null +++ b/components/camel-xslt-saxon/src/test/java/org/apache/camel/component/xslt/saxon/XsltSaxonHelperConfigurationTest.java @@ -0,0 +1,75 @@ +/* + * 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.saxon; + +import java.io.ByteArrayInputStream; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.sax.SAXSource; + +import net.sf.saxon.TransformerFactoryImpl; +import org.apache.camel.util.xml.StringSource; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Unit tests for the configuration helpers shared by {@link XsltSaxonEndpoint} and + * {@link XsltSaxonAggregationStrategy}. + */ +class XsltSaxonHelperConfigurationTest { + + @Test + void shouldRestrictExternalResourceAccessOnFactory() { + TransformerFactoryImpl factory = new TransformerFactoryImpl(); + XsltSaxonHelper.configureExternalAccess(factory); + + assertEquals("", factory.getAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET)); + } + + @Test + void shouldWrapStreamBasedSourceWithRestrictedReader() throws Exception { + Source secured = XsltSaxonHelper.secureSource(new StringSource("<item>A</item>")); + + SAXSource saxSource = assertInstanceOf(SAXSource.class, secured); + assertNotNull(saxSource.getXMLReader(), "A restricted reader should be installed on the source"); + assertTrue(saxSource.getXMLReader().getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); + assertFalse(saxSource.getXMLReader().getFeature("http://xml.org/sax/features/external-general-entities")); + assertFalse(saxSource.getXMLReader().getFeature("http://xml.org/sax/features/external-parameter-entities")); + assertFalse(saxSource.getXMLReader().getFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd")); + } + + @Test + void shouldLeaveAlreadyParsedSourceUnchanged() throws Exception { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setNamespaceAware(true); + DOMSource domSource = new DOMSource( + dbf.newDocumentBuilder().parse(new ByteArrayInputStream("<item>A</item>".getBytes()))); + + Source secured = XsltSaxonHelper.secureSource(domSource); + + assertSame(domSource, secured, "A source that is already parsed should be returned unchanged"); + } +} diff --git a/components/camel-xslt-saxon/src/test/resources/org/apache/camel/component/xslt/saxon/aggregate-included.xsl b/components/camel-xslt-saxon/src/test/resources/org/apache/camel/component/xslt/saxon/aggregate-included.xsl new file mode 100644 index 000000000000..32e6c4dc1916 --- /dev/null +++ b/components/camel-xslt-saxon/src/test/resources/org/apache/camel/component/xslt/saxon/aggregate-included.xsl @@ -0,0 +1,28 @@ +<?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. + +--> +<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + + <!-- Included from the classpath by aggregate-with-include.xsl, to check that an xsl:include is still resolved + when the aggregation strategy restricts external stylesheet access (ACCESS_EXTERNAL_STYLESHEET=""). --> + <xsl:template name="prefix"> + <xsl:text>INCLUDED-</xsl:text> + </xsl:template> + +</xsl:stylesheet> diff --git a/components/camel-xslt-saxon/src/test/resources/org/apache/camel/component/xslt/saxon/aggregate-with-include.xsl b/components/camel-xslt-saxon/src/test/resources/org/apache/camel/component/xslt/saxon/aggregate-with-include.xsl new file mode 100644 index 000000000000..32a5cd045e09 --- /dev/null +++ b/components/camel-xslt-saxon/src/test/resources/org/apache/camel/component/xslt/saxon/aggregate-with-include.xsl @@ -0,0 +1,38 @@ +<?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. + +--> +<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + + <xsl:output method="xml" indent="no"/> + <xsl:strip-space elements="*"/> + + <xsl:param name="new-exchange"/> + + <!-- A classpath include, resolved relative to this stylesheet by Camel's URI resolver. --> + <xsl:include href="aggregate-included.xsl"/> + + <xsl:template match="/"> + <item> + <xsl:call-template name="prefix"/> + <xsl:value-of select="."/> + <xsl:value-of select="$new-exchange/item"/> + </item> + </xsl:template> + +</xsl:stylesheet> diff --git a/components/camel-xslt-saxon/src/test/resources/org/apache/camel/component/xslt/saxon/dom-source-root.xsl b/components/camel-xslt-saxon/src/test/resources/org/apache/camel/component/xslt/saxon/dom-source-root.xsl new file mode 100644 index 000000000000..935d5ed411bf --- /dev/null +++ b/components/camel-xslt-saxon/src/test/resources/org/apache/camel/component/xslt/saxon/dom-source-root.xsl @@ -0,0 +1,38 @@ +<?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. + +--> +<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:req="urn:request" xmlns:inl="urn:login"> + <xsl:template match="/"> + <root> + <xsl:apply-templates select="//req:Authentication"/> + </root> + </xsl:template> + <xsl:template match="req:Request"> + <element-context> + <xsl:apply-templates select="req:Authentication"/> + </element-context> + </xsl:template> + <xsl:template match="req:Authentication"> + <inl:LogIn_Input> + <inl:UserId><xsl:value-of select="req:UserName"/></inl:UserId> + <inl:Password><xsl:value-of select="req:Password"/></inl:Password> + </inl:LogIn_Input> + </xsl:template> +</xsl:stylesheet> diff --git a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/XjComponentBuilderFactory.java b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/XjComponentBuilderFactory.java index 9291ba0ff2bf..0e4d06513956 100644 --- a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/XjComponentBuilderFactory.java +++ b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/XjComponentBuilderFactory.java @@ -190,26 +190,6 @@ public interface XjComponentBuilderFactory { return this; } - - /** - * Feature for XML secure processing (see javax.xml.XMLConstants). This - * is enabled by default. However, when using Saxon Professional you may - * need to turn this off to allow Saxon to be able to use Java extension - * functions. - * - * The option is a: <code>boolean</code> type. - * - * Default: true - * Group: advanced - * - * @param secureProcessing the value to set - * @return the dsl builder - */ - default XjComponentBuilder secureProcessing(boolean secureProcessing) { - doSetProperty("secureProcessing", secureProcessing); - return this; - } - /** * To use a custom XSLT transformer factory, specified as a FQN class * name. @@ -296,6 +276,28 @@ public interface XjComponentBuilderFactory { doSetProperty("xpathTotalOpLimit", xpathTotalOpLimit); return this; } + + + /** + * Feature for XML secure processing (see javax.xml.XMLConstants). This + * is enabled by default. However, when using Saxon Professional you may + * need to turn this off to allow Saxon to be able to use Java extension + * functions. Note that turning it off also restores the previous, + * unrestricted parsing of a Source message body that is still to be + * parsed, so only do so for trusted input. + * + * The option is a: <code>boolean</code> type. + * + * Default: true + * Group: security + * + * @param secureProcessing the value to set + * @return the dsl builder + */ + default XjComponentBuilder secureProcessing(boolean secureProcessing) { + doSetProperty("secureProcessing", secureProcessing); + return this; + } } class XjComponentBuilderImpl @@ -318,12 +320,12 @@ public interface XjComponentBuilderFactory { case "saxonConfiguration": ((XJComponent) component).setSaxonConfiguration((net.sf.saxon.Configuration) value); return true; case "saxonConfigurationProperties": ((XJComponent) component).setSaxonConfigurationProperties((java.util.Map) value); return true; case "saxonExtensionFunctions": ((XJComponent) component).setSaxonExtensionFunctions((java.lang.String) value); return true; - case "secureProcessing": ((XJComponent) component).setSecureProcessing((boolean) value); return true; case "transformerFactoryClass": ((XJComponent) component).setTransformerFactoryClass((java.lang.String) value); return true; case "transformerFactoryConfigurationStrategy": ((XJComponent) component).setTransformerFactoryConfigurationStrategy((org.apache.camel.component.xslt.TransformerFactoryConfigurationStrategy) value); return true; case "uriResolver": ((XJComponent) component).setUriResolver((javax.xml.transform.URIResolver) value); return true; case "uriResolverFactory": ((XJComponent) component).setUriResolverFactory((org.apache.camel.component.xslt.XsltUriResolverFactory) value); return true; case "xpathTotalOpLimit": ((XJComponent) component).setXpathTotalOpLimit((int) value); return true; + case "secureProcessing": ((XJComponent) component).setSecureProcessing((boolean) value); return true; default: return false; } } diff --git a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/XsltSaxonComponentBuilderFactory.java b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/XsltSaxonComponentBuilderFactory.java index 9ae7c4cb9298..5aac7cbb6f21 100644 --- a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/XsltSaxonComponentBuilderFactory.java +++ b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/XsltSaxonComponentBuilderFactory.java @@ -190,26 +190,6 @@ public interface XsltSaxonComponentBuilderFactory { return this; } - - /** - * Feature for XML secure processing (see javax.xml.XMLConstants). This - * is enabled by default. However, when using Saxon Professional you may - * need to turn this off to allow Saxon to be able to use Java extension - * functions. - * - * The option is a: <code>boolean</code> type. - * - * Default: true - * Group: advanced - * - * @param secureProcessing the value to set - * @return the dsl builder - */ - default XsltSaxonComponentBuilder secureProcessing(boolean secureProcessing) { - doSetProperty("secureProcessing", secureProcessing); - return this; - } - /** * To use a custom XSLT transformer factory, specified as a FQN class * name. @@ -296,6 +276,28 @@ public interface XsltSaxonComponentBuilderFactory { doSetProperty("xpathTotalOpLimit", xpathTotalOpLimit); return this; } + + + /** + * Feature for XML secure processing (see javax.xml.XMLConstants). This + * is enabled by default. However, when using Saxon Professional you may + * need to turn this off to allow Saxon to be able to use Java extension + * functions. Note that turning it off also restores the previous, + * unrestricted parsing of a Source message body that is still to be + * parsed, so only do so for trusted input. + * + * The option is a: <code>boolean</code> type. + * + * Default: true + * Group: security + * + * @param secureProcessing the value to set + * @return the dsl builder + */ + default XsltSaxonComponentBuilder secureProcessing(boolean secureProcessing) { + doSetProperty("secureProcessing", secureProcessing); + return this; + } } class XsltSaxonComponentBuilderImpl @@ -318,12 +320,12 @@ public interface XsltSaxonComponentBuilderFactory { case "saxonConfiguration": ((XsltSaxonComponent) component).setSaxonConfiguration((net.sf.saxon.Configuration) value); return true; case "saxonConfigurationProperties": ((XsltSaxonComponent) component).setSaxonConfigurationProperties((java.util.Map) value); return true; case "saxonExtensionFunctions": ((XsltSaxonComponent) component).setSaxonExtensionFunctions((java.lang.String) value); return true; - case "secureProcessing": ((XsltSaxonComponent) component).setSecureProcessing((boolean) value); return true; case "transformerFactoryClass": ((XsltSaxonComponent) component).setTransformerFactoryClass((java.lang.String) value); return true; case "transformerFactoryConfigurationStrategy": ((XsltSaxonComponent) component).setTransformerFactoryConfigurationStrategy((org.apache.camel.component.xslt.TransformerFactoryConfigurationStrategy) value); return true; case "uriResolver": ((XsltSaxonComponent) component).setUriResolver((javax.xml.transform.URIResolver) value); return true; case "uriResolverFactory": ((XsltSaxonComponent) component).setUriResolverFactory((org.apache.camel.component.xslt.XsltUriResolverFactory) value); return true; case "xpathTotalOpLimit": ((XsltSaxonComponent) component).setXpathTotalOpLimit((int) value); return true; + case "secureProcessing": ((XsltSaxonComponent) component).setSecureProcessing((boolean) value); return true; default: return false; } } diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/XJEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/XJEndpointBuilderFactory.java index 1a277c12ee5c..1b6bbf399dd8 100644 --- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/XJEndpointBuilderFactory.java +++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/XJEndpointBuilderFactory.java @@ -593,42 +593,6 @@ public interface XJEndpointBuilderFactory { doSetProperty("saxonExtensionFunctions", saxonExtensionFunctions); return this; } - /** - * Feature for XML secure processing (see javax.xml.XMLConstants). This - * is enabled by default. However, when using Saxon Professional you may - * need to turn this off to allow Saxon to be able to use Java extension - * functions. - * - * The option is a: <code>boolean</code> type. - * - * Default: true - * Group: advanced - * - * @param secureProcessing the value to set - * @return the dsl builder - */ - default AdvancedXJEndpointBuilder secureProcessing(boolean secureProcessing) { - doSetProperty("secureProcessing", secureProcessing); - return this; - } - /** - * Feature for XML secure processing (see javax.xml.XMLConstants). This - * is enabled by default. However, when using Saxon Professional you may - * need to turn this off to allow Saxon to be able to use Java extension - * functions. - * - * The option will be converted to a <code>boolean</code> type. - * - * Default: true - * Group: advanced - * - * @param secureProcessing the value to set - * @return the dsl builder - */ - default AdvancedXJEndpointBuilder secureProcessing(String secureProcessing) { - doSetProperty("secureProcessing", secureProcessing); - return this; - } /** * To use a custom XSLT transformer factory. * @@ -765,6 +729,46 @@ public interface XJEndpointBuilderFactory { doSetProperty("xsltMessageLogger", xsltMessageLogger); return this; } + /** + * Feature for XML secure processing (see javax.xml.XMLConstants). This + * is enabled by default. However, when using Saxon Professional you may + * need to turn this off to allow Saxon to be able to use Java extension + * functions. Note that turning it off also restores the previous, + * unrestricted parsing of a Source message body that is still to be + * parsed, so only do so for trusted input. + * + * The option is a: <code>boolean</code> type. + * + * Default: true + * Group: security + * + * @param secureProcessing the value to set + * @return the dsl builder + */ + default AdvancedXJEndpointBuilder secureProcessing(boolean secureProcessing) { + doSetProperty("secureProcessing", secureProcessing); + return this; + } + /** + * Feature for XML secure processing (see javax.xml.XMLConstants). This + * is enabled by default. However, when using Saxon Professional you may + * need to turn this off to allow Saxon to be able to use Java extension + * functions. Note that turning it off also restores the previous, + * unrestricted parsing of a Source message body that is still to be + * parsed, so only do so for trusted input. + * + * The option will be converted to a <code>boolean</code> type. + * + * Default: true + * Group: security + * + * @param secureProcessing the value to set + * @return the dsl builder + */ + default AdvancedXJEndpointBuilder secureProcessing(String secureProcessing) { + doSetProperty("secureProcessing", secureProcessing); + return this; + } } public interface XJBuilders { diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/XsltSaxonEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/XsltSaxonEndpointBuilderFactory.java index 5b7729d6da46..0347b927cd7a 100644 --- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/XsltSaxonEndpointBuilderFactory.java +++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/XsltSaxonEndpointBuilderFactory.java @@ -561,42 +561,6 @@ public interface XsltSaxonEndpointBuilderFactory { doSetProperty("saxonExtensionFunctions", saxonExtensionFunctions); return this; } - /** - * Feature for XML secure processing (see javax.xml.XMLConstants). This - * is enabled by default. However, when using Saxon Professional you may - * need to turn this off to allow Saxon to be able to use Java extension - * functions. - * - * The option is a: <code>boolean</code> type. - * - * Default: true - * Group: advanced - * - * @param secureProcessing the value to set - * @return the dsl builder - */ - default AdvancedXsltSaxonEndpointBuilder secureProcessing(boolean secureProcessing) { - doSetProperty("secureProcessing", secureProcessing); - return this; - } - /** - * Feature for XML secure processing (see javax.xml.XMLConstants). This - * is enabled by default. However, when using Saxon Professional you may - * need to turn this off to allow Saxon to be able to use Java extension - * functions. - * - * The option will be converted to a <code>boolean</code> type. - * - * Default: true - * Group: advanced - * - * @param secureProcessing the value to set - * @return the dsl builder - */ - default AdvancedXsltSaxonEndpointBuilder secureProcessing(String secureProcessing) { - doSetProperty("secureProcessing", secureProcessing); - return this; - } /** * To use a custom XSLT transformer factory. * @@ -733,6 +697,46 @@ public interface XsltSaxonEndpointBuilderFactory { doSetProperty("xsltMessageLogger", xsltMessageLogger); return this; } + /** + * Feature for XML secure processing (see javax.xml.XMLConstants). This + * is enabled by default. However, when using Saxon Professional you may + * need to turn this off to allow Saxon to be able to use Java extension + * functions. Note that turning it off also restores the previous, + * unrestricted parsing of a Source message body that is still to be + * parsed, so only do so for trusted input. + * + * The option is a: <code>boolean</code> type. + * + * Default: true + * Group: security + * + * @param secureProcessing the value to set + * @return the dsl builder + */ + default AdvancedXsltSaxonEndpointBuilder secureProcessing(boolean secureProcessing) { + doSetProperty("secureProcessing", secureProcessing); + return this; + } + /** + * Feature for XML secure processing (see javax.xml.XMLConstants). This + * is enabled by default. However, when using Saxon Professional you may + * need to turn this off to allow Saxon to be able to use Java extension + * functions. Note that turning it off also restores the previous, + * unrestricted parsing of a Source message body that is still to be + * parsed, so only do so for trusted input. + * + * The option will be converted to a <code>boolean</code> type. + * + * Default: true + * Group: security + * + * @param secureProcessing the value to set + * @return the dsl builder + */ + default AdvancedXsltSaxonEndpointBuilder secureProcessing(String secureProcessing) { + doSetProperty("secureProcessing", secureProcessing); + return this; + } } public interface XsltSaxonBuilders {
