This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch re in repository https://gitbox.apache.org/repos/asf/camel.git
commit 376f0c52c4bb1f8d6efae8817f2983e9ea8d72a6 Author: Claus Ibsen <[email protected]> AuthorDate: Thu Jun 26 10:23:36 2025 +0200 CAMEL-22200: components that are resource endpoint based should have content cache true as default and make it configurable on component level. --- .../component/jsonpatch/JsonPatchEndpoint.java | 2 +- .../jsonata/JsonataComponentConfigurer.java | 12 +++++ .../apache/camel/component/jsonata/jsonata.json | 8 +-- .../camel/component/jsonata/JsonataComponent.java | 33 +++++++++++- .../camel/component/jsonata/JsonataRefTest.java | 63 ++++++++++++++++++++++ 5 files changed, 113 insertions(+), 5 deletions(-) diff --git a/components/camel-json-patch/src/main/java/org/apache/camel/component/jsonpatch/JsonPatchEndpoint.java b/components/camel-json-patch/src/main/java/org/apache/camel/component/jsonpatch/JsonPatchEndpoint.java index 985c139d941..e0c07825345 100644 --- a/components/camel-json-patch/src/main/java/org/apache/camel/component/jsonpatch/JsonPatchEndpoint.java +++ b/components/camel-json-patch/src/main/java/org/apache/camel/component/jsonpatch/JsonPatchEndpoint.java @@ -33,7 +33,7 @@ import org.apache.camel.spi.UriParam; category = { Category.TRANSFORMATION }, headersClass = JsonPatchConstants.class) public class JsonPatchEndpoint extends ResourceEndpoint { - @UriParam(defaultValue = "false") + @UriParam private boolean allowTemplateFromHeader; public JsonPatchEndpoint() { diff --git a/components/camel-jsonata/src/generated/java/org/apache/camel/component/jsonata/JsonataComponentConfigurer.java b/components/camel-jsonata/src/generated/java/org/apache/camel/component/jsonata/JsonataComponentConfigurer.java index 86bb0ad4957..c6829e5994d 100644 --- a/components/camel-jsonata/src/generated/java/org/apache/camel/component/jsonata/JsonataComponentConfigurer.java +++ b/components/camel-jsonata/src/generated/java/org/apache/camel/component/jsonata/JsonataComponentConfigurer.java @@ -23,8 +23,12 @@ public class JsonataComponentConfigurer extends PropertyConfigurerSupport implem public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) { JsonataComponent target = (JsonataComponent) obj; switch (ignoreCase ? name.toLowerCase() : name) { + case "allowtemplatefromheader": + case "allowTemplateFromHeader": target.setAllowTemplateFromHeader(property(camelContext, boolean.class, value)); return true; case "autowiredenabled": case "autowiredEnabled": target.setAutowiredEnabled(property(camelContext, boolean.class, value)); return true; + case "contentcache": + case "contentCache": target.setContentCache(property(camelContext, boolean.class, value)); return true; case "framebinding": case "frameBinding": target.setFrameBinding(property(camelContext, org.apache.camel.component.jsonata.JsonataFrameBinding.class, value)); return true; case "lazystartproducer": @@ -36,8 +40,12 @@ public class JsonataComponentConfigurer extends PropertyConfigurerSupport implem @Override public Class<?> getOptionType(String name, boolean ignoreCase) { switch (ignoreCase ? name.toLowerCase() : name) { + case "allowtemplatefromheader": + case "allowTemplateFromHeader": return boolean.class; case "autowiredenabled": case "autowiredEnabled": return boolean.class; + case "contentcache": + case "contentCache": return boolean.class; case "framebinding": case "frameBinding": return org.apache.camel.component.jsonata.JsonataFrameBinding.class; case "lazystartproducer": @@ -50,8 +58,12 @@ public class JsonataComponentConfigurer extends PropertyConfigurerSupport implem public Object getOptionValue(Object obj, String name, boolean ignoreCase) { JsonataComponent target = (JsonataComponent) obj; switch (ignoreCase ? name.toLowerCase() : name) { + case "allowtemplatefromheader": + case "allowTemplateFromHeader": return target.isAllowTemplateFromHeader(); case "autowiredenabled": case "autowiredEnabled": return target.isAutowiredEnabled(); + case "contentcache": + case "contentCache": return target.isContentCache(); case "framebinding": case "frameBinding": return target.getFrameBinding(); case "lazystartproducer": diff --git a/components/camel-jsonata/src/generated/resources/META-INF/org/apache/camel/component/jsonata/jsonata.json b/components/camel-jsonata/src/generated/resources/META-INF/org/apache/camel/component/jsonata/jsonata.json index ab46b61d8a8..af8b338bccf 100644 --- a/components/camel-jsonata/src/generated/resources/META-INF/org/apache/camel/component/jsonata/jsonata.json +++ b/components/camel-jsonata/src/generated/resources/META-INF/org/apache/camel/component/jsonata/jsonata.json @@ -24,9 +24,11 @@ "remote": false }, "componentProperties": { - "lazyStartProducer": { "index": 0, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "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 producer may otherwise fail [...] - "autowiredEnabled": { "index": 1, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...] - "frameBinding": { "index": 2, "kind": "property", "displayName": "Frame Binding", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.jsonata.JsonataFrameBinding", "deprecated": false, "autowired": false, "secret": false, "description": "To configure custom frame bindings and inject user functions." } + "allowTemplateFromHeader": { "index": 0, "kind": "property", "displayName": "Allow Template From Header", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to allow to use resource template from header or not (default false). Enabling this allows to specify dynamic templates via message header. However this can be seen as a potential se [...] + "contentCache": { "index": 1, "kind": "property", "displayName": "Content Cache", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Sets whether to use resource content cache or not" }, + "lazyStartProducer": { "index": 2, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "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 producer may otherwise fail [...] + "autowiredEnabled": { "index": 3, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...] + "frameBinding": { "index": 4, "kind": "property", "displayName": "Frame Binding", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.jsonata.JsonataFrameBinding", "deprecated": false, "autowired": false, "secret": false, "description": "To configure custom frame bindings and inject user functions." } }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will look [...] diff --git a/components/camel-jsonata/src/main/java/org/apache/camel/component/jsonata/JsonataComponent.java b/components/camel-jsonata/src/main/java/org/apache/camel/component/jsonata/JsonataComponent.java index e799c01a4de..d3449fac41f 100644 --- a/components/camel-jsonata/src/main/java/org/apache/camel/component/jsonata/JsonataComponent.java +++ b/components/camel-jsonata/src/main/java/org/apache/camel/component/jsonata/JsonataComponent.java @@ -26,6 +26,11 @@ import org.apache.camel.support.ResourceHelper; @Component("jsonata") public class JsonataComponent extends DefaultComponent { + + @Metadata(defaultValue = "true", description = "Sets whether to use resource content cache or not") + private boolean contentCache; + @Metadata(defaultValue = "false") + private boolean allowTemplateFromHeader; @Metadata(label = "advanced", description = "To configure custom frame bindings and inject user functions.") protected JsonataFrameBinding frameBinding; @@ -35,7 +40,7 @@ public class JsonataComponent extends DefaultComponent { @Override protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception { - boolean cache = getAndRemoveParameter(parameters, "contentCache", Boolean.class, Boolean.TRUE); + boolean cache = getAndRemoveParameter(parameters, "contentCache", Boolean.class, contentCache); JsonataFrameBinding frameBinding = resolveAndRemoveReferenceParameter(parameters, "frameBinding", JsonataFrameBinding.class); @@ -46,6 +51,7 @@ public class JsonataComponent extends DefaultComponent { JsonataEndpoint answer = new JsonataEndpoint(uri, this, remaining, frameBinding); answer.setContentCache(cache); + answer.setAllowTemplateFromHeader(allowTemplateFromHeader); // if its a http resource then append any remaining parameters and update the resource uri if (ResourceHelper.isHttpUri(remaining)) { @@ -56,6 +62,31 @@ public class JsonataComponent extends DefaultComponent { return answer; } + public boolean isContentCache() { + return contentCache; + } + + /** + * Sets whether to use resource content cache or not + */ + public void setContentCache(boolean contentCache) { + this.contentCache = contentCache; + } + + public boolean isAllowTemplateFromHeader() { + return allowTemplateFromHeader; + } + + /** + * Whether to allow to use resource template from header or not (default false). + * + * Enabling this allows to specify dynamic templates via message header. However this can be seen as a potential + * security vulnerability if the header is coming from a malicious user, so use this with care. + */ + public void setAllowTemplateFromHeader(boolean allowTemplateFromHeader) { + this.allowTemplateFromHeader = allowTemplateFromHeader; + } + /** * To use the custom JsonataFrameBinding to perform configuration of custom functions that will be used. */ diff --git a/components/camel-jsonata/src/test/java/org/apache/camel/component/jsonata/JsonataRefTest.java b/components/camel-jsonata/src/test/java/org/apache/camel/component/jsonata/JsonataRefTest.java new file mode 100644 index 00000000000..d3bdc6f31b5 --- /dev/null +++ b/components/camel-jsonata/src/test/java/org/apache/camel/component/jsonata/JsonataRefTest.java @@ -0,0 +1,63 @@ +/* + * 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.jsonata; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.support.ResourceHelper; +import org.apache.camel.test.junit5.CamelTestSupport; +import org.apache.camel.util.IOHelper; +import org.junit.jupiter.api.Test; + +class JsonataRefTest extends CamelTestSupport { + + private static String TEMP = """ + { + "name": Surname & " " & FirstName, + "mobile": Phone[type = "mobile"].number + } + """; + + @Test + void testRef() throws Exception { + getMockEndpoint("mock:result").expectedBodiesReceived( + IOHelper.loadText( + ResourceHelper.resolveMandatoryResourceAsInputStream( + context, "org/apache/camel/component/jsonata/firstSample/output2.json")) + .trim() // Remove the last newline added by IOHelper.loadText() + ); + + sendBody("direct://start", + ResourceHelper.resolveMandatoryResourceAsInputStream( + context, "org/apache/camel/component/jsonata/firstSample/input.json")); + + MockEndpoint.assertIsSatisfied(context); + } + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + public void configure() { + context.getRegistry().bind("mytemp", TEMP); + + from("direct://start") + .to("jsonata:ref:mytemp?inputType=JsonString&outputType=JsonString") + .to("mock:result"); + } + }; + } +}
