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();