This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch po in repository https://gitbox.apache.org/repos/asf/camel.git
commit b2a22f4ede5afa8d1252c76019b7cb7d290eb608 Author: Claus Ibsen <[email protected]> AuthorDate: Sat Jun 29 18:00:21 2024 +0200 CAMEL-20929: properties function with fine grained control whether a property is optional or not. --- .../org/apache/camel/spi/PropertiesFunction.java | 10 +++ .../properties/DefaultPropertiesParser.java | 12 ++-- ...rtyFunctionOptionalPropertyPlaceholderTest.java | 79 ++++++++++++++++++++++ 3 files changed, 97 insertions(+), 4 deletions(-) diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesFunction.java b/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesFunction.java index 6e3482db6d6..f995a496308 100644 --- a/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesFunction.java +++ b/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesFunction.java @@ -46,4 +46,14 @@ public interface PropertiesFunction { return false; } + /** + * If the property value cannot be found should the property be regarded as optional and ignore missing value. + * + * @param remainder the remainder value + * @return true to make this property as optional + */ + default boolean optional(String remainder) { + return false; + } + } diff --git a/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesParser.java b/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesParser.java index 40840041e48..ef7286d8e6c 100644 --- a/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesParser.java +++ b/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesParser.java @@ -321,10 +321,10 @@ public class DefaultPropertiesParser implements PropertiesParser { PropertiesFunction function = propertiesComponent.getPropertiesFunction(prefix); if (function != null) { String remainder = StringHelper.after(key, ":"); + boolean remainderOptional = remainder.startsWith(OPTIONAL_TOKEN); if (function.lookupFirst(remainder)) { - boolean functionOptional = remainder.startsWith(OPTIONAL_TOKEN); String value = getPropertyValue(remainder, input); - if (functionOptional && value == null) { + if (value == null && (remainderOptional || function.optional(remainder))) { return null; } // it was not possible to resolve @@ -337,11 +337,15 @@ public class DefaultPropertiesParser implements PropertiesParser { log.debug("Property with key [{}] is applied by function [{}]", key, function.getName()); String value = function.apply(remainder); if (value == null) { - if (!optional && propertiesComponent != null && propertiesComponent.isIgnoreMissingProperty()) { + if (!remainderOptional) { + remainderOptional = function.optional(remainder); + } + if (!remainderOptional && propertiesComponent != null + && propertiesComponent.isIgnoreMissingProperty()) { // property is missing, but we should ignore this and return the placeholder unresolved return UNRESOLVED_PREFIX_TOKEN + key + UNRESOLVED_SUFFIX_TOKEN; } - if (!optional) { + if (!remainderOptional) { throw new IllegalArgumentException( "Property with key [" + key + "] using function [" + function.getName() + "]" + " returned null value which is not allowed, from input: " diff --git a/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertyFunctionOptionalPropertyPlaceholderTest.java b/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertyFunctionOptionalPropertyPlaceholderTest.java index 44e91c2be5a..790c5ea8142 100644 --- a/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertyFunctionOptionalPropertyPlaceholderTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertyFunctionOptionalPropertyPlaceholderTest.java @@ -107,6 +107,52 @@ public class PropertyFunctionOptionalPropertyPlaceholderTest extends ContextTest assertEquals(2, getMockEndpoint("mock:result").getReceivedExchanges().size()); } + @Test + public void testFunctionMagic() throws Exception { + context.addRoutes(new RouteBuilder() { + @Override + public void configure() { + from("direct:start") + .setBody().constant("{{magic:myMagic}}") + .to("mock:result"); + } + }); + context.start(); + + getMockEndpoint("mock:result").expectedMessageCount(2); + getMockEndpoint("mock:result").allMessages().body().isEqualTo("magic"); + + template.sendBody("direct:start", "Hello World"); + template.sendBody("direct:start", "Bye World"); + + assertMockEndpointsSatisfied(); + + assertEquals(2, getMockEndpoint("mock:result").getReceivedExchanges().size()); + } + + @Test + public void testFunctionMagicOptional() throws Exception { + context.addRoutes(new RouteBuilder() { + @Override + public void configure() { + from("direct:start") + .setBody().constant("{{magic:myOptional}}") + .to("mock:result"); + } + }); + context.start(); + + getMockEndpoint("mock:result").expectedMessageCount(2); + getMockEndpoint("mock:result").allMessages().body().isNull(); + + template.sendBody("direct:start", "Hello World"); + template.sendBody("direct:start", "Bye World"); + + assertMockEndpointsSatisfied(); + + assertEquals(2, getMockEndpoint("mock:result").getReceivedExchanges().size()); + } + @Test public void testFunctionPresent() throws Exception { Properties prop = new Properties(); @@ -188,6 +234,9 @@ public class PropertyFunctionOptionalPropertyPlaceholderTest extends ContextTest ReverseFunction func = new ReverseFunction(); func.setCamelContext(context); context.getPropertiesComponent().addPropertiesFunction(func); + MagicFunction func2 = new MagicFunction(); + func2.setCamelContext(context); + context.getPropertiesComponent().addPropertiesFunction(func2); return context; } @@ -225,4 +274,34 @@ public class PropertyFunctionOptionalPropertyPlaceholderTest extends ContextTest } } + private static class MagicFunction implements PropertiesFunction, CamelContextAware { + + private CamelContext camelContext; + + @Override + public CamelContext getCamelContext() { + return camelContext; + } + + @Override + public void setCamelContext(CamelContext camelContext) { + this.camelContext = camelContext; + } + + @Override + public String getName() { + return "magic"; + } + + @Override + public String apply(String remainder) { + return "myMagic".equals(remainder) ? "magic" : null; + } + + @Override + public boolean optional(String remainder) { + return "myOptional".equals(remainder); + } + } + }
