This is an automated email from the ASF dual-hosted git repository. igarashitm pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push: new 26764ab3c48 CAMEL-22011: camel-xslt-saxon: Allow JSON input body 26764ab3c48 is described below commit 26764ab3c48440968885199eb5150beb4395fcee Author: Tomohisa Igarashi <tm.igara...@gmail.com> AuthorDate: Wed Sep 10 21:27:50 2025 -0400 CAMEL-22011: camel-xslt-saxon: Allow JSON input body --- .../org/apache/camel/catalog/components/xj.json | 25 ++--- .../camel/catalog/components/xslt-saxon.json | 25 ++--- .../camel/component/xj/XJEndpointUriFactory.java | 3 +- .../META-INF/org/apache/camel/component/xj/xj.json | 25 ++--- components/camel-xslt-saxon/pom.xml | 10 ++ .../xslt/saxon/XsltSaxonEndpointConfigurer.java | 6 ++ .../xslt/saxon/XsltSaxonEndpointUriFactory.java | 3 +- .../camel/component/xslt/saxon/xslt-saxon.json | 25 ++--- .../src/main/docs/xslt-saxon-component.adoc | 48 +++++++++ .../saxon/SaxonXmlSourceHandlerFactoryImpl.java | 88 ++++++++++++++++ .../component/xslt/saxon/XsltSaxonBuilder.java | 13 ++- .../component/xslt/saxon/XsltSaxonEndpoint.java | 17 ++++ .../xslt/saxon/XsltSaxonJsonBodyTest.java | 111 +++++++++++++++++++++ .../camel/component/xslt/saxon/json-transform.xsl | 41 ++++++++ .../endpoint/dsl/XJEndpointBuilderFactory.java | 38 +++++++ .../dsl/XsltSaxonEndpointBuilderFactory.java | 38 +++++++ 16 files changed, 465 insertions(+), 51 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 cf498701f78..560e50e20db 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 @@ -53,17 +53,18 @@ "source": { "index": 7, "kind": "parameter", "displayName": "Source", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Source to use, instead of message body. You can prefix with variable:, header:, or property: to specify kind of source. Otherwise, the source is assumed to be a variable. Use empty or null to use default source, which is the message body." }, "transformDirection": { "index": 8, "kind": "parameter", "displayName": "Transform Direction", "group": "producer", "label": "", "required": true, "type": "object", "javaType": "org.apache.camel.component.xj.TransformDirection", "enum": [ "XML2JSON", "JSON2XML" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Transform direction. Either XML2JSON or JSON2XML" }, "transformerCacheSize": { "index": 9, "kind": "parameter", "displayName": "Transformer Cache Size", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "The number of javax.xml.transform.Transformer object that are cached for reuse to avoid calls to Template.newTransformer()." }, - "lazyStartProducer": { "index": 10, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...] - "entityResolver": { "index": 11, "kind": "parameter", "displayName": "Entity Resolver", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.xml.sax.EntityResolver", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom org.xml.sax.EntityResolver with javax.xml.transform.sax.SAXSource." }, - "errorListener": { "index": 12, "kind": "parameter", "displayName": "Error Listener", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.xml.transform.ErrorListener", "deprecated": false, "autowired": false, "secret": false, "description": "Allows to configure to use a custom javax.xml.transform.ErrorListener. Beware when doing this then the default error listener which captures any errors or fatal errors and store information on the Exc [...] - "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 [...] - "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." }, - "uriResolver": { "index": 20, "kind": "parameter", "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 javax.xml.transform.URIResolver" }, - "xsltMessageLogger": { "index": 21, "kind": "parameter", "displayName": "Xslt Message Logger", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.xslt.XsltMessageLogger", "deprecated": false, "autowired": false, "secret": false, "description": "A consumer to messages generated during XSLT transformations." } + "useJsonBody": { "index": 10, "kind": "parameter", "displayName": "Use JSON Body", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to use JSON body as input. When enabled, the message body is expected to be JSON and will be converted to XML representation of JSON using XSLT3 json-to-xml() function before XSLT pr [...] + "lazyStartProducer": { "index": 11, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...] + "entityResolver": { "index": 12, "kind": "parameter", "displayName": "Entity Resolver", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.xml.sax.EntityResolver", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom org.xml.sax.EntityResolver with javax.xml.transform.sax.SAXSource." }, + "errorListener": { "index": 13, "kind": "parameter", "displayName": "Error Listener", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.xml.transform.ErrorListener", "deprecated": false, "autowired": false, "secret": false, "description": "Allows to configure to use a custom javax.xml.transform.ErrorListener. Beware when doing this then the default error listener which captures any errors or fatal errors and store information on the Exc [...] + "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 [...] + "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." }, + "uriResolver": { "index": 21, "kind": "parameter", "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 javax.xml.transform.URIResolver" }, + "xsltMessageLogger": { "index": 22, "kind": "parameter", "displayName": "Xslt Message Logger", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.xslt.XsltMessageLogger", "deprecated": false, "autowired": false, "secret": false, "description": "A consumer to messages generated during XSLT transformations." } } } 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 962087e3ed3..606b781000d 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 @@ -52,17 +52,18 @@ "output": { "index": 6, "kind": "parameter", "displayName": "Output", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.xslt.XsltOutput", "enum": [ "string", "bytes", "DOM", "file" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "string", "description": "Option to specify which output type to use. Possible values are: string, bytes, DOM, file. The first three options are all in memory based, whe [...] "source": { "index": 7, "kind": "parameter", "displayName": "Source", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Source to use, instead of message body. You can prefix with variable:, header:, or property: to specify kind of source. Otherwise, the source is assumed to be a variable. Use empty or null to use default source, which is the message body." }, "transformerCacheSize": { "index": 8, "kind": "parameter", "displayName": "Transformer Cache Size", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "The number of javax.xml.transform.Transformer object that are cached for reuse to avoid calls to Template.newTransformer()." }, - "lazyStartProducer": { "index": 9, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produc [...] - "entityResolver": { "index": 10, "kind": "parameter", "displayName": "Entity Resolver", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.xml.sax.EntityResolver", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom org.xml.sax.EntityResolver with javax.xml.transform.sax.SAXSource." }, - "errorListener": { "index": 11, "kind": "parameter", "displayName": "Error Listener", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.xml.transform.ErrorListener", "deprecated": false, "autowired": false, "secret": false, "description": "Allows to configure to use a custom javax.xml.transform.ErrorListener. Beware when doing this then the default error listener which captures any errors or fatal errors and store information on the Exc [...] - "resultHandlerFactory": { "index": 12, "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": 13, "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": 14, "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": 15, "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 [...] - "transformerFactory": { "index": 16, "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": 17, "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": 18, "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." }, - "uriResolver": { "index": 19, "kind": "parameter", "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 javax.xml.transform.URIResolver" }, - "xsltMessageLogger": { "index": 20, "kind": "parameter", "displayName": "Xslt Message Logger", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.xslt.XsltMessageLogger", "deprecated": false, "autowired": false, "secret": false, "description": "A consumer to messages generated during XSLT transformations." } + "useJsonBody": { "index": 9, "kind": "parameter", "displayName": "Use JSON Body", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to use JSON body as input. When enabled, the message body is expected to be JSON and will be converted to XML representation of JSON using XSLT3 json-to-xml() function before XSLT pro [...] + "lazyStartProducer": { "index": 10, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...] + "entityResolver": { "index": 11, "kind": "parameter", "displayName": "Entity Resolver", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.xml.sax.EntityResolver", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom org.xml.sax.EntityResolver with javax.xml.transform.sax.SAXSource." }, + "errorListener": { "index": 12, "kind": "parameter", "displayName": "Error Listener", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.xml.transform.ErrorListener", "deprecated": false, "autowired": false, "secret": false, "description": "Allows to configure to use a custom javax.xml.transform.ErrorListener. Beware when doing this then the default error listener which captures any errors or fatal errors and store information on the Exc [...] + "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 [...] + "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." }, + "uriResolver": { "index": 20, "kind": "parameter", "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 javax.xml.transform.URIResolver" }, + "xsltMessageLogger": { "index": 21, "kind": "parameter", "displayName": "Xslt Message Logger", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.xslt.XsltMessageLogger", "deprecated": false, "autowired": false, "secret": false, "description": "A consumer to messages generated during XSLT transformations." } } } diff --git a/components/camel-xj/src/generated/java/org/apache/camel/component/xj/XJEndpointUriFactory.java b/components/camel-xj/src/generated/java/org/apache/camel/component/xj/XJEndpointUriFactory.java index 48de05f4484..5fec77a107b 100644 --- a/components/camel-xj/src/generated/java/org/apache/camel/component/xj/XJEndpointUriFactory.java +++ b/components/camel-xj/src/generated/java/org/apache/camel/component/xj/XJEndpointUriFactory.java @@ -23,7 +23,7 @@ public class XJEndpointUriFactory extends org.apache.camel.support.component.End private static final Set<String> SECRET_PROPERTY_NAMES; private static final Set<String> MULTI_VALUE_PREFIXES; static { - Set<String> props = new HashSet<>(22); + Set<String> props = new HashSet<>(23); props.add("allowStAX"); props.add("allowTemplateFromHeader"); props.add("contentCache"); @@ -45,6 +45,7 @@ public class XJEndpointUriFactory extends org.apache.camel.support.component.End props.add("transformerFactoryClass"); props.add("transformerFactoryConfigurationStrategy"); props.add("uriResolver"); + props.add("useJsonBody"); props.add("xsltMessageLogger"); PROPERTY_NAMES = Collections.unmodifiableSet(props); SECRET_PROPERTY_NAMES = Collections.emptySet(); 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 cf498701f78..560e50e20db 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 @@ -53,17 +53,18 @@ "source": { "index": 7, "kind": "parameter", "displayName": "Source", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Source to use, instead of message body. You can prefix with variable:, header:, or property: to specify kind of source. Otherwise, the source is assumed to be a variable. Use empty or null to use default source, which is the message body." }, "transformDirection": { "index": 8, "kind": "parameter", "displayName": "Transform Direction", "group": "producer", "label": "", "required": true, "type": "object", "javaType": "org.apache.camel.component.xj.TransformDirection", "enum": [ "XML2JSON", "JSON2XML" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Transform direction. Either XML2JSON or JSON2XML" }, "transformerCacheSize": { "index": 9, "kind": "parameter", "displayName": "Transformer Cache Size", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "The number of javax.xml.transform.Transformer object that are cached for reuse to avoid calls to Template.newTransformer()." }, - "lazyStartProducer": { "index": 10, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...] - "entityResolver": { "index": 11, "kind": "parameter", "displayName": "Entity Resolver", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.xml.sax.EntityResolver", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom org.xml.sax.EntityResolver with javax.xml.transform.sax.SAXSource." }, - "errorListener": { "index": 12, "kind": "parameter", "displayName": "Error Listener", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.xml.transform.ErrorListener", "deprecated": false, "autowired": false, "secret": false, "description": "Allows to configure to use a custom javax.xml.transform.ErrorListener. Beware when doing this then the default error listener which captures any errors or fatal errors and store information on the Exc [...] - "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 [...] - "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." }, - "uriResolver": { "index": 20, "kind": "parameter", "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 javax.xml.transform.URIResolver" }, - "xsltMessageLogger": { "index": 21, "kind": "parameter", "displayName": "Xslt Message Logger", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.xslt.XsltMessageLogger", "deprecated": false, "autowired": false, "secret": false, "description": "A consumer to messages generated during XSLT transformations." } + "useJsonBody": { "index": 10, "kind": "parameter", "displayName": "Use JSON Body", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to use JSON body as input. When enabled, the message body is expected to be JSON and will be converted to XML representation of JSON using XSLT3 json-to-xml() function before XSLT pr [...] + "lazyStartProducer": { "index": 11, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...] + "entityResolver": { "index": 12, "kind": "parameter", "displayName": "Entity Resolver", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.xml.sax.EntityResolver", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom org.xml.sax.EntityResolver with javax.xml.transform.sax.SAXSource." }, + "errorListener": { "index": 13, "kind": "parameter", "displayName": "Error Listener", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.xml.transform.ErrorListener", "deprecated": false, "autowired": false, "secret": false, "description": "Allows to configure to use a custom javax.xml.transform.ErrorListener. Beware when doing this then the default error listener which captures any errors or fatal errors and store information on the Exc [...] + "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 [...] + "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." }, + "uriResolver": { "index": 21, "kind": "parameter", "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 javax.xml.transform.URIResolver" }, + "xsltMessageLogger": { "index": 22, "kind": "parameter", "displayName": "Xslt Message Logger", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.xslt.XsltMessageLogger", "deprecated": false, "autowired": false, "secret": false, "description": "A consumer to messages generated during XSLT transformations." } } } diff --git a/components/camel-xslt-saxon/pom.xml b/components/camel-xslt-saxon/pom.xml index 35a75a404f3..c889342fa34 100644 --- a/components/camel-xslt-saxon/pom.xml +++ b/components/camel-xslt-saxon/pom.xml @@ -48,11 +48,21 @@ </dependency> <!-- test dependencies --> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-spring-xml</artifactId> + <scope>test</scope> + </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-test-spring-junit5</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.xmlunit</groupId> + <artifactId>xmlunit-assertj3</artifactId> + <scope>test</scope> + </dependency> </dependencies> </project> diff --git a/components/camel-xslt-saxon/src/generated/java/org/apache/camel/component/xslt/saxon/XsltSaxonEndpointConfigurer.java b/components/camel-xslt-saxon/src/generated/java/org/apache/camel/component/xslt/saxon/XsltSaxonEndpointConfigurer.java index b38f59265f3..0cab44103f0 100644 --- a/components/camel-xslt-saxon/src/generated/java/org/apache/camel/component/xslt/saxon/XsltSaxonEndpointConfigurer.java +++ b/components/camel-xslt-saxon/src/generated/java/org/apache/camel/component/xslt/saxon/XsltSaxonEndpointConfigurer.java @@ -31,6 +31,8 @@ public class XsltSaxonEndpointConfigurer extends XsltEndpointConfigurer implemen case "saxonExtensionFunctions": target.setSaxonExtensionFunctions(property(camelContext, java.lang.String.class, value)); return true; case "secureprocessing": case "secureProcessing": target.setSecureProcessing(property(camelContext, boolean.class, value)); return true; + case "usejsonbody": + case "useJsonBody": target.setUseJsonBody(property(camelContext, boolean.class, value)); return true; default: return super.configure(camelContext, obj, name, value, ignoreCase); } } @@ -46,6 +48,8 @@ public class XsltSaxonEndpointConfigurer extends XsltEndpointConfigurer implemen case "saxonExtensionFunctions": return java.lang.String.class; case "secureprocessing": case "secureProcessing": return boolean.class; + case "usejsonbody": + case "useJsonBody": return boolean.class; default: return super.getOptionType(name, ignoreCase); } } @@ -62,6 +66,8 @@ public class XsltSaxonEndpointConfigurer extends XsltEndpointConfigurer implemen case "saxonExtensionFunctions": return target.getSaxonExtensionFunctions(); case "secureprocessing": case "secureProcessing": return target.isSecureProcessing(); + case "usejsonbody": + case "useJsonBody": return target.isUseJsonBody(); default: return super.getOptionValue(obj, name, ignoreCase); } } diff --git a/components/camel-xslt-saxon/src/generated/java/org/apache/camel/component/xslt/saxon/XsltSaxonEndpointUriFactory.java b/components/camel-xslt-saxon/src/generated/java/org/apache/camel/component/xslt/saxon/XsltSaxonEndpointUriFactory.java index a6c2fa90d6b..bd7386a6a2a 100644 --- a/components/camel-xslt-saxon/src/generated/java/org/apache/camel/component/xslt/saxon/XsltSaxonEndpointUriFactory.java +++ b/components/camel-xslt-saxon/src/generated/java/org/apache/camel/component/xslt/saxon/XsltSaxonEndpointUriFactory.java @@ -23,7 +23,7 @@ public class XsltSaxonEndpointUriFactory extends org.apache.camel.support.compon private static final Set<String> SECRET_PROPERTY_NAMES; private static final Set<String> MULTI_VALUE_PREFIXES; static { - Set<String> props = new HashSet<>(21); + Set<String> props = new HashSet<>(22); props.add("allowStAX"); props.add("allowTemplateFromHeader"); props.add("contentCache"); @@ -44,6 +44,7 @@ public class XsltSaxonEndpointUriFactory extends org.apache.camel.support.compon props.add("transformerFactoryClass"); props.add("transformerFactoryConfigurationStrategy"); props.add("uriResolver"); + props.add("useJsonBody"); props.add("xsltMessageLogger"); PROPERTY_NAMES = Collections.unmodifiableSet(props); SECRET_PROPERTY_NAMES = Collections.emptySet(); 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 962087e3ed3..606b781000d 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 @@ -52,17 +52,18 @@ "output": { "index": 6, "kind": "parameter", "displayName": "Output", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.xslt.XsltOutput", "enum": [ "string", "bytes", "DOM", "file" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "string", "description": "Option to specify which output type to use. Possible values are: string, bytes, DOM, file. The first three options are all in memory based, whe [...] "source": { "index": 7, "kind": "parameter", "displayName": "Source", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Source to use, instead of message body. You can prefix with variable:, header:, or property: to specify kind of source. Otherwise, the source is assumed to be a variable. Use empty or null to use default source, which is the message body." }, "transformerCacheSize": { "index": 8, "kind": "parameter", "displayName": "Transformer Cache Size", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "The number of javax.xml.transform.Transformer object that are cached for reuse to avoid calls to Template.newTransformer()." }, - "lazyStartProducer": { "index": 9, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produc [...] - "entityResolver": { "index": 10, "kind": "parameter", "displayName": "Entity Resolver", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.xml.sax.EntityResolver", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom org.xml.sax.EntityResolver with javax.xml.transform.sax.SAXSource." }, - "errorListener": { "index": 11, "kind": "parameter", "displayName": "Error Listener", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.xml.transform.ErrorListener", "deprecated": false, "autowired": false, "secret": false, "description": "Allows to configure to use a custom javax.xml.transform.ErrorListener. Beware when doing this then the default error listener which captures any errors or fatal errors and store information on the Exc [...] - "resultHandlerFactory": { "index": 12, "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": 13, "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": 14, "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": 15, "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 [...] - "transformerFactory": { "index": 16, "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": 17, "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": 18, "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." }, - "uriResolver": { "index": 19, "kind": "parameter", "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 javax.xml.transform.URIResolver" }, - "xsltMessageLogger": { "index": 20, "kind": "parameter", "displayName": "Xslt Message Logger", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.xslt.XsltMessageLogger", "deprecated": false, "autowired": false, "secret": false, "description": "A consumer to messages generated during XSLT transformations." } + "useJsonBody": { "index": 9, "kind": "parameter", "displayName": "Use JSON Body", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to use JSON body as input. When enabled, the message body is expected to be JSON and will be converted to XML representation of JSON using XSLT3 json-to-xml() function before XSLT pro [...] + "lazyStartProducer": { "index": 10, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...] + "entityResolver": { "index": 11, "kind": "parameter", "displayName": "Entity Resolver", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.xml.sax.EntityResolver", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom org.xml.sax.EntityResolver with javax.xml.transform.sax.SAXSource." }, + "errorListener": { "index": 12, "kind": "parameter", "displayName": "Error Listener", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.xml.transform.ErrorListener", "deprecated": false, "autowired": false, "secret": false, "description": "Allows to configure to use a custom javax.xml.transform.ErrorListener. Beware when doing this then the default error listener which captures any errors or fatal errors and store information on the Exc [...] + "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 [...] + "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." }, + "uriResolver": { "index": 20, "kind": "parameter", "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 javax.xml.transform.URIResolver" }, + "xsltMessageLogger": { "index": 21, "kind": "parameter", "displayName": "Xslt Message Logger", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.xslt.XsltMessageLogger", "deprecated": false, "autowired": false, "secret": false, "description": "A consumer to messages generated during XSLT transformations." } } } diff --git a/components/camel-xslt-saxon/src/main/docs/xslt-saxon-component.adoc b/components/camel-xslt-saxon/src/main/docs/xslt-saxon-component.adoc index 43c5c561541..c4996a53df3 100644 --- a/components/camel-xslt-saxon/src/main/docs/xslt-saxon-component.adoc +++ b/components/camel-xslt-saxon/src/main/docs/xslt-saxon-component.adoc @@ -266,5 +266,53 @@ an empty dob field. And to include a custom error message using The exception is stored on the Exchange as a warning with the key `Exchange.XSLT_WARNING.` +=== Consume JSON body + +By default, the input body is assumed as XML. You can set `useJsonBody=true` to consume JSON data from Camel Message body. + +[source,java] +---- +from("direct:transform") + .to("xslt-saxon:template.xsl?useJsonBody=true"); +---- + +If `useJsonBody=true` is set, the JSON body is transformed into XML representation of JSON https://www.w3.org/TR/xslt-30/#json-to-xml-mapping[defined in XSLT 3.0 specification]. + +For example, when we have following JSON data +[source,json] +---- +{ + "name": "John Doe", + "age": 30, + "email": "john....@example.com", + "address": { + "street": "123 Main St", + "city": "New York", + "zipcode": "10001" + }, + "hobbies": ["reading", "cycling", "swimming"] +} +---- + +XSLT 3.0 XML representation of JSON is +[source,xml] +---- +<?xml version="1.0" encoding="UTF-8"?> +<map xmlns="http://www.w3.org/2005/xpath-functions"> + <string key="name">John Doe</string> + <number key="age">30</number> + <string key="email">john....@example.com</string> + <map key="address"> + <string key="street">123 Main St</string> + <string key="city">New York</string> + <string key="zipcode">10001</string> + </map> + <array key="hobbies"> + <string>reading</string> + <string>cycling</string> + <string>swimming</string> + </array> +</map> +---- include::spring-boot:partial$starter.adoc[] 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 297fd667fdb..faadda01297 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 @@ -16,20 +16,61 @@ */ package org.apache.camel.component.xslt.saxon; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stax.StAXSource; +import net.sf.saxon.s9api.DOMDestination; +import net.sf.saxon.s9api.Processor; +import net.sf.saxon.s9api.SaxonApiException; import org.apache.camel.Exchange; import org.apache.camel.component.xslt.XmlSourceHandlerFactoryImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class SaxonXmlSourceHandlerFactoryImpl extends XmlSourceHandlerFactoryImpl { + private static final Logger LOG = LoggerFactory.getLogger(SaxonXmlSourceHandlerFactoryImpl.class); + + private boolean useJsonBody = false; + + public boolean isUseJsonBody() { + return useJsonBody; + } + + public void setUseJsonBody(boolean useJsonBody) { + this.useJsonBody = useJsonBody; + } + + 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) { // body may already be a source if (body instanceof Source) { return (Source) body; } + + if (useJsonBody && body != null) { + try { + String jsonString = exchange.getContext().getTypeConverter().convertTo(String.class, body); + if (jsonString != null) { + Source xmlSource = convertJsonToXmlSource(jsonString); + if (xmlSource != null) { + LOG.debug("Converted JSON input to XML using XSLT3 json-to-xml() function"); + return xmlSource; + } + } + } catch (Exception e) { + LOG.warn("Failed to convert JSON to XML, falling back to standard processing: {}", e.getMessage()); + } + } + Source source = null; if (body != null) { // try StAX if enabled @@ -40,4 +81,51 @@ public class SaxonXmlSourceHandlerFactoryImpl extends XmlSourceHandlerFactoryImp } return source; } + + private Source convertJsonToXmlSource(String jsonString) { + try { + net.sf.saxon.s9api.XPathSelector selector = getSaxonJsonToXmlExecutable().load(); + selector.setContextItem(new net.sf.saxon.s9api.XdmAtomicValue(jsonString)); + net.sf.saxon.s9api.XdmValue result = selector.evaluate(); + + if (!result.isEmpty()) { + net.sf.saxon.s9api.XdmItem item = result.itemAt(0); + if (item instanceof net.sf.saxon.s9api.XdmNode xdmNode) { + // The most efficient way would be: + // return xdmNode.getUnderlyingNode(); + // In order to make it work however, this pre-process and the main XSLT processing later on + // have to use same Saxon internal Processor/Configuration. While it would be possible, it + // would require a refactoring across camel-xslt and camel-xslt-saxon. + var doc = getDocumentBuilder().newDocument(); + DOMDestination domDest = new DOMDestination(doc); + saxonProcessor.writeXdmValue(xdmNode, domDest); + + return new DOMSource(doc); + } + } + + } catch (SaxonApiException | ParserConfigurationException e) { + LOG.warn("Failed to convert JSON to XML using XSLT3 json-to-xml() function: {}", e.getMessage()); + } + + return null; + } + + private synchronized net.sf.saxon.s9api.XPathExecutable getSaxonJsonToXmlExecutable() throws SaxonApiException { + if (saxonJsonToXmlExecutable == null) { + saxonProcessor = new Processor(false); + net.sf.saxon.s9api.XPathCompiler xpathCompiler = saxonProcessor.newXPathCompiler(); + saxonJsonToXmlExecutable = xpathCompiler.compile("json-to-xml(.)"); + LOG.debug("Initialized reusable XPathExecutable for json-to-xml() function"); + } + return this.saxonJsonToXmlExecutable; + } + + private synchronized DocumentBuilder getDocumentBuilder() throws SaxonApiException, ParserConfigurationException { + if (documentBuilder == null) { + var factory = DocumentBuilderFactory.newInstance(); + documentBuilder = factory.newDocumentBuilder(); + } + return documentBuilder; + } } 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 7fbd61ca777..bd3c58e0402 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 @@ -39,6 +39,7 @@ import org.apache.camel.support.builder.xml.StAX2SAXSource; public class XsltSaxonBuilder extends XsltBuilder { private boolean allowStAX = true; + private boolean useJsonBody = false; @Override protected Source prepareSource(Source source) { @@ -65,9 +66,19 @@ public class XsltSaxonBuilder extends XsltBuilder { this.allowStAX = allowStAX; } + public boolean isUseJsonBody() { + return useJsonBody; + } + + public void setUseJsonBody(boolean useJsonBody) { + this.useJsonBody = useJsonBody; + } + @Override protected XmlSourceHandlerFactoryImpl createXmlSourceHandlerFactoryImpl() { - return new SaxonXmlSourceHandlerFactoryImpl(); + SaxonXmlSourceHandlerFactoryImpl factory = new SaxonXmlSourceHandlerFactoryImpl(); + factory.setUseJsonBody(useJsonBody); + return factory; } @Override 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 43040569f38..87b3fed7a42 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 @@ -80,6 +80,9 @@ public class XsltSaxonEndpoint extends XsltEndpoint { private boolean allowStAX = true; @UriParam(label = "advanced", defaultValue = "true") private boolean secureProcessing = true; + @UriParam + @Metadata(firstVersion = "4.15.0", displayName = "Use JSON Body", defaultValue = "false", required = false) + private boolean useJsonBody = false; public XsltSaxonEndpoint(String endpointUri, Component component) { super(endpointUri, component); @@ -171,6 +174,19 @@ public class XsltSaxonEndpoint extends XsltEndpoint { this.secureProcessing = secureProcessing; } + public boolean isUseJsonBody() { + return useJsonBody; + } + + /** + * Whether to use JSON body as input. When enabled, the message body is expected to be JSON and will be converted to + * XML representation of JSON using XSLT3 `json-to-xml()` function before XSLT processing. This allows XSLT + * stylesheets to process JSON input directly using standard XPath expressions. + */ + public void setUseJsonBody(boolean useJsonBody) { + this.useJsonBody = useJsonBody; + } + @Override protected void doInit() throws Exception { super.doInit(); @@ -242,6 +258,7 @@ public class XsltSaxonEndpoint extends XsltEndpoint { xslt.setUriResolver(getUriResolver()); xslt.setEntityResolver(getEntityResolver()); xslt.setAllowStAX(allowStAX); + xslt.setUseJsonBody(useJsonBody); xslt.setDeleteOutputFile(isDeleteOutputFile()); xslt.setSource(ExpressionBuilder.singleInputExpression(getSource())); diff --git a/components/camel-xslt-saxon/src/test/java/org/apache/camel/component/xslt/saxon/XsltSaxonJsonBodyTest.java b/components/camel-xslt-saxon/src/test/java/org/apache/camel/component/xslt/saxon/XsltSaxonJsonBodyTest.java new file mode 100644 index 00000000000..6233694e3ba --- /dev/null +++ b/components/camel-xslt-saxon/src/test/java/org/apache/camel/component/xslt/saxon/XsltSaxonJsonBodyTest.java @@ -0,0 +1,111 @@ +/* + * 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.util.List; + +import org.w3c.dom.Document; + +import org.apache.camel.Exchange; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.junit5.CamelTestSupport; +import org.junit.jupiter.api.Test; +import org.xmlunit.assertj3.XmlAssert; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class XsltSaxonJsonBodyTest extends CamelTestSupport { + + private static final String JSON_INPUT = """ + { + "name": "John Doe", + "age": 30, + "email": "john....@example.com", + "address": { + "street": "123 Main St", + "city": "New York", + "zipcode": "10001" + }, + "hobbies": ["reading", "cycling", "swimming"] + } + """; + + @Test + public void testJsonBodyTransformation() throws Exception { + MockEndpoint endpoint = getMockEndpoint("mock:json-result"); + endpoint.expectedMessageCount(1); + + template.sendBody("direct:json-start", JSON_INPUT); + + MockEndpoint.assertIsSatisfied(context); + + List<Exchange> list = endpoint.getReceivedExchanges(); + Exchange exchange = list.get(0); + Document res = exchange.getIn().getBody(Document.class); + + String expected = """ + <Person> + <Name>John Doe</Name> + <Age>30</Age> + <Email>john....@example.com</Email> + <Address> + <Street>123 Main St</Street> + <City>New York</City> + <Zipcode>10001</Zipcode> + </Address> + <Hobbies> + <Hobby>reading</Hobby> + <Hobby>cycling</Hobby> + <Hobby>swimming</Hobby> + </Hobbies> + </Person> + """; + XmlAssert.assertThat(res) + .and(expected) + .ignoreWhitespace() + .ignoreComments() + .areIdentical(); + } + + @Test + public void testJsonBodyDisabled() throws Exception { + MockEndpoint endpoint = getMockEndpoint("mock:no-json-result"); + endpoint.expectedMessageCount(1); + + try { + template.sendBody("direct:no-json-start", JSON_INPUT); + } catch (Exception e) { + assertTrue(e.getCause().getMessage().contains("Content is not allowed in prolog")); + } + } + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + public void configure() { + from("direct:json-start") + .to("xslt-saxon:org/apache/camel/component/xslt/saxon/json-transform.xsl?useJsonBody=true") + .to("mock:json-result"); + + from("direct:no-json-start") + .to("xslt-saxon:org/apache/camel/component/xslt/saxon/json-transform.xsl") + .to("mock:no-json-result"); + } + }; + } +} diff --git a/components/camel-xslt-saxon/src/test/resources/org/apache/camel/component/xslt/saxon/json-transform.xsl b/components/camel-xslt-saxon/src/test/resources/org/apache/camel/component/xslt/saxon/json-transform.xsl new file mode 100644 index 00000000000..32f1a708b11 --- /dev/null +++ b/components/camel-xslt-saxon/src/test/resources/org/apache/camel/component/xslt/saxon/json-transform.xsl @@ -0,0 +1,41 @@ +<?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="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xf="http://www.w3.org/2005/xpath-functions"> + + <xsl:output method="xml" indent="yes"/> + + <xsl:template match="/"> + <Person> + <Name><xsl:value-of select="xf:map/xf:string[@key='name']" /></Name> + <Age><xsl:value-of select="xf:map/xf:number[@key='age']" /></Age> + <Email><xsl:value-of select="xf:map/xf:string[@key='email']" /></Email> + <Address> + <Street><xsl:value-of select="xf:map/xf:map[@key='address']/xf:string[@key='street']" /></Street> + <City><xsl:value-of select="xf:map/xf:map[@key='address']/xf:string[@key='city']" /></City> + <Zipcode><xsl:value-of select="xf:map/xf:map[@key='address']/xf:string[@key='zipcode']" /></Zipcode> + </Address> + <Hobbies> + <xsl:for-each select="xf:map/xf:array[@key='hobbies']/xf:string"> + <Hobby><xsl:value-of select="." /></Hobby> + </xsl:for-each> + </Hobbies> + </Person> + </xsl:template> +</xsl:stylesheet> 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 86e30cb746a..1a277c12ee5 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 @@ -347,6 +347,44 @@ public interface XJEndpointBuilderFactory { doSetProperty("transformerCacheSize", transformerCacheSize); return this; } + /** + * Whether to use JSON body as input. When enabled, the message body is + * expected to be JSON and will be converted to XML representation of + * JSON using XSLT3 json-to-xml() function before XSLT processing. This + * allows XSLT stylesheets to process JSON input directly using standard + * XPath expressions. + * + * The option is a: <code>boolean</code> type. + * + * Default: false + * Group: producer + * + * @param useJsonBody the value to set + * @return the dsl builder + */ + default XJEndpointBuilder useJsonBody(boolean useJsonBody) { + doSetProperty("useJsonBody", useJsonBody); + return this; + } + /** + * Whether to use JSON body as input. When enabled, the message body is + * expected to be JSON and will be converted to XML representation of + * JSON using XSLT3 json-to-xml() function before XSLT processing. This + * allows XSLT stylesheets to process JSON input directly using standard + * XPath expressions. + * + * The option will be converted to a <code>boolean</code> type. + * + * Default: false + * Group: producer + * + * @param useJsonBody the value to set + * @return the dsl builder + */ + default XJEndpointBuilder useJsonBody(String useJsonBody) { + doSetProperty("useJsonBody", useJsonBody); + return this; + } } /** 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 fd4e77357da..5b7729d6da4 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 @@ -315,6 +315,44 @@ public interface XsltSaxonEndpointBuilderFactory { doSetProperty("transformerCacheSize", transformerCacheSize); return this; } + /** + * Whether to use JSON body as input. When enabled, the message body is + * expected to be JSON and will be converted to XML representation of + * JSON using XSLT3 json-to-xml() function before XSLT processing. This + * allows XSLT stylesheets to process JSON input directly using standard + * XPath expressions. + * + * The option is a: <code>boolean</code> type. + * + * Default: false + * Group: producer + * + * @param useJsonBody the value to set + * @return the dsl builder + */ + default XsltSaxonEndpointBuilder useJsonBody(boolean useJsonBody) { + doSetProperty("useJsonBody", useJsonBody); + return this; + } + /** + * Whether to use JSON body as input. When enabled, the message body is + * expected to be JSON and will be converted to XML representation of + * JSON using XSLT3 json-to-xml() function before XSLT processing. This + * allows XSLT stylesheets to process JSON input directly using standard + * XPath expressions. + * + * The option will be converted to a <code>boolean</code> type. + * + * Default: false + * Group: producer + * + * @param useJsonBody the value to set + * @return the dsl builder + */ + default XsltSaxonEndpointBuilder useJsonBody(String useJsonBody) { + doSetProperty("useJsonBody", useJsonBody); + return this; + } } /**