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

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

commit 2277b60789080c0cc4278c162098e741d966f35a
Author: Claus Ibsen <[email protected]>
AuthorDate: Sat Feb 18 11:08:41 2023 +0100

    CAMEL-19071: camel-main / camel-jbang - Reload properties should reload 
components in dev mode.
---
 .../{ResourceReload.java => PropertiesReload.java} | 15 +++--
 .../java/org/apache/camel/spi/ResourceReload.java  |  7 +-
 .../org/apache/camel/main/BaseMainSupport.java     | 75 ++++++++++++++++++++++
 .../apache/camel/main/MainPropertiesReload.java    | 57 ++++++++++++++++
 .../camel/support/RouteWatcherReloadStrategy.java  | 20 +++++-
 5 files changed, 163 insertions(+), 11 deletions(-)

diff --git 
a/core/camel-api/src/main/java/org/apache/camel/spi/ResourceReload.java 
b/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesReload.java
similarity index 65%
copy from core/camel-api/src/main/java/org/apache/camel/spi/ResourceReload.java
copy to core/camel-api/src/main/java/org/apache/camel/spi/PropertiesReload.java
index cdbb63255e1..2c795a6cbb0 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/ResourceReload.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesReload.java
@@ -16,18 +16,21 @@
  */
 package org.apache.camel.spi;
 
+import java.util.Properties;
+
 /**
- * Listener for re-loading a {@link Resource} such as a Camel route.
+ * Listener for re-loading a {@link java.util.Properties} such as a Camel 
route.
  */
 @FunctionalInterface
-public interface ResourceReload {
+public interface PropertiesReload {
 
     /**
-     * Callback when the resource is re-loaded.
+     * Callback when the properties is re-loaded.
      *
-     * @param name     name of the resource such as the file name (absolute)
-     * @param resource the resource
+     * @param  name       name of the resource such as the file name (absolute)
+     * @param  properties the properties that was re-loaded
+     * @throws Exception  error reloading properties
      */
-    void onReload(String name, Resource resource);
+    void onReload(String name, Properties properties) throws Exception;
 
 }
diff --git 
a/core/camel-api/src/main/java/org/apache/camel/spi/ResourceReload.java 
b/core/camel-api/src/main/java/org/apache/camel/spi/ResourceReload.java
index cdbb63255e1..5176ef8cbcd 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/ResourceReload.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/ResourceReload.java
@@ -25,9 +25,10 @@ public interface ResourceReload {
     /**
      * Callback when the resource is re-loaded.
      *
-     * @param name     name of the resource such as the file name (absolute)
-     * @param resource the resource
+     * @param  name      name of the resource such as the file name (absolute)
+     * @param  resource  the resource
+     * @throws Exception error reloading the resources
      */
-    void onReload(String name, Resource resource);
+    void onReload(String name, Resource resource) throws Exception;
 
 }
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 eb4b3f90bbf..ce1b2aaa190 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
@@ -488,6 +488,8 @@ public abstract class BaseMainSupport extends BaseService {
         if (mainConfigurationProperties.isAutoConfigurationEnabled()) {
             autoConfigurationFromProperties(camelContext, 
autoConfiguredProperties);
             autowireWildcardProperties(camelContext);
+            // register properties reloader so we can auto-update if updated
+            camelContext.addService(new MainPropertiesReload(this));
         }
 
         // log summary of configurations
@@ -1622,8 +1624,78 @@ public abstract class BaseMainSupport extends 
BaseService {
             prop.remove(key);
         }
 
+        doAutoConfigurationFromProperties(camelContext, prop, properties, 
false, autoConfiguredProperties);
+    }
+
+    protected void autoConfigurationFromReloadedProperties(
+            CamelContext camelContext, OrderedLocationProperties 
reloadedProperties)
+            throws Exception {
+
+        Map<PropertyOptionKey, OrderedLocationProperties> properties = new 
LinkedHashMap<>();
+
+        // filter out wildcard properties
+        for (String key : reloadedProperties.stringPropertyNames()) {
+            if (key.contains("*")) {
+                String loc = reloadedProperties.getLocation(key);
+                wildcardProperties.put(loc, key, 
reloadedProperties.getProperty(key));
+            }
+        }
+        // and remove wildcards
+        for (String key : wildcardProperties.stringPropertyNames()) {
+            reloadedProperties.remove(key);
+        }
+
+        OrderedLocationProperties autoConfiguredProperties = new 
OrderedLocationProperties();
+        doAutoConfigurationFromProperties(camelContext, reloadedProperties, 
properties, true, autoConfiguredProperties);
+
+        // log summary of configurations
+        if (mainConfigurationProperties.isAutoConfigurationLogSummary() && 
!autoConfiguredProperties.isEmpty()) {
+            boolean header = false;
+            for (var entry : autoConfiguredProperties.entrySet()) {
+                String k = entry.getKey().toString();
+                Object v = entry.getValue();
+                String loc = locationSummary(autoConfiguredProperties, k);
+
+                // tone down logging noise for our own internal configurations
+                boolean debug = loc.contains("[camel-main]");
+                if (debug && !LOG.isDebugEnabled()) {
+                    continue;
+                }
+
+                if (!header) {
+                    LOG.info("Auto-configuration summary");
+                    header = true;
+                }
+
+                if (SensitiveUtils.containsSensitive(k)) {
+                    if (debug) {
+                        LOG.debug("    {} {}=xxxxxx", loc, k);
+                    } else {
+                        LOG.info("    {} {}=xxxxxx", loc, k);
+                    }
+                } else {
+                    if (debug) {
+                        LOG.debug("    {} {}={}", loc, k, v);
+                    } else {
+                        LOG.info("    {} {}={}", loc, k, v);
+                    }
+                }
+            }
+        }
+    }
+
+    protected void doAutoConfigurationFromProperties(
+            CamelContext camelContext, OrderedLocationProperties prop,
+            Map<PropertyOptionKey, OrderedLocationProperties> properties, 
boolean reload,
+            OrderedLocationProperties autoConfiguredProperties)
+            throws Exception {
+
         for (String key : prop.stringPropertyNames()) {
             computeProperties("camel.component.", key, prop, properties, name 
-> {
+                if (reload) {
+                    // force re-creating component on reload
+                    camelContext.removeComponent(name);
+                }
                 // its an existing component name
                 Component target = camelContext.getComponent(name);
                 if (target == null) {
@@ -1706,6 +1778,9 @@ public abstract class BaseMainSupport extends BaseService 
{
                 doAutowireWildcardProperties(name, component);
             }
         });
+
+        // clear in case we reload later
+        wildcardProperties.clear();
     }
 
     protected void doAutowireWildcardProperties(String name, Component 
component) {
diff --git 
a/core/camel-main/src/main/java/org/apache/camel/main/MainPropertiesReload.java 
b/core/camel-main/src/main/java/org/apache/camel/main/MainPropertiesReload.java
new file mode 100644
index 00000000000..34ddef39139
--- /dev/null
+++ 
b/core/camel-main/src/main/java/org/apache/camel/main/MainPropertiesReload.java
@@ -0,0 +1,57 @@
+/*
+ * 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.util.Properties;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.spi.PropertiesReload;
+import org.apache.camel.support.service.ServiceSupport;
+import org.apache.camel.util.OrderedLocationProperties;
+
+/**
+ * Reloading of application.properties when using Camel Main in reload mode, 
such as when using camel-jbang.
+ */
+public class MainPropertiesReload extends ServiceSupport implements 
PropertiesReload, CamelContextAware {
+
+    private final BaseMainSupport main;
+    private CamelContext camelContext;
+
+    public MainPropertiesReload(BaseMainSupport main) {
+        this.main = main;
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public void onReload(String name, Properties properties) throws Exception {
+        if (properties instanceof OrderedLocationProperties) {
+            OrderedLocationProperties prop = (OrderedLocationProperties) 
properties;
+            main.autoConfigurationFromReloadedProperties(camelContext, prop);
+            main.autowireWildcardProperties(camelContext);
+        }
+    }
+}
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/RouteWatcherReloadStrategy.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/RouteWatcherReloadStrategy.java
index faa64ed8997..caef6d0e41d 100644
--- 
a/core/camel-support/src/main/java/org/apache/camel/support/RouteWatcherReloadStrategy.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/RouteWatcherReloadStrategy.java
@@ -17,6 +17,7 @@
 package org.apache.camel.support;
 
 import java.io.File;
+import java.io.InputStream;
 import java.net.URI;
 import java.nio.file.Files;
 import java.nio.file.Paths;
@@ -32,10 +33,14 @@ import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.ServiceStatus;
 import org.apache.camel.StartupSummaryLevel;
 import org.apache.camel.spi.PropertiesComponent;
+import org.apache.camel.spi.PropertiesReload;
 import org.apache.camel.spi.Resource;
 import org.apache.camel.util.AntPathMatcher;
 import org.apache.camel.util.FileUtil;
+import org.apache.camel.util.IOHelper;
 import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.OrderedLocationProperties;
+import org.apache.camel.util.OrderedProperties;
 import org.apache.camel.util.URISupport;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -157,13 +162,24 @@ public class RouteWatcherReloadStrategy extends 
FileWatcherResourceReloadStrateg
         return "Live route reloading enabled (directory: " + dir + ")";
     }
 
-    protected void onPropertiesReload(Resource resource) {
-        LOG.info("Reloading properties: {}. (Only Camel routes can be updated 
with changes)",
+    protected void onPropertiesReload(Resource resource) throws Exception {
+        LOG.info("Reloading properties: {}. (Only Camel routes and components 
can be updated with changes)",
                 resource.getLocation());
 
         PropertiesComponent pc = getCamelContext().getPropertiesComponent();
         boolean reloaded = pc.reloadProperties(resource.getLocation());
         if (reloaded) {
+            PropertiesReload pr = 
getCamelContext().hasService(PropertiesReload.class);
+            if (pr != null) {
+                // load the properties, so we can update (remember location)
+                InputStream is = resource.getInputStream();
+                OrderedProperties tmp = new OrderedProperties();
+                tmp.load(is);
+                IOHelper.close(is);
+                OrderedLocationProperties properties = new 
OrderedLocationProperties();
+                properties.putAll(resource.getLocation(), tmp);
+                pr.onReload(resource.getLocation(), properties);
+            }
             // trigger all routes to be reloaded
             onRouteReload(null);
         }

Reply via email to