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

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


The following commit(s) were added to refs/heads/main by this push:
     new 767ada7  CAMEL-16585: camel-kamelet - Main class to easily bootstrap 
Camel with Kamelets
767ada7 is described below

commit 767ada71ddec46f3438f3c5dbd586f0e153a5c69
Author: Claus Ibsen <[email protected]>
AuthorDate: Sat May 22 08:18:43 2021 +0200

    CAMEL-16585: camel-kamelet - Main class to easily bootstrap Camel with 
Kamelets
---
 .../apache/camel/catalog/components/kamelet.json   |   3 +-
 .../camel/catalog/docs/kamelet-component.adoc      |   3 +-
 .../apache/camel/catalog/docs/kamelet-main.adoc    |  13 ++
 .../apache/camel/main/DependencyDownloader.java    |  80 +++++++++++
 .../camel/main/KameletDependencyDownloader.java    | 157 +++++++++++++++++++++
 .../java/org/apache/camel/main/KameletMain.java    |  24 ++++
 .../kamelet/KameletComponentConfigurer.java        |   6 +
 .../apache/camel/component/kamelet/kamelet.json    |   3 +-
 .../src/main/docs/kamelet-component.adoc           |   3 +-
 .../camel/component/kamelet/KameletComponent.java  |  23 +++
 .../kamelet/KameletResourceLoaderListener.java     |  36 +++++
 .../dsl/KameletComponentBuilderFactory.java        |  18 +++
 .../modules/ROOT/pages/kamelet-component.adoc      |   3 +-
 .../modules/others/pages/kamelet-main.adoc         |  13 ++
 .../dsl/yaml/YamlRoutesBuilderLoaderSupport.java   |   2 +-
 15 files changed, 381 insertions(+), 6 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/kamelet.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/kamelet.json
index 253afb7..e4a6af8 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/kamelet.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/kamelet.json
@@ -29,7 +29,8 @@
     "block": { "kind": "property", "displayName": "Block", "group": 
"producer", "label": "producer", "required": false, "type": "boolean", 
"javaType": "boolean", "deprecated": false, "autowired": false, "secret": 
false, "defaultValue": true, "description": "If sending a message to a kamelet 
endpoint which has no active consumer, then we can tell the producer to block 
and wait for the consumer to become active." },
     "lazyStartProducer": { "kind": "property", "displayName": "Lazy Start 
Producer", "group": "producer", "label": "producer", "required": false, "type": 
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": false, "description": "Whether the producer 
should be started lazy (on the first message). By starting lazy you can use 
this to allow CamelContext and routes to startup in situations where a producer 
may otherwise fail during star [...]
     "timeout": { "kind": "property", "displayName": "Timeout", "group": 
"producer", "label": "producer", "required": false, "type": "integer", 
"javaType": "long", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": 30000, "description": "The timeout value to use if block is 
enabled." },
-    "autowiredEnabled": { "kind": "property", "displayName": "Autowired 
Enabled", "group": "advanced", "label": "advanced", "required": false, "type": 
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": true, "description": "Whether autowiring is 
enabled. This is used for automatic autowiring options (the option must be 
marked as autowired) by looking up in the registry to find if there is a single 
instance of matching type, which t [...]
+    "autowiredEnabled": { "kind": "property", "displayName": "Autowired 
Enabled", "group": "advanced", "label": "advanced", "required": false, "type": 
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": true, "description": "Whether autowiring is 
enabled. This is used for automatic autowiring options (the option must be 
marked as autowired) by looking up in the registry to find if there is a single 
instance of matching type, which t [...]
+    "kameletResourceLoaderListener": { "kind": "property", "displayName": 
"Kamelet Resource Loader Listener", "group": "advanced", "label": "advanced", 
"required": false, "type": "object", "javaType": 
"org.apache.camel.component.kamelet.KameletResourceLoaderListener", 
"deprecated": false, "autowired": false, "secret": false, "description": "To 
plugin a custom listener for when the Kamelet component is loading Kamelets 
from external resources." }
   },
   "properties": {
     "templateId": { "kind": "path", "displayName": "Template Id", "group": 
"common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The Route Template ID" },
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/kamelet-component.adoc
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/kamelet-component.adoc
index 31f1f36..07c8d02 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/kamelet-component.adoc
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/kamelet-component.adoc
@@ -27,7 +27,7 @@ kamelet:templateId/routeId[?options]
 
 
 // component options: START
-The Kamelet component supports 8 options, which are listed below.
+The Kamelet component supports 9 options, which are listed below.
 
 
 
@@ -42,6 +42,7 @@ The Kamelet component supports 8 options, which are listed 
below.
 | *lazyStartProducer* (producer) | Whether the producer should be started lazy 
(on the first message). By starting lazy you can use this to allow CamelContext 
and routes to startup in situations where a producer may otherwise fail during 
starting and cause the route to fail being started. By deferring this startup 
to be lazy then the startup failure can be handled during routing messages via 
Camel's routing error handlers. Beware that when the first message is processed 
then creating and [...]
 | *timeout* (producer) | The timeout value to use if block is enabled. | 30000 
| long
 | *autowiredEnabled* (advanced) | Whether autowiring is enabled. This is used 
for automatic autowiring options (the option must be marked as autowired) by 
looking up in the registry to find if there is a single instance of matching 
type, which then gets configured on the component. This can be used for 
automatic configuring JDBC data sources, JMS connection factories, AWS Clients, 
etc. | true | boolean
+| *kameletResourceLoaderListener* (advanced) | To plugin a custom listener for 
when the Kamelet component is loading Kamelets from external resources. |  | 
KameletResourceLoaderListener
 |===
 // component options: END
 
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/kamelet-main.adoc
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/kamelet-main.adoc
index 24c1ab9..2120967 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/kamelet-main.adoc
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/kamelet-main.adoc
@@ -10,3 +10,16 @@ 
include::{cq-version}@camel-quarkus:ROOT:partial$reference/others/kamelet-main.a
 *Since Camel {since}*
 
 A `main` class that is opinionated to boostrap and run Camel standalone with 
Kameleets for development and demo purposes.
+
+== Initial configuration
+
+The `KameletMain` is pre-configured with the following properties:
+
+[source,properties]
+----
+camel.component.kamelet.location = 
classpath:/kamelets,github:apache:camel-kamelets
+camel.main.routes-include-pattern = classpath:camel/*
+camel.main.lightweight = true
+----
+
+These settings can be overridden by configuration in `application.properties`.
\ No newline at end of file
diff --git 
a/components/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloader.java
 
b/components/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloader.java
new file mode 100644
index 0000000..e6fe851
--- /dev/null
+++ 
b/components/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloader.java
@@ -0,0 +1,80 @@
+/*
+ * 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.main;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.component.kamelet.KameletComponent;
+import org.apache.camel.component.kamelet.KameletResourceLoaderListener;
+import org.apache.camel.spi.Resource;
+import org.apache.camel.support.service.ServiceHelper;
+import org.apache.camel.support.service.ServiceSupport;
+
+/**
+ * To automatic downloaded dependencies that Kamelets requires.
+ */
+public final class DependencyDownloader extends ServiceSupport implements 
CamelContextAware, KameletResourceLoaderListener {
+
+    private final KameletDependencyDownloader downloader = new 
KameletDependencyDownloader("yaml");
+    private CamelContext camelContext;
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    protected void doBuild() throws Exception {
+        KameletComponent kc = camelContext.getComponent("kamelet", 
KameletComponent.class);
+        kc.setKameletResourceLoaderListener(this);
+
+        downloader.setCamelContext(camelContext);
+        ServiceHelper.buildService(downloader);
+    }
+
+    @Override
+    protected void doInit() throws Exception {
+        ServiceHelper.initService(downloader);
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        ServiceHelper.startService(downloader);
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        ServiceHelper.stopService(downloader);
+    }
+
+    @Override
+    public void loadKamelets(Resource resource) {
+        if (resource.getLocation().endsWith(".yaml")) {
+            try {
+                downloader.doLoadRouteBuilder(resource);
+            } catch (Exception e) {
+                throw RuntimeCamelException.wrapRuntimeException(e);
+            }
+        }
+    }
+}
diff --git 
a/components/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletDependencyDownloader.java
 
b/components/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletDependencyDownloader.java
new file mode 100644
index 0000000..7709078
--- /dev/null
+++ 
b/components/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletDependencyDownloader.java
@@ -0,0 +1,157 @@
+/*
+ * 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.main;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.dsl.yaml.YamlRoutesBuilderLoaderSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.snakeyaml.engine.v2.nodes.Node;
+import org.snakeyaml.engine.v2.nodes.NodeType;
+import org.snakeyaml.engine.v2.nodes.ScalarNode;
+import org.snakeyaml.engine.v2.nodes.SequenceNode;
+
+import static org.apache.camel.dsl.yaml.common.YamlDeserializerSupport.nodeAt;
+
+/**
+ * Reuse the YAML DSL support for parsing Kamelets
+ */
+public class KameletDependencyDownloader extends 
YamlRoutesBuilderLoaderSupport implements CamelContextAware {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(KameletDependencyDownloader.class);
+    private CamelContext camelContext;
+    private final String cp = System.getProperty("java.class.path");
+    private final Set<String> downloaded = new HashSet<>();
+
+    public KameletDependencyDownloader(String extension) {
+        super(extension);
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    protected RouteBuilder builder(Node node) {
+        final List<String> dependencies = new ArrayList<>();
+
+        Node deps = nodeAt(node, "/spec/dependencies");
+        if (deps.getNodeType() == NodeType.SEQUENCE) {
+            SequenceNode sn = (SequenceNode) deps;
+            for (Node child : sn.getValue()) {
+                if (child.getNodeType() == NodeType.SCALAR) {
+                    ScalarNode scn = (ScalarNode) child;
+                    String dep = scn.getValue();
+                    if (dep != null) {
+                        LOG.trace("Kamelet dependency: {}", dep);
+                        dependencies.add(dep);
+                    }
+
+                }
+            }
+        }
+
+        downloadDependencies(dependencies);
+
+        // need to fool and return an empty route builder
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // noop
+            }
+        };
+    }
+
+    private void downloadDependencies(List<String> dependencies) {
+        final List<String> gavs = new ArrayList<>();
+        for (String dep : dependencies) {
+            String gav = dep;
+            if (dep.startsWith("camel:")) {
+                // its a known camel component
+                gav = "org.apache.camel:camel-" + dep.substring(6) + ":" + 
camelContext.getVersion();
+            }
+            if (isValidGav(gav)) {
+                gavs.add(gav);
+            }
+        }
+
+        for (String gav : gavs) {
+            LOG.debug("Downloading dependency: {}", gav);
+            // TODO: download dependency and add to classpath
+        }
+    }
+
+    private boolean isValidGav(String gav) {
+        if (downloaded.contains(gav)) {
+            // already downloaded
+            return false;
+        }
+
+        // skip camel-core and camel-kamelet as they are already included
+        if (gav.startsWith("org.apache.camel:camel-core") || 
gav.startsWith("org.apache.camel:camel-kamelet:")) {
+            return false;
+        }
+
+        String[] arr = gav.split(":");
+        String name = null;
+        if (arr.length == 3) {
+            String aid = arr[1];
+            String v = arr[2];
+            name = aid + "-" + v + ".jar";
+        }
+
+        if (name != null && cp != null) {
+            // is it already on classpath
+            if (cp.contains(name)) {
+                // already on classpath
+                return false;
+            }
+        }
+
+        if (name != null && camelContext.getApplicationContextClassLoader() != 
null) {
+            ClassLoader cl = camelContext.getApplicationContextClassLoader();
+            if (cl instanceof URLClassLoader) {
+                URLClassLoader ucl = (URLClassLoader) cl;
+                for (URL u : ucl.getURLs()) {
+                    String s = u.toString();
+                    if (s.contains(name)) {
+                        // already on classpath
+                        return false;
+                    }
+                }
+            }
+        }
+
+        return true;
+    }
+
+}
diff --git 
a/components/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
 
b/components/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
index eece4d2..dcbf733 100644
--- 
a/components/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
+++ 
b/components/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
@@ -20,6 +20,7 @@ import java.util.Map;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.ProducerTemplate;
+import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.spi.Registry;
 
@@ -30,6 +31,7 @@ public class KameletMain extends MainCommandLineSupport {
 
     protected static KameletMain instance;
     protected final MainRegistry registry = new MainRegistry();
+    private boolean download = true;
 
     public static void main(String... args) throws Exception {
         KameletMain main = new KameletMain();
@@ -91,6 +93,18 @@ public class KameletMain extends MainCommandLineSupport {
         return registry.findByTypeWithName(type);
     }
 
+    public boolean isDownload() {
+        return download;
+    }
+
+    /**
+     * Whether to allow automatic downloaded JAR dependencies, over the 
internet, that Kamelets requires. This is by
+     * default enabled.
+     */
+    public void setDownload(boolean download) {
+        this.download = download;
+    }
+
     // Implementation methods
     // 
-------------------------------------------------------------------------
 
@@ -136,10 +150,20 @@ public class KameletMain extends MainCommandLineSupport {
     protected CamelContext createCamelContext() {
         // do not build/init camel context yet
         DefaultCamelContext answer = new DefaultCamelContext(false);
+        
answer.setApplicationContextClassLoader(KameletMain.class.getClassLoader());
         answer.setRegistry(registry);
         instance.addInitialProperty("camel.component.kamelet.location", 
"classpath:/kamelets,github:apache:camel-kamelets");
         instance.addInitialProperty("camel.main.routes-include-pattern", 
"classpath:camel/*");
         instance.addInitialProperty("camel.main.lightweight", "true");
+
+        if (download) {
+            try {
+                answer.addService(new DependencyDownloader());
+            } catch (Exception e) {
+                throw RuntimeCamelException.wrapRuntimeException(e);
+            }
+        }
+
         return answer;
     }
 
diff --git 
a/components/camel-kamelet/src/generated/java/org/apache/camel/component/kamelet/KameletComponentConfigurer.java
 
b/components/camel-kamelet/src/generated/java/org/apache/camel/component/kamelet/KameletComponentConfigurer.java
index 1cc8ff6..ab5be2f 100644
--- 
a/components/camel-kamelet/src/generated/java/org/apache/camel/component/kamelet/KameletComponentConfigurer.java
+++ 
b/components/camel-kamelet/src/generated/java/org/apache/camel/component/kamelet/KameletComponentConfigurer.java
@@ -26,6 +26,8 @@ public class KameletComponentConfigurer extends 
PropertyConfigurerSupport implem
         case "block": target.setBlock(property(camelContext, boolean.class, 
value)); return true;
         case "bridgeerrorhandler":
         case "bridgeErrorHandler": 
target.setBridgeErrorHandler(property(camelContext, boolean.class, value)); 
return true;
+        case "kameletresourceloaderlistener":
+        case "kameletResourceLoaderListener": 
target.setKameletResourceLoaderListener(property(camelContext, 
org.apache.camel.component.kamelet.KameletResourceLoaderListener.class, 
value)); return true;
         case "lazystartproducer":
         case "lazyStartProducer": 
target.setLazyStartProducer(property(camelContext, boolean.class, value)); 
return true;
         case "location": target.setLocation(property(camelContext, 
java.lang.String.class, value)); return true;
@@ -46,6 +48,8 @@ public class KameletComponentConfigurer extends 
PropertyConfigurerSupport implem
         case "block": return boolean.class;
         case "bridgeerrorhandler":
         case "bridgeErrorHandler": return boolean.class;
+        case "kameletresourceloaderlistener":
+        case "kameletResourceLoaderListener": return 
org.apache.camel.component.kamelet.KameletResourceLoaderListener.class;
         case "lazystartproducer":
         case "lazyStartProducer": return boolean.class;
         case "location": return java.lang.String.class;
@@ -67,6 +71,8 @@ public class KameletComponentConfigurer extends 
PropertyConfigurerSupport implem
         case "block": return target.isBlock();
         case "bridgeerrorhandler":
         case "bridgeErrorHandler": return target.isBridgeErrorHandler();
+        case "kameletresourceloaderlistener":
+        case "kameletResourceLoaderListener": return 
target.getKameletResourceLoaderListener();
         case "lazystartproducer":
         case "lazyStartProducer": return target.isLazyStartProducer();
         case "location": return target.getLocation();
diff --git 
a/components/camel-kamelet/src/generated/resources/org/apache/camel/component/kamelet/kamelet.json
 
b/components/camel-kamelet/src/generated/resources/org/apache/camel/component/kamelet/kamelet.json
index 253afb7..e4a6af8 100644
--- 
a/components/camel-kamelet/src/generated/resources/org/apache/camel/component/kamelet/kamelet.json
+++ 
b/components/camel-kamelet/src/generated/resources/org/apache/camel/component/kamelet/kamelet.json
@@ -29,7 +29,8 @@
     "block": { "kind": "property", "displayName": "Block", "group": 
"producer", "label": "producer", "required": false, "type": "boolean", 
"javaType": "boolean", "deprecated": false, "autowired": false, "secret": 
false, "defaultValue": true, "description": "If sending a message to a kamelet 
endpoint which has no active consumer, then we can tell the producer to block 
and wait for the consumer to become active." },
     "lazyStartProducer": { "kind": "property", "displayName": "Lazy Start 
Producer", "group": "producer", "label": "producer", "required": false, "type": 
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": false, "description": "Whether the producer 
should be started lazy (on the first message). By starting lazy you can use 
this to allow CamelContext and routes to startup in situations where a producer 
may otherwise fail during star [...]
     "timeout": { "kind": "property", "displayName": "Timeout", "group": 
"producer", "label": "producer", "required": false, "type": "integer", 
"javaType": "long", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": 30000, "description": "The timeout value to use if block is 
enabled." },
-    "autowiredEnabled": { "kind": "property", "displayName": "Autowired 
Enabled", "group": "advanced", "label": "advanced", "required": false, "type": 
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": true, "description": "Whether autowiring is 
enabled. This is used for automatic autowiring options (the option must be 
marked as autowired) by looking up in the registry to find if there is a single 
instance of matching type, which t [...]
+    "autowiredEnabled": { "kind": "property", "displayName": "Autowired 
Enabled", "group": "advanced", "label": "advanced", "required": false, "type": 
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": true, "description": "Whether autowiring is 
enabled. This is used for automatic autowiring options (the option must be 
marked as autowired) by looking up in the registry to find if there is a single 
instance of matching type, which t [...]
+    "kameletResourceLoaderListener": { "kind": "property", "displayName": 
"Kamelet Resource Loader Listener", "group": "advanced", "label": "advanced", 
"required": false, "type": "object", "javaType": 
"org.apache.camel.component.kamelet.KameletResourceLoaderListener", 
"deprecated": false, "autowired": false, "secret": false, "description": "To 
plugin a custom listener for when the Kamelet component is loading Kamelets 
from external resources." }
   },
   "properties": {
     "templateId": { "kind": "path", "displayName": "Template Id", "group": 
"common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The Route Template ID" },
diff --git a/components/camel-kamelet/src/main/docs/kamelet-component.adoc 
b/components/camel-kamelet/src/main/docs/kamelet-component.adoc
index 31f1f36..07c8d02 100644
--- a/components/camel-kamelet/src/main/docs/kamelet-component.adoc
+++ b/components/camel-kamelet/src/main/docs/kamelet-component.adoc
@@ -27,7 +27,7 @@ kamelet:templateId/routeId[?options]
 
 
 // component options: START
-The Kamelet component supports 8 options, which are listed below.
+The Kamelet component supports 9 options, which are listed below.
 
 
 
@@ -42,6 +42,7 @@ The Kamelet component supports 8 options, which are listed 
below.
 | *lazyStartProducer* (producer) | Whether the producer should be started lazy 
(on the first message). By starting lazy you can use this to allow CamelContext 
and routes to startup in situations where a producer may otherwise fail during 
starting and cause the route to fail being started. By deferring this startup 
to be lazy then the startup failure can be handled during routing messages via 
Camel's routing error handlers. Beware that when the first message is processed 
then creating and [...]
 | *timeout* (producer) | The timeout value to use if block is enabled. | 30000 
| long
 | *autowiredEnabled* (advanced) | Whether autowiring is enabled. This is used 
for automatic autowiring options (the option must be marked as autowired) by 
looking up in the registry to find if there is a single instance of matching 
type, which then gets configured on the component. This can be used for 
automatic configuring JDBC data sources, JMS connection factories, AWS Clients, 
etc. | true | boolean
+| *kameletResourceLoaderListener* (advanced) | To plugin a custom listener for 
when the Kamelet component is loading Kamelets from external resources. |  | 
KameletResourceLoaderListener
 |===
 // component options: END
 
diff --git 
a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletComponent.java
 
b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletComponent.java
index 64cd01b..d14ec93 100644
--- 
a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletComponent.java
+++ 
b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletComponent.java
@@ -60,6 +60,9 @@ public class KameletComponent extends DefaultComponent {
     // active kamelet EIPs
     private final Map<String, Processor> kameletEips = new 
ConcurrentHashMap<>();
 
+    @Metadata(label = "advanced")
+    private KameletResourceLoaderListener kameletResourceLoaderListener;
+
     // counter that is used for producers to keep track if any consumer was 
added/removed since they last checked
     // this is used for optimization to avoid each producer to get consumer 
for each message processed
     // (locking via synchronized, and then lookup in the map as the cost)
@@ -278,6 +281,17 @@ public class KameletComponent extends DefaultComponent {
         this.location = location;
     }
 
+    public KameletResourceLoaderListener getKameletResourceLoaderListener() {
+        return kameletResourceLoaderListener;
+    }
+
+    /**
+     * To plugin a custom listener for when the Kamelet component is loading 
Kamelets from external resources.
+     */
+    public void setKameletResourceLoaderListener(KameletResourceLoaderListener 
kameletResourceLoaderListener) {
+        this.kameletResourceLoaderListener = kameletResourceLoaderListener;
+    }
+
     int getStateCounter() {
         return stateCounter;
     }
@@ -380,6 +394,15 @@ public class KameletComponent extends DefaultComponent {
                     String name = path + templateId + ".kamelet.yaml";
                     Resource res = 
ecc.getResourceLoader().resolveResource(name);
                     if (res.exists()) {
+                        try {
+                            if (kameletResourceLoaderListener != null) {
+                                
kameletResourceLoaderListener.loadKamelets(res);
+                            }
+                        } catch (Exception e) {
+                            LOGGER.warn("KameletResourceLoaderListener error 
due to " + e.getMessage()
+                                        + ". This exception is ignored",
+                                    e);
+                        }
                         ecc.getRoutesLoader().loadRoutes(res);
                         found = true;
                         break;
diff --git 
a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletResourceLoaderListener.java
 
b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletResourceLoaderListener.java
new file mode 100644
index 0000000..3692a52
--- /dev/null
+++ 
b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletResourceLoaderListener.java
@@ -0,0 +1,36 @@
+/*
+ * 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.component.kamelet;
+
+import org.apache.camel.spi.Resource;
+
+/**
+ * Listener when the Kamelet component is loaing Kamelet(s) from a {@link 
Resource}.
+ *
+ * For example when Kamelets are loaded from YAML files from the classpath, or 
via github from the Apache Camel Kamelet
+ * Catalog.
+ */
+@FunctionalInterface
+public interface KameletResourceLoaderListener {
+
+    /**
+     * About to load kamelets from the given resource.
+     *
+     * @param resource the resource that has kamelets to be loaded
+     */
+    void loadKamelets(Resource resource);
+}
diff --git 
a/core/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/KameletComponentBuilderFactory.java
 
b/core/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/KameletComponentBuilderFactory.java
index 73a935a..f4c2d89 100644
--- 
a/core/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/KameletComponentBuilderFactory.java
+++ 
b/core/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/KameletComponentBuilderFactory.java
@@ -197,6 +197,23 @@ public interface KameletComponentBuilderFactory {
             doSetProperty("autowiredEnabled", autowiredEnabled);
             return this;
         }
+        /**
+         * To plugin a custom listener for when the Kamelet component is 
loading
+         * Kamelets from external resources.
+         * 
+         * The option is a:
+         * 
&lt;code&gt;org.apache.camel.component.kamelet.KameletResourceLoaderListener&lt;/code&gt;
 type.
+         * 
+         * Group: advanced
+         * 
+         * @param kameletResourceLoaderListener the value to set
+         * @return the dsl builder
+         */
+        default KameletComponentBuilder kameletResourceLoaderListener(
+                
org.apache.camel.component.kamelet.KameletResourceLoaderListener 
kameletResourceLoaderListener) {
+            doSetProperty("kameletResourceLoaderListener", 
kameletResourceLoaderListener);
+            return this;
+        }
     }
 
     class KameletComponentBuilderImpl
@@ -222,6 +239,7 @@ public interface KameletComponentBuilderFactory {
             case "lazyStartProducer": ((KameletComponent) 
component).setLazyStartProducer((boolean) value); return true;
             case "timeout": ((KameletComponent) component).setTimeout((long) 
value); return true;
             case "autowiredEnabled": ((KameletComponent) 
component).setAutowiredEnabled((boolean) value); return true;
+            case "kameletResourceLoaderListener": ((KameletComponent) 
component).setKameletResourceLoaderListener((org.apache.camel.component.kamelet.KameletResourceLoaderListener)
 value); return true;
             default: return false;
             }
         }
diff --git a/docs/components/modules/ROOT/pages/kamelet-component.adoc 
b/docs/components/modules/ROOT/pages/kamelet-component.adoc
index 2cbc496..982b910 100644
--- a/docs/components/modules/ROOT/pages/kamelet-component.adoc
+++ b/docs/components/modules/ROOT/pages/kamelet-component.adoc
@@ -29,7 +29,7 @@ kamelet:templateId/routeId[?options]
 
 
 // component options: START
-The Kamelet component supports 8 options, which are listed below.
+The Kamelet component supports 9 options, which are listed below.
 
 
 
@@ -44,6 +44,7 @@ The Kamelet component supports 8 options, which are listed 
below.
 | *lazyStartProducer* (producer) | Whether the producer should be started lazy 
(on the first message). By starting lazy you can use this to allow CamelContext 
and routes to startup in situations where a producer may otherwise fail during 
starting and cause the route to fail being started. By deferring this startup 
to be lazy then the startup failure can be handled during routing messages via 
Camel's routing error handlers. Beware that when the first message is processed 
then creating and [...]
 | *timeout* (producer) | The timeout value to use if block is enabled. | 30000 
| long
 | *autowiredEnabled* (advanced) | Whether autowiring is enabled. This is used 
for automatic autowiring options (the option must be marked as autowired) by 
looking up in the registry to find if there is a single instance of matching 
type, which then gets configured on the component. This can be used for 
automatic configuring JDBC data sources, JMS connection factories, AWS Clients, 
etc. | true | boolean
+| *kameletResourceLoaderListener* (advanced) | To plugin a custom listener for 
when the Kamelet component is loading Kamelets from external resources. |  | 
KameletResourceLoaderListener
 |===
 // component options: END
 
diff --git a/docs/components/modules/others/pages/kamelet-main.adoc 
b/docs/components/modules/others/pages/kamelet-main.adoc
index 06aa14d..3d26044 100644
--- a/docs/components/modules/others/pages/kamelet-main.adoc
+++ b/docs/components/modules/others/pages/kamelet-main.adoc
@@ -12,3 +12,16 @@ 
include::{cq-version}@camel-quarkus:ROOT:partial$reference/others/kamelet-main.a
 *Since Camel {since}*
 
 A `main` class that is opinionated to boostrap and run Camel standalone with 
Kameleets for development and demo purposes.
+
+== Initial configuration
+
+The `KameletMain` is pre-configured with the following properties:
+
+[source,properties]
+----
+camel.component.kamelet.location = 
classpath:/kamelets,github:apache:camel-kamelets
+camel.main.routes-include-pattern = classpath:camel/*
+camel.main.lightweight = true
+----
+
+These settings can be overridden by configuration in `application.properties`.
\ No newline at end of file
diff --git 
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoaderSupport.java
 
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoaderSupport.java
index 9f8078c..25c1560 100644
--- 
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoaderSupport.java
+++ 
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoaderSupport.java
@@ -39,7 +39,7 @@ import org.snakeyaml.engine.v2.parser.Parser;
 import org.snakeyaml.engine.v2.parser.ParserImpl;
 import org.snakeyaml.engine.v2.scanner.StreamReader;
 
-abstract class YamlRoutesBuilderLoaderSupport extends 
RouteBuilderLoaderSupport {
+public abstract class YamlRoutesBuilderLoaderSupport extends 
RouteBuilderLoaderSupport {
     public static final String DESERIALIZATION_MODE = 
"CamelYamlDslDeserializationMode";
 
     private LoadSettings settings;

Reply via email to