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 2020/09/25 18:45:03 UTC

[camel] 06/16: CAMEL-15567: components - Generate source code for creating endpoint uri via a map of properties. WIP

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch uri-assembler
in repository https://gitbox.apache.org/repos/asf/camel.git

commit b497a65a5f325b736240b6a39705bdc9db0d853e
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri Sep 25 11:44:00 2020 +0200

    CAMEL-15567: components - Generate source code for creating endpoint uri via a map of properties. WIP
---
 .../component/ahc/AhcEndpointUriAssembler.java     |  12 +-
 .../jetty9/JettyHttp9EndpointUriAssembler.java     |  12 +-
 .../component/log/LogEndpointUriAssembler.java}    |  16 ++-
 .../org/apache/camel/assembler/log-endpoint        |   2 +
 .../component/mail/MailEndpointUriAssembler.java   |  39 +++++++
 .../org/apache/camel/assembler/imap-endpoint       |   2 +
 .../org/apache/camel/assembler/imaps-endpoint      |   2 +
 .../org/apache/camel/assembler/pop3-endpoint       |   2 +
 .../org/apache/camel/assembler/pop3s-endpoint      |   2 +
 .../org/apache/camel/assembler/smtp-endpoint       |   2 +
 .../org/apache/camel/assembler/smtps-endpoint      |   2 +
 .../netty/http/NettyHttpEndpointUriAssembler.java  |  18 ++-
 .../org/apache/camel/ExtendedCamelContext.java     |  11 ++
 ...intUriAssembler.java => AssemblerResolver.java} |  21 ++--
 .../org/apache/camel/spi/EndpointUriAssembler.java |   5 +-
 .../camel/impl/engine/AbstractCamelContext.java    |  28 +++--
 .../impl/engine/DefaultAssemblerResolver.java      | 126 +++++++++++++++++++++
 .../camel/impl/engine/SimpleCamelContext.java      |   6 +
 .../impl/CamelCatalogEndpointUriAssembler.java     |   7 ++
 .../camel/impl/ExtendedCamelContextConfigurer.java |   5 +
 .../camel/impl/lw/LightweightCamelContext.java     |  11 ++
 .../impl/lw/LightweightRuntimeCamelContext.java    |  12 +-
 .../catalog/CustomEndpointUriAssemblerTest.java    |  29 ++++-
 .../component/log/LogEndpointUriAssemblerTest.java |  31 +++++
 .../apache/camel/impl/AssembleResolverTest.java    |  43 +++++++
 .../component/EndpointUriAssemblerSupport.java     |   2 +-
 .../packaging/EndpointUriAssemblerGenerator.java   |  51 ++++++++-
 27 files changed, 454 insertions(+), 45 deletions(-)

diff --git a/components/camel-ahc/src/generated/java/org/apache/camel/component/ahc/AhcEndpointUriAssembler.java b/components/camel-ahc/src/generated/java/org/apache/camel/component/ahc/AhcEndpointUriAssembler.java
index 3e3d8ae..d2860d0 100644
--- a/components/camel-ahc/src/generated/java/org/apache/camel/component/ahc/AhcEndpointUriAssembler.java
+++ b/components/camel-ahc/src/generated/java/org/apache/camel/component/ahc/AhcEndpointUriAssembler.java
@@ -12,13 +12,19 @@ import org.apache.camel.spi.EndpointUriAssembler;
  */
 public class AhcEndpointUriAssembler extends org.apache.camel.support.component.EndpointUriAssemblerSupport implements EndpointUriAssembler {
 
-    private static final String SYNTAX = "ahc:httpUri";
+    private static final String BASE = ":httpUri";
+
+    @Override
+    public boolean isEnabled(String scheme) {
+        return "ahc".equals(scheme);
+    }
 
     @Override
     public String buildUri(CamelContext camelContext, String scheme, Map<String, Object> parameters) throws URISyntaxException {
-        String uri = SYNTAX;
+        String syntax = scheme + BASE;
+        String uri = syntax;
 
-        uri = buildPathParameter(camelContext, SYNTAX, uri, "httpUri", null, true, parameters);
+        uri = buildPathParameter(camelContext, syntax, uri, "httpUri", null, true, parameters);
         uri = buildQueryParameters(camelContext, uri, parameters);
         return uri;
     }
diff --git a/components/camel-jetty/src/generated/java/org/apache/camel/component/jetty9/JettyHttp9EndpointUriAssembler.java b/components/camel-jetty/src/generated/java/org/apache/camel/component/jetty9/JettyHttp9EndpointUriAssembler.java
index e0f4418..68943b1c 100644
--- a/components/camel-jetty/src/generated/java/org/apache/camel/component/jetty9/JettyHttp9EndpointUriAssembler.java
+++ b/components/camel-jetty/src/generated/java/org/apache/camel/component/jetty9/JettyHttp9EndpointUriAssembler.java
@@ -12,13 +12,19 @@ import org.apache.camel.spi.EndpointUriAssembler;
  */
 public class JettyHttp9EndpointUriAssembler extends org.apache.camel.support.component.EndpointUriAssemblerSupport implements EndpointUriAssembler {
 
-    private static final String SYNTAX = "jetty:httpUri";
+    private static final String BASE = ":httpUri";
+
+    @Override
+    public boolean isEnabled(String scheme) {
+        return "jetty".equals(scheme);
+    }
 
     @Override
     public String buildUri(CamelContext camelContext, String scheme, Map<String, Object> parameters) throws URISyntaxException {
-        String uri = SYNTAX;
+        String syntax = scheme + BASE;
+        String uri = syntax;
 
-        uri = buildPathParameter(camelContext, SYNTAX, uri, "httpUri", null, true, parameters);
+        uri = buildPathParameter(camelContext, syntax, uri, "httpUri", null, true, parameters);
         uri = buildQueryParameters(camelContext, uri, parameters);
         return uri;
     }
diff --git a/components/camel-ahc/src/generated/java/org/apache/camel/component/ahc/AhcEndpointUriAssembler.java b/components/camel-log/src/generated/java/org/apache/camel/component/log/LogEndpointUriAssembler.java
similarity index 58%
copy from components/camel-ahc/src/generated/java/org/apache/camel/component/ahc/AhcEndpointUriAssembler.java
copy to components/camel-log/src/generated/java/org/apache/camel/component/log/LogEndpointUriAssembler.java
index 3e3d8ae..250bb46 100644
--- a/components/camel-ahc/src/generated/java/org/apache/camel/component/ahc/AhcEndpointUriAssembler.java
+++ b/components/camel-log/src/generated/java/org/apache/camel/component/log/LogEndpointUriAssembler.java
@@ -1,5 +1,5 @@
 /* Generated by camel build tools - do NOT edit this file! */
-package org.apache.camel.component.ahc;
+package org.apache.camel.component.log;
 
 import java.net.URISyntaxException;
 import java.util.Map;
@@ -10,15 +10,21 @@ import org.apache.camel.spi.EndpointUriAssembler;
 /**
  * Generated by camel build tools - do NOT edit this file!
  */
-public class AhcEndpointUriAssembler extends org.apache.camel.support.component.EndpointUriAssemblerSupport implements EndpointUriAssembler {
+public class LogEndpointUriAssembler extends org.apache.camel.support.component.EndpointUriAssemblerSupport implements EndpointUriAssembler {
 
-    private static final String SYNTAX = "ahc:httpUri";
+    private static final String BASE = ":loggerName";
+
+    @Override
+    public boolean isEnabled(String scheme) {
+        return "log".equals(scheme);
+    }
 
     @Override
     public String buildUri(CamelContext camelContext, String scheme, Map<String, Object> parameters) throws URISyntaxException {
-        String uri = SYNTAX;
+        String syntax = scheme + BASE;
+        String uri = syntax;
 
-        uri = buildPathParameter(camelContext, SYNTAX, uri, "httpUri", null, true, parameters);
+        uri = buildPathParameter(camelContext, syntax, uri, "loggerName", null, true, parameters);
         uri = buildQueryParameters(camelContext, uri, parameters);
         return uri;
     }
diff --git a/components/camel-log/src/generated/resources/META-INF/services/org/apache/camel/assembler/log-endpoint b/components/camel-log/src/generated/resources/META-INF/services/org/apache/camel/assembler/log-endpoint
new file mode 100644
index 0000000..f461f57
--- /dev/null
+++ b/components/camel-log/src/generated/resources/META-INF/services/org/apache/camel/assembler/log-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.log.LogEndpointUriAssembler
diff --git a/components/camel-mail/src/generated/java/org/apache/camel/component/mail/MailEndpointUriAssembler.java b/components/camel-mail/src/generated/java/org/apache/camel/component/mail/MailEndpointUriAssembler.java
new file mode 100644
index 0000000..f5fae41
--- /dev/null
+++ b/components/camel-mail/src/generated/java/org/apache/camel/component/mail/MailEndpointUriAssembler.java
@@ -0,0 +1,39 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.mail;
+
+import java.net.URISyntaxException;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.EndpointUriAssembler;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+public class MailEndpointUriAssembler extends org.apache.camel.support.component.EndpointUriAssemblerSupport implements EndpointUriAssembler {
+
+    private static final String BASE = ":host:port";
+    private static final String[] SCHEMES = new String[]{"imap", "imaps", "pop3", "pop3s", "smtp", "smtps"};
+
+    @Override
+    public boolean isEnabled(String scheme) {
+        for (String s : SCHEMES) {
+            if (s.equals(scheme)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String buildUri(CamelContext camelContext, String scheme, Map<String, Object> parameters) throws URISyntaxException {
+        String syntax = scheme + BASE;
+        String uri = syntax;
+
+        uri = buildPathParameter(camelContext, syntax, uri, "host", null, true, parameters);
+        uri = buildPathParameter(camelContext, syntax, uri, "port", null, false, parameters);
+        uri = buildQueryParameters(camelContext, uri, parameters);
+        return uri;
+    }
+}
+
diff --git a/components/camel-mail/src/generated/resources/META-INF/services/org/apache/camel/assembler/imap-endpoint b/components/camel-mail/src/generated/resources/META-INF/services/org/apache/camel/assembler/imap-endpoint
new file mode 100644
index 0000000..500af80
--- /dev/null
+++ b/components/camel-mail/src/generated/resources/META-INF/services/org/apache/camel/assembler/imap-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.mail.MailEndpointUriAssembler
diff --git a/components/camel-mail/src/generated/resources/META-INF/services/org/apache/camel/assembler/imaps-endpoint b/components/camel-mail/src/generated/resources/META-INF/services/org/apache/camel/assembler/imaps-endpoint
new file mode 100644
index 0000000..500af80
--- /dev/null
+++ b/components/camel-mail/src/generated/resources/META-INF/services/org/apache/camel/assembler/imaps-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.mail.MailEndpointUriAssembler
diff --git a/components/camel-mail/src/generated/resources/META-INF/services/org/apache/camel/assembler/pop3-endpoint b/components/camel-mail/src/generated/resources/META-INF/services/org/apache/camel/assembler/pop3-endpoint
new file mode 100644
index 0000000..500af80
--- /dev/null
+++ b/components/camel-mail/src/generated/resources/META-INF/services/org/apache/camel/assembler/pop3-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.mail.MailEndpointUriAssembler
diff --git a/components/camel-mail/src/generated/resources/META-INF/services/org/apache/camel/assembler/pop3s-endpoint b/components/camel-mail/src/generated/resources/META-INF/services/org/apache/camel/assembler/pop3s-endpoint
new file mode 100644
index 0000000..500af80
--- /dev/null
+++ b/components/camel-mail/src/generated/resources/META-INF/services/org/apache/camel/assembler/pop3s-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.mail.MailEndpointUriAssembler
diff --git a/components/camel-mail/src/generated/resources/META-INF/services/org/apache/camel/assembler/smtp-endpoint b/components/camel-mail/src/generated/resources/META-INF/services/org/apache/camel/assembler/smtp-endpoint
new file mode 100644
index 0000000..500af80
--- /dev/null
+++ b/components/camel-mail/src/generated/resources/META-INF/services/org/apache/camel/assembler/smtp-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.mail.MailEndpointUriAssembler
diff --git a/components/camel-mail/src/generated/resources/META-INF/services/org/apache/camel/assembler/smtps-endpoint b/components/camel-mail/src/generated/resources/META-INF/services/org/apache/camel/assembler/smtps-endpoint
new file mode 100644
index 0000000..500af80
--- /dev/null
+++ b/components/camel-mail/src/generated/resources/META-INF/services/org/apache/camel/assembler/smtps-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.mail.MailEndpointUriAssembler
diff --git a/components/camel-netty-http/src/generated/java/org/apache/camel/component/netty/http/NettyHttpEndpointUriAssembler.java b/components/camel-netty-http/src/generated/java/org/apache/camel/component/netty/http/NettyHttpEndpointUriAssembler.java
index e252977..3bc4475 100644
--- a/components/camel-netty-http/src/generated/java/org/apache/camel/component/netty/http/NettyHttpEndpointUriAssembler.java
+++ b/components/camel-netty-http/src/generated/java/org/apache/camel/component/netty/http/NettyHttpEndpointUriAssembler.java
@@ -12,16 +12,22 @@ import org.apache.camel.spi.EndpointUriAssembler;
  */
 public class NettyHttpEndpointUriAssembler extends org.apache.camel.support.component.EndpointUriAssemblerSupport implements EndpointUriAssembler {
 
-    private static final String SYNTAX = "netty-http:protocol:host:port/path";
+    private static final String BASE = ":protocol:host:port/path";
+
+    @Override
+    public boolean isEnabled(String scheme) {
+        return "netty-http".equals(scheme);
+    }
 
     @Override
     public String buildUri(CamelContext camelContext, String scheme, Map<String, Object> parameters) throws URISyntaxException {
-        String uri = SYNTAX;
+        String syntax = scheme + BASE;
+        String uri = syntax;
 
-        uri = buildPathParameter(camelContext, SYNTAX, uri, "protocol", null, true, parameters);
-        uri = buildPathParameter(camelContext, SYNTAX, uri, "host", null, true, parameters);
-        uri = buildPathParameter(camelContext, SYNTAX, uri, "port", null, false, parameters);
-        uri = buildPathParameter(camelContext, SYNTAX, uri, "path", null, false, parameters);
+        uri = buildPathParameter(camelContext, syntax, uri, "protocol", null, true, parameters);
+        uri = buildPathParameter(camelContext, syntax, uri, "host", null, true, parameters);
+        uri = buildPathParameter(camelContext, syntax, uri, "port", null, false, parameters);
+        uri = buildPathParameter(camelContext, syntax, uri, "path", null, false, parameters);
         uri = buildQueryParameters(camelContext, uri, parameters);
         return uri;
     }
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 4122a85..239e163 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
@@ -25,6 +25,7 @@ import java.util.concurrent.ScheduledExecutorService;
 
 import org.apache.camel.catalog.RuntimeCamelCatalog;
 import org.apache.camel.spi.AnnotationBasedProcessorFactory;
+import org.apache.camel.spi.AssemblerResolver;
 import org.apache.camel.spi.AsyncProcessorAwaitManager;
 import org.apache.camel.spi.BeanIntrospection;
 import org.apache.camel.spi.BeanProcessorFactory;
@@ -551,6 +552,16 @@ public interface ExtendedCamelContext extends CamelContext {
     void setConfigurerResolver(ConfigurerResolver configurerResolver);
 
     /**
+     * Gets the {@link AssemblerResolver} to use.
+     */
+    AssemblerResolver getAssemblerResolver();
+
+    /**
+     * Sets the {@link AssemblerResolver} to use.
+     */
+    void setAssemblerResolver(AssemblerResolver assemblerResolver);
+
+    /**
      * Internal {@link RouteController} that are only used internally by Camel to perform basic route operations. Do not
      * use this as end user.
      */
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/EndpointUriAssembler.java b/core/camel-api/src/main/java/org/apache/camel/spi/AssemblerResolver.java
similarity index 59%
copy from core/camel-api/src/main/java/org/apache/camel/spi/EndpointUriAssembler.java
copy to core/camel-api/src/main/java/org/apache/camel/spi/AssemblerResolver.java
index c1ed600..7e55562 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/EndpointUriAssembler.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/AssemblerResolver.java
@@ -16,26 +16,19 @@
  */
 package org.apache.camel.spi;
 
-import java.net.URISyntaxException;
-import java.util.Map;
-
 import org.apache.camel.CamelContext;
 
 /**
- * To assemble an endpoint uri String from a map of parameters.
+ * A pluggable strategy for resolving different assemblers in a loosely coupled manner
  */
-public interface EndpointUriAssembler {
-
-    // TODO: Consider a better name.
+public interface AssemblerResolver {
 
     /**
-     * Assembles an endpoint uri for the given component name with the given parameters.
+     * Resolves the given assembler.
      *
-     * @param  camelContext the Camel context
-     * @param  scheme       the component name
-     * @param  parameters   endpoint options
-     * @return              the constructed endpoint uri
+     * @param  name    the name of the assembler (timer-endpoint etc)
+     * @param  context the camel context
+     * @return         the resolved assembler, or <tt>null</tt> if no assembler could be found
      */
-    String buildUri(CamelContext camelContext, String scheme, Map<String, Object> parameters) throws URISyntaxException;
-
+    EndpointUriAssembler resolveAssembler(String name, CamelContext context);
 }
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/EndpointUriAssembler.java b/core/camel-api/src/main/java/org/apache/camel/spi/EndpointUriAssembler.java
index c1ed600..427d526 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/EndpointUriAssembler.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/EndpointUriAssembler.java
@@ -26,7 +26,10 @@ import org.apache.camel.CamelContext;
  */
 public interface EndpointUriAssembler {
 
-    // TODO: Consider a better name.
+    /**
+     * Checks whether this assembler supports the given component name
+     */
+    boolean isEnabled(String scheme);
 
     /**
      * Assembles an endpoint uri for the given component name with the given parameters.
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 dd810cb..c549440 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
@@ -77,6 +77,7 @@ import org.apache.camel.impl.transformer.TransformerKey;
 import org.apache.camel.impl.validator.ValidatorKey;
 import org.apache.camel.spi.AnnotationBasedProcessorFactory;
 import org.apache.camel.spi.AnnotationScanTypeConverters;
+import org.apache.camel.spi.AssemblerResolver;
 import org.apache.camel.spi.AsyncProcessorAwaitManager;
 import org.apache.camel.spi.BeanIntrospection;
 import org.apache.camel.spi.BeanProcessorFactory;
@@ -257,6 +258,7 @@ public abstract class AbstractCamelContext extends BaseService
     private volatile ComponentNameResolver componentNameResolver;
     private volatile LanguageResolver languageResolver;
     private volatile ConfigurerResolver configurerResolver;
+    private volatile AssemblerResolver assemblerResolver;
     private volatile DataFormatResolver dataFormatResolver;
     private volatile ManagementStrategy managementStrategy;
     private volatile ManagementMBeanAssembler managementMBeanAssembler;
@@ -1876,6 +1878,21 @@ public abstract class AbstractCamelContext extends BaseService
         this.configurerResolver = doAddService(configurerResolver);
     }
 
+    public AssemblerResolver getAssemblerResolver() {
+        if (assemblerResolver == null) {
+            synchronized (lock) {
+                if (assemblerResolver == null) {
+                    setAssemblerResolver(createAssemblerResolver());
+                }
+            }
+        }
+        return assemblerResolver;
+    }
+
+    public void setAssemblerResolver(AssemblerResolver assemblerResolver) {
+        this.assemblerResolver = doAddService(assemblerResolver);
+    }
+
     public boolean isAutoCreateComponents() {
         return autoCreateComponents;
     }
@@ -3206,6 +3223,7 @@ public abstract class AbstractCamelContext extends BaseService
         getRegistry();
         getLanguageResolver();
         getConfigurerResolver();
+        getAssemblerResolver();
         getExecutorServiceManager();
         getInflightRepository();
         getAsyncProcessorAwaitManager();
@@ -4208,6 +4226,8 @@ public abstract class AbstractCamelContext extends BaseService
 
     protected abstract ConfigurerResolver createConfigurerResolver();
 
+    protected abstract AssemblerResolver createAssemblerResolver();
+
     protected abstract RestRegistryFactory createRestRegistryFactory();
 
     protected abstract EndpointRegistry<EndpointKey> createEndpointRegistry(Map<EndpointKey, Endpoint> endpoints);
@@ -4237,13 +4257,7 @@ public abstract class AbstractCamelContext extends BaseService
 
     @Override
     public EndpointUriAssembler getEndpointUriAssembler(String scheme) {
-        // TODO: lookup factory specific for a given component
-
-        // no specific factory found so lets fallback to use runtime catalog
-        return new BaseServiceResolver<>(RuntimeCamelCatalog.ENDPOINT_URI_ASSEMBLER_FACTORY, EndpointUriAssembler.class)
-                .resolve(getCamelContextReference())
-                .orElseThrow(() -> new IllegalArgumentException(
-                        "Cannot find RuntimeCamelCatalog on classpath. Add camel-core-catalog to classpath."));
+        return getAssemblerResolver().resolveAssembler(scheme, this);
     }
 
     public enum Initialization {
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultAssemblerResolver.java b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultAssemblerResolver.java
new file mode 100644
index 0000000..c8ffea6
--- /dev/null
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultAssemblerResolver.java
@@ -0,0 +1,126 @@
+/*
+ * 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.impl.engine;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.NoFactoryAvailableException;
+import org.apache.camel.spi.AssemblerResolver;
+import org.apache.camel.spi.EndpointUriAssembler;
+import org.apache.camel.spi.FactoryFinder;
+import org.apache.camel.support.LRUCacheFactory;
+import org.apache.camel.support.service.ServiceSupport;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Default assembler resolver that looks for assembler factories in
+ * <b>META-INF/services/org/apache/camel/assembler/</b>.
+ */
+public class DefaultAssemblerResolver extends ServiceSupport implements CamelContextAware, AssemblerResolver {
+    public static final String RESOURCE_PATH = "META-INF/services/org/apache/camel/assembler/";
+
+    private static final Logger LOG = LoggerFactory.getLogger(DefaultAssemblerResolver.class);
+
+    private final Map<String, EndpointUriAssembler> cache = LRUCacheFactory.newLRUSoftCache(1000);
+    private CamelContext camelContext;
+    private FactoryFinder factoryFinder;
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public EndpointUriAssembler resolveAssembler(final String name, CamelContext context) {
+        if (ObjectHelper.isEmpty(name)) {
+            return null;
+        }
+
+        EndpointUriAssembler answer = cache.get(name);
+        if (answer != null) {
+            return answer;
+        }
+
+        // lookup in registry first
+        Set<EndpointUriAssembler> assemblers = context.getRegistry().findByType(EndpointUriAssembler.class);
+        answer = assemblers.stream().filter(a -> a.isEnabled(name)).findFirst().orElse(null);
+        if (answer != null) {
+            cache.put(name, answer);
+            return answer;
+        }
+
+        // not in registry then use assembler factory for endpoints
+        Class<?> type;
+        try {
+            type = findAssembler(name + "-endpoint", context);
+        } catch (NoFactoryAvailableException e) {
+            // its optional so its okay
+            type = null;
+        } catch (Exception e) {
+            throw new IllegalArgumentException("Invalid URI, no Assembler registered for scheme: " + name, e);
+        }
+
+        if (type != null) {
+            if (getLog().isDebugEnabled()) {
+                getLog().debug("Found assembler: {} via type: {} via: {}{}", name, type.getName(),
+                        factoryFinder.getResourcePath(),
+                        name);
+            }
+
+            // create the assembler
+            if (EndpointUriAssembler.class.isAssignableFrom(type)) {
+                answer = (EndpointUriAssembler) context.getInjector().newInstance(type, false);
+                cache.put(name, answer);
+                return answer;
+            } else {
+                throw new IllegalArgumentException(
+                        "Type is not a EndpointUriAssembler implementation. Found: " + type.getName());
+            }
+        }
+
+        return answer;
+    }
+
+    private Class<?> findAssembler(String name, CamelContext context) throws IOException {
+        if (factoryFinder == null) {
+            factoryFinder = context.adapt(ExtendedCamelContext.class).getFactoryFinder(RESOURCE_PATH);
+        }
+        return factoryFinder.findClass(name).orElse(null);
+    }
+
+    protected Logger getLog() {
+        return LOG;
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        cache.clear();
+    }
+
+}
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java b/core/camel-base/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
index 952f00d..0391da8 100644
--- a/core/camel-base/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
@@ -32,6 +32,7 @@ import org.apache.camel.impl.converter.DefaultTypeConverter;
 import org.apache.camel.impl.transformer.TransformerKey;
 import org.apache.camel.impl.validator.ValidatorKey;
 import org.apache.camel.processor.MulticastProcessor;
+import org.apache.camel.spi.AssemblerResolver;
 import org.apache.camel.spi.AsyncProcessorAwaitManager;
 import org.apache.camel.spi.BeanIntrospection;
 import org.apache.camel.spi.BeanProcessorFactory;
@@ -360,6 +361,11 @@ public class SimpleCamelContext extends AbstractCamelContext {
     }
 
     @Override
+    protected AssemblerResolver createAssemblerResolver() {
+        return new DefaultAssemblerResolver();
+    }
+
+    @Override
     protected RestRegistryFactory createRestRegistryFactory() {
         return new BaseServiceResolver<>(RestRegistryFactory.FACTORY, RestRegistryFactory.class)
                 .resolve(getCamelContextReference())
diff --git a/core/camel-core-catalog/src/main/java/org/apache/camel/catalog/impl/CamelCatalogEndpointUriAssembler.java b/core/camel-core-catalog/src/main/java/org/apache/camel/catalog/impl/CamelCatalogEndpointUriAssembler.java
index 7245b8d..13aaba1 100644
--- a/core/camel-core-catalog/src/main/java/org/apache/camel/catalog/impl/CamelCatalogEndpointUriAssembler.java
+++ b/core/camel-core-catalog/src/main/java/org/apache/camel/catalog/impl/CamelCatalogEndpointUriAssembler.java
@@ -17,9 +17,16 @@ import static org.apache.camel.catalog.RuntimeCamelCatalog.ENDPOINT_URI_ASSEMBLE
  * Uses {@link RuntimeCamelCatalog} to assemble the endpoint uri.
  */
 @JdkService(ENDPOINT_URI_ASSEMBLER_FACTORY)
+@Deprecated
 public class CamelCatalogEndpointUriAssembler implements EndpointUriAssembler {
 
     @Override
+    public boolean isEnabled(String scheme) {
+        // as its a fallback then assume it can handle this
+        return true;
+    }
+
+    @Override
     public String buildUri(CamelContext camelContext, String scheme, Map<String, Object> parameters) {
         try {
             Map<String, String> copy = new LinkedHashMap<>();
diff --git a/core/camel-core-engine/src/generated/java/org/apache/camel/impl/ExtendedCamelContextConfigurer.java b/core/camel-core-engine/src/generated/java/org/apache/camel/impl/ExtendedCamelContextConfigurer.java
index 74b77e7..1cfa827 100644
--- a/core/camel-core-engine/src/generated/java/org/apache/camel/impl/ExtendedCamelContextConfigurer.java
+++ b/core/camel-core-engine/src/generated/java/org/apache/camel/impl/ExtendedCamelContextConfigurer.java
@@ -23,6 +23,8 @@ public class ExtendedCamelContextConfigurer extends org.apache.camel.support.com
         case "AllowUseOriginalMessage": target.setAllowUseOriginalMessage(property(camelContext, java.lang.Boolean.class, value)); return true;
         case "applicationcontextclassloader":
         case "ApplicationContextClassLoader": target.setApplicationContextClassLoader(property(camelContext, java.lang.ClassLoader.class, value)); return true;
+        case "assemblerresolver":
+        case "AssemblerResolver": target.setAssemblerResolver(property(camelContext, org.apache.camel.spi.AssemblerResolver.class, value)); return true;
         case "asyncprocessorawaitmanager":
         case "AsyncProcessorAwaitManager": target.setAsyncProcessorAwaitManager(property(camelContext, org.apache.camel.spi.AsyncProcessorAwaitManager.class, value)); return true;
         case "autostartup":
@@ -162,6 +164,7 @@ public class ExtendedCamelContextConfigurer extends org.apache.camel.support.com
         Map<String, Object> answer = new CaseInsensitiveMap();
         answer.put("AllowUseOriginalMessage", java.lang.Boolean.class);
         answer.put("ApplicationContextClassLoader", java.lang.ClassLoader.class);
+        answer.put("AssemblerResolver", org.apache.camel.spi.AssemblerResolver.class);
         answer.put("AsyncProcessorAwaitManager", org.apache.camel.spi.AsyncProcessorAwaitManager.class);
         answer.put("AutoStartup", java.lang.Boolean.class);
         answer.put("BacklogTracing", java.lang.Boolean.class);
@@ -238,6 +241,8 @@ public class ExtendedCamelContextConfigurer extends org.apache.camel.support.com
         case "AllowUseOriginalMessage": return target.isAllowUseOriginalMessage();
         case "applicationcontextclassloader":
         case "ApplicationContextClassLoader": return target.getApplicationContextClassLoader();
+        case "assemblerresolver":
+        case "AssemblerResolver": return target.getAssemblerResolver();
         case "asyncprocessorawaitmanager":
         case "AsyncProcessorAwaitManager": return target.getAsyncProcessorAwaitManager();
         case "autostartup":
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 235fdfa..139b69b 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
@@ -71,6 +71,7 @@ import org.apache.camel.model.transformer.TransformerDefinition;
 import org.apache.camel.model.validator.ValidatorDefinition;
 import org.apache.camel.processor.channel.DefaultChannel;
 import org.apache.camel.spi.AnnotationBasedProcessorFactory;
+import org.apache.camel.spi.AssemblerResolver;
 import org.apache.camel.spi.AsyncProcessorAwaitManager;
 import org.apache.camel.spi.BeanIntrospection;
 import org.apache.camel.spi.BeanProcessorFactory;
@@ -1412,6 +1413,16 @@ public class LightweightCamelContext implements ExtendedCamelContext, CatalogCam
     }
 
     @Override
+    public AssemblerResolver getAssemblerResolver() {
+        return getExtendedCamelContext().getAssemblerResolver();
+    }
+
+    @Override
+    public void setAssemblerResolver(AssemblerResolver assemblerResolver) {
+        getExtendedCamelContext().setAssemblerResolver(assemblerResolver);
+    }
+
+    @Override
     public RouteController getInternalRouteController() {
         return getExtendedCamelContext().getInternalRouteController();
     }
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 4c993ae..cbc7fc8 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
@@ -67,6 +67,7 @@ import org.apache.camel.impl.engine.DefaultDataFormatResolver;
 import org.apache.camel.impl.engine.DefaultLanguageResolver;
 import org.apache.camel.impl.engine.EndpointKey;
 import org.apache.camel.spi.AnnotationBasedProcessorFactory;
+import org.apache.camel.spi.AssemblerResolver;
 import org.apache.camel.spi.AsyncProcessorAwaitManager;
 import org.apache.camel.spi.BeanIntrospection;
 import org.apache.camel.spi.BeanProcessorFactory;
@@ -1858,8 +1859,17 @@ public class LightweightRuntimeCamelContext implements ExtendedCamelContext, Cat
     }
 
     @Override
+    public AssemblerResolver getAssemblerResolver() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void setAssemblerResolver(AssemblerResolver assemblerResolver) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public EndpointUriAssembler getEndpointUriAssembler(String scheme) {
-        // TODO: If this experiment is continued then this should be implemented
         throw new UnsupportedOperationException();
     }
 
diff --git a/core/camel-core/src/test/java/org/apache/camel/catalog/CustomEndpointUriAssemblerTest.java b/core/camel-core/src/test/java/org/apache/camel/catalog/CustomEndpointUriAssemblerTest.java
index 30ef452..4dbdb16 100644
--- a/core/camel-core/src/test/java/org/apache/camel/catalog/CustomEndpointUriAssemblerTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/catalog/CustomEndpointUriAssemblerTest.java
@@ -23,6 +23,7 @@ import java.util.Map;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.ContextTestSupport;
+import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.spi.EndpointUriAssembler;
 import org.apache.camel.support.component.EndpointUriAssemblerSupport;
 import org.junit.jupiter.api.Assertions;
@@ -45,6 +46,21 @@ public class CustomEndpointUriAssemblerTest extends ContextTestSupport {
     }
 
     @Test
+    public void testCustomAssembleRegistry() throws Exception {
+        context.getRegistry().bind("myAssembler", new MyAssembler());
+
+        Map<String, Object> params = new HashMap<>();
+        params.put("name", "foo");
+        params.put("amount", "123");
+        params.put("port", 4444);
+        params.put("verbose", true);
+
+        EndpointUriAssembler assembler = context.adapt(ExtendedCamelContext.class).getEndpointUriAssembler("acme");
+        String uri = assembler.buildUri(context, "acme", params);
+        Assertions.assertEquals("acme:foo:4444?amount=123&verbose=true", uri);
+    }
+
+    @Test
     public void testCustomAssembleUnsorted() throws Exception {
         EndpointUriAssembler assembler = new MyAssembler();
 
@@ -71,7 +87,8 @@ public class CustomEndpointUriAssemblerTest extends ContextTestSupport {
             assembler.buildUri(context, "acme", params);
             Assertions.fail();
         } catch (IllegalArgumentException e) {
-            Assertions.assertEquals("Option name is required when creating endpoint uri with syntax acme:name:port", e.getMessage());
+            Assertions.assertEquals("Option name is required when creating endpoint uri with syntax acme:name:port",
+                    e.getMessage());
         }
     }
 
@@ -149,6 +166,11 @@ public class CustomEndpointUriAssemblerTest extends ContextTestSupport {
         private static final String SYNTAX = "acme:name:port";
 
         @Override
+        public boolean isEnabled(String scheme) {
+            return "acme".equals(scheme);
+        }
+
+        @Override
         public String buildUri(CamelContext camelContext, String scheme, Map<String, Object> parameters)
                 throws URISyntaxException {
             // begin from syntax
@@ -170,6 +192,11 @@ public class CustomEndpointUriAssemblerTest extends ContextTestSupport {
         private static final String SYNTAX = "acme2:name/path:port";
 
         @Override
+        public boolean isEnabled(String scheme) {
+            return "acme2".equals(scheme);
+        }
+
+        @Override
         public String buildUri(CamelContext camelContext, String scheme, Map<String, Object> parameters)
                 throws URISyntaxException {
             // begin from syntax
diff --git a/core/camel-core/src/test/java/org/apache/camel/component/log/LogEndpointUriAssemblerTest.java b/core/camel-core/src/test/java/org/apache/camel/component/log/LogEndpointUriAssemblerTest.java
new file mode 100644
index 0000000..f8115fd
--- /dev/null
+++ b/core/camel-core/src/test/java/org/apache/camel/component/log/LogEndpointUriAssemblerTest.java
@@ -0,0 +1,31 @@
+package org.apache.camel.component.log;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.spi.EndpointUriAssembler;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class LogEndpointUriAssemblerTest extends ContextTestSupport {
+
+    @Test
+    public void testLogAssembler() throws Exception {
+        Map<String, Object> params = new HashMap<>();
+        params.put("loggerName", "foo");
+        params.put("groupSize", "123");
+        params.put("showExchangePattern", false);
+        params.put("logMask", true);
+
+        // should find the source code generated assembler via classpath
+        EndpointUriAssembler assembler = context.adapt(ExtendedCamelContext.class).getEndpointUriAssembler("log");
+        Assertions.assertNotNull(assembler);
+        boolean generated = assembler instanceof LogEndpointUriAssembler;
+        Assertions.assertTrue(generated);
+
+        String uri = assembler.buildUri(context, "log", params);
+        Assertions.assertEquals("log:foo?groupSize=123&logMask=true&showExchangePattern=false", uri);
+    }
+}
diff --git a/core/camel-core/src/test/java/org/apache/camel/impl/AssembleResolverTest.java b/core/camel-core/src/test/java/org/apache/camel/impl/AssembleResolverTest.java
new file mode 100644
index 0000000..f4225d9
--- /dev/null
+++ b/core/camel-core/src/test/java/org/apache/camel/impl/AssembleResolverTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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.impl;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.catalog.impl.CamelCatalogEndpointUriAssembler;
+import org.apache.camel.spi.EndpointUriAssembler;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class AssembleResolverTest extends ContextTestSupport {
+
+    @Test
+    public void testAssembleResolver() throws Exception {
+        // will use source code generated
+        EndpointUriAssembler assembler = context.adapt(ExtendedCamelContext.class).getAssemblerResolver()
+                .resolveAssembler("log", context);
+        Assertions.assertNotNull(assembler);
+        // TODO: check classname
+
+        // will then use fallback that is catalog based
+        assembler = context.adapt(ExtendedCamelContext.class).getAssemblerResolver()
+                .resolveAssembler("unknown", context);
+        Assertions.assertNotNull(assembler);
+        boolean catalog = assembler instanceof CamelCatalogEndpointUriAssembler;
+        Assertions.assertTrue(catalog);
+    }
+}
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/component/EndpointUriAssemblerSupport.java b/core/camel-support/src/main/java/org/apache/camel/support/component/EndpointUriAssemblerSupport.java
index d3e1c8c..9b5a6f6 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/component/EndpointUriAssemblerSupport.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/component/EndpointUriAssemblerSupport.java
@@ -49,7 +49,7 @@ public abstract class EndpointUriAssemblerSupport {
             int pos = uri.indexOf(name);
             if (pos != -1) {
                 // remove from syntax
-                uri = uri.replace(name, "");
+                uri = uri.replaceFirst(name, "");
                 pos = pos - 1;
                 // remove the separator char
                 char ch = uri.charAt(pos);
diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/EndpointUriAssemblerGenerator.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/EndpointUriAssemblerGenerator.java
index 01b2e38..abba8520 100644
--- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/EndpointUriAssemblerGenerator.java
+++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/EndpointUriAssemblerGenerator.java
@@ -18,6 +18,7 @@ package org.apache.camel.maven.packaging;
 
 import java.io.IOException;
 import java.io.Writer;
+import java.util.StringJoiner;
 
 import org.apache.camel.tooling.model.BaseOptionModel;
 import org.apache.camel.tooling.model.ComponentModel;
@@ -46,14 +47,34 @@ public final class EndpointUriAssemblerGenerator {
         w.write(" */\n");
         w.write("public class " + cn + " extends " + psn + " implements EndpointUriAssembler {\n");
         w.write("\n");
-        w.write("    private static final String SYNTAX = \"" + model.getSyntax() + "\";\n");
+        w.write("    private static final String BASE = \"" + baseSyntax(model) + "\";\n");
+
+        String alternative = alternativeSchemes(model);
+        if (alternative != null) {
+            w.write("    private static final String[] SCHEMES = " + alternative + ";\n");
+        }
+        w.write("\n");
+        w.write("    @Override\n");
+        w.write("    public boolean isEnabled(String scheme) {\n");
+        if (alternative == null) {
+            w.write("        return \"" + model.getScheme() + "\".equals(scheme);\n");
+        } else {
+            w.write("        for (String s : SCHEMES) {\n");
+            w.write("            if (s.equals(scheme)) {\n");
+            w.write("                return true;\n");
+            w.write("            }\n");
+            w.write("        }\n");
+            w.write("        return false;\n");
+        }
+        w.write("    }\n");
         w.write("\n");
         w.write("    @Override\n");
         w.write("    public String buildUri(CamelContext camelContext, String scheme, Map<String, Object> parameters) throws URISyntaxException {\n");
-        w.write("        String uri = SYNTAX;\n");
+        w.write("        String syntax = scheme + BASE;\n");
+        w.write("        String uri = syntax;\n");
         w.write("\n");
         for (BaseOptionModel option : model.getEndpointPathOptions()) {
-            w.write("        uri = buildPathParameter(camelContext, SYNTAX, uri, \"" + option.getName() + "\", "
+            w.write("        uri = buildPathParameter(camelContext, syntax, uri, \"" + option.getName() + "\", "
                     + option.getDefaultValue() + ", " + option.isRequired() + ", parameters);\n");
         }
         w.write("        uri = buildQueryParameters(camelContext, uri, parameters);\n");
@@ -63,4 +84,28 @@ public final class EndpointUriAssemblerGenerator {
         w.write("\n");
     }
 
+    private static String alternativeSchemes(ComponentModel model) {
+        StringBuilder sb = new StringBuilder();
+        if (model.getAlternativeSchemes() != null) {
+            sb.append("new String[]{");
+            String[] alts = model.getAlternativeSchemes().split(",");
+            StringJoiner sj = new StringJoiner(", ");
+            for (String alt : alts) {
+                sj.add("\"" + alt + "\"");
+            }
+            sb.append(sj.toString());
+            sb.append("}");
+        }
+        if (sb.length() == 0) {
+            return null;
+        }
+        return sb.toString();
+    }
+
+    private static String baseSyntax(ComponentModel model) {
+        String base = model.getSyntax();
+        base = base.replaceFirst(model.getScheme(), "");
+        return base;
+    }
+
 }