You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2021/03/05 14:05:30 UTC
[camel] 01/02: CAMEL-16302: camel-core - Optional property
placeholders in properties component.
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git
commit ace4998312724006ba00e79745147a5ffe2edcd3
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri Mar 5 14:39:24 2021 +0100
CAMEL-16302: camel-core - Optional property placeholders in properties component.
---
.../spi/BridgePropertyPlaceholderConfigurer.java | 12 +-
.../main/java/org/apache/camel/CamelContext.java | 3 +
.../org/apache/camel/ExtendedCamelContext.java | 14 ++
.../org/apache/camel/spi/PropertiesComponent.java | 20 ++
.../camel/impl/engine/AbstractCamelContext.java | 18 +-
.../properties/DefaultPropertiesParser.java | 66 ++++--
.../component/properties/PropertiesComponent.java | 13 +-
.../component/properties/PropertiesParser.java | 4 +-
.../impl/cloud/ServiceCallProcessorFactory.java | 3 +-
.../camel/impl/lw/LightweightCamelContext.java | 5 +
.../impl/lw/LightweightRuntimeCamelContext.java | 7 +-
.../camel/processor/SendDynamicProcessor.java | 4 +-
.../org/apache/camel/reifier/AggregateReifier.java | 17 +-
.../apache/camel/reifier/ClaimCheckReifier.java | 5 +-
.../apache/camel/reifier/DynamicRouterReifier.java | 5 +-
.../org/apache/camel/reifier/EnrichReifier.java | 5 +-
.../camel/reifier/IdempotentConsumerReifier.java | 6 +-
.../reifier/InterceptSendToEndpointReifier.java | 5 +-
.../org/apache/camel/reifier/MulticastReifier.java | 7 +-
.../apache/camel/reifier/PollEnrichReifier.java | 12 +-
.../org/apache/camel/reifier/ProcessorReifier.java | 6 +-
.../apache/camel/reifier/RecipientListReifier.java | 22 +-
.../apache/camel/reifier/ResequenceReifier.java | 25 ++-
.../apache/camel/reifier/RoutingSlipReifier.java | 5 +-
.../java/org/apache/camel/reifier/SagaReifier.java | 5 +-
.../org/apache/camel/reifier/SamplingReifier.java | 7 +-
.../java/org/apache/camel/reifier/SortReifier.java | 5 +-
.../org/apache/camel/reifier/SplitReifier.java | 13 +-
.../org/apache/camel/reifier/ThreadsReifier.java | 10 +-
.../org/apache/camel/reifier/ThrottleReifier.java | 2 +-
.../camel/reifier/ThrowExceptionReifier.java | 5 +-
.../org/apache/camel/reifier/ToDynamicReifier.java | 8 +-
.../org/apache/camel/reifier/WireTapReifier.java | 10 +-
.../reifier/dataformat/YAMLDataFormatReifier.java | 7 +-
.../loadbalancer/FailoverLoadBalancerReifier.java | 5 +-
.../transformer/CustomTransformeReifier.java | 5 +-
.../core/xml/AbstractCamelEndpointFactoryBean.java | 3 +-
.../OptionalPropertyPlaceholderEipTest.java | 84 ++++++++
.../OptionalPropertyPlaceholderTest.java | 228 +++++++++++++++++++++
.../builder/endpoint/AbstractEndpointBuilder.java | 19 +-
.../endpoint/OptionalPropertyPlaceholderTest.java | 121 +++++++++++
.../org/apache/camel/support/EndpointHelper.java | 92 ++++++++-
.../component/EndpointUriFactorySupport.java | 39 +---
.../java/org/apache/camel/util/StringHelper.java | 20 +-
.../java/org/apache/camel/util/URISupport.java | 14 ++
45 files changed, 824 insertions(+), 167 deletions(-)
diff --git a/components/camel-spring/src/main/java/org/apache/camel/spring/spi/BridgePropertyPlaceholderConfigurer.java b/components/camel-spring/src/main/java/org/apache/camel/spring/spi/BridgePropertyPlaceholderConfigurer.java
index 2317cb3..e97c81b 100644
--- a/components/camel-spring/src/main/java/org/apache/camel/spring/spi/BridgePropertyPlaceholderConfigurer.java
+++ b/components/camel-spring/src/main/java/org/apache/camel/spring/spi/BridgePropertyPlaceholderConfigurer.java
@@ -83,9 +83,10 @@ public class BridgePropertyPlaceholderConfigurer extends PropertyPlaceholderConf
}
@Override
- public String parseUri(String text, PropertiesLookup properties, boolean fallback) throws IllegalArgumentException {
+ public String parseUri(String text, PropertiesLookup properties, boolean fallback, boolean keepUnresolvedOptional)
+ throws IllegalArgumentException {
// first let Camel parse the text as it may contain Camel placeholders
- String answer = parser.parseUri(text, properties, fallback);
+ String answer = parser.parseUri(text, properties, fallback, keepUnresolvedOptional);
// then let Spring parse it to resolve any Spring placeholders
if (answer != null) {
@@ -172,15 +173,16 @@ public class BridgePropertyPlaceholderConfigurer extends PropertyPlaceholderConf
}
@Override
- public String parseUri(String text, PropertiesLookup properties, boolean fallback) throws IllegalArgumentException {
+ public String parseUri(String text, PropertiesLookup properties, boolean fallback, boolean keepUnresolvedOptional)
+ throws IllegalArgumentException {
String answer = null;
if (delegate != null) {
- answer = delegate.parseUri(text, properties, fallback);
+ answer = delegate.parseUri(text, properties, fallback, keepUnresolvedOptional);
}
if (answer != null) {
text = answer;
}
- return parser.parseUri(text, properties, fallback);
+ return parser.parseUri(text, properties, fallback, keepUnresolvedOptional);
}
@Override
diff --git a/core/camel-api/src/main/java/org/apache/camel/CamelContext.java b/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
index 44b31ed..bbc1863 100644
--- a/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
+++ b/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
@@ -725,6 +725,9 @@ public interface CamelContext extends CamelContextLifecycle, RuntimeConfiguratio
/**
* Parses the given text and resolve any property placeholders - using {{key}}.
+ * <p/>
+ * <b>Important:</b> If resolving placeholders on an endpoint uri, then you SHOULD use
+ * EndpointHelper#resolveEndpointUriPropertyPlaceholders instead.
*
* @param text the text such as an endpoint uri or the likes
* @return the text with resolved property placeholders
diff --git a/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java b/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
index 114eeab..654cc52 100644
--- a/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
+++ b/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
@@ -769,4 +769,18 @@ public interface ExtendedCamelContext extends CamelContext {
*/
String getTestExcludeRoutes();
+ /**
+ * Parses the given text and resolve any property placeholders - using {{key}}.
+ * <p/>
+ * <b>Important:</b> If resolving placeholders on an endpoint uri, then you SHOULD use
+ * EndpointHelper#resolveEndpointUriPropertyPlaceholders instead.
+ *
+ * @param text the text such as an endpoint uri or the likes
+ * @param keepUnresolvedOptional whether to keep placeholders that are optional and was unresolved
+ * @return the text with resolved property placeholders
+ * @throws IllegalArgumentException is thrown if property placeholders was used and there was an error resolving
+ * them
+ */
+ String resolvePropertyPlaceholders(String text, boolean keepUnresolvedOptional);
+
}
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesComponent.java b/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesComponent.java
index 83e2fd9..80dd27e 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesComponent.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesComponent.java
@@ -46,6 +46,16 @@ public interface PropertiesComponent extends StaticService {
String SUFFIX_TOKEN = "}}";
/**
+ * The token for marking a placeholder as optional
+ */
+ String OPTIONAL_TOKEN = "?";
+
+ /**
+ * The prefix and optional tokens
+ */
+ String PREFIX_OPTIONAL_TOKEN = PREFIX_TOKEN + OPTIONAL_TOKEN;
+
+ /**
* Parses the input text and resolve all property placeholders from within the text.
*
* @param uri input text
@@ -55,6 +65,16 @@ public interface PropertiesComponent extends StaticService {
String parseUri(String uri);
/**
+ * Parses the input text and resolve all property placeholders from within the text.
+ *
+ * @param uri input text
+ * @param keepUnresolvedOptional whether to keep placeholders that are optional and was unresolved
+ * @return text with resolved property placeholders
+ * @throws IllegalArgumentException is thrown if error during parsing
+ */
+ String parseUri(String uri, boolean keepUnresolvedOptional);
+
+ /**
* Looks up the property with the given key
*
* @param key the name of the property
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
index 45a1a92..3d2d334 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
@@ -818,7 +818,7 @@ public abstract class AbstractCamelContext extends BaseService
@Override
public NormalizedEndpointUri normalizeUri(String uri) {
try {
- uri = resolvePropertyPlaceholders(uri);
+ uri = EndpointHelper.resolveEndpointUriPropertyPlaceholders(this, uri);
uri = URISupport.normalizeUri(uri);
return new NormalizedUri(uri);
} catch (Exception e) {
@@ -874,14 +874,9 @@ public abstract class AbstractCamelContext extends BaseService
LOG.trace("Getting endpoint with uri: {} and parameters: {}", uri, parameters);
- // in case path has property placeholders then try to let property
- // component resolve those
+ // in case path has property placeholders then try to let property component resolve those
if (!normalized) {
- try {
- uri = resolvePropertyPlaceholders(uri);
- } catch (Exception e) {
- throw new ResolveEndpointFailedException(uri, e);
- }
+ uri = EndpointHelper.resolveEndpointUriPropertyPlaceholders(this, uri);
}
final String rawUri = uri;
@@ -1767,9 +1762,14 @@ public abstract class AbstractCamelContext extends BaseService
@Override
public String resolvePropertyPlaceholders(String text) {
+ return resolvePropertyPlaceholders(text, false);
+ }
+
+ @Override
+ public String resolvePropertyPlaceholders(String text, boolean keepUnresolvedOptional) {
if (text != null && text.contains(PropertiesComponent.PREFIX_TOKEN)) {
// the parser will throw exception if property key was not found
- String answer = getPropertiesComponent().parseUri(text);
+ String answer = getPropertiesComponent().parseUri(text, keepUnresolvedOptional);
LOG.debug("Resolved text: {} -> {}", text, answer);
return answer;
}
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 e83b20a..9d13f56 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
@@ -25,6 +25,7 @@ import org.apache.camel.util.StringHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static org.apache.camel.spi.PropertiesComponent.OPTIONAL_TOKEN;
import static org.apache.camel.spi.PropertiesComponent.PREFIX_TOKEN;
import static org.apache.camel.spi.PropertiesComponent.SUFFIX_TOKEN;
import static org.apache.camel.util.IOHelper.lookupEnvironmentVariable;
@@ -33,6 +34,8 @@ import static org.apache.camel.util.IOHelper.lookupEnvironmentVariable;
* A parser to parse a string which contains property placeholders.
*/
public class DefaultPropertiesParser implements PropertiesParser {
+ private static final String UNRESOLVED_PREFIX_TOKEN = "@@[";
+ private static final String UNRESOLVED_SUFFIX_TOKEN = "]@@";
private static final String GET_OR_ELSE_TOKEN = ":";
protected final Logger log = LoggerFactory.getLogger(getClass());
@@ -55,10 +58,17 @@ public class DefaultPropertiesParser implements PropertiesParser {
}
@Override
- public String parseUri(String text, PropertiesLookup properties, boolean defaultFallbackEnabled)
+ public String parseUri(
+ String text, PropertiesLookup properties, boolean defaultFallbackEnabled, boolean keepUnresolvedOptional)
throws IllegalArgumentException {
- ParsingContext context = new ParsingContext(properties, defaultFallbackEnabled);
- return context.parse(text);
+ ParsingContext context = new ParsingContext(properties, defaultFallbackEnabled, keepUnresolvedOptional);
+ String answer = context.parse(text);
+ if (keepUnresolvedOptional && answer != null && answer.contains(UNRESOLVED_PREFIX_TOKEN)) {
+ // replace temporary unresolved keys back to with placeholders so they are kept as-is
+ answer = StringHelper.replaceAll(answer, UNRESOLVED_PREFIX_TOKEN, PREFIX_TOKEN);
+ answer = StringHelper.replaceAll(answer, UNRESOLVED_SUFFIX_TOKEN, SUFFIX_TOKEN);
+ }
+ return answer;
}
@Override
@@ -72,10 +82,12 @@ public class DefaultPropertiesParser implements PropertiesParser {
private final class ParsingContext {
private final PropertiesLookup properties;
private final boolean defaultFallbackEnabled;
+ private final boolean keepUnresolvedOptional;
- ParsingContext(PropertiesLookup properties, boolean defaultFallbackEnabled) {
+ ParsingContext(PropertiesLookup properties, boolean defaultFallbackEnabled, boolean keepUnresolvedOptional) {
this.properties = properties;
this.defaultFallbackEnabled = defaultFallbackEnabled;
+ this.keepUnresolvedOptional = keepUnresolvedOptional;
}
/**
@@ -102,10 +114,15 @@ public class DefaultPropertiesParser implements PropertiesParser {
String answer = input;
Property property;
while ((property = readProperty(answer)) != null) {
- // Check for circular references
if (replacedPropertyKeys.contains(property.getKey())) {
- throw new IllegalArgumentException(
- "Circular reference detected with key [" + property.getKey() + "] from text: " + input);
+ // Check for circular references (skip optional)
+ boolean optional = property.getKey().startsWith(OPTIONAL_TOKEN);
+ if (optional) {
+ break;
+ } else {
+ throw new IllegalArgumentException(
+ "Circular reference detected with key [" + property.getKey() + "] from text: " + input);
+ }
}
Set<String> newReplaced = new HashSet<>(replacedPropertyKeys);
@@ -113,7 +130,18 @@ public class DefaultPropertiesParser implements PropertiesParser {
String before = answer.substring(0, property.getBeginIndex());
String after = answer.substring(property.getEndIndex());
- answer = before + doParse(property.getValue(), newReplaced) + after;
+ String parsed = doParse(property.getValue(), newReplaced);
+ if (parsed != null) {
+ answer = before + parsed + after;
+ } else {
+ if (property.getBeginIndex() == 0 && input.length() == property.getEndIndex()) {
+ // its only a single placeholder which is parsed as null
+ answer = null;
+ break;
+ } else {
+ answer = before + after;
+ }
+ }
}
return answer;
}
@@ -237,6 +265,11 @@ public class DefaultPropertiesParser implements PropertiesParser {
key = StringHelper.before(key, GET_OR_ELSE_TOKEN);
}
+ boolean optional = key != null && key.startsWith(OPTIONAL_TOKEN);
+ if (optional) {
+ key = key.substring(OPTIONAL_TOKEN.length());
+ }
+
String value = doGetPropertyValue(key);
if (value == null && defaultValue != null) {
log.debug("Property with key [{}] not found, using default value: {}", key, defaultValue);
@@ -244,10 +277,19 @@ public class DefaultPropertiesParser implements PropertiesParser {
}
if (value == null) {
- StringBuilder esb = new StringBuilder();
- esb.append("Property with key [").append(key).append("] ");
- esb.append("not found in properties from text: ").append(input);
- throw new IllegalArgumentException(esb.toString());
+ if (!optional) {
+ StringBuilder esb = new StringBuilder();
+ esb.append("Property with key [").append(key).append("] ");
+ esb.append("not found in properties from text: ").append(input);
+ throw new IllegalArgumentException(esb.toString());
+ } else {
+ if (keepUnresolvedOptional) {
+ // mark the key as unresolved
+ return UNRESOLVED_PREFIX_TOKEN + OPTIONAL_TOKEN + key + UNRESOLVED_SUFFIX_TOKEN;
+ } else {
+ return null;
+ }
+ }
}
return value;
diff --git a/core/camel-base/src/main/java/org/apache/camel/component/properties/PropertiesComponent.java b/core/camel-base/src/main/java/org/apache/camel/component/properties/PropertiesComponent.java
index 52c5e29..0bb2868 100644
--- a/core/camel-base/src/main/java/org/apache/camel/component/properties/PropertiesComponent.java
+++ b/core/camel-base/src/main/java/org/apache/camel/component/properties/PropertiesComponent.java
@@ -152,13 +152,18 @@ public class PropertiesComponent extends ServiceSupport
@Override
public String parseUri(String uri) {
- return parseUri(uri, propertiesLookup);
+ return parseUri(uri, false);
+ }
+
+ @Override
+ public String parseUri(String uri, boolean keepUnresolvedOptional) {
+ return parseUri(uri, propertiesLookup, keepUnresolvedOptional);
}
@Override
public Optional<String> resolveProperty(String key) {
try {
- String value = parseUri(key, propertiesLookup);
+ String value = parseUri(key, propertiesLookup, false);
return Optional.of(value);
} catch (IllegalArgumentException e) {
// property not found
@@ -243,7 +248,7 @@ public class PropertiesComponent extends ServiceSupport
return prop;
}
- protected String parseUri(String uri, PropertiesLookup properties) {
+ protected String parseUri(String uri, PropertiesLookup properties, boolean keepUnresolvedOptional) {
// enclose tokens if missing
if (!uri.contains(PREFIX_TOKEN) && !uri.startsWith(PREFIX_TOKEN)) {
uri = PREFIX_TOKEN + uri;
@@ -253,7 +258,7 @@ public class PropertiesComponent extends ServiceSupport
}
LOG.trace("Parsing uri {}", uri);
- return propertiesParser.parseUri(uri, properties, defaultFallbackEnabled);
+ return propertiesParser.parseUri(uri, properties, defaultFallbackEnabled, keepUnresolvedOptional);
}
@Override
diff --git a/core/camel-base/src/main/java/org/apache/camel/component/properties/PropertiesParser.java b/core/camel-base/src/main/java/org/apache/camel/component/properties/PropertiesParser.java
index 6a558da..d251640 100644
--- a/core/camel-base/src/main/java/org/apache/camel/component/properties/PropertiesParser.java
+++ b/core/camel-base/src/main/java/org/apache/camel/component/properties/PropertiesParser.java
@@ -27,10 +27,12 @@ public interface PropertiesParser {
* @param text the text to be parsed
* @param properties the properties resolved which values should be looked up
* @param fallback whether to support using fallback values if a property cannot be found
+ * @param keepUnresolvedOptional whether to keep placeholders that are optional and was unresolved
* @return the parsed text with replaced placeholders
* @throws IllegalArgumentException if uri syntax is not valid or a property is not found
*/
- String parseUri(String text, PropertiesLookup properties, boolean fallback) throws IllegalArgumentException;
+ String parseUri(String text, PropertiesLookup properties, boolean fallback, boolean keepUnresolvedOptional)
+ throws IllegalArgumentException;
/**
* While parsing the uri using parseUri method each parsed property found invokes this callback.
diff --git a/core/camel-cloud/src/main/java/org/apache/camel/impl/cloud/ServiceCallProcessorFactory.java b/core/camel-cloud/src/main/java/org/apache/camel/impl/cloud/ServiceCallProcessorFactory.java
index 0124765..9227576 100644
--- a/core/camel-cloud/src/main/java/org/apache/camel/impl/cloud/ServiceCallProcessorFactory.java
+++ b/core/camel-cloud/src/main/java/org/apache/camel/impl/cloud/ServiceCallProcessorFactory.java
@@ -41,6 +41,7 @@ import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition;
import org.apache.camel.model.cloud.ServiceCallDefinition;
import org.apache.camel.model.cloud.ServiceCallDefinitionConstants;
import org.apache.camel.support.CamelContextHelper;
+import org.apache.camel.support.EndpointHelper;
import org.apache.camel.support.TypedProcessorFactory;
import org.apache.camel.util.ObjectHelper;
import org.apache.camel.util.function.Suppliers;
@@ -126,7 +127,7 @@ public class ServiceCallProcessorFactory extends TypedProcessorFactory<ServiceCa
endpointScheme = ThrowingHelper.applyIfNotEmpty(endpointScheme, camelContext::resolvePropertyPlaceholders,
() -> ServiceCallDefinitionConstants.DEFAULT_COMPONENT);
- endpointUri = ThrowingHelper.applyIfNotEmpty(endpointUri, camelContext::resolvePropertyPlaceholders, () -> null);
+ endpointUri = EndpointHelper.resolveEndpointUriPropertyPlaceholders(camelContext, endpointUri);
ExchangePattern pattern = CamelContextHelper.parse(camelContext, ExchangePattern.class, definition.getPattern());
Expression expression = retrieveExpression(camelContext, endpointScheme);
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
index 16f4521..6101ee5 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
@@ -640,6 +640,11 @@ public class LightweightCamelContext implements ExtendedCamelContext, CatalogCam
}
@Override
+ public String resolvePropertyPlaceholders(String text, boolean keepUnresolvedOptional) {
+ return getExtendedCamelContext().resolvePropertyPlaceholders(text, keepUnresolvedOptional);
+ }
+
+ @Override
public PropertiesComponent getPropertiesComponent() {
return delegate.getPropertiesComponent();
}
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
index afed430..74af3ab 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
@@ -914,9 +914,14 @@ public class LightweightRuntimeCamelContext implements ExtendedCamelContext, Cat
@Override
public String resolvePropertyPlaceholders(String text) {
+ return resolvePropertyPlaceholders(text, false);
+ }
+
+ @Override
+ public String resolvePropertyPlaceholders(String text, boolean keepUnresolvedOptional) {
if (text != null && text.contains(PropertiesComponent.PREFIX_TOKEN)) {
// the parser will throw exception if property key was not found
- return getPropertiesComponent().parseUri(text);
+ return getPropertiesComponent().parseUri(text, keepUnresolvedOptional);
}
// is the value a known field (currently we only support
// constants from Exchange.class)
diff --git a/core/camel-core-processor/src/main/java/org/apache/camel/processor/SendDynamicProcessor.java b/core/camel-core-processor/src/main/java/org/apache/camel/processor/SendDynamicProcessor.java
index 9f26dee..76cdc79 100644
--- a/core/camel-core-processor/src/main/java/org/apache/camel/processor/SendDynamicProcessor.java
+++ b/core/camel-core-processor/src/main/java/org/apache/camel/processor/SendDynamicProcessor.java
@@ -233,7 +233,7 @@ public class SendDynamicProcessor extends AsyncProcessorSupport implements IdAwa
// in case path has property placeholders then try to let property component resolve those
try {
- uri = exchange.getContext().resolvePropertyPlaceholders(uri);
+ uri = EndpointHelper.resolveEndpointUriPropertyPlaceholders(exchange.getContext(), uri);
} catch (Exception e) {
throw new ResolveEndpointFailedException(uri, e);
}
@@ -310,7 +310,7 @@ public class SendDynamicProcessor extends AsyncProcessorSupport implements IdAwa
if ((isAllowOptimisedComponents() || isAutoStartupComponents()) && uri != null) {
// in case path has property placeholders then try to let property component resolve those
- String u = camelContext.resolvePropertyPlaceholders(uri);
+ String u = EndpointHelper.resolveEndpointUriPropertyPlaceholders(camelContext, uri);
// find out which component it is
scheme = ExchangeHelper.resolveScheme(u);
}
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/AggregateReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/AggregateReifier.java
index a01b4de..97c29cc 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/AggregateReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/AggregateReifier.java
@@ -207,17 +207,20 @@ public class AggregateReifier extends ProcessorReifier<AggregateDefinition> {
public OptimisticLockRetryPolicy createOptimisticLockRetryPolicy(OptimisticLockRetryPolicyDefinition definition) {
OptimisticLockRetryPolicy policy = new OptimisticLockRetryPolicy();
- if (definition.getMaximumRetries() != null) {
- policy.setMaximumRetries(parseInt(definition.getMaximumRetries()));
+ Integer num = parseInt(definition.getMaximumRetries());
+ if (num != null) {
+ policy.setMaximumRetries(num);
}
- if (definition.getRetryDelay() != null) {
- policy.setRetryDelay(parseDuration(definition.getRetryDelay()));
+ Long dur = parseDuration(definition.getRetryDelay());
+ if (dur != null) {
+ policy.setRetryDelay(dur);
}
- if (definition.getMaximumRetryDelay() != null) {
- policy.setMaximumRetryDelay(parseDuration(definition.getMaximumRetryDelay()));
+ dur = parseDuration(definition.getMaximumRetryDelay());
+ if (dur != null) {
+ policy.setMaximumRetryDelay(dur);
}
if (definition.getExponentialBackOff() != null) {
- policy.setExponentialBackOff(parseBoolean(definition.getExponentialBackOff(), false));
+ policy.setExponentialBackOff(parseBoolean(definition.getExponentialBackOff(), true));
}
if (definition.getRandomBackOff() != null) {
policy.setRandomBackOff(parseBoolean(definition.getRandomBackOff(), false));
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ClaimCheckReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ClaimCheckReifier.java
index 47b5a14..b6a4ce8 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ClaimCheckReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ClaimCheckReifier.java
@@ -109,8 +109,9 @@ public class ClaimCheckReifier extends ProcessorReifier<ClaimCheckDefinition> {
private AggregationStrategy createAggregationStrategy() {
AggregationStrategy strategy = definition.getAggregationStrategy();
- if (strategy == null && definition.getAggregationStrategyRef() != null) {
- Object aggStrategy = lookup(parseString(definition.getAggregationStrategyRef()), Object.class);
+ String ref = parseString(definition.getAggregationStrategyRef());
+ if (strategy == null && ref != null) {
+ Object aggStrategy = lookup(ref, Object.class);
if (aggStrategy instanceof AggregationStrategy) {
strategy = (AggregationStrategy) aggStrategy;
} else if (aggStrategy != null) {
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/DynamicRouterReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/DynamicRouterReifier.java
index bc760e0..c4e5169 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/DynamicRouterReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/DynamicRouterReifier.java
@@ -40,8 +40,9 @@ public class DynamicRouterReifier extends ExpressionReifier<DynamicRouterDefinit
if (definition.getIgnoreInvalidEndpoints() != null) {
dynamicRouter.setIgnoreInvalidEndpoints(parseBoolean(definition.getIgnoreInvalidEndpoints(), false));
}
- if (definition.getCacheSize() != null) {
- dynamicRouter.setCacheSize(parseInt(definition.getCacheSize()));
+ Integer num = parseInt(definition.getCacheSize());
+ if (num != null) {
+ dynamicRouter.setCacheSize(num);
}
AsyncProcessor errorHandler
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/EnrichReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/EnrichReifier.java
index 2367851..ffe0387 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/EnrichReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/EnrichReifier.java
@@ -41,8 +41,9 @@ public class EnrichReifier extends ExpressionReifier<EnrichDefinition> {
Enricher enricher = new Enricher(exp);
enricher.setShareUnitOfWork(isShareUnitOfWork);
enricher.setIgnoreInvalidEndpoint(isIgnoreInvalidEndpoint);
- if (definition.getCacheSize() != null) {
- enricher.setCacheSize(parseInt(definition.getCacheSize()));
+ Integer num = parseInt(definition.getCacheSize());
+ if (num != null) {
+ enricher.setCacheSize(num);
}
AggregationStrategy strategy = createAggregationStrategy();
if (strategy != null) {
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/IdempotentConsumerReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/IdempotentConsumerReifier.java
index 172bf3b..8e743b8 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/IdempotentConsumerReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/IdempotentConsumerReifier.java
@@ -58,9 +58,9 @@ public class IdempotentConsumerReifier extends ExpressionReifier<IdempotentConsu
* @return the repository
*/
protected <T> IdempotentRepository resolveMessageIdRepository() {
- if (definition.getMessageIdRepositoryRef() != null) {
- definition.setMessageIdRepository(
- mandatoryLookup(parseString(definition.getMessageIdRepositoryRef()), IdempotentRepository.class));
+ String ref = parseString(definition.getMessageIdRepositoryRef());
+ if (ref != null) {
+ definition.setMessageIdRepository(mandatoryLookup(ref, IdempotentRepository.class));
}
return definition.getMessageIdRepository();
}
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/InterceptSendToEndpointReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/InterceptSendToEndpointReifier.java
index 15897c8..0fe838d 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/InterceptSendToEndpointReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/InterceptSendToEndpointReifier.java
@@ -44,8 +44,9 @@ public class InterceptSendToEndpointReifier extends ProcessorReifier<InterceptSe
final Processor before = this.createChildProcessor(true);
// create the after
Processor afterProcessor = null;
- if (definition.getAfterUri() != null) {
- ToDefinition to = new ToDefinition(parseString(definition.getAfterUri()));
+ String afterUri = parseString(definition.getAfterUri());
+ if (afterUri != null) {
+ ToDefinition to = new ToDefinition(afterUri);
// at first use custom factory
afterProcessor = camelContext.adapt(ExtendedCamelContext.class).getProcessorFactory().createProcessor(route, to);
// fallback to default implementation if factory did not create the processor
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/MulticastReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/MulticastReifier.java
index 2f1445b..a7ff33d 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/MulticastReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/MulticastReifier.java
@@ -65,7 +65,7 @@ public class MulticastReifier extends ProcessorReifier<MulticastDefinition> {
boolean shutdownThreadPool = willCreateNewThreadPool(definition, isParallelProcessing);
ExecutorService threadPool = getConfiguredExecutorService("Multicast", definition, isParallelProcessing);
- long timeout = definition.getTimeout() != null ? parseDuration(definition.getTimeout()) : 0;
+ long timeout = parseDuration(definition.getTimeout(), 0);
if (timeout > 0 && !isParallelProcessing) {
throw new IllegalArgumentException("Timeout is used but ParallelProcessing has not been enabled.");
}
@@ -82,8 +82,9 @@ public class MulticastReifier extends ProcessorReifier<MulticastDefinition> {
private AggregationStrategy createAggregationStrategy() {
AggregationStrategy strategy = definition.getAggregationStrategy();
- if (strategy == null && definition.getStrategyRef() != null) {
- Object aggStrategy = lookup(parseString(definition.getStrategyRef()), Object.class);
+ String ref = parseString(definition.getStrategyRef());
+ if (strategy == null && ref != null) {
+ Object aggStrategy = lookup(ref, Object.class);
if (aggStrategy instanceof AggregationStrategy) {
strategy = (AggregationStrategy) aggStrategy;
} else if (aggStrategy != null) {
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/PollEnrichReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/PollEnrichReifier.java
index c4de005..06b18af 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/PollEnrichReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/PollEnrichReifier.java
@@ -39,7 +39,7 @@ public class PollEnrichReifier extends ProcessorReifier<PollEnrichDefinition> {
public Processor createProcessor() throws Exception {
// if no timeout then we should block, and there use a negative timeout
- long time = definition.getTimeout() != null ? parseDuration(definition.getTimeout()) : -1;
+ long time = parseDuration(definition.getTimeout(), -1);
boolean isIgnoreInvalidEndpoint = parseBoolean(definition.getIgnoreInvalidEndpoint(), false);
PollEnricher enricher;
@@ -62,8 +62,9 @@ public class PollEnrichReifier extends ProcessorReifier<PollEnrichDefinition> {
if (definition.getAggregateOnException() != null) {
enricher.setAggregateOnException(parseBoolean(definition.getAggregateOnException(), false));
}
- if (definition.getCacheSize() != null) {
- enricher.setCacheSize(parseInt(definition.getCacheSize()));
+ Integer num = parseInt(definition.getCacheSize());
+ if (num != null) {
+ enricher.setCacheSize(num);
}
enricher.setIgnoreInvalidEndpoint(isIgnoreInvalidEndpoint);
@@ -72,8 +73,9 @@ public class PollEnrichReifier extends ProcessorReifier<PollEnrichDefinition> {
private AggregationStrategy createAggregationStrategy() {
AggregationStrategy strategy = definition.getAggregationStrategy();
- if (strategy == null && definition.getAggregationStrategyRef() != null) {
- Object aggStrategy = lookup(parseString(definition.getAggregationStrategyRef()), Object.class);
+ String ref = parseString(definition.getAggregationStrategyRef());
+ if (strategy == null && ref != null) {
+ Object aggStrategy = lookup(ref, Object.class);
if (aggStrategy instanceof AggregationStrategy) {
strategy = (AggregationStrategy) aggStrategy;
} else if (aggStrategy != null) {
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ProcessorReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ProcessorReifier.java
index 5805116..0c95252 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ProcessorReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ProcessorReifier.java
@@ -362,12 +362,12 @@ public abstract class ProcessorReifier<T extends ProcessorDefinition<?>> extends
ObjectHelper.notNull(manager, "ExecutorServiceManager", camelContext);
// prefer to use explicit configured executor on the definition
+ String ref = parseString(definition.getExecutorServiceRef());
if (definition.getExecutorService() != null) {
return definition.getExecutorService();
- } else if (definition.getExecutorServiceRef() != null) {
+ } else if (ref != null) {
// lookup in registry first and use existing thread pool if exists
- ExecutorService answer
- = lookupExecutorServiceRef(name, definition, parseString(definition.getExecutorServiceRef()));
+ ExecutorService answer = lookupExecutorServiceRef(name, definition, ref);
if (answer == null) {
throw new IllegalArgumentException(
"ExecutorServiceRef " + definition.getExecutorServiceRef()
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/RecipientListReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/RecipientListReifier.java
index 3d44191..7d8c1a7 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/RecipientListReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/RecipientListReifier.java
@@ -52,8 +52,9 @@ public class RecipientListReifier extends ProcessorReifier<RecipientListDefiniti
boolean isStopOnAggregateException = parseBoolean(definition.getStopOnAggregateException(), false);
RecipientList answer;
- if (definition.getDelimiter() != null) {
- answer = new RecipientList(camelContext, expression, parseString(definition.getDelimiter()));
+ String delimiter = parseString(definition.getDelimiter());
+ if (delimiter != null) {
+ answer = new RecipientList(camelContext, expression, delimiter);
} else {
answer = new RecipientList(camelContext, expression);
}
@@ -65,8 +66,9 @@ public class RecipientListReifier extends ProcessorReifier<RecipientListDefiniti
answer.setStopOnException(isStopOnException);
answer.setIgnoreInvalidEndpoints(isIgnoreInvalidEndpoints);
answer.setStopOnAggregateException(isStopOnAggregateException);
- if (definition.getCacheSize() != null) {
- answer.setCacheSize(parseInt(definition.getCacheSize()));
+ Integer num = parseInt(definition.getCacheSize());
+ if (num != null) {
+ answer.setCacheSize(num);
}
if (definition.getOnPrepareRef() != null) {
definition.setOnPrepare(mandatoryLookup(definition.getOnPrepareRef(), Processor.class));
@@ -74,15 +76,16 @@ public class RecipientListReifier extends ProcessorReifier<RecipientListDefiniti
if (definition.getOnPrepare() != null) {
answer.setOnPrepare(definition.getOnPrepare());
}
- if (definition.getTimeout() != null) {
- answer.setTimeout(parseDuration(definition.getTimeout()));
+ Long dur = parseDuration(definition.getTimeout());
+ if (dur != null) {
+ answer.setTimeout(dur);
}
boolean shutdownThreadPool = willCreateNewThreadPool(definition, isParallelProcessing);
ExecutorService threadPool = getConfiguredExecutorService("RecipientList", definition, isParallelProcessing);
answer.setExecutorService(threadPool);
answer.setShutdownExecutorService(shutdownThreadPool);
- long timeout = definition.getTimeout() != null ? parseDuration(definition.getTimeout()) : 0;
+ long timeout = parseDuration(definition.getTimeout(), 0);
if (timeout > 0 && !isParallelProcessing) {
throw new IllegalArgumentException("Timeout is used but ParallelProcessing has not been enabled.");
}
@@ -110,8 +113,9 @@ public class RecipientListReifier extends ProcessorReifier<RecipientListDefiniti
private AggregationStrategy createAggregationStrategy() {
AggregationStrategy strategy = definition.getAggregationStrategy();
- if (strategy == null && definition.getStrategyRef() != null) {
- Object aggStrategy = lookup(parseString(definition.getStrategyRef()), Object.class);
+ String ref = parseString(definition.getStrategyRef());
+ if (strategy == null && ref != null) {
+ Object aggStrategy = lookup(ref, Object.class);
if (aggStrategy instanceof AggregationStrategy) {
strategy = (AggregationStrategy) aggStrategy;
} else if (aggStrategy != null) {
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ResequenceReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ResequenceReifier.java
index 86db86a..c7b8d06 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ResequenceReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ResequenceReifier.java
@@ -84,8 +84,14 @@ public class ResequenceReifier extends ProcessorReifier<ResequenceDefinition> {
boolean isAllowDuplicates = parseBoolean(config.getAllowDuplicates(), false);
Resequencer resequencer = new Resequencer(camelContext, target, expression, isAllowDuplicates, isReverse);
- resequencer.setBatchSize(parseInt(config.getBatchSize()));
- resequencer.setBatchTimeout(parseDuration(config.getBatchTimeout()));
+ Integer num = parseInt(config.getBatchSize());
+ if (num != null) {
+ resequencer.setBatchSize(num);
+ }
+ Long dur = parseDuration(config.getBatchTimeout());
+ if (dur != null) {
+ resequencer.setBatchTimeout(dur);
+ }
resequencer.setReverse(isReverse);
resequencer.setAllowDuplicates(isAllowDuplicates);
if (config.getIgnoreInvalidExchanges() != null) {
@@ -123,11 +129,18 @@ public class ResequenceReifier extends ProcessorReifier<ResequenceDefinition> {
comparator.setExpression(expression);
StreamResequencer resequencer = new StreamResequencer(camelContext, target, comparator, expression);
- resequencer.setTimeout(parseDuration(config.getTimeout()));
- if (config.getDeliveryAttemptInterval() != null) {
- resequencer.setDeliveryAttemptInterval(parseDuration(config.getDeliveryAttemptInterval()));
+ Long dur = parseDuration(config.getTimeout());
+ if (dur != null) {
+ resequencer.setTimeout(dur);
+ }
+ dur = parseDuration(config.getDeliveryAttemptInterval());
+ if (dur != null) {
+ resequencer.setDeliveryAttemptInterval(dur);
+ }
+ Integer num = parseInt(config.getCapacity());
+ if (num != null) {
+ resequencer.setCapacity(num);
}
- resequencer.setCapacity(parseInt(config.getCapacity()));
resequencer.setRejectOld(parseBoolean(config.getRejectOld(), false));
if (config.getIgnoreInvalidExchanges() != null) {
resequencer.setIgnoreInvalidExchanges(parseBoolean(config.getIgnoreInvalidExchanges(), false));
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/RoutingSlipReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/RoutingSlipReifier.java
index 6a871ba..0b54b7f 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/RoutingSlipReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/RoutingSlipReifier.java
@@ -44,8 +44,9 @@ public class RoutingSlipReifier extends ExpressionReifier<RoutingSlipDefinition<
if (definition.getIgnoreInvalidEndpoints() != null) {
routingSlip.setIgnoreInvalidEndpoints(parseBoolean(definition.getIgnoreInvalidEndpoints(), false));
}
- if (definition.getCacheSize() != null) {
- routingSlip.setCacheSize(parseInt(definition.getCacheSize()));
+ Integer num = parseInt(definition.getCacheSize());
+ if (num != null) {
+ routingSlip.setCacheSize(num);
}
// and wrap this in an error handler
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/SagaReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/SagaReifier.java
index a60152e..447adae 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/SagaReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/SagaReifier.java
@@ -93,8 +93,9 @@ public class SagaReifier extends ProcessorReifier<SagaDefinition> {
return sagaService;
}
- if (definition.getSagaServiceRef() != null) {
- return mandatoryLookup(parseString(definition.getSagaServiceRef()), CamelSagaService.class);
+ String ref = parseString(definition.getSagaServiceRef());
+ if (ref != null) {
+ return mandatoryLookup(ref, CamelSagaService.class);
}
sagaService = camelContext.hasService(CamelSagaService.class);
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/SamplingReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/SamplingReifier.java
index 547719c..a07273b 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/SamplingReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/SamplingReifier.java
@@ -32,11 +32,12 @@ public class SamplingReifier extends ProcessorReifier<SamplingDefinition> {
@Override
public Processor createProcessor() throws Exception {
- if (definition.getMessageFrequency() != null) {
- return new SamplingThrottler(parseLong(definition.getMessageFrequency()));
+ Long freq = parseLong(definition.getMessageFrequency());
+ if (freq != null) {
+ return new SamplingThrottler(freq);
} else {
// should default be 1 sample period
- long time = definition.getSamplePeriod() != null ? parseDuration(definition.getSamplePeriod()) : 1L;
+ long time = parseDuration(definition.getSamplePeriod(), 1);
// should default be in seconds
TimeUnit tu = definition.getUnits() != null ? parse(TimeUnit.class, definition.getUnits()) : TimeUnit.SECONDS;
return new SamplingThrottler(time, tu);
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/SortReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/SortReifier.java
index 6de9bca..2a2c123 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/SortReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/SortReifier.java
@@ -38,8 +38,9 @@ public class SortReifier<T, U extends SortDefinition<T>> extends ExpressionReifi
@SuppressWarnings("unchecked")
public Processor createProcessor() throws Exception {
// lookup in registry
- if (isNotEmpty(definition.getComparatorRef())) {
- definition.setComparator(lookup(parseString(definition.getComparatorRef()), Comparator.class));
+ String ref = parseString(definition.getComparatorRef());
+ if (isNotEmpty(ref)) {
+ definition.setComparator(lookup(ref, Comparator.class));
}
// if no comparator then default on to string representation
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/SplitReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/SplitReifier.java
index 03dd7c6..b290c3d 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/SplitReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/SplitReifier.java
@@ -49,23 +49,24 @@ public class SplitReifier extends ExpressionReifier<SplitDefinition> {
boolean shutdownThreadPool = willCreateNewThreadPool(definition, isParallelProcessing);
ExecutorService threadPool = getConfiguredExecutorService("Split", definition, isParallelProcessing);
- long timeout = definition.getTimeout() != null ? parseDuration(definition.getTimeout()) : 0;
+ long timeout = parseDuration(definition.getTimeout(), 0);
if (timeout > 0 && !isParallelProcessing) {
throw new IllegalArgumentException("Timeout is used but ParallelProcessing has not been enabled.");
}
- if (definition.getOnPrepareRef() != null) {
- definition.setOnPrepare(mandatoryLookup(parseString(definition.getOnPrepareRef()), Processor.class));
+ String ref = parseString(definition.getOnPrepareRef());
+ if (ref != null) {
+ definition.setOnPrepare(mandatoryLookup(ref, Processor.class));
}
Expression exp = createExpression(definition.getExpression());
+ String delimiter = parseString(definition.getDelimiter());
Splitter answer;
- if (definition.getDelimiter() != null) {
+ if (delimiter != null) {
answer = new Splitter(
camelContext, route, exp, childProcessor, definition.getAggregationStrategy(), isParallelProcessing,
threadPool, shutdownThreadPool, isStreaming, isStopOnException, timeout, definition.getOnPrepare(),
- isShareUnitOfWork, isParallelAggregate, isStopOnAggregateException,
- parseString(definition.getDelimiter()));
+ isShareUnitOfWork, isParallelAggregate, isStopOnAggregateException, delimiter);
} else {
answer = new Splitter(
camelContext, route, exp, childProcessor, definition.getAggregationStrategy(), isParallelProcessing,
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ThreadsReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ThreadsReifier.java
index 08f57d8..0474177 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ThreadsReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ThreadsReifier.java
@@ -37,7 +37,10 @@ public class ThreadsReifier extends ProcessorReifier<ThreadsDefinition> {
@Override
public Processor createProcessor() throws Exception {
// the threads name
- String name = definition.getThreadName() != null ? parseString(definition.getThreadName()) : "Threads";
+ String name = parseString(definition.getThreadName());
+ if (name == null || name.isEmpty()) {
+ name = "Threads";
+ }
// prefer any explicit configured executor service
boolean shutdownThreadPool = willCreateNewThreadPool(definition, true);
ExecutorService threadPool = getConfiguredExecutorService(name, definition, false);
@@ -101,9 +104,10 @@ public class ThreadsReifier extends ProcessorReifier<ThreadsDefinition> {
}
protected ThreadPoolRejectedPolicy resolveRejectedPolicy() {
- if (definition.getExecutorServiceRef() != null && definition.getRejectedPolicy() == null) {
+ String ref = parseString(definition.getExecutorServiceRef());
+ if (ref != null && definition.getRejectedPolicy() == null) {
ThreadPoolProfile threadPoolProfile = camelContext.getExecutorServiceManager()
- .getThreadPoolProfile(parseString(definition.getExecutorServiceRef()));
+ .getThreadPoolProfile(ref);
if (threadPoolProfile != null) {
return threadPoolProfile.getRejectedPolicy();
}
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ThrottleReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ThrottleReifier.java
index e1168e4..20dc0be 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ThrottleReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ThrottleReifier.java
@@ -38,7 +38,7 @@ public class ThrottleReifier extends ExpressionReifier<ThrottleDefinition> {
ScheduledExecutorService threadPool = getConfiguredScheduledExecutorService("Throttle", definition, true);
// should be default 1000 millis
- long period = definition.getTimePeriodMillis() != null ? parseDuration(definition.getTimePeriodMillis()) : 1000L;
+ long period = parseDuration(definition.getTimePeriodMillis(), 1000L);
// max requests per period is mandatory
Expression maxRequestsExpression = createMaxRequestsPerPeriodExpression();
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ThrowExceptionReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ThrowExceptionReifier.java
index f7959da..51e0924 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ThrowExceptionReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ThrowExceptionReifier.java
@@ -31,8 +31,9 @@ public class ThrowExceptionReifier extends ProcessorReifier<ThrowExceptionDefini
@Override
public Processor createProcessor() {
Exception exception = definition.getException();
- if (exception == null && definition.getRef() != null) {
- exception = lookup(parseString(definition.getRef()), Exception.class);
+ String ref = parseString(definition.getRef());
+ if (exception == null && ref != null) {
+ exception = lookup(ref, Exception.class);
}
Class<? extends Exception> exceptionClass = definition.getExceptionClass();
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ToDynamicReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ToDynamicReifier.java
index d68fb6f..fc4ad92 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ToDynamicReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ToDynamicReifier.java
@@ -24,6 +24,7 @@ import org.apache.camel.model.ProcessorDefinition;
import org.apache.camel.model.ToDynamicDefinition;
import org.apache.camel.processor.SendDynamicProcessor;
import org.apache.camel.spi.Language;
+import org.apache.camel.support.EndpointHelper;
import org.apache.camel.util.StringHelper;
public class ToDynamicReifier<T extends ToDynamicDefinition> extends ProcessorReifier<T> {
@@ -47,8 +48,9 @@ public class ToDynamicReifier<T extends ToDynamicDefinition> extends ProcessorRe
SendDynamicProcessor processor = new SendDynamicProcessor(uri, exp);
processor.setCamelContext(camelContext);
processor.setPattern(parse(ExchangePattern.class, definition.getPattern()));
- if (definition.getCacheSize() != null) {
- processor.setCacheSize(parseInt(definition.getCacheSize()));
+ Integer num = parseInt(definition.getCacheSize());
+ if (num != null) {
+ processor.setCacheSize(num);
}
if (definition.getIgnoreInvalidEndpoint() != null) {
processor.setIgnoreInvalidEndpoint(parseBoolean(definition.getIgnoreInvalidEndpoint(), false));
@@ -64,7 +66,7 @@ public class ToDynamicReifier<T extends ToDynamicDefinition> extends ProcessorRe
protected Expression createExpression(String uri) {
// make sure to parse property placeholders
- uri = camelContext.resolvePropertyPlaceholders(uri);
+ uri = EndpointHelper.resolveEndpointUriPropertyPlaceholders(camelContext, uri);
// we use simple language by default but you can configure a different language
String language = "simple";
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/WireTapReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/WireTapReifier.java
index d8f1dfd..79c1d55 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/WireTapReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/WireTapReifier.java
@@ -65,8 +65,9 @@ public class WireTapReifier extends ToDynamicReifier<WireTapDefinition<?>> {
parseBoolean(definition.getDynamicUri(), true));
answer.setCopy(isCopy);
Processor newExchangeProcessor = definition.getNewExchangeProcessor();
- if (definition.getNewExchangeProcessorRef() != null) {
- newExchangeProcessor = mandatoryLookup(parseString(definition.getNewExchangeProcessorRef()), Processor.class);
+ String ref = parseString(definition.getNewExchangeProcessorRef());
+ if (ref != null) {
+ newExchangeProcessor = mandatoryLookup(ref, Processor.class);
}
if (newExchangeProcessor != null) {
answer.addNewExchangeProcessor(newExchangeProcessor);
@@ -81,8 +82,9 @@ public class WireTapReifier extends ToDynamicReifier<WireTapDefinition<?>> {
}
}
Processor onPrepare = definition.getOnPrepare();
- if (definition.getOnPrepareRef() != null) {
- onPrepare = mandatoryLookup(parseString(definition.getOnPrepareRef()), Processor.class);
+ ref = parseString(definition.getOnPrepareRef());
+ if (ref != null) {
+ onPrepare = mandatoryLookup(ref, Processor.class);
}
if (onPrepare != null) {
answer.setOnPrepare(onPrepare);
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/dataformat/YAMLDataFormatReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/dataformat/YAMLDataFormatReifier.java
index c455990..849bb18 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/dataformat/YAMLDataFormatReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/dataformat/YAMLDataFormatReifier.java
@@ -64,15 +64,16 @@ public class YAMLDataFormatReifier extends DataFormatReifier<YAMLDataFormat> {
List<String> typeFilterDefinitions = new ArrayList<>(definition.getTypeFilters().size());
for (YAMLTypeFilterDefinition definition : definition.getTypeFilters()) {
String value = parseString(definition.getValue());
- if (!value.startsWith("type") && !value.startsWith("regexp")) {
+ if (value != null && !value.startsWith("type") && !value.startsWith("regexp")) {
YAMLTypeFilterType type = parse(YAMLTypeFilterType.class, definition.getType());
if (type == null) {
type = YAMLTypeFilterType.type;
}
-
value = type.name() + ":" + value;
}
- typeFilterDefinitions.add(value);
+ if (value != null) {
+ typeFilterDefinitions.add(value);
+ }
}
return typeFilterDefinitions;
} else {
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/loadbalancer/FailoverLoadBalancerReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/loadbalancer/FailoverLoadBalancerReifier.java
index bf4aafa..037c668 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/loadbalancer/FailoverLoadBalancerReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/loadbalancer/FailoverLoadBalancerReifier.java
@@ -57,8 +57,9 @@ public class FailoverLoadBalancerReifier extends LoadBalancerReifier<FailoverLoa
answer = new FailOverLoadBalancer(classes);
}
- if (definition.getMaximumFailoverAttempts() != null) {
- answer.setMaximumFailoverAttempts(parseInt(definition.getMaximumFailoverAttempts()));
+ Integer num = parseInt(definition.getMaximumFailoverAttempts());
+ if (num != null) {
+ answer.setMaximumFailoverAttempts(num);
}
if (definition.getRoundRobin() != null) {
answer.setRoundRobin(parseBoolean(definition.getRoundRobin(), false));
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/transformer/CustomTransformeReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/transformer/CustomTransformeReifier.java
index cf1e2ff..ae3531d 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/transformer/CustomTransformeReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/transformer/CustomTransformeReifier.java
@@ -33,8 +33,9 @@ public class CustomTransformeReifier extends TransformerReifier<CustomTransforme
throw new IllegalArgumentException("'ref' or 'className' must be specified for customTransformer");
}
Transformer transformer;
- if (definition.getRef() != null) {
- transformer = lookup(parseString(definition.getRef()), Transformer.class);
+ String ref = parseString(definition.getRef());
+ if (ref != null) {
+ transformer = lookup(ref, Transformer.class);
if (transformer == null) {
throw new IllegalArgumentException("Cannot find transformer with ref:" + definition.getRef());
}
diff --git a/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelEndpointFactoryBean.java b/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelEndpointFactoryBean.java
index 407d56e..32f2086 100644
--- a/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelEndpointFactoryBean.java
+++ b/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelEndpointFactoryBean.java
@@ -31,6 +31,7 @@ import org.apache.camel.Endpoint;
import org.apache.camel.NoSuchEndpointException;
import org.apache.camel.model.PropertyDefinition;
import org.apache.camel.spi.Metadata;
+import org.apache.camel.support.EndpointHelper;
import org.apache.camel.util.URISupport;
@XmlAccessorType(XmlAccessType.FIELD)
@@ -48,7 +49,7 @@ public abstract class AbstractCamelEndpointFactoryBean extends AbstractCamelFact
public Endpoint getObject() throws Exception {
if (endpoint == null || !endpoint.isSingleton()) {
// resolve placeholders (but leave the original uri unchanged)
- String resolved = getCamelContext().resolvePropertyPlaceholders(uri);
+ String resolved = EndpointHelper.resolveEndpointUriPropertyPlaceholders(getCamelContext(), uri);
String target = createUri(resolved);
this.endpoint = getCamelContext().getEndpoint(target);
if (endpoint == null) {
diff --git a/core/camel-core/src/test/java/org/apache/camel/component/properties/OptionalPropertyPlaceholderEipTest.java b/core/camel-core/src/test/java/org/apache/camel/component/properties/OptionalPropertyPlaceholderEipTest.java
new file mode 100644
index 0000000..24ad76a
--- /dev/null
+++ b/core/camel-core/src/test/java/org/apache/camel/component/properties/OptionalPropertyPlaceholderEipTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.properties;
+
+import java.util.Properties;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.jupiter.api.Test;
+
+public class OptionalPropertyPlaceholderEipTest extends ContextTestSupport {
+
+ @Override
+ public boolean isUseRouteBuilder() {
+ return false;
+ }
+
+ @Test
+ public void testQueryOptionalNotPresent() throws Exception {
+ context.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start")
+ .split(body()).delimiter("{{?myDelim}}")
+ .to("mock:line");
+ }
+ });
+ context.start();
+
+ getMockEndpoint("mock:line").expectedMessageCount(2);
+ template.sendBody("direct:start", "A,B");
+ assertMockEndpointsSatisfied();
+ }
+
+ @Test
+ public void testQueryOptionalPresent() throws Exception {
+ Properties prop = new Properties();
+ prop.put("myDelim", ";");
+ context.getPropertiesComponent().setInitialProperties(prop);
+
+ context.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start")
+ .split(body()).delimiter("{{?myDelim}}")
+ .to("mock:line");
+ }
+ });
+ context.start();
+
+ getMockEndpoint("mock:line").expectedMessageCount(1);
+ template.sendBody("direct:start", "A,B");
+ assertMockEndpointsSatisfied();
+
+ resetMocks();
+
+ getMockEndpoint("mock:line").expectedMessageCount(3);
+ template.sendBody("direct:start", "A;B;C");
+ assertMockEndpointsSatisfied();
+ }
+
+ @Override
+ protected CamelContext createCamelContext() throws Exception {
+ CamelContext context = super.createCamelContext();
+ context.getPropertiesComponent().setLocation("classpath:org/apache/camel/component/properties/myproperties.properties");
+ return context;
+ }
+
+}
diff --git a/core/camel-core/src/test/java/org/apache/camel/component/properties/OptionalPropertyPlaceholderTest.java b/core/camel-core/src/test/java/org/apache/camel/component/properties/OptionalPropertyPlaceholderTest.java
new file mode 100644
index 0000000..63edb17
--- /dev/null
+++ b/core/camel-core/src/test/java/org/apache/camel/component/properties/OptionalPropertyPlaceholderTest.java
@@ -0,0 +1,228 @@
+/*
+ * 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.properties;
+
+import java.util.Properties;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class OptionalPropertyPlaceholderTest extends ContextTestSupport {
+
+ // TODO: eip test
+ // TODO: reuse code in AbstractCamelContext and endpoint-dsl
+
+ @Override
+ public boolean isUseRouteBuilder() {
+ return false;
+ }
+
+ @Test
+ public void testQueryOptionalNotPresent() throws Exception {
+ context.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start")
+ .to("mock:result?retainFirst={{?maxKeep}}");
+ }
+ });
+ context.start();
+
+ getMockEndpoint("mock:result").expectedMessageCount(2);
+
+ template.sendBody("direct:start", "Hello World");
+ template.sendBody("direct:start", "Bye World");
+
+ assertMockEndpointsSatisfied();
+
+ assertEquals(2, getMockEndpoint("mock:result").getReceivedExchanges().size());
+ }
+
+ @Test
+ public void testQueryOptionalPresent() throws Exception {
+ Properties prop = new Properties();
+ prop.put("maxKeep", "1");
+ context.getPropertiesComponent().setInitialProperties(prop);
+
+ context.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start")
+ .to("mock:result?retainFirst={{?maxKeep}}");
+ }
+ });
+ context.start();
+
+ getMockEndpoint("mock:result?retainFirst=1").expectedMessageCount(2);
+
+ template.sendBody("direct:start", "Hello World");
+ template.sendBody("direct:start", "Bye World");
+
+ assertMockEndpointsSatisfied();
+
+ assertEquals(1, getMockEndpoint("mock:result?retainFirst=1").getReceivedExchanges().size());
+ }
+
+ @Test
+ public void testPathOptionalNotPresent() throws Exception {
+ context.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start")
+ .to("mock:res{{?unknown}}ult");
+ }
+ });
+ context.start();
+
+ getMockEndpoint("mock:result").expectedMessageCount(2);
+
+ template.sendBody("direct:start", "Hello World");
+ template.sendBody("direct:start", "Bye World");
+
+ assertMockEndpointsSatisfied();
+ }
+
+ @Test
+ public void testPathOptionalPresent() throws Exception {
+ Properties prop = new Properties();
+ prop.put("whereTo", "result");
+ context.getPropertiesComponent().setInitialProperties(prop);
+
+ context.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start")
+ .to("mock:{{?whereTo}}");
+ }
+ });
+ context.start();
+
+ getMockEndpoint("mock:result").expectedMessageCount(2);
+
+ template.sendBody("direct:start", "Hello World");
+ template.sendBody("direct:start", "Bye World");
+
+ assertMockEndpointsSatisfied();
+ }
+
+ @Test
+ public void testQueryAndPathOptionalNotPresent() throws Exception {
+ context.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start")
+ .to("mock:res{{?unknown}}ult?retainFirst={{?maxKeep}}");
+ }
+ });
+ context.start();
+
+ getMockEndpoint("mock:result").expectedMessageCount(2);
+
+ template.sendBody("direct:start", "Hello World");
+ template.sendBody("direct:start", "Bye World");
+
+ assertMockEndpointsSatisfied();
+
+ assertEquals(2, getMockEndpoint("mock:result").getReceivedExchanges().size());
+ }
+
+ @Test
+ public void testQueryAndPathOptionalPresent() throws Exception {
+ Properties prop = new Properties();
+ prop.put("maxKeep", "1");
+ prop.put("whereTo", "result");
+ context.getPropertiesComponent().setInitialProperties(prop);
+
+ context.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start")
+ .to("mock:{{?whereTo}}?retainFirst={{?maxKeep}}");
+ }
+ });
+ context.start();
+
+ getMockEndpoint("mock:result?retainFirst=1").expectedMessageCount(2);
+
+ template.sendBody("direct:start", "Hello World");
+ template.sendBody("direct:start", "Bye World");
+
+ assertMockEndpointsSatisfied();
+
+ assertEquals(1, getMockEndpoint("mock:result?retainFirst=1").getReceivedExchanges().size());
+ }
+
+ @Test
+ public void testQueryAndPathOptionalMixed() throws Exception {
+ Properties prop = new Properties();
+ prop.put("maxKeep", "1");
+ context.getPropertiesComponent().setInitialProperties(prop);
+
+ context.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start")
+ .to("mock:res{{?unknown}}ult?retainFirst={{?maxKeep}}");
+ }
+ });
+ context.start();
+
+ getMockEndpoint("mock:result?retainFirst=1").expectedMessageCount(2);
+
+ template.sendBody("direct:start", "Hello World");
+ template.sendBody("direct:start", "Bye World");
+
+ assertMockEndpointsSatisfied();
+
+ assertEquals(1, getMockEndpoint("mock:result?retainFirst=1").getReceivedExchanges().size());
+ }
+
+ @Test
+ public void testQueryAndPathOptionalMixedTwo() throws Exception {
+ Properties prop = new Properties();
+ prop.put("whereTo", "result");
+ context.getPropertiesComponent().setInitialProperties(prop);
+
+ context.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start")
+ .to("mock:{{?whereTo}}?retainFirst={{?maxKeep}}");
+ }
+ });
+ context.start();
+
+ getMockEndpoint("mock:result").expectedMessageCount(2);
+
+ template.sendBody("direct:start", "Hello World");
+ template.sendBody("direct:start", "Bye World");
+
+ assertMockEndpointsSatisfied();
+ }
+
+ @Override
+ protected CamelContext createCamelContext() throws Exception {
+ CamelContext context = super.createCamelContext();
+ context.getPropertiesComponent().setLocation("classpath:org/apache/camel/component/properties/myproperties.properties");
+ return context;
+ }
+
+}
diff --git a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/AbstractEndpointBuilder.java b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/AbstractEndpointBuilder.java
index b6f24aa..a279a09 100644
--- a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/AbstractEndpointBuilder.java
+++ b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/AbstractEndpointBuilder.java
@@ -18,8 +18,10 @@ package org.apache.camel.builder.endpoint;
import java.net.URISyntaxException;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.Set;
import java.util.TreeMap;
import org.apache.camel.CamelContext;
@@ -30,6 +32,8 @@ import org.apache.camel.NoSuchEndpointException;
import org.apache.camel.RuntimeCamelException;
import org.apache.camel.builder.SimpleBuilder;
import org.apache.camel.spi.NormalizedEndpointUri;
+import org.apache.camel.spi.PropertiesComponent;
+import org.apache.camel.support.EndpointHelper;
import org.apache.camel.support.NormalizedUri;
import org.apache.camel.util.URISupport;
@@ -68,16 +72,25 @@ public class AbstractEndpointBuilder {
}
private static void resolvePropertyPlaceholders(CamelContext context, Map<String, Object> properties) {
+ Set<String> toRemove = new HashSet<>();
for (Map.Entry<String, Object> entry : properties.entrySet()) {
Object value = entry.getValue();
if (value instanceof String) {
String text = (String) value;
- String changed = context.resolvePropertyPlaceholders(text);
- if (!changed.equals(text)) {
+ String changed = context.adapt(ExtendedCamelContext.class).resolvePropertyPlaceholders(text, true);
+ if (changed.startsWith(PropertiesComponent.PREFIX_OPTIONAL_TOKEN)) {
+ // unresolved then remove it
+ toRemove.add(entry.getKey());
+ } else if (!changed.equals(text)) {
entry.setValue(changed);
}
}
}
+ if (!toRemove.isEmpty()) {
+ for (String key : toRemove) {
+ properties.remove(key);
+ }
+ }
}
public <T extends Endpoint> T resolve(CamelContext context, Class<T> endpointType) throws NoSuchEndpointException {
@@ -109,7 +122,7 @@ public class AbstractEndpointBuilder {
String targetPath = path;
if (camelContext != null) {
targetScheme = camelContext.resolvePropertyPlaceholders(targetScheme);
- targetPath = camelContext.resolvePropertyPlaceholders(targetPath);
+ targetPath = EndpointHelper.resolveEndpointUriPropertyPlaceholders(camelContext, targetPath);
}
if (params.isEmpty()) {
diff --git a/core/camel-endpointdsl/src/test/java/org/apache/camel/builder/endpoint/OptionalPropertyPlaceholderTest.java b/core/camel-endpointdsl/src/test/java/org/apache/camel/builder/endpoint/OptionalPropertyPlaceholderTest.java
new file mode 100644
index 0000000..08de571
--- /dev/null
+++ b/core/camel-endpointdsl/src/test/java/org/apache/camel/builder/endpoint/OptionalPropertyPlaceholderTest.java
@@ -0,0 +1,121 @@
+/*
+ * 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.builder.endpoint;
+
+import java.util.Properties;
+
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class OptionalPropertyPlaceholderTest extends CamelTestSupport {
+
+ @Override
+ public boolean isUseRouteBuilder() {
+ return false;
+ }
+
+ @Test
+ public void testQueryOptionalNotPresent() throws Exception {
+ context.addRoutes(new EndpointRouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from(direct("start")).to(mock("result").retainFirst("{{?maxKeep}}").failFast(false));
+ }
+ });
+ context.start();
+
+ getMockEndpoint("mock:result").expectedMessageCount(2);
+
+ template.sendBody("direct:start", "Hello World");
+ template.sendBody("direct:start", "Bye World");
+
+ assertMockEndpointsSatisfied();
+
+ assertEquals(2, getMockEndpoint("mock:result").getReceivedExchanges().size());
+ }
+
+ @Test
+ public void testQueryOptionalPresent() throws Exception {
+ Properties prop = new Properties();
+ prop.put("maxKeep", "1");
+ context.getPropertiesComponent().setInitialProperties(prop);
+
+ context.addRoutes(new EndpointRouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from(direct("start")).to(mock("result").retainFirst("{{?maxKeep}}").failFast(false));
+ }
+ });
+ context.start();
+
+ getMockEndpoint("mock:result?retainFirst=1").expectedMessageCount(2);
+
+ template.sendBody("direct:start", "Hello World");
+ template.sendBody("direct:start", "Bye World");
+
+ assertMockEndpointsSatisfied();
+
+ assertEquals(1, getMockEndpoint("mock:result?retainFirst=1").getReceivedExchanges().size());
+ }
+
+ @Test
+ public void testPathOptionalNotPresent() throws Exception {
+ context.addRoutes(new EndpointRouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from(direct("start")).to(mock("res{{?whereTo}}ult").failFast(false));
+ }
+ });
+ context.start();
+
+ getMockEndpoint("mock:result").expectedMessageCount(2);
+
+ template.sendBody("direct:start", "Hello World");
+ template.sendBody("direct:start", "Bye World");
+
+ assertMockEndpointsSatisfied();
+
+ assertEquals(2, getMockEndpoint("mock:result").getReceivedExchanges().size());
+ }
+
+ @Test
+ public void testPathOptionalPresent() throws Exception {
+ Properties prop = new Properties();
+ prop.put("whereTo", "result");
+ context.getPropertiesComponent().setInitialProperties(prop);
+
+ context.addRoutes(new EndpointRouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from(direct("start")).to(mock("{{?whereTo}}").failFast(false));
+ }
+ });
+ context.start();
+
+ getMockEndpoint("mock:result").expectedMessageCount(2);
+
+ template.sendBody("direct:start", "Hello World");
+ template.sendBody("direct:start", "Bye World");
+
+ assertMockEndpointsSatisfied();
+
+ assertEquals(2, getMockEndpoint("mock:result").getReceivedExchanges().size());
+ }
+
+}
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/EndpointHelper.java b/core/camel-support/src/main/java/org/apache/camel/support/EndpointHelper.java
index 97fdf66..285ca71 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/EndpointHelper.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/EndpointHelper.java
@@ -20,6 +20,7 @@ import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -36,6 +37,7 @@ import org.apache.camel.PollingConsumer;
import org.apache.camel.Processor;
import org.apache.camel.ResolveEndpointFailedException;
import org.apache.camel.Route;
+import org.apache.camel.spi.PropertiesComponent;
import org.apache.camel.support.service.ServiceHelper;
import org.apache.camel.util.StringHelper;
import org.apache.camel.util.URISupport;
@@ -57,6 +59,90 @@ public final class EndpointHelper {
}
/**
+ * Resolves the endpoint uri that may have property placeholders (supports optional property placeholders).
+ *
+ * @param camelContext the camel context
+ * @param uri the endpoint uri
+ * @return returns endpoint uri with property placeholders resolved
+ */
+ public static String resolveEndpointUriPropertyPlaceholders(CamelContext camelContext, String uri) {
+ // the uri may have optional property placeholders which is not possible to resolve
+ // so we keep the unresolved in the uri, which we then afterwards will remove
+ // which is a little complex depending on the placeholder is from context-path or query parameters
+ // in the uri string
+ try {
+ uri = camelContext.adapt(ExtendedCamelContext.class).resolvePropertyPlaceholders(uri, true);
+ if (uri == null || uri.isEmpty()) {
+ return uri;
+ }
+ String prefix = PropertiesComponent.PREFIX_OPTIONAL_TOKEN;
+ if (uri.contains(prefix)) {
+ String unresolved = uri;
+ uri = doResolveEndpointUriOptionalPropertyPlaceholders(unresolved);
+ LOG.trace("Unresolved optional placeholders removed from uri: {} -> {}", unresolved, uri);
+ }
+ LOG.trace("Resolved property placeholders with uri: {}", uri);
+ } catch (Exception e) {
+ throw new ResolveEndpointFailedException(uri, e);
+ }
+ return uri;
+ }
+
+ private static String doResolveEndpointUriOptionalPropertyPlaceholders(String uri) throws URISyntaxException {
+ String prefix = PropertiesComponent.PREFIX_OPTIONAL_TOKEN;
+
+ // find query position which is the first question mark that is not part of the optional token prefix
+ int pos = 0;
+ for (int i = 0; i < uri.length(); i++) {
+ char ch = uri.charAt(i);
+ if (ch == '?') {
+ // ensure that its not part of property prefix
+ if (i > 2) {
+ char ch1 = uri.charAt(i - 1);
+ char ch2 = uri.charAt(i - 2);
+ if (ch1 != '{' && ch2 != '{') {
+ pos = i;
+ break;
+ }
+ } else {
+ pos = i;
+ break;
+ }
+ }
+ }
+ String base = pos > 0 ? uri.substring(0, pos) : uri;
+ String query = pos > 0 ? uri.substring(pos + 1) : null;
+
+ // the base (context path) should remove all unresolved property placeholders
+ // which is done by replacing all begin...end tokens with an empty string
+ String pattern = "\\{\\{?.*}}";
+ base = base.replaceAll(pattern, "");
+
+ // the query parameters needs to be rebuild by removing the unresolved key=value pairs
+ if (query != null && query.contains(prefix)) {
+ Map<String, Object> params = URISupport.parseQuery(query);
+ Map<String, Object> keep = new LinkedHashMap<>();
+ for (Map.Entry<String, Object> entry : params.entrySet()) {
+ String key = entry.getKey();
+ if (key.startsWith(prefix)) {
+ continue;
+ }
+ Object value = entry.getValue();
+ if (value instanceof String && ((String) value).startsWith(prefix)) {
+ continue;
+ }
+ keep.put(key, value);
+ }
+ // rebuild query
+ query = URISupport.createQueryString(keep);
+ }
+
+ // assemble uri as answer
+ uri = query != null && !query.isEmpty() ? base + "?" + query : base;
+ return uri;
+ }
+
+ /**
* Normalize uri so we can do endpoint hits with minor mistakes and parameters is not in the same order.
*
* @param uri the uri
@@ -112,7 +198,7 @@ public final class EndpointHelper {
* Matches the endpoint with the given pattern.
* <p/>
* The endpoint will first resolve property placeholders using
- * {@link CamelContext#resolvePropertyPlaceholders(String)}.
+ * {@link #resolveEndpointUriPropertyPlaceholders(CamelContext, String)}
* <p/>
* The match rules are applied in this order:
* <ul>
@@ -131,7 +217,7 @@ public final class EndpointHelper {
public static boolean matchEndpoint(CamelContext context, String uri, String pattern) {
if (context != null) {
try {
- uri = context.resolvePropertyPlaceholders(uri);
+ uri = resolveEndpointUriPropertyPlaceholders(context, uri);
} catch (Exception e) {
throw new ResolveEndpointFailedException(uri, e);
}
@@ -163,7 +249,7 @@ public final class EndpointHelper {
/**
* Toggles // separators in the given uri. If the uri does not contain ://, the slashes are added, otherwise they
* are removed.
- *
+ *
* @param normalizedUri The uri to add/remove separators in
* @return The uri with separators added or removed
*/
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/component/EndpointUriFactorySupport.java b/core/camel-support/src/main/java/org/apache/camel/support/component/EndpointUriFactorySupport.java
index 47b8d57..26a78df 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/component/EndpointUriFactorySupport.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/component/EndpointUriFactorySupport.java
@@ -56,9 +56,9 @@ public abstract class EndpointUriFactorySupport implements CamelContextAware, En
}
if (ObjectHelper.isNotEmpty(obj)) {
String str = camelContext.getTypeConverter().convertTo(String.class, obj);
- int occurence = StringHelper.countOccurence(uri, name);
- if (occurence > 1) {
- uri = StringHelper.replaceFromSecondOccurence(uri, name, str);
+ int occurrence = StringHelper.countOccurrence(uri, name);
+ if (occurrence > 1) {
+ uri = StringHelper.replaceFromSecondOccurrence(uri, name, str);
} else {
uri = uri.replace(name, str);
}
@@ -110,37 +110,4 @@ public abstract class EndpointUriFactorySupport implements CamelContextAware, En
return uri;
}
- private int countOccurence(String str, String findStr) {
- int lastIndex = 0;
- int count = 0;
-
- while (lastIndex != -1) {
-
- lastIndex = str.indexOf(findStr, lastIndex);
-
- if (lastIndex != -1) {
- count++;
- lastIndex += findStr.length();
- }
- }
- return count;
- }
-
- private String replaceFromSecondOccurence(String str, String name, String repl) {
- int index = str.indexOf(name);
- boolean replace = false;
-
- while (index != -1) {
- String tempString = str.substring(index);
- if (replace) {
- tempString = tempString.replaceFirst(name, repl);
- str = str.substring(0, index) + tempString;
- replace = false;
- } else {
- replace = true;
- }
- index = str.indexOf(name, index + 1);
- }
- return str;
- }
}
diff --git a/core/camel-util/src/main/java/org/apache/camel/util/StringHelper.java b/core/camel-util/src/main/java/org/apache/camel/util/StringHelper.java
index 684790c..ddde325 100644
--- a/core/camel-util/src/main/java/org/apache/camel/util/StringHelper.java
+++ b/core/camel-util/src/main/java/org/apache/camel/util/StringHelper.java
@@ -1034,13 +1034,13 @@ public final class StringHelper {
}
/**
- * Returns the occurence of a search string in to a string
+ * Returns the occurrence of a search string in to a string.
*
* @param text the text
* @param search the string to search
- * @return an integer reporting the number of occurence of the searched string in to the text
+ * @return an integer reporting the number of occurrence of the searched string in to the text
*/
- public static int countOccurence(String text, String search) {
+ public static int countOccurrence(String text, String search) {
int lastIndex = 0;
int count = 0;
while (lastIndex != -1) {
@@ -1054,21 +1054,21 @@ public final class StringHelper {
}
/**
- * Replaces a string in to a text starting from his second occurence
+ * Replaces a string in to a text starting from his second occurrence.
*
- * @param text the text
- * @param search the string to search
- * @param repl the replacement for the string
- * @return the string with the replacement
+ * @param text the text
+ * @param search the string to search
+ * @param replacement the replacement for the string
+ * @return the string with the replacement
*/
- public static String replaceFromSecondOccurence(String text, String search, String repl) {
+ public static String replaceFromSecondOccurrence(String text, String search, String replacement) {
int index = text.indexOf(search);
boolean replace = false;
while (index != -1) {
String tempString = text.substring(index);
if (replace) {
- tempString = tempString.replaceFirst(search, repl);
+ tempString = tempString.replaceFirst(search, replacement);
text = text.substring(0, index) + tempString;
replace = false;
} else {
diff --git a/core/camel-util/src/main/java/org/apache/camel/util/URISupport.java b/core/camel-util/src/main/java/org/apache/camel/util/URISupport.java
index 6d77017..3839a86 100644
--- a/core/camel-util/src/main/java/org/apache/camel/util/URISupport.java
+++ b/core/camel-util/src/main/java/org/apache/camel/util/URISupport.java
@@ -134,6 +134,20 @@ public final class URISupport {
}
/**
+ * Strips the query parameters from the uri
+ *
+ * @param uri the uri
+ * @return the uri without the query parameter
+ */
+ public static String stripQuery(String uri) {
+ int idx = uri.indexOf('?');
+ if (idx > -1) {
+ uri = uri.substring(0, idx);
+ }
+ return uri;
+ }
+
+ /**
* Parses the query part of the uri (eg the parameters).
* <p/>
* The URI parameters will by default be URI encoded. However you can define a parameter values with the syntax: