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 d06f03e74f013a812ba7e5bf10793e33e711baff Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Sat Sep 26 21:48:42 2020 +0200 CAMEL-14499: Optimize to avoid using camel-core-catalog for SendDynamicAware for camel-file/camel-ftp. --- components/camel-file/pom.xml | 5 - .../file/GenericFileSendDynamicAware.java | 18 ++-- .../camel/http/base/HttpSendDynamicAware.java | 26 +++-- .../org/apache/camel/spi/SendDynamicAware.java | 33 +++++-- .../camel/processor/SendDynamicAwareResolver.java | 1 + .../camel/processor/SendDynamicProcessor.java | 5 +- .../camel/component/bar/BarSendDynamicAware.java | 17 +++- .../support/component/SendDynamicAwareSupport.java | 105 +++++++++++++++++++-- 8 files changed, 158 insertions(+), 52 deletions(-) diff --git a/components/camel-file/pom.xml b/components/camel-file/pom.xml index 138ea49..b1f73d3 100644 --- a/components/camel-file/pom.xml +++ b/components/camel-file/pom.xml @@ -43,11 +43,6 @@ <groupId>org.apache.camel</groupId> <artifactId>camel-cluster</artifactId> </dependency> - <!-- needed for dynamic to --> - <dependency> - <groupId>org.apache.camel</groupId> - <artifactId>camel-core-catalog</artifactId> - </dependency> </dependencies> </project> diff --git a/components/camel-file/src/main/java/org/apache/camel/component/file/GenericFileSendDynamicAware.java b/components/camel-file/src/main/java/org/apache/camel/component/file/GenericFileSendDynamicAware.java index 0c04241..71566b9 100644 --- a/components/camel-file/src/main/java/org/apache/camel/component/file/GenericFileSendDynamicAware.java +++ b/components/camel-file/src/main/java/org/apache/camel/component/file/GenericFileSendDynamicAware.java @@ -16,7 +16,6 @@ */ package org.apache.camel.component.file; -import java.util.LinkedHashMap; import java.util.Map; import org.apache.camel.Exchange; @@ -26,21 +25,19 @@ import org.apache.camel.util.URISupport; public abstract class GenericFileSendDynamicAware extends SendDynamicAwareSupport { - private String scheme; - @Override - public void setScheme(String scheme) { - this.scheme = scheme; + public boolean isOnlyDynamicQueryParameters() { + return true; } @Override - public String getScheme() { - return scheme; + public boolean isLenientProperties() { + return false; } @Override public DynamicAwareEntry prepare(Exchange exchange, String uri, String originalUri) throws Exception { - Map<String, String> properties = endpointProperties(exchange, uri); + Map<String, Object> properties = endpointProperties(exchange, uri); return new DynamicAwareEntry(uri, originalUri, properties, null); } @@ -56,8 +53,9 @@ public abstract class GenericFileSendDynamicAware extends SendDynamicAwareSuppor // if any of the above are in use, then they should not be pre evaluated // and we need to rebuild a new uri with them as-is if (fileName || tempFileName || idempotentKey || move || moveFailed || preMove || moveExisting) { - Map<String, String> params = new LinkedHashMap<>(entry.getProperties()); + Map<String, Object> params = entry.getProperties(); + // TODO: parseQuery should only have the query part, this is not correct Map<String, Object> originalParams = URISupport.parseQuery(entry.getOriginalUri()); if (fileName) { Object val = originalParams.get("fileName"); @@ -102,7 +100,7 @@ public abstract class GenericFileSendDynamicAware extends SendDynamicAwareSuppor } } - return asEndpointUri(exchange, scheme, params); + return asEndpointUri(exchange, entry.getUri(), params); } else { return entry.getUri(); } diff --git a/components/camel-http-base/src/main/java/org/apache/camel/http/base/HttpSendDynamicAware.java b/components/camel-http-base/src/main/java/org/apache/camel/http/base/HttpSendDynamicAware.java index 9892acb..5692ec5 100644 --- a/components/camel-http-base/src/main/java/org/apache/camel/http/base/HttpSendDynamicAware.java +++ b/components/camel-http-base/src/main/java/org/apache/camel/http/base/HttpSendDynamicAware.java @@ -38,22 +38,20 @@ public class HttpSendDynamicAware extends SendDynamicAwareSupport { private final Processor postProcessor = new HttpSendDynamicPostProcessor(); - private String scheme; - @Override - public void setScheme(String scheme) { - this.scheme = scheme; + public boolean isOnlyDynamicQueryParameters() { + return false; } @Override - public String getScheme() { - return scheme; + public boolean isLenientProperties() { + return true; } @Override public DynamicAwareEntry prepare(Exchange exchange, String uri, String originalUri) throws Exception { - Map<String, String> properties = endpointProperties(exchange, uri); - Map<String, String> lenient = endpointLenientProperties(exchange, uri); + Map<String, Object> properties = endpointProperties(exchange, uri); + Map<String, Object> lenient = endpointLenientProperties(exchange, uri); return new DynamicAwareEntry(uri, originalUri, properties, lenient); } @@ -65,7 +63,7 @@ public class HttpSendDynamicAware extends SendDynamicAwareSupport { if (path != null || !entry.getLenientProperties().isEmpty()) { // the context path can be dynamic or any lenient properties // and therefore build a new static uri without path or lenient options - Map<String, String> params = new LinkedHashMap<>(entry.getProperties()); + Map<String, Object> params = entry.getProperties(); for (String k : entry.getLenientProperties().keySet()) { params.remove(k); } @@ -75,12 +73,12 @@ public class HttpSendDynamicAware extends SendDynamicAwareSupport { params.put("httpUri", host); } else if (params.containsKey("httpURI")) { params.put("httpURI", host); - } else if ("netty-http".equals(scheme)) { + } else if ("netty-http".equals(getScheme())) { // the netty-http stores host,port etc in other fields than httpURI so we can just remove the path parameter params.remove("path"); } } - return asEndpointUri(exchange, scheme, params); + return asEndpointUri(exchange, entry.getUri(), params); } else { // no need for optimisation return null; @@ -118,10 +116,10 @@ public class HttpSendDynamicAware extends SendDynamicAwareSupport { String u = entry.getUri(); // remove scheme prefix (unless its camel-http or camel-http) - boolean httpComponent = "http".equals(scheme) || "https".equals(scheme); + boolean httpComponent = "http".equals(getScheme()) || "https".equals(getScheme()); if (!httpComponent) { - String prefix = scheme + "://"; - String prefix2 = scheme + ":"; + String prefix = getScheme() + "://"; + String prefix2 = getScheme() + ":"; if (u.startsWith(prefix)) { u = u.substring(prefix.length()); } else if (u.startsWith(prefix2)) { diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/SendDynamicAware.java b/core/camel-api/src/main/java/org/apache/camel/spi/SendDynamicAware.java index 2efb5f0..c07ec4a 100644 --- a/core/camel-api/src/main/java/org/apache/camel/spi/SendDynamicAware.java +++ b/core/camel-api/src/main/java/org/apache/camel/spi/SendDynamicAware.java @@ -18,16 +18,19 @@ package org.apache.camel.spi; import java.util.Map; +import org.apache.camel.CamelContextAware; +import org.apache.camel.Endpoint; import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.Service; /** * Used for components that can optimise the usage of {@link org.apache.camel.processor.SendDynamicProcessor} (toD) to * reuse a static {@link org.apache.camel.Endpoint} and {@link Producer} that supports using headers to provide the * dynamic parts. For example many of the HTTP components supports this. */ -public interface SendDynamicAware { +public interface SendDynamicAware extends Service, CamelContextAware { /** * Sets the component name. @@ -42,6 +45,22 @@ public interface SendDynamicAware { String getScheme(); /** + * Whether only the query parameters can be dynamic and the context-path must be static. + * + * If true then Camel can restructure endpoint uri using a simple and faster parser. + * On the other hand if the context-path and authority part of the URI can be dynamic + * then Camel has to use a more complex and slower parser. + */ + boolean isOnlyDynamicQueryParameters(); + + /** + * Whether the endpoint is lenient or not. + * + * @see Endpoint#isLenientProperties() + */ + boolean isLenientProperties(); + + /** * An entry of detailed information from the recipient uri, which allows the {@link SendDynamicAware} implementation * to prepare pre- and post- processor and the static uri to be used for the optimised dynamic to. */ @@ -49,11 +68,11 @@ public interface SendDynamicAware { private final String uri; private final String originalUri; - private final Map<String, String> properties; - private final Map<String, String> lenientProperties; + private final Map<String, Object> properties; + private final Map<String, Object> lenientProperties; - public DynamicAwareEntry(String uri, String originalUri, Map<String, String> properties, - Map<String, String> lenientProperties) { + public DynamicAwareEntry(String uri, String originalUri, Map<String, Object> properties, + Map<String, Object> lenientProperties) { this.uri = uri; this.originalUri = originalUri; this.properties = properties; @@ -68,11 +87,11 @@ public interface SendDynamicAware { return originalUri; } - public Map<String, String> getProperties() { + public Map<String, Object> getProperties() { return properties; } - public Map<String, String> getLenientProperties() { + public Map<String, Object> getLenientProperties() { return lenientProperties; } } diff --git a/core/camel-base/src/main/java/org/apache/camel/processor/SendDynamicAwareResolver.java b/core/camel-base/src/main/java/org/apache/camel/processor/SendDynamicAwareResolver.java index 6bbefea..8ee8b0c 100644 --- a/core/camel-base/src/main/java/org/apache/camel/processor/SendDynamicAwareResolver.java +++ b/core/camel-base/src/main/java/org/apache/camel/processor/SendDynamicAwareResolver.java @@ -51,6 +51,7 @@ public class SendDynamicAwareResolver { if (SendDynamicAware.class.isAssignableFrom(type)) { SendDynamicAware answer = (SendDynamicAware) context.getInjector().newInstance(type, false); answer.setScheme(scheme); + answer.setCamelContext(context); return answer; } else { throw new IllegalArgumentException("Type is not a SendDynamicAware implementation. Found: " + type.getName()); diff --git a/core/camel-base/src/main/java/org/apache/camel/processor/SendDynamicProcessor.java b/core/camel-base/src/main/java/org/apache/camel/processor/SendDynamicProcessor.java index 118aee1..2ce3ede 100644 --- a/core/camel-base/src/main/java/org/apache/camel/processor/SendDynamicProcessor.java +++ b/core/camel-base/src/main/java/org/apache/camel/processor/SendDynamicProcessor.java @@ -336,6 +336,7 @@ public class SendDynamicProcessor extends AsyncProcessorSupport implements IdAwa } } } + ServiceHelper.initService(dynamicAware); } @Override @@ -355,12 +356,12 @@ public class SendDynamicProcessor extends AsyncProcessorSupport implements IdAwa } } - ServiceHelper.startService(producerCache); + ServiceHelper.startService(dynamicAware, producerCache); } @Override protected void doStop() throws Exception { - ServiceHelper.stopService(producerCache); + ServiceHelper.stopService(producerCache, dynamicAware); } public EndpointUtilizationStatistics getEndpointUtilizationStatistics() { diff --git a/core/camel-core/src/test/java/org/apache/camel/component/bar/BarSendDynamicAware.java b/core/camel-core/src/test/java/org/apache/camel/component/bar/BarSendDynamicAware.java index 2b81589..a044830 100644 --- a/core/camel-core/src/test/java/org/apache/camel/component/bar/BarSendDynamicAware.java +++ b/core/camel-core/src/test/java/org/apache/camel/component/bar/BarSendDynamicAware.java @@ -16,7 +16,6 @@ */ package org.apache.camel.component.bar; -import java.util.LinkedHashMap; import java.util.Map; import org.apache.camel.Exchange; @@ -24,11 +23,11 @@ import org.apache.camel.Processor; import org.apache.camel.builder.ExpressionBuilder; import org.apache.camel.processor.RemoveHeaderProcessor; import org.apache.camel.processor.SetHeaderProcessor; -import org.apache.camel.spi.SendDynamicAware; +import org.apache.camel.support.component.SendDynamicAwareSupport; import org.apache.camel.util.StringHelper; import org.apache.camel.util.URISupport; -public class BarSendDynamicAware implements SendDynamicAware { +public class BarSendDynamicAware extends SendDynamicAwareSupport { private String scheme; @@ -43,10 +42,20 @@ public class BarSendDynamicAware implements SendDynamicAware { } @Override + public boolean isOnlyDynamicQueryParameters() { + return false; + } + + @Override + public boolean isLenientProperties() { + return false; + } + + @Override public DynamicAwareEntry prepare(Exchange exchange, String uri, String originalUri) throws Exception { String query = StringHelper.after(uri, "?"); if (query != null) { - Map<String, String> map = new LinkedHashMap(URISupport.parseQuery(query)); + Map<String, Object> map = URISupport.parseQuery(query); return new DynamicAwareEntry(uri, originalUri, map, null); } else { return new DynamicAwareEntry(uri, originalUri, null, null); diff --git a/core/camel-support/src/main/java/org/apache/camel/support/component/SendDynamicAwareSupport.java b/core/camel-support/src/main/java/org/apache/camel/support/component/SendDynamicAwareSupport.java index 12262db..485e7a4 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/component/SendDynamicAwareSupport.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/component/SendDynamicAwareSupport.java @@ -16,32 +16,117 @@ */ package org.apache.camel.support.component; +import java.util.Collections; +import java.util.LinkedHashMap; import java.util.Map; +import java.util.Set; +import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.ExtendedCamelContext; import org.apache.camel.catalog.RuntimeCamelCatalog; import org.apache.camel.spi.SendDynamicAware; +import org.apache.camel.support.service.ServiceSupport; +import org.apache.camel.util.URISupport; /** * Support class for {@link SendDynamicAware} implementations. */ -public abstract class SendDynamicAwareSupport implements SendDynamicAware { +public abstract class SendDynamicAwareSupport extends ServiceSupport implements SendDynamicAware { - public Map<String, String> endpointProperties(Exchange exchange, String uri) throws Exception { - RuntimeCamelCatalog catalog = exchange.getContext().adapt(ExtendedCamelContext.class).getRuntimeCamelCatalog(); - Map<String, String> properties = catalog.endpointProperties(uri); + private CamelContext camelContext; + private Set<String> knownProperties; + private String scheme; + + @Override + public CamelContext getCamelContext() { + return camelContext; + } + + @Override + public void setCamelContext(CamelContext camelContext) { + this.camelContext = camelContext; + } + + @Override + public void setScheme(String scheme) { + this.scheme = scheme; + } + + @Override + public String getScheme() { + return scheme; + } + + @Override + protected void doInit() throws Exception { + if (isOnlyDynamicQueryParameters()) { + knownProperties = getCamelContext().adapt(ExtendedCamelContext.class).getEndpointUriFactory(getScheme()).propertyNames(); + } + } + + public Map<String, Object> endpointProperties(Exchange exchange, String uri) throws Exception { + Map<String, Object> properties; + if (isOnlyDynamicQueryParameters()) { + // optimize as we know its only query parameters that can be dynamic, and that there are no lenient properties + Map<String, Object> map; + int pos = uri.indexOf('?'); + if (pos != -1) { + String query = uri.substring(pos + 1); + map = URISupport.parseQuery(query); + } else { + map = Collections.EMPTY_MAP; + } + if (map != null && isLenientProperties()) { + properties = new LinkedHashMap<>(map.size()); + // okay so only add the known properties as they are the non lenient properties + map.forEach((k, v) -> { + if (knownProperties.contains(k)) { + properties.put(k, v); + } + }); + } else { + properties = map; + } + } else { + RuntimeCamelCatalog catalog = exchange.getContext().adapt(ExtendedCamelContext.class).getRuntimeCamelCatalog(); + properties = new LinkedHashMap<>(catalog.endpointProperties(uri)); + } return properties; } - public Map<String, String> endpointLenientProperties(Exchange exchange, String uri) throws Exception { - RuntimeCamelCatalog catalog = exchange.getContext().adapt(ExtendedCamelContext.class).getRuntimeCamelCatalog(); - Map<String, String> properties = catalog.endpointLenientProperties(uri); + public Map<String, Object> endpointLenientProperties(Exchange exchange, String uri) throws Exception { + Map<String, Object> properties; + if (isOnlyDynamicQueryParameters()) { + // optimize as we know its only query parameters that can be dynamic + Map<String, Object> map = URISupport.parseQuery(uri); + properties = new LinkedHashMap<>(); + map.forEach((k, v) -> { + if (!knownProperties.contains(k)) { + properties.put(k, v.toString()); + } + }); + } else { + RuntimeCamelCatalog catalog = exchange.getContext().adapt(ExtendedCamelContext.class).getRuntimeCamelCatalog(); + properties = new LinkedHashMap<>(catalog.endpointLenientProperties(uri)); + } return properties; } - public String asEndpointUri(Exchange exchange, String scheme, Map<String, String> properties) throws Exception { - RuntimeCamelCatalog catalog = exchange.getContext().adapt(ExtendedCamelContext.class).getRuntimeCamelCatalog(); - return catalog.asEndpointUri(scheme, properties, false); + public String asEndpointUri(Exchange exchange, String uri, Map<String, Object> properties) throws Exception { + if (isOnlyDynamicQueryParameters()) { + String answer; + String query = URISupport.createQueryString(properties, false); + int pos = uri.indexOf('?'); + if (pos != -1) { + answer = uri.substring(0, pos) + "?" + query; + } else { + answer = uri + "?" + query; + } + return answer; + } else { + RuntimeCamelCatalog catalog = exchange.getContext().adapt(ExtendedCamelContext.class).getRuntimeCamelCatalog(); + return catalog.asEndpointUri(getScheme(), new LinkedHashMap(properties), false); + } } }