This is an automated email from the ASF dual-hosted git repository. gnodet pushed a commit to branch endpoint-dsl in repository https://gitbox.apache.org/repos/asf/camel.git
commit 2afa0447bc60f5a01a2021d25d50aa4282768ab6 Author: Guillaume Nodet <gno...@gmail.com> AuthorDate: Tue Jun 11 17:51:51 2019 +0200 Fix endpoint resolution --- .../main/java/org/apache/camel/CamelContext.java | 11 +++ .../src/main/java/org/apache/camel/Component.java | 14 +++ .../java/org/apache/camel/spi/RouteContext.java | 5 +- .../camel/impl/engine/AbstractCamelContext.java | 105 +++++++++++++++++++++ .../camel/impl/engine/DefaultRouteContext.java | 24 +++-- .../camel/model/AbstractEndpointBuilder.java | 2 +- .../java/org/apache/camel/reifier/SendReifier.java | 2 +- .../component/file/FileAbsolutePathIssueTest.java | 6 +- .../file/FileBatchConsumerMemoryLeakTest.java | 10 +- 9 files changed, 154 insertions(+), 25 deletions(-) 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 eb142b4..db1244c 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 @@ -427,6 +427,17 @@ public interface CamelContext extends StatefulService, RuntimeConfiguration { * If the name has a singleton endpoint registered, then the singleton is returned. * Otherwise, a new {@link Endpoint} is created and registered in the {@link org.apache.camel.spi.EndpointRegistry}. * + * @param uri the URI of the endpoint + * @param parameters the parameters to customize the endpoint + * @return the endpoint + */ + Endpoint getEndpoint(String uri, Map<String, Object> parameters); + + /** + * Resolves the given name to an {@link Endpoint} of the specified type. + * If the name has a singleton endpoint registered, then the singleton is returned. + * Otherwise, a new {@link Endpoint} is created and registered in the {@link org.apache.camel.spi.EndpointRegistry}. + * * @param name the name of the endpoint * @param endpointType the expected type * @return the endpoint diff --git a/core/camel-api/src/main/java/org/apache/camel/Component.java b/core/camel-api/src/main/java/org/apache/camel/Component.java index bbd2d74..39c4010 100644 --- a/core/camel-api/src/main/java/org/apache/camel/Component.java +++ b/core/camel-api/src/main/java/org/apache/camel/Component.java @@ -44,6 +44,20 @@ public interface Component extends CamelContextAware { */ Endpoint createEndpoint(String uri) throws Exception; + /** + * Attempt to resolve an endpoint for the given URI if the component is + * capable of handling the URI. + * <p/> + * See {@link #useRawUri()} for controlling whether the passed in uri + * should be as-is (raw), or encoded (default). + * + * @param uri the URI to create; either raw or encoded (default) + * @param parameters the parameters for the endpoint + * @return a newly created {@link Endpoint} or null if this component cannot create + * {@link Endpoint} instances using the given uri + * @throws Exception is thrown if error creating the endpoint + * @see #useRawUri() + */ Endpoint createEndpoint(String uri, Map<String, Object> parameters) throws Exception; /** diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/RouteContext.java b/core/camel-api/src/main/java/org/apache/camel/spi/RouteContext.java index 3c3c9e5..a7c194a 100644 --- a/core/camel-api/src/main/java/org/apache/camel/spi/RouteContext.java +++ b/core/camel-api/src/main/java/org/apache/camel/spi/RouteContext.java @@ -74,12 +74,11 @@ public interface RouteContext extends RuntimeConfiguration, EndpointAware { /** * Resolves an endpoint from the scheme, path and properties * - * @param scheme the URI scheme - * @param path the endpoint path + * @param uri the URI scheme * @param properties the endpoint properties * @return the resolved endpoint */ - Endpoint resolveEndpoint(String scheme, String path, Map<String, Object> properties); + Endpoint resolveEndpoint(String uri, Map<String, Object> properties); /** * lookup an object by name and type diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java b/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java index dd71ffd..83ec9b7 100644 --- a/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java +++ b/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java @@ -788,6 +788,111 @@ public abstract class AbstractCamelContext extends ServiceSupport implements Ext return answer; } + public Endpoint getEndpoint(String uri, Map<String, Object> parameters) { + init(); + + StringHelper.notEmpty(uri, "uri"); + + log.trace("Getting endpoint with uri: {} and parameters: {}", uri, parameters); + + // in case path has property placeholders then try to let property + // component resolve those + try { + uri = resolvePropertyPlaceholders(uri); + } catch (Exception e) { + throw new ResolveEndpointFailedException(uri, e); + } + + final String rawUri = uri; + + // normalize uri so we can do endpoint hits with minor mistakes and + // parameters is not in the same order + uri = normalizeEndpointUri(uri); + + log.trace("Getting endpoint with raw uri: {}, normalized uri: {}", rawUri, uri); + + Endpoint answer; + String scheme = null; + // use optimized method to get the endpoint uri + EndpointKey key = getEndpointKeyPreNormalized(uri); + answer = endpoints.get(key); + if (answer == null) { + try { + // Use the URI prefix to find the component. + String[] splitURI = StringHelper.splitOnCharacter(uri, ":", 2); + if (splitURI[1] != null) { + scheme = splitURI[0]; + log.trace("Endpoint uri: {} is from component with name: {}", uri, scheme); + Component component = getComponent(scheme); + + // Ask the component to resolve the endpoint. + if (component != null) { + log.trace("Creating endpoint from uri: {} using component: {}", uri, component); + + // Have the component create the endpoint if it can. + if (component.useRawUri()) { + answer = component.createEndpoint(rawUri, parameters); + } else { + answer = component.createEndpoint(uri, parameters); + } + + if (answer != null && log.isDebugEnabled()) { + log.debug("{} converted to endpoint: {} by component: {}", URISupport.sanitizeUri(uri), answer, component); + } + } + } + + if (answer == null) { + // no component then try in registry and elsewhere + answer = createEndpoint(uri); + log.trace("No component to create endpoint from uri: {} fallback lookup in registry -> {}", uri, answer); + } + + if (answer == null && splitURI[1] == null) { + // the uri has no context-path which is rare and it was not + // referring to an endpoint in the registry + // so try to see if it can be created by a component + + int pos = uri.indexOf('?'); + String componentName = pos > 0 ? uri.substring(0, pos) : uri; + + Component component = getComponent(componentName); + + // Ask the component to resolve the endpoint. + if (component != null) { + log.trace("Creating endpoint from uri: {} using component: {}", uri, component); + + // Have the component create the endpoint if it can. + if (component.useRawUri()) { + answer = component.createEndpoint(rawUri, parameters); + } else { + answer = component.createEndpoint(uri, parameters); + } + + if (answer != null && log.isDebugEnabled()) { + log.debug("{} converted to endpoint: {} by component: {}", URISupport.sanitizeUri(uri), answer, component); + } + } + + } + + if (answer != null) { + addService(answer); + answer = addEndpointToRegistry(uri, answer); + } + } catch (Exception e) { + throw new ResolveEndpointFailedException(uri, e); + } + } + + // unknown scheme + if (answer == null && scheme != null) { + throw new ResolveEndpointFailedException(uri, "No component found with scheme: " + scheme); + } + + return answer; + } + public <T extends Endpoint> T getEndpoint(String name, Class<T> endpointType) { Endpoint endpoint = getEndpoint(name); if (endpoint == null) { diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultRouteContext.java b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultRouteContext.java index 3f7d459..0e4f728 100644 --- a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultRouteContext.java +++ b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultRouteContext.java @@ -45,6 +45,8 @@ import org.apache.camel.spi.RouteController; import org.apache.camel.spi.RouteError; import org.apache.camel.spi.RoutePolicy; import org.apache.camel.support.CamelContextHelper; +import org.apache.camel.util.StringHelper; +import org.apache.camel.util.URISupport; /** * The context used to activate new routing rules @@ -118,7 +120,7 @@ public class DefaultRouteContext implements RouteContext { public Endpoint resolveEndpoint(String uri, String ref) { Endpoint endpoint = null; if (uri != null) { - endpoint = resolveEndpoint(uri); + endpoint = camelContext.getEndpoint(uri); if (endpoint == null) { throw new NoSuchEndpointException(uri); } @@ -146,19 +148,15 @@ public class DefaultRouteContext implements RouteContext { } } - public Endpoint resolveEndpoint(String scheme, String path, Map<String, Object> properties) { - Component component = camelContext.getComponent(scheme); - if (component != null) { - try { - Endpoint endpoint = component.createEndpoint(scheme + ":" + path, properties); - if (endpoint != null) { - return endpoint; - } - } catch (Exception e) { - throw new ResolveEndpointFailedException(scheme + ":" + path, e); - } + public Endpoint resolveEndpoint(String uri, Map<String, Object> properties) { + Endpoint endpoint = camelContext.hasEndpoint(uri); + if (endpoint == null) { + endpoint = camelContext.getEndpoint(uri, properties); + } + if (endpoint != null) { + return endpoint; } - throw new NoSuchEndpointException(scheme + ":" + path); + throw new NoSuchEndpointException(uri); } public <T> T lookup(String name, Class<T> type) { diff --git a/core/camel-core/src/main/java/org/apache/camel/model/AbstractEndpointBuilder.java b/core/camel-core/src/main/java/org/apache/camel/model/AbstractEndpointBuilder.java index 810d736..dadd5a7 100644 --- a/core/camel-core/src/main/java/org/apache/camel/model/AbstractEndpointBuilder.java +++ b/core/camel-core/src/main/java/org/apache/camel/model/AbstractEndpointBuilder.java @@ -38,7 +38,7 @@ public class AbstractEndpointBuilder<T extends AbstractEndpointBuilder> { } public Endpoint resolve(RouteContext context) throws NoSuchEndpointException { - return context.resolveEndpoint(scheme, path, properties); + return context.resolveEndpoint(scheme + ":" + path, properties); } } diff --git a/core/camel-core/src/main/java/org/apache/camel/reifier/SendReifier.java b/core/camel-core/src/main/java/org/apache/camel/reifier/SendReifier.java index 4901595..75389ee 100644 --- a/core/camel-core/src/main/java/org/apache/camel/reifier/SendReifier.java +++ b/core/camel-core/src/main/java/org/apache/camel/reifier/SendReifier.java @@ -38,7 +38,7 @@ class SendReifier extends ProcessorReifier<SendDefinition<?>> { public Endpoint resolveEndpoint(RouteContext context) { if (definition.getEndpoint() == null) { if (definition.getEndpointProducerBuilder() == null) { - return context.resolveEndpoint(definition.getUri(), null); + return context.resolveEndpoint(definition.getUri(), (String) null); } else { return definition.getEndpointProducerBuilder().resolve(context); } diff --git a/core/camel-core/src/test/java/org/apache/camel/component/file/FileAbsolutePathIssueTest.java b/core/camel-core/src/test/java/org/apache/camel/component/file/FileAbsolutePathIssueTest.java index 0f2459d..8a47dd4 100644 --- a/core/camel-core/src/test/java/org/apache/camel/component/file/FileAbsolutePathIssueTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/component/file/FileAbsolutePathIssueTest.java @@ -19,6 +19,7 @@ import java.io.File; import org.apache.camel.ContextTestSupport; import org.apache.camel.Exchange; +import org.apache.camel.builder.EndpointRouteBuilder; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; import org.junit.Before; @@ -56,10 +57,11 @@ public class FileAbsolutePathIssueTest extends ContextTestSupport { @Override protected RouteBuilder createRouteBuilder() throws Exception { - return new RouteBuilder() { + return new EndpointRouteBuilder() { @Override public void configure() throws Exception { - from(uri).to("mock:result"); + from(fromFile(start).initialDelay(0).delay(10).move(done + "/${file:name}")) + .to(toMock("result")); } }; } diff --git a/core/camel-core/src/test/java/org/apache/camel/component/file/FileBatchConsumerMemoryLeakTest.java b/core/camel-core/src/test/java/org/apache/camel/component/file/FileBatchConsumerMemoryLeakTest.java index 6dfa777..01cd67e 100644 --- a/core/camel-core/src/test/java/org/apache/camel/component/file/FileBatchConsumerMemoryLeakTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/component/file/FileBatchConsumerMemoryLeakTest.java @@ -18,7 +18,7 @@ package org.apache.camel.component.file; import org.apache.camel.ContextTestSupport; import org.apache.camel.Exchange; import org.apache.camel.Processor; -import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.builder.EndpointRouteBuilder; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -29,7 +29,7 @@ import org.junit.Test; @Ignore("Manual test") public class FileBatchConsumerMemoryLeakTest extends ContextTestSupport { - private String fileUrl = "file://target/data/filesorter/"; + private String fileUrl = "target/data/filesorter/"; @Override @Before @@ -67,17 +67,17 @@ public class FileBatchConsumerMemoryLeakTest extends ContextTestSupport { for (int c = 0; c < 100; c++) { template.sendBodyAndHeader(fileUrl + "c", "test", Exchange.FILE_NAME, c + ".dat"); } - context.addRoutes(new RouteBuilder() { + context.addRoutes(new EndpointRouteBuilder() { @Override public void configure() throws Exception { - from(fileUrl + "c/?sortBy=ignoreCase:file:name") + from(fromFile(fileUrl + "/c/").sortBy("ignoreCase:file:name")) .process(new Processor() { public void process(Exchange exchange) throws Exception { StringBuilder buf = new StringBuilder(10000000); buf.setLength(1000000); exchange.getIn().setBody(buf.toString()); } - }).to("file:target/data/filesorter/archiv"); + }).to(toFile("target/data/filesorter/archiv")); } }); context.start();