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

commit d2eb4972d0bbf2fcf7f0d5fecd680247a6044e77
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Sat Mar 19 00:27:52 2022 +0100

    CAMEL-17815: camel-jbang - In modeline mode then eager discover routes and 
pre-load modeline to allow properties to be used during bootstrap.
---
 .../camel/impl/engine/DefaultRoutesLoader.java     |   6 +
 .../org/apache/camel/main/BaseMainSupport.java     | 124 ++++++++++++++++++++-
 .../org/apache/camel/main/RoutesConfigurer.java    |  71 +++++++-----
 .../apache/camel/dsl/modeline/PropertyTrait.java   |  14 ++-
 .../java/org/apache/camel/main/KameletMain.java    |   2 +-
 5 files changed, 186 insertions(+), 31 deletions(-)

diff --git 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultRoutesLoader.java
 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultRoutesLoader.java
index f06701f..1d134e3 100644
--- 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultRoutesLoader.java
+++ 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultRoutesLoader.java
@@ -101,6 +101,12 @@ public class DefaultRoutesLoader extends ServiceSupport 
implements RoutesLoader,
                         "Cannot find RoutesBuilderLoader in classpath 
supporting file extension: " + extension);
             }
 
+            if (camelContext.isModeline()) {
+                ModelineFactory factory = 
camelContext.adapt(ExtendedCamelContext.class).getModelineFactory();
+                // gather resources for modeline
+                factory.parseModeline(resource);
+            }
+
             RoutesBuilder builder = loader.loadRoutesBuilder(resource);
             if (builder != null) {
                 answer.add(builder);
diff --git 
a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java 
b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
index 5004766..0675f31 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
@@ -383,6 +383,13 @@ public abstract class BaseMainSupport extends BaseService {
         if (mainConfigurationProperties.isAutoConfigurationEnabled()) {
             autoConfigurationFailFast(camelContext, autoConfiguredProperties);
             autoConfigurationPropertiesComponent(camelContext, 
autoConfiguredProperties);
+
+            // eager load properties from modeline by scanning DSL sources and 
gather properties for auto configuration
+            if (camelContext.isModeline() || configure().isModeline()) {
+                autoConfigurationRoutesIncludePattern(camelContext, 
autoConfiguredProperties);
+                modelineRoutes(camelContext);
+            }
+
             autoConfigurationMainConfiguration(camelContext, 
mainConfigurationProperties, autoConfiguredProperties);
         }
 
@@ -490,10 +497,32 @@ public abstract class BaseMainSupport extends BaseService 
{
         }
     }
 
+    protected void modelineRoutes(CamelContext camelContext) throws Exception {
+        // then configure and add the routes
+        RoutesConfigurer configurer = new RoutesConfigurer();
+
+        if (mainConfigurationProperties.isRoutesCollectorEnabled()) {
+            configurer.setRoutesCollector(routesCollector);
+        }
+
+        
configurer.setBeanPostProcessor(camelContext.adapt(ExtendedCamelContext.class).getBeanPostProcessor());
+        
configurer.setRoutesBuilders(mainConfigurationProperties.getRoutesBuilders());
+        
configurer.setRoutesBuilderClasses(mainConfigurationProperties.getRoutesBuilderClasses());
+        if (mainConfigurationProperties.isBasePackageScanEnabled()) {
+            // only set the base package if enabled
+            
configurer.setBasePackageScan(mainConfigurationProperties.getBasePackageScan());
+        }
+        
configurer.setJavaRoutesExcludePattern(mainConfigurationProperties.getJavaRoutesExcludePattern());
+        
configurer.setJavaRoutesIncludePattern(mainConfigurationProperties.getJavaRoutesIncludePattern());
+        
configurer.setRoutesExcludePattern(mainConfigurationProperties.getRoutesExcludePattern());
+        
configurer.setRoutesIncludePattern(mainConfigurationProperties.getRoutesIncludePattern());
+
+        configurer.configureModeline(camelContext);
+    }
+
     protected void configureRoutes(CamelContext camelContext) throws Exception 
{
         // then configure and add the routes
         RoutesConfigurer configurer = new RoutesConfigurer();
-        configurer.setmodeline(camelContext.isModeline());
 
         if (mainConfigurationProperties.isRoutesCollectorEnabled()) {
             configurer.setRoutesCollector(routesCollector);
@@ -510,6 +539,7 @@ public abstract class BaseMainSupport extends BaseService {
         
configurer.setJavaRoutesIncludePattern(mainConfigurationProperties.getJavaRoutesIncludePattern());
         
configurer.setRoutesExcludePattern(mainConfigurationProperties.getRoutesExcludePattern());
         
configurer.setRoutesIncludePattern(mainConfigurationProperties.getRoutesIncludePattern());
+
         configurer.configureRoutes(camelContext);
     }
 
@@ -649,6 +679,96 @@ public abstract class BaseMainSupport extends BaseService {
         }
     }
 
+    protected void autoConfigurationRoutesIncludePattern(
+            CamelContext camelContext, Map<String, String> 
autoConfiguredProperties)
+            throws Exception {
+
+        Object pattern = 
getInitialProperties().getProperty("camel.main.routesIncludePattern");
+        if (pattern != null) {
+            mainConfigurationProperties
+                    
.setRoutesIncludePattern(CamelContextHelper.parseText(camelContext, 
pattern.toString()));
+            autoConfiguredProperties.put("camel.main.routes-include-pattern", 
pattern.toString());
+        }
+
+        // load properties
+        Properties prop = 
camelContext.getPropertiesComponent().loadProperties(name -> 
name.startsWith("camel."));
+        LOG.debug("Properties from Camel properties component:");
+        for (String key : prop.stringPropertyNames()) {
+            LOG.debug("    {}={}", key, prop.getProperty(key));
+        }
+
+        // special for environment-variable-enabled as we need to know this 
early before we set all the other options
+        pattern = prop.remove("camel.main.routesIncludePattern");
+        if (pattern == null) {
+            pattern = prop.remove("camel.main.routes-include-pattern");
+            if (pattern != null) {
+                mainConfigurationProperties.setRoutesIncludePattern(
+                        CamelContextHelper.parseText(camelContext, 
pattern.toString()));
+                
autoConfiguredProperties.put("camel.main.auto-configuration-environment-variables-enabled",
+                        pattern.toString());
+            }
+        }
+        // special for system-properties-enabled as we need to know this early 
before we set all the other options
+        Object jvmEnabled = prop.remove("camel.main.routesIncludePattern");
+        if (jvmEnabled == null) {
+            jvmEnabled = prop.remove("camel.main.routes-include-pattern");
+            if (jvmEnabled != null) {
+                mainConfigurationProperties.setRoutesIncludePattern(
+                        CamelContextHelper.parseText(camelContext, 
jvmEnabled.toString()));
+                
autoConfiguredProperties.put("camel.main.routes-include-pattern",
+                        jvmEnabled.toString());
+            }
+        }
+
+        // load properties from ENV (override existing)
+        Properties propENV = null;
+        if 
(mainConfigurationProperties.isAutoConfigurationEnvironmentVariablesEnabled()) {
+            propENV = helper.loadEnvironmentVariablesAsProperties(new String[] 
{ "camel.main." });
+            if (!propENV.isEmpty()) {
+                prop.putAll(propENV);
+                LOG.debug("Properties from OS environment variables:");
+                for (String key : propENV.stringPropertyNames()) {
+                    LOG.debug("    {}={}", key, propENV.getProperty(key));
+                }
+            }
+        }
+        // load properties from JVM (override existing)
+        Properties propJVM = null;
+        if 
(mainConfigurationProperties.isAutoConfigurationSystemPropertiesEnabled()) {
+            propJVM = helper.loadJvmSystemPropertiesAsProperties(new String[] 
{ "camel.main." });
+            if (!propJVM.isEmpty()) {
+                prop.putAll(propJVM);
+                LOG.debug("Properties from JVM system properties:");
+                for (String key : propJVM.stringPropertyNames()) {
+                    LOG.debug("    {}={}", key, propJVM.getProperty(key));
+                }
+            }
+        }
+
+        // special for fail-fast as we need to know this early before we set 
all the other options
+        pattern = propENV != null ? 
propENV.remove("camel.main.routesincludepattern") : null;
+        if (propJVM != null) {
+            Object val = propJVM.remove("camel.main.routesincludepattern");
+            if (val != null) {
+                pattern = val;
+            }
+        }
+        if (pattern != null) {
+            mainConfigurationProperties
+                    
.setRoutesIncludePattern(CamelContextHelper.parseText(camelContext, 
pattern.toString()));
+        } else {
+            pattern = prop.remove("camel.main.routesIncludePattern");
+            if (pattern == null) {
+                pattern = prop.remove("camel.main.routes-include-pattern");
+            }
+            if (pattern != null) {
+                mainConfigurationProperties
+                        
.setRoutesIncludePattern(CamelContextHelper.parseText(camelContext, 
pattern.toString()));
+                
autoConfiguredProperties.put("camel.main.routes-include-pattern", 
pattern.toString());
+            }
+        }
+    }
+
     /**
      * Configures CamelContext from the {@link MainConfigurationProperties} 
properties.
      */
@@ -1087,11 +1207,9 @@ public abstract class BaseMainSupport extends 
BaseService {
         for (String key : keys) {
             String name = StringHelper.before(key, ".");
             if ("aws".equalsIgnoreCase(name)) {
-                // TODO: add more vault providers here
                 target = target.aws();
             }
             if ("gcp".equalsIgnoreCase(name)) {
-                // TODO: add more vault providers here
                 target = target.gcp();
             }
             // configure all the properties on the vault at once (to ensure 
they are configured in right order)
diff --git 
a/core/camel-main/src/main/java/org/apache/camel/main/RoutesConfigurer.java 
b/core/camel-main/src/main/java/org/apache/camel/main/RoutesConfigurer.java
index aad2a68..9e979ef 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/RoutesConfigurer.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/RoutesConfigurer.java
@@ -46,7 +46,6 @@ public class RoutesConfigurer {
     private CamelBeanPostProcessor beanPostProcessor;
     private List<RoutesBuilder> routesBuilders;
     private String basePackageScan;
-    private boolean modeline;
     private String routesBuilderClasses;
     private String javaRoutesExcludePattern;
     private String javaRoutesIncludePattern;
@@ -69,14 +68,6 @@ public class RoutesConfigurer {
         this.basePackageScan = basePackageScan;
     }
 
-    public boolean ismodeline() {
-        return modeline;
-    }
-
-    public void setmodeline(boolean modeline) {
-        this.modeline = modeline;
-    }
-
     public String getRoutesBuilderClasses() {
         return routesBuilderClasses;
     }
@@ -232,22 +223,6 @@ public class RoutesConfigurer {
         // sort routes according to ordered
         routes.sort(OrderedComparator.get());
 
-        if (modeline) {
-            ExtendedCamelContext ecc = 
camelContext.adapt(ExtendedCamelContext.class);
-            ModelineFactory factory = ecc.getModelineFactory();
-            List<Resource> resources = new ArrayList<>();
-            // gather resources for modeline
-            for (RoutesBuilder builder : routes) {
-                if (builder instanceof RouteBuilder) {
-                    resources.add(((RouteBuilder) builder).getResource());
-                }
-            }
-            for (Resource resource : resources) {
-                LOG.debug("Parsing modeline: {}", resource);
-                factory.parseModeline(resource);
-            }
-        }
-
         // first add the routes configurations as they are globally for all 
routes
         for (RoutesBuilder builder : routes) {
             if (builder instanceof RouteConfigurationsBuilder) {
@@ -263,4 +238,50 @@ public class RoutesConfigurer {
         }
     }
 
+    /**
+     * Discover routes and rests from directories and scan for modeline 
present in their source code, which is then
+     * parsed using {@link ModelineFactory}.
+     *
+     * @param camelContext the Camel context
+     */
+    public void configureModeline(CamelContext camelContext) throws Exception {
+        final List<RoutesBuilder> routes = new ArrayList<>();
+
+        if (getRoutesCollector() != null) {
+            try {
+                LOG.debug("RoutesCollectorEnabled: {}", getRoutesCollector());
+
+                // add discovered routes from directories
+                StopWatch watch = new StopWatch();
+                Collection<RoutesBuilder> routesFromDirectory = 
getRoutesCollector().collectRoutesFromDirectory(
+                        camelContext,
+                        getRoutesExcludePattern(),
+                        getRoutesIncludePattern());
+                routes.addAll(routesFromDirectory);
+
+            } catch (Exception e) {
+                throw RuntimeCamelException.wrapRuntimeException(e);
+            }
+        }
+
+        // sort routes according to ordered
+        routes.sort(OrderedComparator.get());
+
+        ExtendedCamelContext ecc = 
camelContext.adapt(ExtendedCamelContext.class);
+        ModelineFactory factory = ecc.getModelineFactory();
+        List<Resource> resources = new ArrayList<>();
+        // gather resources for modeline
+        for (RoutesBuilder builder : routes) {
+            if (builder instanceof RouteBuilder) {
+                resources.add(((RouteBuilder) builder).getResource());
+            }
+        }
+        LOG.debug("Discovered {} resources with potential modeline", 
resources.size());
+
+        for (Resource resource : resources) {
+            LOG.debug("Parsing modeline: {}", resource);
+            factory.parseModeline(resource);
+        }
+    }
+
 }
diff --git 
a/dsl/camel-dsl-modeline/src/main/java/org/apache/camel/dsl/modeline/PropertyTrait.java
 
b/dsl/camel-dsl-modeline/src/main/java/org/apache/camel/dsl/modeline/PropertyTrait.java
index 02dbbba..68f2f49 100644
--- 
a/dsl/camel-dsl-modeline/src/main/java/org/apache/camel/dsl/modeline/PropertyTrait.java
+++ 
b/dsl/camel-dsl-modeline/src/main/java/org/apache/camel/dsl/modeline/PropertyTrait.java
@@ -22,6 +22,7 @@ import java.util.Properties;
 import org.apache.camel.CamelContext;
 import org.apache.camel.CamelContextAware;
 import org.apache.camel.spi.CamelContextCustomizer;
+import org.apache.camel.spi.PropertiesComponent;
 import org.apache.camel.spi.PropertiesSource;
 import org.apache.camel.spi.annotations.JdkService;
 import org.apache.camel.support.ResourceHelper;
@@ -37,6 +38,7 @@ public class PropertyTrait implements Trait, 
PropertiesSource, CamelContextAware
 
     private final Properties properties = new OrderedProperties();
     private CamelContext camelContext;
+    private PropertiesComponent pc;
 
     @Override
     public CamelContext getCamelContext() {
@@ -63,7 +65,7 @@ public class PropertyTrait implements Trait, 
PropertiesSource, CamelContextAware
         if (trait.contains("=")) {
             String key = StringHelper.before(trait, "=").trim();
             String value = StringHelper.after(trait, "=").trim();
-            properties.setProperty(key, value);
+            setProperty(key, value);
         } else {
             if (ResourceHelper.hasScheme(trait)) {
                 // it is a properties file so load resource
@@ -74,7 +76,7 @@ public class PropertyTrait implements Trait, 
PropertiesSource, CamelContextAware
                         String v = prop.getProperty(k);
                         String key = k.trim();
                         String value = v.trim();
-                        properties.setProperty(key, value);
+                        setProperty(key, value);
                     }
                 } catch (Exception e) {
                     // ignore
@@ -84,6 +86,14 @@ public class PropertyTrait implements Trait, 
PropertiesSource, CamelContextAware
         return null;
     }
 
+    protected void setProperty(String key, String value) {
+        properties.setProperty(key, value);
+        if (!camelContext.isStarted()) {
+            // if we are bootstrapping then also set as initial property, so 
it can be used there as well
+            camelContext.getPropertiesComponent().addInitialProperty(key, 
value);
+        }
+    }
+
     @Override
     public String toString() {
         return "camel-dsl-modeline";
diff --git 
a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java 
b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
index 48a7167..a5ef447 100644
--- 
a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
+++ 
b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
@@ -183,6 +183,7 @@ public class KameletMain extends MainCommandLineSupport {
             VertxHttpServer.registerConsole(answer);
         }
         configure().withLoadHealthChecks(true);
+        configure().withModeline(true);
 
         boolean health = 
"true".equals(getInitialProperties().get("camel.jbang.health"));
         if (health && port == null) {
@@ -190,7 +191,6 @@ public class KameletMain extends MainCommandLineSupport {
             VertxHttpServer.registerServer(answer, 8080);
         }
         if (health) {
-            configure().withLoadHealthChecks(true);
             VertxHttpServer.registerHealthCheck(answer);
         }
 

Reply via email to