You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by gn...@apache.org on 2019/06/11 16:15:56 UTC

[camel] 03/05: Fix endpoint resolution

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 <gn...@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();