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 2019/06/26 12:46:32 UTC

[camel] branch master updated (bfb6d51 -> ceb0253)

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

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


    from bfb6d51  Fixed CS issues
     new 68a93674 CAMEL-13681: camel-main - Allow ENV variables to configure any option
     new e37c4a4  CAMEL-13681: Property binding support should have support for ignore case in property keys
     new 13a2457  CAMEL-13681: Property binding support should have support for ignore case in property keys
     new 1076cc0  CAMEL-13681: Camel main should ignore case in property keys
     new c2bd36f  CAMEL-13683: camel-main - configuring properties report better error if missing JARs on classpathand other mistakes.
     new 7d11d5d  CAMEL-13683: camel-main - Allow to turn of fail fast if configuring properties fail
     new ceb0253  CAMEL-13683: camel-main - configuring properties report better error if missing JARs on classpathand other mistakes.

The 7 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../properties/DefaultPropertiesParser.java        |  18 +-
 .../main/java/org/apache/camel/CamelContext.java   |   3 +-
 .../camel/support/IntrospectionSupportTest.java    |   2 +-
 .../camel/support/PropertyBindingSupportTest.java  |  51 ++++
 .../camel/main/MainConfigurationProperties.java    |  26 ++
 .../java/org/apache/camel/main/MainSupport.java    | 314 +++++++++++++++------
 .../camel-main-configuration-metadata.json         |   7 +
 .../apache/camel/support/IntrospectionSupport.java |  96 +++++--
 .../camel/support/PropertyBindingSupport.java      | 153 +++++++---
 .../main/java/org/apache/camel/util/IOHelper.java  |  16 ++
 .../META-INF/spring-configuration-metadata.json    |   7 +
 .../META-INF/spring-configuration-metadata.json    |   7 +
 12 files changed, 530 insertions(+), 170 deletions(-)


[camel] 07/07: CAMEL-13683: camel-main - configuring properties report better error if missing JARs on classpathand other mistakes.

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit ceb025376979c0a1db29e2d540d6aac785969c7c
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Jun 26 13:26:09 2019 +0200

    CAMEL-13683: camel-main - configuring properties report better error if missing JARs on classpathand other mistakes.
---
 .../java/org/apache/camel/main/MainSupport.java    | 157 ++++++++++++++-------
 1 file changed, 105 insertions(+), 52 deletions(-)

diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java b/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
index 673a6a3..3d0e4db 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
@@ -28,6 +28,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Properties;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -733,6 +734,7 @@ public abstract class MainSupport extends ServiceSupport {
 
         // need to eager allow to auto configure properties component
         if (mainConfigurationProperties.isAutoConfigurationEnabled()) {
+            autoConfigurationFailFast(camelContext);
             autoConfigurationPropertiesComponent(camelContext);
             autoConfigurationMainConfiguration(camelContext, mainConfigurationProperties);
         }
@@ -765,6 +767,31 @@ public abstract class MainSupport extends ServiceSupport {
         }
     }
 
+    protected void autoConfigurationFailFast(CamelContext camelContext) throws Exception {
+        // load properties
+        Properties prop = camelContext.getPropertiesComponent().loadProperties();
+        LOG.debug("Properties from Camel properties component:");
+        for (String key : prop.stringPropertyNames()) {
+            LOG.debug("    {}={}", key, prop.getProperty(key));
+        }
+
+        // load properties from ENV (override existing)
+        Properties propENV = 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));
+            }
+        }
+
+        // special for fail-fast as we need to know this early before we set all the other options
+        Object failFast = propENV.remove("camel.main.autoconfigurationfailfast");
+        if (failFast != null) {
+            PropertyBindingSupport.bindMandatoryProperty(camelContext, mainConfigurationProperties, "autoConfigurationFailFast", failFast, true);
+        }
+    }
+
     /**
      * Configures CamelContext from the {@link MainConfigurationProperties} properties.
      */
@@ -864,73 +891,57 @@ public abstract class MainSupport extends ServiceSupport {
             }
             setPropertiesOnTarget(camelContext, rest, restProperties, mainConfigurationProperties.isAutoConfigurationFailFast(), true);
         }
+
+        // TODO: Log which options was not set
     }
 
     protected void autoConfigurationPropertiesComponent(CamelContext camelContext) throws Exception {
         // load properties
         Properties prop = camelContext.getPropertiesComponent().loadProperties();
-        LOG.debug("Properties from Camel properties component:");
-        for (String key : prop.stringPropertyNames()) {
-            LOG.debug("    {}={}", key, prop.getProperty(key));
-        }
 
         // load properties from ENV (override existing)
         Properties propENV = loadEnvironmentVariablesAsProperties(new String[]{"camel.component.properties."});
         if (!propENV.isEmpty()) {
             prop.putAll(propENV);
-            LOG.debug("Properties from OS environment variables:");
-            for (String key : propENV.stringPropertyNames()) {
-                LOG.debug("    {}={}", key, propENV.getProperty(key));
-            }
         }
 
-        Map<Object, Map<String, Object>> properties = new LinkedHashMap<>();
+        Map<String, Object> properties = new LinkedHashMap<>();
 
         for (String key : prop.stringPropertyNames()) {
             if (key.startsWith("camel.component.properties.")) {
-                Component component = camelContext.getPropertiesComponent();
                 int dot = key.indexOf(".", 26);
                 String option = dot == -1 ? "" : key.substring(dot + 1);
                 String value = prop.getProperty(key, "");
                 validateOptionAndValue(key, option, value);
-                Map<String, Object> values = properties.getOrDefault(component, new LinkedHashMap<>());
-                values.put(optionKey(option), value);
-                properties.put(component, values);
+                properties.put(optionKey(option), value);
             }
         }
 
         if (!properties.isEmpty()) {
-            long total = properties.values().stream().mapToLong(Map::size).sum();
-            LOG.info("Auto configuring properties component from loaded properties: {}", total);
+            LOG.info("Auto configuring properties component from loaded properties: {}", properties.size());
+            setPropertiesOnTarget(camelContext, camelContext.getPropertiesComponent(), properties, mainConfigurationProperties.isAutoConfigurationFailFast(), true);
         }
 
-        for (Object obj : properties.keySet()) {
-            Map<String, Object> values = properties.get(obj);
-            setPropertiesOnTarget(camelContext, obj, values, mainConfigurationProperties.isAutoConfigurationFailFast(), true);
+        // log which options was not set
+        if (!properties.isEmpty()) {
+            properties.forEach((k, v) -> {
+                LOG.warn("Property not auto configured: camel.component.properties.{}={} on object: {}", k, v, camelContext.getPropertiesComponent());
+            });
         }
     }
 
     protected void autoConfigurationMainConfiguration(CamelContext camelContext, MainConfigurationProperties config) throws Exception {
         // load properties
         Properties prop = camelContext.getPropertiesComponent().loadProperties();
-        LOG.debug("Properties from Camel properties component:");
-        for (String key : prop.stringPropertyNames()) {
-            LOG.debug("    {}={}", key, prop.getProperty(key));
-        }
 
         // load properties from ENV (override existing)
         Properties propENV = 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));
-            }
         }
 
         Map<String, Object> properties = new LinkedHashMap<>();
 
-
         for (String key : prop.stringPropertyNames()) {
             if (key.startsWith("camel.main.")) {
                 // grab the value
@@ -941,16 +952,17 @@ public abstract class MainSupport extends ServiceSupport {
             }
         }
 
-        // special for fail-fast as we need to know this early before we set all the other options
-        Object failFast = properties.remove("autoconfigurationfailfast");
-        if (failFast != null) {
-            PropertyBindingSupport.bindMandatoryProperty(camelContext, config, "autoConfigurationFailFast", failFast, true);
-        }
-
         if (!properties.isEmpty()) {
             LOG.info("Auto configuring main from loaded properties: {}", properties.size());
             setPropertiesOnTarget(camelContext, config, properties, mainConfigurationProperties.isAutoConfigurationFailFast(), true);
         }
+
+        // log which options was not set
+        if (!properties.isEmpty()) {
+            properties.forEach((k, v) -> {
+                LOG.warn("Property not auto configured: camel.main.{}={} on object: {}", k, v, config);
+            });
+        }
     }
 
     protected void autoConfigurationFromProperties(CamelContext camelContext) throws Exception {
@@ -978,22 +990,14 @@ public abstract class MainSupport extends ServiceSupport {
         // load properties from properties component (override existing)
         Properties propPC = camelContext.getPropertiesComponent().loadProperties();
         prop.putAll(propPC);
-        LOG.debug("Properties from Camel properties component:");
-        for (String key : propPC.stringPropertyNames()) {
-            LOG.debug("    {}={}", key, propPC.getProperty(key));
-        }
 
         // load properties from ENV (override existing)
         Properties propENV = loadEnvironmentVariablesAsProperties(new String[]{"camel.component.", "camel.dataformat.", "camel.language."});
         if (!propENV.isEmpty()) {
             prop.putAll(propENV);
-            LOG.debug("Properties from OS environment variables:");
-            for (String key : propENV.stringPropertyNames()) {
-                LOG.debug("    {}={}", key, propENV.getProperty(key));
-            }
         }
 
-        Map<Object, Map<String, Object>> properties = new LinkedHashMap<>();
+        Map<PropertyOptionKey, Map<String, Object>> properties = new LinkedHashMap<>();
 
         for (String key : prop.stringPropertyNames()) {
             if (key.startsWith("camel.component.")) {
@@ -1012,10 +1016,11 @@ public abstract class MainSupport extends ServiceSupport {
                 String option = dot == -1 ? "" : key.substring(dot + 1);
                 String value = prop.getProperty(key, "");
                 validateOptionAndValue(key, option, value);
-                Map<String, Object> values = properties.getOrDefault(component, new LinkedHashMap<>());
+                PropertyOptionKey pok = new PropertyOptionKey(key, component);
+                Map<String, Object> values = properties.getOrDefault(pok, new LinkedHashMap<>());
                 // we ignore case for property keys (so we should store them in canonical style
                 values.put(optionKey(option), value);
-                properties.put(component, values);
+                properties.put(pok, values);
             }
             if (key.startsWith("camel.dataformat.")) {
                 // grab name
@@ -1029,9 +1034,10 @@ public abstract class MainSupport extends ServiceSupport {
                 String option = dot == -1 ? "" : key.substring(dot + 1);
                 String value = prop.getProperty(key, "");
                 validateOptionAndValue(key, option, value);
-                Map<String, Object> values = properties.getOrDefault(dataformat, new LinkedHashMap<>());
+                PropertyOptionKey pok = new PropertyOptionKey(key, dataformat);
+                Map<String, Object> values = properties.getOrDefault(pok, new LinkedHashMap<>());
                 values.put(optionKey(option), value);
-                properties.put(dataformat, values);
+                properties.put(pok, values);
             }
             if (key.startsWith("camel.language.")) {
                 // grab name
@@ -1047,9 +1053,10 @@ public abstract class MainSupport extends ServiceSupport {
                 String option = dot == -1 ? "" : key.substring(dot + 1);
                 String value = prop.getProperty(key, "");
                 validateOptionAndValue(key, option, value);
-                Map<String, Object> values = properties.getOrDefault(language, new LinkedHashMap<>());
+                PropertyOptionKey pok = new PropertyOptionKey(key, language);
+                Map<String, Object> values = properties.getOrDefault(pok, new LinkedHashMap<>());
                 values.put(optionKey(option), value);
-                properties.put(language, values);
+                properties.put(pok, values);
             }
         }
 
@@ -1058,12 +1065,21 @@ public abstract class MainSupport extends ServiceSupport {
             LOG.info("Auto configuring {} components/dataformat/languages from loaded properties: {}", properties.size(), total);
         }
 
-        for (Object obj : properties.keySet()) {
-            Map<String, Object> values = properties.get(obj);
-            setPropertiesOnTarget(camelContext, obj, values, mainConfigurationProperties.isAutoConfigurationFailFast(), true);
+        // TODO: Better error if setting some property fails
+        for (PropertyOptionKey pok : properties.keySet()) {
+            Map<String, Object> values = properties.get(pok);
+            setPropertiesOnTarget(camelContext, pok.getInstance(), values, mainConfigurationProperties.isAutoConfigurationFailFast(), true);
         }
 
-        // TODO: Log which options was not set
+        // log which options was not set
+        if (!properties.isEmpty()) {
+            for (PropertyOptionKey pok : properties.keySet()) {
+                Map<String, Object> values = properties.get(pok);
+                values.forEach((k, v) -> {
+                    LOG.warn("Property not auto configured: {}={} on object: {}", pok.getKey(), v, pok.getInstance());
+                });
+            }
+        }
     }
 
     protected void autoConfigurationFromRegistry(CamelContext camelContext, boolean deepNesting) throws Exception {
@@ -1165,6 +1181,43 @@ public abstract class MainSupport extends ServiceSupport {
         return rc;
     }
 
+    private static class PropertyOptionKey {
+
+        private final String key;
+        private final Object instance;
+
+        private PropertyOptionKey(String key, Object instance) {
+            this.key = key;
+            this.instance = instance;
+        }
+
+        public String getKey() {
+            return key;
+        }
+
+        public Object getInstance() {
+            return instance;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+            PropertyOptionKey that = (PropertyOptionKey) o;
+            return key.equals(that.key) &&
+                    instance.equals(that.instance);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(key, instance);
+        }
+    }
+
     public abstract class Option {
         private String abbreviation;
         private String fullName;


[camel] 01/07: CAMEL-13681: camel-main - Allow ENV variables to configure any option

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 68a93674a82e01b1d0c0312ff5998c05de94b8ae
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Jun 25 15:58:46 2019 +0200

    CAMEL-13681: camel-main - Allow ENV variables to configure any option
---
 .../properties/DefaultPropertiesParser.java        | 18 +-----
 .../java/org/apache/camel/main/MainSupport.java    | 71 ++++++++++++++++++++--
 .../main/java/org/apache/camel/util/IOHelper.java  | 16 +++++
 3 files changed, 83 insertions(+), 22 deletions(-)

diff --git a/components/camel-properties/src/main/java/org/apache/camel/component/properties/DefaultPropertiesParser.java b/components/camel-properties/src/main/java/org/apache/camel/component/properties/DefaultPropertiesParser.java
index bc78cb5..f035912 100644
--- a/components/camel-properties/src/main/java/org/apache/camel/component/properties/DefaultPropertiesParser.java
+++ b/components/camel-properties/src/main/java/org/apache/camel/component/properties/DefaultPropertiesParser.java
@@ -25,6 +25,8 @@ import org.apache.camel.util.StringHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.camel.util.IOHelper.lookupEnvironmentVariable;
+
 /**
  * A parser to parse a string which contains property placeholders.
  */
@@ -350,22 +352,6 @@ public class DefaultPropertiesParser implements AugmentedPropertyNameAwareProper
     }
 
     /**
-     * Lookup the OS environment variable in a safe manner by
-     * using upper case keys and underscore instead of dash.
-     */
-    private static String lookupEnvironmentVariable(String key) {
-        // lookup OS env with upper case key
-        String upperKey = key.toUpperCase();
-        String value = System.getenv(upperKey);
-        // some OS do not support dashes in keys, so replace with underscore
-        if (value == null) {
-            String noDashKey = upperKey.replace('-', '_');
-            value = System.getenv(noDashKey);
-        }
-        return value;
-    }
-
-    /**
      * This inner class is the definition of a property used in a string
      */
     private static final class Property {
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java b/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
index 9e8ebf1..3f80690 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
@@ -26,6 +26,7 @@ import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Properties;
 import java.util.concurrent.CountDownLatch;
@@ -62,6 +63,7 @@ import org.slf4j.LoggerFactory;
 
 import static org.apache.camel.support.ObjectHelper.invokeMethod;
 import static org.apache.camel.util.ReflectionHelper.findMethod;
+import static org.apache.camel.util.StringHelper.dashToCamelCase;
 import static org.apache.camel.util.StringHelper.matches;
 
 /**
@@ -855,9 +857,44 @@ public abstract class MainSupport extends ServiceSupport {
         }
     }
 
+    protected Properties loadEnvironmentVariablesAsProperties(String[] prefixes) {
+        Properties answer = new OrderedProperties();
+        if (prefixes == null || prefixes.length == 0) {
+            return answer;
+        }
+
+        for (String prefix : prefixes) {
+            final String pk = prefix.toUpperCase(Locale.US).replaceAll("[^\\w]", "-");
+            final String pk2 = pk.replace('-', '_');
+            System.getenv().forEach((k, v) -> {
+                k = k.toUpperCase(Locale.US);
+                if (k.startsWith(pk) || k.startsWith(pk2)) {
+                    String key = k.toLowerCase(Locale.US).replace('_', '.');
+                    answer.put(key, v);
+                }
+            });
+        }
+
+        return answer;
+    }
+
     protected void autoConfigurationPropertiesComponent(CamelContext camelContext) throws Exception {
         // load properties
         Properties prop = camelContext.getPropertiesComponent().loadProperties();
+        LOG.debug("Properties from Camel properties component:");
+        for (String key : prop.stringPropertyNames()) {
+            LOG.debug("    {}={}", key, prop.getProperty(key));
+        }
+
+        // load properties from ENV (override existing)
+        Properties propENV = loadEnvironmentVariablesAsProperties(new String[]{"camel.component.properties."});
+        if (!propENV.isEmpty()) {
+            prop.putAll(propENV);
+            LOG.debug("Properties from OS environment variables:");
+            for (String key : propENV.stringPropertyNames()) {
+                LOG.debug("    {}={}", key, propENV.getProperty(key));
+            }
+        }
 
         Map<Object, Map<String, Object>> properties = new LinkedHashMap<>();
 
@@ -890,6 +927,20 @@ public abstract class MainSupport extends ServiceSupport {
     protected void autoConfigurationMainConfiguration(CamelContext camelContext, MainConfigurationProperties config) throws Exception {
         // load properties
         Properties prop = camelContext.getPropertiesComponent().loadProperties();
+        LOG.debug("Properties from Camel properties component:");
+        for (String key : prop.stringPropertyNames()) {
+            LOG.debug("    {}={}", key, prop.getProperty(key));
+        }
+
+        // load properties from ENV (override existing)
+        Properties propENV = 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));
+            }
+        }
 
         Map<String, Object> properties = new LinkedHashMap<>();
 
@@ -932,13 +983,21 @@ public abstract class MainSupport extends ServiceSupport {
             // ignore as this file is optional
         }
 
-        // load properties from properties component
+        // load properties from properties component (override existing)
         Properties propPC = camelContext.getPropertiesComponent().loadProperties();
-        if (propPC != null) {
-            prop.putAll(propPC);
-            LOG.debug("Properties from Camel properties component:");
-            for (String key : propPC.stringPropertyNames()) {
-                LOG.debug("    {}={}", key, propPC.getProperty(key));
+        prop.putAll(propPC);
+        LOG.debug("Properties from Camel properties component:");
+        for (String key : propPC.stringPropertyNames()) {
+            LOG.debug("    {}={}", key, propPC.getProperty(key));
+        }
+
+        // load properties from ENV (override existing)
+        Properties propENV = loadEnvironmentVariablesAsProperties(new String[]{"camel.component.", "camel.dataformat.", "camel.language."});
+        if (!propENV.isEmpty()) {
+            prop.putAll(propENV);
+            LOG.debug("Properties from OS environment variables:");
+            for (String key : propENV.stringPropertyNames()) {
+                LOG.debug("    {}={}", key, propENV.getProperty(key));
             }
         }
 
diff --git a/core/camel-util/src/main/java/org/apache/camel/util/IOHelper.java b/core/camel-util/src/main/java/org/apache/camel/util/IOHelper.java
index ee52b06..565b54c 100644
--- a/core/camel-util/src/main/java/org/apache/camel/util/IOHelper.java
+++ b/core/camel-util/src/main/java/org/apache/camel/util/IOHelper.java
@@ -519,6 +519,22 @@ public final class IOHelper {
     }
 
     /**
+     * Lookup the OS environment variable in a safe manner by
+     * using upper case keys and underscore instead of dash.
+     */
+    public static String lookupEnvironmentVariable(String key) {
+        // lookup OS env with upper case key
+        String upperKey = key.toUpperCase();
+        String value = System.getenv(upperKey);
+        // some OS do not support dashes in keys, so replace with underscore
+        if (value == null) {
+            String noDashKey = upperKey.replace('-', '_');
+            value = System.getenv(noDashKey);
+        }
+        return value;
+    }
+
+    /**
      * Encoding-aware input stream.
      */
     public static class EncodingInputStream extends InputStream {


[camel] 02/07: CAMEL-13681: Property binding support should have support for ignore case in property keys

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit e37c4a4dcc04ee14e5bf0008dfc9973da92e4af8
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Jun 26 09:25:09 2019 +0200

    CAMEL-13681: Property binding support should have support for ignore case in property keys
---
 .../camel/support/IntrospectionSupportTest.java    |   2 +-
 .../camel/support/PropertyBindingSupportTest.java  |  51 +++++++
 .../java/org/apache/camel/main/MainSupport.java    |  19 ++-
 .../apache/camel/support/IntrospectionSupport.java |  96 +++++++++----
 .../camel/support/PropertyBindingSupport.java      | 153 ++++++++++++++-------
 5 files changed, 239 insertions(+), 82 deletions(-)

diff --git a/core/camel-core/src/test/java/org/apache/camel/support/IntrospectionSupportTest.java b/core/camel-core/src/test/java/org/apache/camel/support/IntrospectionSupportTest.java
index debe26b..6043a6c 100644
--- a/core/camel-core/src/test/java/org/apache/camel/support/IntrospectionSupportTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/support/IntrospectionSupportTest.java
@@ -552,7 +552,7 @@ public class IntrospectionSupportTest extends ContextTestSupport {
 
     @Test
     public void testFindSetterMethodsOrderedByParameterType() throws Exception {
-        List<Method> setters = IntrospectionSupport.findSetterMethodsOrderedByParameterType(MyOverloadedBean.class, "bean", false, false);
+        List<Method> setters = IntrospectionSupport.findSetterMethodsOrderedByParameterType(MyOverloadedBean.class, "bean", false, false, false);
 
         assertNotNull(setters);
         assertEquals(2, setters.size());
diff --git a/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportTest.java b/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportTest.java
index fdc9c7a..588f3ec 100644
--- a/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportTest.java
@@ -68,6 +68,32 @@ public class PropertyBindingSupportTest extends ContextTestSupport {
         assertTrue(foo.getBar().isGoldCustomer());
         assertEquals(123, foo.getBar().getWork().getId());
         assertEquals("Acme", foo.getBar().getWork().getName());
+
+        assertTrue("Should bind all properties", prop.isEmpty());
+    }
+
+    @Test
+    public void testPropertiesIgnoreCase() throws Exception {
+        Foo foo = new Foo();
+
+        Map<String, Object> prop = new HashMap<>();
+        prop.put("name", "James");
+        prop.put("bar.AGE", "33");
+        prop.put("BAR.{{committer}}", "true");
+        prop.put("bar.gOLd-Customer", "true");
+        prop.put("bAr.work.ID", "123");
+        prop.put("bar.WORk.naME", "{{companyName}}");
+
+        PropertyBindingSupport.bindProperties(context, foo, prop, true);
+
+        assertEquals("James", foo.getName());
+        assertEquals(33, foo.getBar().getAge());
+        assertTrue(foo.getBar().isRider());
+        assertTrue(foo.getBar().isGoldCustomer());
+        assertEquals(123, foo.getBar().getWork().getId());
+        assertEquals("Acme", foo.getBar().getWork().getName());
+
+        assertTrue("Should bind all properties", prop.isEmpty());
     }
 
     @Test
@@ -96,6 +122,31 @@ public class PropertyBindingSupportTest extends ContextTestSupport {
     }
 
     @Test
+    public void testBindPropertiesWithOptionPrefixIgnoreCase() throws Exception {
+        Foo foo = new Foo();
+
+        Map<String, Object> prop = new HashMap<>();
+        prop.put("my.prefix.name", "James");
+        prop.put("my.PREFIX.bar.AGE", "33");
+        prop.put("my.prefix.bar.{{committer}}", "true");
+        prop.put("My.prefix.bar.Gold-custoMER", "true");
+        prop.put("mY.prefix.bar.work.ID", "123");
+        prop.put("my.prEFIx.bar.Work.Name", "{{companyName}}");
+        prop.put("my.other.prefix.something", "test");
+
+        PropertyBindingSupport.bindProperties(context, foo, prop, "my.prefix.", true);
+
+        assertEquals("James", foo.getName());
+        assertEquals(33, foo.getBar().getAge());
+        assertTrue(foo.getBar().isRider());
+        assertTrue(foo.getBar().isGoldCustomer());
+        assertEquals(123, foo.getBar().getWork().getId());
+        assertEquals("Acme", foo.getBar().getWork().getName());
+        assertTrue(prop.containsKey("my.other.prefix.something"));
+        assertEquals(1, prop.size());
+    }
+
+    @Test
     public void testNested() throws Exception {
         Foo foo = new Foo();
 
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java b/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
index 3f80690..c9e3ce1 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
@@ -63,7 +63,6 @@ import org.slf4j.LoggerFactory;
 
 import static org.apache.camel.support.ObjectHelper.invokeMethod;
 import static org.apache.camel.util.ReflectionHelper.findMethod;
-import static org.apache.camel.util.StringHelper.dashToCamelCase;
 import static org.apache.camel.util.StringHelper.matches;
 
 /**
@@ -833,7 +832,7 @@ public abstract class MainSupport extends ServiceSupport {
         }
         if (!properties.isEmpty()) {
             LOG.info("Auto configuring CamelContext from loaded properties: {}", properties.size());
-            setCamelProperties(camelContext, camelContext, properties, true);
+            setPropertiesOnTarget(camelContext, camelContext, properties, true, true);
         }
         if (!hystrixProperties.isEmpty()) {
             LOG.info("Auto configuring Hystrix EIP from loaded properties: {}", hystrixProperties.size());
@@ -843,7 +842,7 @@ public abstract class MainSupport extends ServiceSupport {
                 hystrix = new HystrixConfigurationDefinition();
                 model.setHystrixConfiguration(hystrix);
             }
-            setCamelProperties(camelContext, hystrix, hystrixProperties, true);
+            setPropertiesOnTarget(camelContext, hystrix, hystrixProperties, true, true);
         }
         if (!restProperties.isEmpty()) {
             LOG.info("Auto configuring Rest DSL from loaded properties: {}", restProperties.size());
@@ -853,7 +852,7 @@ public abstract class MainSupport extends ServiceSupport {
                 rest = new RestConfiguration();
                 model.setRestConfiguration(rest);
             }
-            setCamelProperties(camelContext, rest, restProperties, true);
+            setPropertiesOnTarget(camelContext, rest, restProperties, true, true);
         }
     }
 
@@ -920,7 +919,7 @@ public abstract class MainSupport extends ServiceSupport {
 
         for (Object obj : properties.keySet()) {
             Map<String, Object> values = properties.get(obj);
-            setCamelProperties(camelContext, obj, values, true);
+            setPropertiesOnTarget(camelContext, obj, values, true, true);
         }
     }
 
@@ -957,7 +956,7 @@ public abstract class MainSupport extends ServiceSupport {
 
         if (!properties.isEmpty()) {
             LOG.info("Auto configuring main from loaded properties: {}", properties.size());
-            setCamelProperties(camelContext, config, properties, true);
+            setPropertiesOnTarget(camelContext, config, properties, true, true);
         }
     }
 
@@ -1059,7 +1058,7 @@ public abstract class MainSupport extends ServiceSupport {
 
         for (Object obj : properties.keySet()) {
             Map<String, Object> values = properties.get(obj);
-            setCamelProperties(camelContext, obj, values, true);
+            setPropertiesOnTarget(camelContext, obj, values, true, true);
         }
     }
 
@@ -1095,7 +1094,7 @@ public abstract class MainSupport extends ServiceSupport {
         setRouteBuilderClasses(existing);
     }
 
-    private static boolean setCamelProperties(CamelContext context, Object target, Map<String, Object> properties, boolean failIfNotSet) throws Exception {
+    private static boolean setPropertiesOnTarget(CamelContext context, Object target, Map<String, Object> properties, boolean failIfNotSet, boolean ignoreCase) throws Exception {
         ObjectHelper.notNull(context, "context");
         ObjectHelper.notNull(target, "target");
         ObjectHelper.notNull(properties, "properties");
@@ -1111,10 +1110,10 @@ public abstract class MainSupport extends ServiceSupport {
 
             LOG.debug("Setting property {} on {} with value {}", name, target, stringValue);
             if (failIfNotSet) {
-                PropertyBindingSupport.bindMandatoryProperty(context, target, name, stringValue);
+                PropertyBindingSupport.bindMandatoryProperty(context, target, name, stringValue, ignoreCase);
                 rc = true;
             } else {
-                boolean hit = PropertyBindingSupport.bindProperty(context, target, name, stringValue);
+                boolean hit = PropertyBindingSupport.bindProperty(context, target, name, stringValue, ignoreCase);
                 if (hit) {
                     it.remove();
                     rc = true;
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/IntrospectionSupport.java b/core/camel-support/src/main/java/org/apache/camel/support/IntrospectionSupport.java
index d2b325a..21c5d9a 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/IntrospectionSupport.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/IntrospectionSupport.java
@@ -365,30 +365,64 @@ public final class IntrospectionSupport {
         }
     }
 
-    public static Object getProperty(Object target, String property) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+    public static Object getProperty(Object target, String propertyName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
         ObjectHelper.notNull(target, "target");
-        ObjectHelper.notNull(property, "property");
+        ObjectHelper.notNull(propertyName, "property");
 
-        property = property.substring(0, 1).toUpperCase(Locale.ENGLISH) + property.substring(1);
+        propertyName = propertyName.substring(0, 1).toUpperCase(Locale.ENGLISH) + propertyName.substring(1);
 
         Class<?> clazz = target.getClass();
-        Method method = getPropertyGetter(clazz, property);
+        Method method = getPropertyGetter(clazz, propertyName);
         return method.invoke(target);
     }
 
-    public static Object getOrElseProperty(Object target, String property, Object defaultValue) {
+    public static Object getOrElseProperty(Object target, String propertyName, Object defaultValue) {
+        return getOrElseProperty(target, propertyName, defaultValue, false);
+    }
+
+    public static Object getOrElseProperty(Object target, String propertyName, Object defaultValue, boolean ignoreCase) {
         try {
-            return getProperty(target, property);
+            if (ignoreCase) {
+                Class<?> clazz = target.getClass();
+                Method method = getPropertyGetter(clazz, propertyName, true);
+                if (method != null) {
+                    return method.invoke(target);
+                } else {
+                    // not found so return default value
+                    return defaultValue;
+                }
+            } else {
+                return getProperty(target, propertyName);
+            }
         } catch (Exception e) {
             return defaultValue;
         }
     }
 
     public static Method getPropertyGetter(Class<?> type, String propertyName) throws NoSuchMethodException {
-        if (isPropertyIsGetter(type, propertyName)) {
-            return type.getMethod("is" + StringHelper.capitalize(propertyName, true));
+        return getPropertyGetter(type, propertyName, false);
+    }
+
+    public static Method getPropertyGetter(Class<?> type, String propertyName, boolean ignoreCase) throws NoSuchMethodException {
+        if (ignoreCase) {
+            Method[] methods = type.getDeclaredMethods();
+            for (Method m : methods) {
+                if (isGetter(m)) {
+                    if (m.getName().startsWith("is") && m.getName().substring(2).equalsIgnoreCase(propertyName)) {
+                        return m;
+                    } else if (m.getName().startsWith("get") && m.getName().substring(3).equalsIgnoreCase(propertyName)) {
+                        return m;
+                    }
+                }
+            }
+            // not found
+            return null;
         } else {
-            return type.getMethod("get" + StringHelper.capitalize(propertyName, true));
+            if (isPropertyIsGetter(type, propertyName)) {
+                return type.getMethod("is" + StringHelper.capitalize(propertyName, true));
+            } else {
+                return type.getMethod("get" + StringHelper.capitalize(propertyName, true));
+            }
         }
     }
 
@@ -539,7 +573,7 @@ public final class IntrospectionSupport {
      */
     public static boolean setProperty(CamelContext context, TypeConverter typeConverter, Object target, String name, Object value, String refName,
                                       boolean allowBuilderPattern) throws Exception {
-        return setProperty(context, typeConverter, target, name, value, refName, allowBuilderPattern, false);
+        return setProperty(context, typeConverter, target, name, value, refName, allowBuilderPattern, false, false);
     }
 
     /**
@@ -555,7 +589,7 @@ public final class IntrospectionSupport {
      * {@code context} and {@code refName} must NOT be NULL, and {@code value} MUST be NULL.
      */
     public static boolean setProperty(CamelContext context, TypeConverter typeConverter, Object target, String name, Object value, String refName,
-                                      boolean allowBuilderPattern, boolean allowPrivateSetter) throws Exception {
+                                      boolean allowBuilderPattern, boolean allowPrivateSetter, boolean ignoreCase) throws Exception {
 
         // does the property name include a lookup key, then we need to set the property as a map or list
         if (name.contains("[") && name.endsWith("]")) {
@@ -563,10 +597,10 @@ public final class IntrospectionSupport {
             String lookupKey = name.substring(pos + 1, name.length() - 1);
             String key = name.substring(0, pos);
 
-            Object obj = IntrospectionSupport.getOrElseProperty(target, key, null);
+            Object obj = IntrospectionSupport.getOrElseProperty(target, key, null, ignoreCase);
             if (obj == null) {
                 // it was supposed to be a list or map, but its null, so lets create a new list or map and set it automatically
-                Method getter = IntrospectionSupport.getPropertyGetter(target.getClass(), key);
+                Method getter = IntrospectionSupport.getPropertyGetter(target.getClass(), key, ignoreCase);
                 if (getter != null) {
                     // what type does it have
                     Class<?> returnType = getter.getReturnType();
@@ -616,10 +650,10 @@ public final class IntrospectionSupport {
 
         // we need to lookup the value from the registry
         if (context != null && refName != null && value == null) {
-            setters = findSetterMethodsOrderedByParameterType(clazz, name, allowBuilderPattern, allowPrivateSetter);
+            setters = findSetterMethodsOrderedByParameterType(clazz, name, allowBuilderPattern, allowPrivateSetter, ignoreCase);
         } else {
             // find candidates of setter methods as there can be overloaded setters
-            setters = findSetterMethods(clazz, name, value, allowBuilderPattern, allowPrivateSetter);
+            setters = findSetterMethods(clazz, name, value, allowBuilderPattern, allowPrivateSetter, ignoreCase);
         }
         if (setters.isEmpty()) {
             return false;
@@ -740,22 +774,22 @@ public final class IntrospectionSupport {
 
     public static boolean setProperty(CamelContext context, Object target, String name, Object value) throws Exception {
         // allow build pattern as a setter as well
-        return setProperty(context, context != null ? context.getTypeConverter() : null, target, name, value, null, true, false);
+        return setProperty(context, context != null ? context.getTypeConverter() : null, target, name, value, null, true, false, false);
     }
 
     public static boolean setProperty(CamelContext context, TypeConverter typeConverter, Object target, String name, Object value) throws Exception {
         // allow build pattern as a setter as well
-        return setProperty(context, typeConverter, target, name, value, null, true, false);
+        return setProperty(context, typeConverter, target, name, value, null, true, false, false);
     }
     
     public static boolean setProperty(TypeConverter typeConverter, Object target, String name, Object value) throws Exception {
         // allow build pattern as a setter as well
-        return setProperty(null, typeConverter, target, name, value, null, true, false);
+        return setProperty(null, typeConverter, target, name, value, null, true, false, false);
     }
 
     @Deprecated
     public static boolean setProperty(Object target, String name, Object value, boolean allowBuilderPattern) throws Exception {
-        return setProperty(null, null, target, name, value, null, allowBuilderPattern, false);
+        return setProperty(null, null, target, name, value, null, allowBuilderPattern, false, false);
     }
 
     @Deprecated
@@ -764,7 +798,8 @@ public final class IntrospectionSupport {
         return setProperty(target, name, value, true);
     }
 
-    public static Set<Method> findSetterMethods(Class<?> clazz, String name, boolean allowBuilderPattern, boolean allowPrivateSetter) {
+    public static Set<Method> findSetterMethods(Class<?> clazz, String name,
+                                                boolean allowBuilderPattern, boolean allowPrivateSetter, boolean ignoreCase) {
         Set<Method> candidates = new LinkedHashSet<>();
 
         // Build the method name
@@ -778,7 +813,16 @@ public final class IntrospectionSupport {
             Method objectSetMethod = null;
             Method[] methods = allowPrivateSetter ? clazz.getDeclaredMethods() : clazz.getMethods();
             for (Method method : methods) {
-                boolean validName = method.getName().equals(setName) || allowBuilderPattern && method.getName().equals(builderName) || allowBuilderPattern && method.getName().equals(builderName2);
+                boolean validName;
+                if (ignoreCase) {
+                    validName = method.getName().equalsIgnoreCase(setName)
+                            || allowBuilderPattern && method.getName().equalsIgnoreCase(builderName)
+                            || allowBuilderPattern && method.getName().equalsIgnoreCase(builderName2);
+                } else {
+                    validName = method.getName().equals(setName)
+                            || allowBuilderPattern && method.getName().equals(builderName)
+                            || allowBuilderPattern && method.getName().equals(builderName2);
+                }
                 if (validName) {
                     if (isSetter(method, allowBuilderPattern)) {
                         Class<?>[] params = method.getParameterTypes();
@@ -798,8 +842,9 @@ public final class IntrospectionSupport {
         return candidates;
     }
 
-    static Set<Method> findSetterMethods(Class<?> clazz, String name, Object value, boolean allowBuilderPattern, boolean allowPrivateSetter) {
-        Set<Method> candidates = findSetterMethods(clazz, name, allowBuilderPattern, allowPrivateSetter);
+    static Set<Method> findSetterMethods(Class<?> clazz, String name, Object value,
+                                         boolean allowBuilderPattern, boolean allowPrivateSetter, boolean ignoreCase) {
+        Set<Method> candidates = findSetterMethods(clazz, name, allowBuilderPattern, allowPrivateSetter, ignoreCase);
 
         if (candidates.isEmpty()) {
             return candidates;
@@ -824,10 +869,11 @@ public final class IntrospectionSupport {
         }
     }
 
-    static List<Method> findSetterMethodsOrderedByParameterType(Class<?> target, String propertyName, boolean allowBuilderPattern, boolean allowPrivateSetter) {
+    static List<Method> findSetterMethodsOrderedByParameterType(Class<?> target, String propertyName,
+                                                                boolean allowBuilderPattern, boolean allowPrivateSetter, boolean ignoreCase) {
         List<Method> answer = new LinkedList<>();
         List<Method> primitives = new LinkedList<>();
-        Set<Method> setters = findSetterMethods(target, propertyName, allowBuilderPattern, allowPrivateSetter);
+        Set<Method> setters = findSetterMethods(target, propertyName, allowBuilderPattern, allowPrivateSetter, ignoreCase);
         for (Method setter : setters) {
             Class<?> parameterType = setter.getParameterTypes()[0];
             if (PRIMITIVE_CLASSES.contains(parameterType)) {
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java b/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java
index 40752a0..0d32d91 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java
@@ -21,6 +21,7 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 
@@ -43,6 +44,7 @@ import static org.apache.camel.util.ObjectHelper.isNotEmpty;
  *     <li>reference by type - Values can refer to singleton beans by their type in the registry by prefixing with #type: syntax, eg #type:com.foo.MyClassType</li>
  *     <li>autowire by type - Values can refer to singleton beans by auto wiring by setting the value to #autowired</li>
  *     <li>reference new class - Values can refer to creating new beans by their class name by prefixing with #class, eg #class:com.foo.MyClassType</li>
+ *     <li>ignore case - Whether to ignore case for property keys<li>
  * </ul>
  * <p/>
  * This implementations reuses parts of {@link IntrospectionSupport}.
@@ -60,6 +62,7 @@ public final class PropertyBindingSupport {
         private boolean placeholder = true;
         private boolean fluentBuilder = true;
         private boolean allowPrivateSetter = true;
+        private boolean ignoreCase = false;
         private String optionPrefix;
 
         /**
@@ -107,8 +110,16 @@ public final class PropertyBindingSupport {
          * Whether properties should be filtered by prefix.         *
          * Note that the prefix is removed from the key before the property is bound.
          */
-        public Builder withOptionPrefix(String optionPrefix) {
-            this.optionPrefix = optionPrefix;
+        public Builder withAllowPrivateSetter(boolean allowPrivateSetter) {
+            this.allowPrivateSetter = allowPrivateSetter;
+            return this;
+        }
+
+        /**
+         * Whether to ignore case in the property names (keys).
+         */
+        public Builder withIgnoreCase(boolean ignoreCase) {
+            this.ignoreCase = ignoreCase;
             return this;
         }
 
@@ -116,8 +127,8 @@ public final class PropertyBindingSupport {
          * Whether properties should be filtered by prefix.         *
          * Note that the prefix is removed from the key before the property is bound.
          */
-        public Builder withAllowPrivateSetter(boolean allowPrivateSetter) {
-            this.allowPrivateSetter = allowPrivateSetter;
+        public Builder withOptionPrefix(String optionPrefix) {
+            this.optionPrefix = optionPrefix;
             return this;
         }
 
@@ -134,7 +145,8 @@ public final class PropertyBindingSupport {
             org.apache.camel.util.ObjectHelper.notNull(target, "target");
             org.apache.camel.util.ObjectHelper.notNull(properties, "properties");
 
-            return bindProperties(camelContext, target, properties, optionPrefix, nesting, deepNesting, fluentBuilder, allowPrivateSetter, reference, placeholder);
+            return bindProperties(camelContext, target, properties, optionPrefix, ignoreCase, nesting, deepNesting,
+                    fluentBuilder, allowPrivateSetter, reference, placeholder);
         }
 
     }
@@ -215,7 +227,7 @@ public final class PropertyBindingSupport {
         for (Map.Entry<String, Object> entry : properties.entrySet()) {
             String key = entry.getKey();
             Object value = entry.getValue();
-            Class<?> type = getGetterType(target, key);
+            Class<?> type = getGetterType(target, key, false);
 
             boolean skip = parents.contains(value) || value instanceof CamelContext;
             if (skip) {
@@ -242,7 +254,7 @@ public final class PropertyBindingSupport {
                 // attempt to create new instances to walk down the tree if its null (deepNesting option)
                 if (value == null && deepNesting) {
                     // okay is there a setter so we can create a new instance and set it automatic
-                    Method method = findBestSetterMethod(target.getClass(), key, true, true);
+                    Method method = findBestSetterMethod(target.getClass(), key, true, true, false);
                     if (method != null) {
                         Class<?> parameterType = method.getParameterTypes()[0];
                         if (parameterType != null && org.apache.camel.util.ObjectHelper.hasDefaultPublicNoArgConstructor(parameterType)) {
@@ -283,6 +295,19 @@ public final class PropertyBindingSupport {
     }
 
     /**
+     * Binds the properties to the target object, and removes the property that was bound from properties.
+     *
+     * @param camelContext  the camel context
+     * @param target        the target object
+     * @param properties    the properties where the bound properties will be removed from
+     * @param ignoreCase    whether to ignore case for property keys
+     * @return              true if one or more properties was bound
+     */
+    public static boolean bindProperties(CamelContext camelContext, Object target, Map<String, Object> properties, boolean ignoreCase) {
+        return bindProperties(camelContext, target, properties, null, ignoreCase, true, true, true, true, true, true);
+    }
+
+    /**
      * Binds the properties with the given prefix to the target object, and removes the property that was bound from properties.
      * Note that the prefix is removed from the key before the property is bound.
      *
@@ -293,29 +318,22 @@ public final class PropertyBindingSupport {
      * @return              true if one or more properties was bound
      */
     public static boolean bindProperties(CamelContext camelContext, Object target, Map<String, Object> properties, String optionPrefix) {
-        return bindProperties(camelContext, target, properties, optionPrefix, true, true, true, true, true, true);
+        return bindProperties(camelContext, target, properties, optionPrefix, false);
     }
 
     /**
      * Binds the properties with the given prefix to the target object, and removes the property that was bound from properties.
+     * Note that the prefix is removed from the key before the property is bound.
      *
-     * @param camelContext        the camel context
-     * @param target              the target object
-     * @param properties          the properties where the bound properties will be removed from
-     * @param nesting             whether nesting is in use
-     * @param deepNesting         whether deep nesting is in use, where Camel will attempt to walk as deep as possible by creating new objects in the OGNL graph if
-     *                            a property has a setter and the object can be created from a default no-arg constructor.
-     * @param fluentBuilder       whether fluent builder is allowed as a valid getter/setter
-     * @param allowPrivateSetter  whether autowiring components allows to use private setter method when setting the value
-     * @param reference           whether reference parameter (syntax starts with #) is in use
-     * @param placeholder         whether to use Camels property placeholder to resolve placeholders on keys and values
-     * @return                    true if one or more properties was bound
+     * @param camelContext  the camel context
+     * @param target        the target object
+     * @param properties    the properties where the bound properties will be removed from
+     * @param optionPrefix  the prefix used to filter properties
+     * @param ignoreCase    whether to ignore case for property keys
+     * @return              true if one or more properties was bound
      */
-    public static boolean bindProperties(CamelContext camelContext, Object target, Map<String, Object> properties,
-                                         boolean nesting, boolean deepNesting, boolean fluentBuilder, boolean allowPrivateSetter,
-                                         boolean reference, boolean placeholder) {
-
-        return bindProperties(camelContext, target, properties, null, nesting, deepNesting, fluentBuilder, allowPrivateSetter, reference, placeholder);
+    public static boolean bindProperties(CamelContext camelContext, Object target, Map<String, Object> properties, String optionPrefix, boolean ignoreCase) {
+        return bindProperties(camelContext, target, properties, optionPrefix, ignoreCase, true, true, true, true, true, true);
     }
 
     /**
@@ -326,6 +344,7 @@ public final class PropertyBindingSupport {
      * @param target              the target object
      * @param properties          the properties where the bound properties will be removed from
      * @param optionPrefix        the prefix used to filter properties
+     * @param ignoreCase          whether to ignore case for property keys
      * @param nesting             whether nesting is in use
      * @param deepNesting         whether deep nesting is in use, where Camel will attempt to walk as deep as possible by creating new objects in the OGNL graph if
      *                            a property has a setter and the object can be created from a default no-arg constructor.
@@ -336,7 +355,7 @@ public final class PropertyBindingSupport {
      * @return                    true if one or more properties was bound
      */
     public static boolean bindProperties(CamelContext camelContext, Object target, Map<String, Object> properties,
-                                         String optionPrefix,
+                                         String optionPrefix, boolean ignoreCase,
                                          boolean nesting, boolean deepNesting, boolean fluentBuilder, boolean allowPrivateSetter,
                                          boolean reference, boolean placeholder) {
         org.apache.camel.util.ObjectHelper.notNull(camelContext, "camelContext");
@@ -347,19 +366,25 @@ public final class PropertyBindingSupport {
         // must set reference parameters first before the other bindings
         setReferenceProperties(camelContext, target, properties);
 
+        String uOptionPrefix = "";
+        if (ignoreCase && isNotEmpty(optionPrefix)) {
+            uOptionPrefix = optionPrefix.toUpperCase(Locale.US);
+        }
+
         for (Iterator<Map.Entry<String, Object>> iter = properties.entrySet().iterator(); iter.hasNext();) {
             Map.Entry<String, Object> entry = iter.next();
             String key = entry.getKey();
             Object value = entry.getValue();
 
             if (isNotEmpty(optionPrefix)) {
-                if (!key.startsWith(optionPrefix)) {
+                boolean match = key.startsWith(optionPrefix) || ignoreCase && key.toUpperCase(Locale.US).startsWith(uOptionPrefix);
+                if (!match) {
                     continue;
                 }
                 key = key.substring(optionPrefix.length());
             }
 
-            if (bindProperty(camelContext, target, key, value, nesting, deepNesting, fluentBuilder, allowPrivateSetter, reference, placeholder)) {
+            if (bindProperty(camelContext, target, key, value, ignoreCase, nesting, deepNesting, fluentBuilder, allowPrivateSetter, reference, placeholder)) {
                 iter.remove();
                 rc = true;
             }
@@ -378,9 +403,23 @@ public final class PropertyBindingSupport {
      * @return              true if property was bound, false otherwise
      */
     public static boolean bindProperty(CamelContext camelContext, Object target, String name, Object value) {
+        return bindProperty(camelContext, target, name, value, false);
+    }
+
+    /**
+     * Binds the property to the target object.
+     *
+     * @param camelContext  the camel context
+     * @param target        the target object
+     * @param name          name of property
+     * @param value         value of property
+     * @param ignoreCase    whether to ignore case for property keys
+     * @return              true if property was bound, false otherwise
+     */
+    public static boolean bindProperty(CamelContext camelContext, Object target, String name, Object value, boolean ignoreCase) {
         try {
             if (target != null && name != null) {
-                return setProperty(camelContext, target, name, value, false, true, true, true, true, true, true);
+                return setProperty(camelContext, target, name, value, false, ignoreCase, true, true, true, true, true, true);
             }
         } catch (Exception e) {
             throw new PropertyBindingException(target, name, e);
@@ -390,10 +429,11 @@ public final class PropertyBindingSupport {
     }
 
     private static boolean bindProperty(CamelContext camelContext, Object target, String name, Object value,
-                                        boolean nesting, boolean deepNesting, boolean fluentBuilder, boolean allowPrivateSetter, boolean reference, boolean placeholder) {
+                                        boolean ignoreCase, boolean nesting, boolean deepNesting, boolean fluentBuilder,
+                                        boolean allowPrivateSetter, boolean reference, boolean placeholder) {
         try {
             if (target != null && name != null) {
-                return setProperty(camelContext, target, name, value, false, nesting, deepNesting, fluentBuilder, allowPrivateSetter, reference, placeholder);
+                return setProperty(camelContext, target, name, value, false, ignoreCase, nesting, deepNesting, fluentBuilder, allowPrivateSetter, reference, placeholder);
             }
         } catch (Exception e) {
             throw new PropertyBindingException(target, name, e);
@@ -411,9 +451,22 @@ public final class PropertyBindingSupport {
      * @param value         value of property
      */
     public static void bindMandatoryProperty(CamelContext camelContext, Object target, String name, Object value) {
+        bindMandatoryProperty(camelContext, target, name, value, false);
+    }
+
+    /**
+     * Binds the mandatory property to the target object (will fail if not set/bound).
+     *
+     * @param camelContext  the camel context
+     * @param target        the target object
+     * @param name          name of property
+     * @param value         value of property
+     * @param ignoreCase    whether to ignore case for property keys
+     */
+    public static void bindMandatoryProperty(CamelContext camelContext, Object target, String name, Object value, boolean ignoreCase) {
         try {
             if (target != null && name != null) {
-                boolean bound = setProperty(camelContext, target, name, value, true, true, true, true, true, true, true);
+                boolean bound = setProperty(camelContext, target, name, value, true, ignoreCase, true, true, true, true, true, true);
                 if (!bound) {
                     throw new PropertyBindingException(target, name);
                 }
@@ -424,8 +477,8 @@ public final class PropertyBindingSupport {
     }
 
     private static boolean setProperty(CamelContext context, Object target, String name, Object value, boolean mandatory,
-                                       boolean nesting, boolean deepNesting, boolean fluentBuilder, boolean allowPrivateSetter,
-                                       boolean reference, boolean placeholder) throws Exception {
+                                       boolean ignoreCase, boolean nesting, boolean deepNesting, boolean fluentBuilder,
+                                       boolean allowPrivateSetter, boolean reference, boolean placeholder) throws Exception {
         String refName = null;
 
         if (placeholder) {
@@ -448,14 +501,14 @@ public final class PropertyBindingSupport {
                 // we should only iterate until until 2nd last so we use -1 in the for loop
                 for (int i = 0; i < parts.length - 1; i++) {
                     String part = parts[i];
-                    Object prop = getOrElseProperty(newTarget, part, null);
+                    Object prop = getOrElseProperty(newTarget, part, null, ignoreCase);
                     if (prop == null) {
                         if (!deepNesting) {
                             // okay we cannot go further down
                             break;
                         }
                         // okay is there a setter so we can create a new instance and set it automatic
-                        Method method = findBestSetterMethod(newClass, part, fluentBuilder, allowPrivateSetter);
+                        Method method = findBestSetterMethod(newClass, part, fluentBuilder, allowPrivateSetter, ignoreCase);
                         if (method != null) {
                             Class<?> parameterType = method.getParameterTypes()[0];
                             Object instance = null;
@@ -509,7 +562,7 @@ public final class PropertyBindingSupport {
                 }
             } else if (value.toString().equals("#autowired")) {
                 // we should get the type from the setter
-                Method method = findBestSetterMethod(target.getClass(), name, fluentBuilder, allowPrivateSetter);
+                Method method = findBestSetterMethod(target.getClass(), name, fluentBuilder, allowPrivateSetter, ignoreCase);
                 if (method != null) {
                     Class<?> parameterType = method.getParameterTypes()[0];
                     if (parameterType != null) {
@@ -526,7 +579,7 @@ public final class PropertyBindingSupport {
             }
         }
 
-        boolean hit = IntrospectionSupport.setProperty(context, context.getTypeConverter(), target, name, value, refName, fluentBuilder, allowPrivateSetter);
+        boolean hit = IntrospectionSupport.setProperty(context, context.getTypeConverter(), target, name, value, refName, fluentBuilder, allowPrivateSetter, ignoreCase);
         if (!hit && mandatory) {
             // there is no setter with this given name, so lets report this as a problem
             throw new IllegalArgumentException("Cannot find setter method: " + name + " on bean: " + target + " when binding property: " + ognlPath);
@@ -534,7 +587,7 @@ public final class PropertyBindingSupport {
         return hit;
     }
 
-    private static Object getOrElseProperty(Object target, String property, Object defaultValue) {
+    private static Object getOrElseProperty(Object target, String property, Object defaultValue, boolean ignoreCase) {
         String key = property;
         String lookupKey = null;
 
@@ -545,7 +598,7 @@ public final class PropertyBindingSupport {
             key = property.substring(0, pos);
         }
 
-        Object answer = IntrospectionSupport.getOrElseProperty(target, key, defaultValue);
+        Object answer = IntrospectionSupport.getOrElseProperty(target, key, defaultValue, ignoreCase);
         if (answer instanceof Map && lookupKey != null) {
             Map map = (Map) answer;
             answer = map.getOrDefault(lookupKey, defaultValue);
@@ -566,16 +619,17 @@ public final class PropertyBindingSupport {
         return answer != null ? answer : defaultValue;
     }
 
-    private static Method findBestSetterMethod(Class clazz, String name, boolean fluentBuilder, boolean allowPrivateSetter) {
+    private static Method findBestSetterMethod(Class clazz, String name,
+                                               boolean fluentBuilder, boolean allowPrivateSetter, boolean ignoreCase) {
         // is there a direct setter?
-        Set<Method> candidates = findSetterMethods(clazz, name, fluentBuilder, allowPrivateSetter);
+        Set<Method> candidates = findSetterMethods(clazz, name, false, allowPrivateSetter, ignoreCase);
         if (candidates.size() == 1) {
             return candidates.iterator().next();
         }
 
         // okay now try with builder pattern
         if (fluentBuilder) {
-            candidates = findSetterMethods(clazz, name, fluentBuilder, allowPrivateSetter);
+            candidates = findSetterMethods(clazz, name, fluentBuilder, allowPrivateSetter, ignoreCase);
             if (candidates.size() == 1) {
                 return candidates.iterator().next();
             }
@@ -584,11 +638,18 @@ public final class PropertyBindingSupport {
         return null;
     }
 
-    private static Class getGetterType(Object target, String name) {
+    private static Class getGetterType(Object target, String name, boolean ignoreCase) {
         try {
-            Method getter = IntrospectionSupport.getPropertyGetter(target.getClass(), name);
-            if (getter != null) {
-                return getter.getReturnType();
+            if (ignoreCase) {
+                Method getter = IntrospectionSupport.getPropertyGetter(target.getClass(), name, true);
+                if (getter != null) {
+                    return getter.getReturnType();
+                }
+            } else {
+                Method getter = IntrospectionSupport.getPropertyGetter(target.getClass(), name);
+                if (getter != null) {
+                    return getter.getReturnType();
+                }
             }
         } catch (NoSuchMethodException e) {
             // ignore


[camel] 05/07: CAMEL-13683: camel-main - configuring properties report better error if missing JARs on classpathand other mistakes.

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit c2bd36f44038c3f067f1a3029b2d47492808edbc
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Jun 26 11:43:38 2019 +0200

    CAMEL-13683: camel-main - configuring properties report better error if missing JARs on classpathand other mistakes.
---
 .../main/java/org/apache/camel/CamelContext.java   |   3 +-
 .../java/org/apache/camel/main/MainSupport.java    | 171 +++++++++++----------
 2 files changed, 93 insertions(+), 81 deletions(-)

diff --git a/core/camel-api/src/main/java/org/apache/camel/CamelContext.java b/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
index 8a84349..3a41241 100644
--- a/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
+++ b/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
@@ -724,8 +724,9 @@ public interface CamelContext extends StatefulService, RuntimeConfiguration {
      *
      * @param language name of the language
      * @return the resolved language
+     * @throws NoSuchLanguageException is thrown if language could not be resolved
      */
-    Language resolveLanguage(String language);
+    Language resolveLanguage(String language) throws NoSuchLanguageException;
 
     /**
      * Parses the given text and resolve any property placeholders - using {{key}}.
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java b/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
index a5d9993..8024a49 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
@@ -37,6 +37,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 import org.apache.camel.CamelContext;
 import org.apache.camel.Component;
 import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.NoSuchLanguageException;
 import org.apache.camel.ProducerTemplate;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.model.HystrixConfigurationDefinition;
@@ -823,23 +824,20 @@ public abstract class MainSupport extends ServiceSupport {
                 // grab the value
                 String value = prop.getProperty(key);
                 String option = key.substring(14);
-                if (ObjectHelper.isNotEmpty(value) && ObjectHelper.isNotEmpty(option)) {
-                    properties.put(optionKey(option), value);
-                }
+                validateOptionAndValue(key, option, value);
+                properties.put(optionKey(option), value);
             } else if (key.startsWith("camel.hystrix.")) {
                 // grab the value
                 String value = prop.getProperty(key);
                 String option = key.substring(14);
-                if (ObjectHelper.isNotEmpty(value) && ObjectHelper.isNotEmpty(option)) {
-                    hystrixProperties.put(optionKey(option), value);
-                }
+                validateOptionAndValue(key, option, value);
+                hystrixProperties.put(optionKey(option), value);
             } else if (key.startsWith("camel.rest.")) {
                 // grab the value
                 String value = prop.getProperty(key);
                 String option = key.substring(11);
-                if (ObjectHelper.isNotEmpty(value) && ObjectHelper.isNotEmpty(option)) {
-                    restProperties.put(optionKey(option), value);
-                }
+                validateOptionAndValue(key, option, value);
+                restProperties.put(optionKey(option), value);
             }
         }
         if (!properties.isEmpty()) {
@@ -868,27 +866,6 @@ public abstract class MainSupport extends ServiceSupport {
         }
     }
 
-    protected Properties loadEnvironmentVariablesAsProperties(String[] prefixes) {
-        Properties answer = new OrderedProperties();
-        if (prefixes == null || prefixes.length == 0) {
-            return answer;
-        }
-
-        for (String prefix : prefixes) {
-            final String pk = prefix.toUpperCase(Locale.US).replaceAll("[^\\w]", "-");
-            final String pk2 = pk.replace('-', '_');
-            System.getenv().forEach((k, v) -> {
-                k = k.toUpperCase(Locale.US);
-                if (k.startsWith(pk) || k.startsWith(pk2)) {
-                    String key = k.toLowerCase(Locale.US).replace('_', '.');
-                    answer.put(key, v);
-                }
-            });
-        }
-
-        return answer;
-    }
-
     protected void autoConfigurationPropertiesComponent(CamelContext camelContext) throws Exception {
         // load properties
         Properties prop = camelContext.getPropertiesComponent().loadProperties();
@@ -910,17 +887,15 @@ public abstract class MainSupport extends ServiceSupport {
         Map<Object, Map<String, Object>> properties = new LinkedHashMap<>();
 
         for (String key : prop.stringPropertyNames()) {
-            int dot = key.indexOf(".", 26);
-            if (key.startsWith("camel.component.properties.") && dot > 0) {
+            if (key.startsWith("camel.component.properties.")) {
                 Component component = camelContext.getPropertiesComponent();
-                // grab the value
-                String value = prop.getProperty(key);
-                String option = key.substring(dot + 1);
-                if (ObjectHelper.isNotEmpty(value) && ObjectHelper.isNotEmpty(option)) {
-                    Map<String, Object> values = properties.getOrDefault(component, new LinkedHashMap<>());
-                    values.put(optionKey(option), value);
-                    properties.put(component, values);
-                }
+                int dot = key.indexOf(".", 26);
+                String option = dot == -1 ? "" : key.substring(dot + 1);
+                String value = prop.getProperty(key, "");
+                validateOptionAndValue(key, option, value);
+                Map<String, Object> values = properties.getOrDefault(component, new LinkedHashMap<>());
+                values.put(optionKey(option), value);
+                properties.put(component, values);
             }
         }
 
@@ -960,9 +935,8 @@ public abstract class MainSupport extends ServiceSupport {
                 // grab the value
                 String value = prop.getProperty(key);
                 String option = key.substring(11);
-                if (ObjectHelper.isNotEmpty(value) && ObjectHelper.isNotEmpty(option)) {
-                    properties.put(optionKey(option), value);
-                }
+                validateOptionAndValue(key, option, value);
+                properties.put(optionKey(option), value);
             }
         }
 
@@ -1015,52 +989,60 @@ public abstract class MainSupport extends ServiceSupport {
         Map<Object, Map<String, Object>> properties = new LinkedHashMap<>();
 
         for (String key : prop.stringPropertyNames()) {
-            int dot = key.indexOf(".", 16);
-            if (key.startsWith("camel.component.") && dot > 0) {
-                // grab component name
-                String name = key.substring(16, dot);
+            if (key.startsWith("camel.component.")) {
+                // grab name
+                int dot = key.indexOf(".", 16);
+                String name = dot == -1 ? key.substring(16) : key.substring(16, dot);
                 // skip properties as its already configured earlier
                 if ("properties".equals(name)) {
                     continue;
                 }
                 Component component = camelContext.getComponent(name);
-                // grab the value
-                String value = prop.getProperty(key);
-                String option = key.substring(dot + 1);
-                if (component != null && ObjectHelper.isNotEmpty(value) && ObjectHelper.isNotEmpty(option)) {
-                    Map<String, Object> values = properties.getOrDefault(component, new LinkedHashMap<>());
-                    // we ignore case for property keys (so we should store them in canonical style
-                    values.put(optionKey(option), value);
-                    properties.put(component, values);
+                if (component == null) {
+                    throw new IllegalArgumentException("Error configuring property: " + key + " because cannot find component with name " + name
+                            + ". Make sure you have the component on the classpath");
                 }
+                String option = dot == -1 ? "" : key.substring(dot + 1);
+                String value = prop.getProperty(key, "");
+                validateOptionAndValue(key, option, value);
+                Map<String, Object> values = properties.getOrDefault(component, new LinkedHashMap<>());
+                // we ignore case for property keys (so we should store them in canonical style
+                values.put(optionKey(option), value);
+                properties.put(component, values);
             }
-            dot = key.indexOf(".", 17);
-            if (key.startsWith("camel.dataformat.") && dot > 0) {
-                // grab component name
-                String name = key.substring(17, dot);
+            if (key.startsWith("camel.dataformat.")) {
+                // grab name
+                int dot = key.indexOf(".", 17);
+                String name = dot == -1 ? key.substring(17) : key.substring(17, dot);
                 DataFormat dataformat = camelContext.resolveDataFormat(name);
-                // grab the value
-                String value = prop.getProperty(key);
-                String option = key.substring(dot + 1);
-                if (dataformat != null && ObjectHelper.isNotEmpty(value) && ObjectHelper.isNotEmpty(option)) {
-                    Map<String, Object> values = properties.getOrDefault(dataformat, new LinkedHashMap<>());
-                    values.put(optionKey(option), value);
-                    properties.put(dataformat, values);
+                if (dataformat == null) {
+                    throw new IllegalArgumentException("Error configuring property: " + key + " because cannot find dataformat with name " + name
+                            + ". Make sure you have the dataformat on the classpath");
                 }
+                String option = dot == -1 ? "" : key.substring(dot + 1);
+                String value = prop.getProperty(key, "");
+                validateOptionAndValue(key, option, value);
+                Map<String, Object> values = properties.getOrDefault(dataformat, new LinkedHashMap<>());
+                values.put(optionKey(option), value);
+                properties.put(dataformat, values);
             }
-            dot = key.indexOf(".", 15);
-            if (key.startsWith("camel.language.") && dot > 0) {
-                // grab component name
-                String name = key.substring(15, dot);
-                Language language = camelContext.resolveLanguage(name);
-                // grab the value
-                String value = prop.getProperty(key);
-                String option = key.substring(dot + 1);
-                if (language != null && ObjectHelper.isNotEmpty(value) && ObjectHelper.isNotEmpty(option)) {
-                    Map<String, Object> values = properties.getOrDefault(language, new LinkedHashMap<>());
-                    values.put(optionKey(option), value);
-                    properties.put(language, values);
+            if (key.startsWith("camel.language.")) {
+                // grab name
+                int dot = key.indexOf(".", 15);
+                String name = dot == -1 ? key.substring(15) : key.substring(15, dot);
+                Language language;
+                try {
+                    language = camelContext.resolveLanguage(name);
+                } catch (NoSuchLanguageException e) {
+                    throw new IllegalArgumentException("Error configuring property: " + key + " because cannot find language with name " + name
+                            + ". Make sure you have the language on the classpath");
                 }
+                String option = dot == -1 ? "" : key.substring(dot + 1);
+                String value = prop.getProperty(key, "");
+                validateOptionAndValue(key, option, value);
+                Map<String, Object> values = properties.getOrDefault(language, new LinkedHashMap<>());
+                values.put(optionKey(option), value);
+                properties.put(language, values);
             }
         }
 
@@ -1074,8 +1056,7 @@ public abstract class MainSupport extends ServiceSupport {
             setPropertiesOnTarget(camelContext, obj, values, true, true);
         }
 
-        // TODO: Log if any options was not configured (and check if they are on classpath)
-
+        // TODO: log if any options was not configured
     }
 
     protected void autoConfigurationFromRegistry(CamelContext camelContext, boolean deepNesting) throws Exception {
@@ -1090,6 +1071,36 @@ public abstract class MainSupport extends ServiceSupport {
         });
     }
 
+    protected static Properties loadEnvironmentVariablesAsProperties(String[] prefixes) {
+        Properties answer = new OrderedProperties();
+        if (prefixes == null || prefixes.length == 0) {
+            return answer;
+        }
+
+        for (String prefix : prefixes) {
+            final String pk = prefix.toUpperCase(Locale.US).replaceAll("[^\\w]", "-");
+            final String pk2 = pk.replace('-', '_');
+            System.getenv().forEach((k, v) -> {
+                k = k.toUpperCase(Locale.US);
+                if (k.startsWith(pk) || k.startsWith(pk2)) {
+                    String key = k.toLowerCase(Locale.US).replace('_', '.');
+                    answer.put(key, v);
+                }
+            });
+        }
+
+        return answer;
+    }
+
+    protected void validateOptionAndValue(String key, String option, String value) {
+        if (ObjectHelper.isEmpty(option)) {
+            throw new IllegalArgumentException("Error configuring property: " + key + " because option is empty");
+        }
+        if (ObjectHelper.isEmpty(value)) {
+            throw new IllegalArgumentException("Error configuring property: " + key + " because value is empty");
+        }
+    }
+
     private static String optionKey(String key) {
         // as we ignore case for property names we should use keys in same case and without dashes
         key = StringHelper.replaceAll(key, "-", "");


[camel] 04/07: CAMEL-13681: Camel main should ignore case in property keys

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 1076cc0e55b13a350e5bc7b3a800641a098ce5cc
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Jun 26 10:29:32 2019 +0200

    CAMEL-13681: Camel main should ignore case in property keys
---
 .../java/org/apache/camel/main/MainSupport.java    | 38 ++++++++++++++++------
 1 file changed, 28 insertions(+), 10 deletions(-)

diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java b/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
index fb8abff..a5d9993 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
@@ -57,6 +57,7 @@ import org.apache.camel.util.FileUtil;
 import org.apache.camel.util.IOHelper;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.OrderedProperties;
+import org.apache.camel.util.StringHelper;
 import org.apache.camel.util.concurrent.ThreadHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -803,6 +804,17 @@ public abstract class MainSupport extends ServiceSupport {
 
         // now configure context/hystrix/rest with additional properties
         Properties prop = camelContext.getPropertiesComponent().loadProperties();
+
+        // load properties from ENV (override existing)
+        Properties propENV = loadEnvironmentVariablesAsProperties(new String[]{"camel.component.properties."});
+        if (!propENV.isEmpty()) {
+            prop.putAll(propENV);
+            LOG.debug("Properties from OS environment variables:");
+            for (String key : propENV.stringPropertyNames()) {
+                LOG.debug("    {}={}", key, propENV.getProperty(key));
+            }
+        }
+
         Map<String, Object> properties = new LinkedHashMap<>();
         Map<String, Object> hystrixProperties = new LinkedHashMap<>();
         Map<String, Object> restProperties = new LinkedHashMap<>();
@@ -812,21 +824,21 @@ public abstract class MainSupport extends ServiceSupport {
                 String value = prop.getProperty(key);
                 String option = key.substring(14);
                 if (ObjectHelper.isNotEmpty(value) && ObjectHelper.isNotEmpty(option)) {
-                    properties.put(option, value);
+                    properties.put(optionKey(option), value);
                 }
             } else if (key.startsWith("camel.hystrix.")) {
                 // grab the value
                 String value = prop.getProperty(key);
                 String option = key.substring(14);
                 if (ObjectHelper.isNotEmpty(value) && ObjectHelper.isNotEmpty(option)) {
-                    hystrixProperties.put(option, value);
+                    hystrixProperties.put(optionKey(option), value);
                 }
             } else if (key.startsWith("camel.rest.")) {
                 // grab the value
                 String value = prop.getProperty(key);
                 String option = key.substring(11);
                 if (ObjectHelper.isNotEmpty(value) && ObjectHelper.isNotEmpty(option)) {
-                    restProperties.put(option, value);
+                    restProperties.put(optionKey(option), value);
                 }
             }
         }
@@ -906,7 +918,7 @@ public abstract class MainSupport extends ServiceSupport {
                 String option = key.substring(dot + 1);
                 if (ObjectHelper.isNotEmpty(value) && ObjectHelper.isNotEmpty(option)) {
                     Map<String, Object> values = properties.getOrDefault(component, new LinkedHashMap<>());
-                    values.put(option, value);
+                    values.put(optionKey(option), value);
                     properties.put(component, values);
                 }
             }
@@ -949,7 +961,7 @@ public abstract class MainSupport extends ServiceSupport {
                 String value = prop.getProperty(key);
                 String option = key.substring(11);
                 if (ObjectHelper.isNotEmpty(value) && ObjectHelper.isNotEmpty(option)) {
-                    properties.put(option, value);
+                    properties.put(optionKey(option), value);
                 }
             }
         }
@@ -1017,7 +1029,8 @@ public abstract class MainSupport extends ServiceSupport {
                 String option = key.substring(dot + 1);
                 if (component != null && ObjectHelper.isNotEmpty(value) && ObjectHelper.isNotEmpty(option)) {
                     Map<String, Object> values = properties.getOrDefault(component, new LinkedHashMap<>());
-                    values.put(option, value);
+                    // we ignore case for property keys (so we should store them in canonical style
+                    values.put(optionKey(option), value);
                     properties.put(component, values);
                 }
             }
@@ -1031,7 +1044,7 @@ public abstract class MainSupport extends ServiceSupport {
                 String option = key.substring(dot + 1);
                 if (dataformat != null && ObjectHelper.isNotEmpty(value) && ObjectHelper.isNotEmpty(option)) {
                     Map<String, Object> values = properties.getOrDefault(dataformat, new LinkedHashMap<>());
-                    values.put(option, value);
+                    values.put(optionKey(option), value);
                     properties.put(dataformat, values);
                 }
             }
@@ -1045,14 +1058,12 @@ public abstract class MainSupport extends ServiceSupport {
                 String option = key.substring(dot + 1);
                 if (language != null && ObjectHelper.isNotEmpty(value) && ObjectHelper.isNotEmpty(option)) {
                     Map<String, Object> values = properties.getOrDefault(language, new LinkedHashMap<>());
-                    values.put(option, value);
+                    values.put(optionKey(option), value);
                     properties.put(language, values);
                 }
             }
         }
 
-        // TODO: filter out duplicte properties due to ignore-case
-
         if (!properties.isEmpty()) {
             long total = properties.values().stream().mapToLong(Map::size).sum();
             LOG.info("Auto configuring {} components/dataformat/languages from loaded properties: {}", properties.size(), total);
@@ -1079,6 +1090,13 @@ public abstract class MainSupport extends ServiceSupport {
         });
     }
 
+    private static String optionKey(String key) {
+        // as we ignore case for property names we should use keys in same case and without dashes
+        key = StringHelper.replaceAll(key, "-", "");
+        key = key.toLowerCase(Locale.US);
+        return key;
+    }
+
     public void addRouteBuilder(RouteBuilder routeBuilder) {
         getRouteBuilders().add(routeBuilder);
     }


[camel] 06/07: CAMEL-13683: camel-main - Allow to turn of fail fast if configuring properties fail

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 7d11d5dd9860ad374fe28df8a8b158b7f31109c2
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Jun 26 12:05:23 2019 +0200

    CAMEL-13683: camel-main - Allow to turn of fail fast if configuring properties fail
---
 .../camel/main/MainConfigurationProperties.java    | 26 ++++++++++++++++++++++
 .../java/org/apache/camel/main/MainSupport.java    | 21 +++++++++++------
 .../camel-main-configuration-metadata.json         |  7 ++++++
 .../META-INF/spring-configuration-metadata.json    |  7 ++++++
 .../META-INF/spring-configuration-metadata.json    |  7 ++++++
 5 files changed, 61 insertions(+), 7 deletions(-)

diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
index 89518b9..2925337 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
@@ -22,6 +22,7 @@ package org.apache.camel.main;
 public class MainConfigurationProperties extends DefaultConfigurationProperties<MainConfigurationProperties> {
 
     private boolean autoConfigurationEnabled = true;
+    private boolean autoConfigurationFailFast = true;
     private boolean autowireComponentProperties = true;
     private boolean autowireComponentPropertiesDeep;
     private boolean autowireComponentPropertiesAllowPrivateSetter = true;
@@ -80,6 +81,20 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties<
         this.autoConfigurationEnabled = autoConfigurationEnabled;
     }
 
+    public boolean isAutoConfigurationFailFast() {
+        return autoConfigurationFailFast;
+    }
+
+    /**
+     * Whether auto configuration should fail fast when configuring one ore more properties fails for whatever reason
+     * such as a invalid property name, etc.
+     * <p/>
+     * This option is default enabled.
+     */
+    public void setAutoConfigurationFailFast(boolean autoConfigurationFailFast) {
+        this.autoConfigurationFailFast = autoConfigurationFailFast;
+    }
+
     public boolean isAutowireComponentProperties() {
         return autowireComponentProperties;
     }
@@ -173,6 +188,17 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties<
     }
 
     /**
+     * Whether auto configuration should fail fast when configuring one ore more properties fails for whatever reason
+     * such as a invalid property name, etc.
+     * <p/>
+     * This option is default enabled.
+     */
+    public MainConfigurationProperties withAutoConfigurationFailFast(boolean autoConfigurationFailFast) {
+        this.autoConfigurationFailFast = autoConfigurationFailFast;
+        return this;
+    }
+
+    /**
      * Whether autowiring components with properties that are of same type, which has been added to the Camel registry, as a singleton instance.
      * This is used for convention over configuration to inject DataSource, AmazonLogin instances to the components.
      * <p/>
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java b/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
index 8024a49..673a6a3 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
@@ -842,7 +842,7 @@ public abstract class MainSupport extends ServiceSupport {
         }
         if (!properties.isEmpty()) {
             LOG.info("Auto configuring CamelContext from loaded properties: {}", properties.size());
-            setPropertiesOnTarget(camelContext, camelContext, properties, true, true);
+            setPropertiesOnTarget(camelContext, camelContext, properties, mainConfigurationProperties.isAutoConfigurationFailFast(), true);
         }
         if (!hystrixProperties.isEmpty()) {
             LOG.info("Auto configuring Hystrix EIP from loaded properties: {}", hystrixProperties.size());
@@ -852,7 +852,7 @@ public abstract class MainSupport extends ServiceSupport {
                 hystrix = new HystrixConfigurationDefinition();
                 model.setHystrixConfiguration(hystrix);
             }
-            setPropertiesOnTarget(camelContext, hystrix, hystrixProperties, true, true);
+            setPropertiesOnTarget(camelContext, hystrix, hystrixProperties, mainConfigurationProperties.isAutoConfigurationFailFast(), true);
         }
         if (!restProperties.isEmpty()) {
             LOG.info("Auto configuring Rest DSL from loaded properties: {}", restProperties.size());
@@ -862,7 +862,7 @@ public abstract class MainSupport extends ServiceSupport {
                 rest = new RestConfiguration();
                 model.setRestConfiguration(rest);
             }
-            setPropertiesOnTarget(camelContext, rest, restProperties, true, true);
+            setPropertiesOnTarget(camelContext, rest, restProperties, mainConfigurationProperties.isAutoConfigurationFailFast(), true);
         }
     }
 
@@ -906,7 +906,7 @@ public abstract class MainSupport extends ServiceSupport {
 
         for (Object obj : properties.keySet()) {
             Map<String, Object> values = properties.get(obj);
-            setPropertiesOnTarget(camelContext, obj, values, true, true);
+            setPropertiesOnTarget(camelContext, obj, values, mainConfigurationProperties.isAutoConfigurationFailFast(), true);
         }
     }
 
@@ -930,6 +930,7 @@ public abstract class MainSupport extends ServiceSupport {
 
         Map<String, Object> properties = new LinkedHashMap<>();
 
+
         for (String key : prop.stringPropertyNames()) {
             if (key.startsWith("camel.main.")) {
                 // grab the value
@@ -940,9 +941,15 @@ public abstract class MainSupport extends ServiceSupport {
             }
         }
 
+        // special for fail-fast as we need to know this early before we set all the other options
+        Object failFast = properties.remove("autoconfigurationfailfast");
+        if (failFast != null) {
+            PropertyBindingSupport.bindMandatoryProperty(camelContext, config, "autoConfigurationFailFast", failFast, true);
+        }
+
         if (!properties.isEmpty()) {
             LOG.info("Auto configuring main from loaded properties: {}", properties.size());
-            setPropertiesOnTarget(camelContext, config, properties, true, true);
+            setPropertiesOnTarget(camelContext, config, properties, mainConfigurationProperties.isAutoConfigurationFailFast(), true);
         }
     }
 
@@ -1053,10 +1060,10 @@ public abstract class MainSupport extends ServiceSupport {
 
         for (Object obj : properties.keySet()) {
             Map<String, Object> values = properties.get(obj);
-            setPropertiesOnTarget(camelContext, obj, values, true, true);
+            setPropertiesOnTarget(camelContext, obj, values, mainConfigurationProperties.isAutoConfigurationFailFast(), true);
         }
 
-        // TODO: log if any options was not configured
+        // TODO: Log which options was not set
     }
 
     protected void autoConfigurationFromRegistry(CamelContext camelContext, boolean deepNesting) throws Exception {
diff --git a/core/camel-main/src/main/resources/META-INF/camel-main-configuration-metadata.json b/core/camel-main/src/main/resources/META-INF/camel-main-configuration-metadata.json
index 096901c..0327eca 100644
--- a/core/camel-main/src/main/resources/META-INF/camel-main-configuration-metadata.json
+++ b/core/camel-main/src/main/resources/META-INF/camel-main-configuration-metadata.json
@@ -31,6 +31,13 @@
 			"defaultValue":"true"
 		},
 		{
+			"name":"camel.main.auto-configuration-fail-fast",
+			"type":"boolean",
+			"sourceType":"org.apache.camel.main.MainConfigurationProperties",
+			"description":"Whether auto configuration should fail fast when configuring one ore more properties fails for whatever reason such as a invalid property name, etc. This option is default enabled.",
+			"defaultValue":"true"
+		},
+		{
 			"name":"camel.main.auto-startup",
 			"type":"boolean",
 			"sourceType":"org.apache.camel.main.DefaultConfigurationProperties",
diff --git a/examples/camel-example-main-artemis/src/main/resources/META-INF/spring-configuration-metadata.json b/examples/camel-example-main-artemis/src/main/resources/META-INF/spring-configuration-metadata.json
index ba64ce0..364d91c 100644
--- a/examples/camel-example-main-artemis/src/main/resources/META-INF/spring-configuration-metadata.json
+++ b/examples/camel-example-main-artemis/src/main/resources/META-INF/spring-configuration-metadata.json
@@ -171,6 +171,13 @@
 			"defaultValue":"true"
 		},
 		{
+			"name":"camel.main.auto-configuration-fail-fast",
+			"type":"boolean",
+			"sourceType":"org.apache.camel.main.MainConfigurationProperties",
+			"description":"Whether auto configuration should fail fast when configuring one ore more properties fails for whatever reason such as a invalid property name, etc. This option is default enabled.",
+			"defaultValue":"true"
+		},
+		{
 			"name":"camel.main.auto-startup",
 			"type":"boolean",
 			"sourceType":"org.apache.camel.main.DefaultConfigurationProperties",
diff --git a/examples/camel-example-main/src/main/resources/META-INF/spring-configuration-metadata.json b/examples/camel-example-main/src/main/resources/META-INF/spring-configuration-metadata.json
index 5340af6..b5bf26c 100644
--- a/examples/camel-example-main/src/main/resources/META-INF/spring-configuration-metadata.json
+++ b/examples/camel-example-main/src/main/resources/META-INF/spring-configuration-metadata.json
@@ -161,6 +161,13 @@
 			"defaultValue":"true"
 		},
 		{
+			"name":"camel.main.auto-configuration-fail-fast",
+			"type":"boolean",
+			"sourceType":"org.apache.camel.main.MainConfigurationProperties",
+			"description":"Whether auto configuration should fail fast when configuring one ore more properties fails for whatever reason such as a invalid property name, etc. This option is default enabled.",
+			"defaultValue":"true"
+		},
+		{
 			"name":"camel.main.auto-startup",
 			"type":"boolean",
 			"sourceType":"org.apache.camel.main.DefaultConfigurationProperties",


[camel] 03/07: CAMEL-13681: Property binding support should have support for ignore case in property keys

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 13a2457ae293e954bb36daac3cce08f3027360d2
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Jun 26 10:06:22 2019 +0200

    CAMEL-13681: Property binding support should have support for ignore case in property keys
---
 .../src/main/java/org/apache/camel/main/MainSupport.java      | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java b/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
index c9e3ce1..fb8abff 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
@@ -1015,7 +1015,7 @@ public abstract class MainSupport extends ServiceSupport {
                 // grab the value
                 String value = prop.getProperty(key);
                 String option = key.substring(dot + 1);
-                if (ObjectHelper.isNotEmpty(value) && ObjectHelper.isNotEmpty(option)) {
+                if (component != null && ObjectHelper.isNotEmpty(value) && ObjectHelper.isNotEmpty(option)) {
                     Map<String, Object> values = properties.getOrDefault(component, new LinkedHashMap<>());
                     values.put(option, value);
                     properties.put(component, values);
@@ -1029,7 +1029,7 @@ public abstract class MainSupport extends ServiceSupport {
                 // grab the value
                 String value = prop.getProperty(key);
                 String option = key.substring(dot + 1);
-                if (ObjectHelper.isNotEmpty(value) && ObjectHelper.isNotEmpty(option)) {
+                if (dataformat != null && ObjectHelper.isNotEmpty(value) && ObjectHelper.isNotEmpty(option)) {
                     Map<String, Object> values = properties.getOrDefault(dataformat, new LinkedHashMap<>());
                     values.put(option, value);
                     properties.put(dataformat, values);
@@ -1043,7 +1043,7 @@ public abstract class MainSupport extends ServiceSupport {
                 // grab the value
                 String value = prop.getProperty(key);
                 String option = key.substring(dot + 1);
-                if (ObjectHelper.isNotEmpty(value) && ObjectHelper.isNotEmpty(option)) {
+                if (language != null && ObjectHelper.isNotEmpty(value) && ObjectHelper.isNotEmpty(option)) {
                     Map<String, Object> values = properties.getOrDefault(language, new LinkedHashMap<>());
                     values.put(option, value);
                     properties.put(language, values);
@@ -1051,6 +1051,8 @@ public abstract class MainSupport extends ServiceSupport {
             }
         }
 
+        // TODO: filter out duplicte properties due to ignore-case
+
         if (!properties.isEmpty()) {
             long total = properties.values().stream().mapToLong(Map::size).sum();
             LOG.info("Auto configuring {} components/dataformat/languages from loaded properties: {}", properties.size(), total);
@@ -1060,6 +1062,9 @@ public abstract class MainSupport extends ServiceSupport {
             Map<String, Object> values = properties.get(obj);
             setPropertiesOnTarget(camelContext, obj, values, true, true);
         }
+
+        // TODO: Log if any options was not configured (and check if they are on classpath)
+
     }
 
     protected void autoConfigurationFromRegistry(CamelContext camelContext, boolean deepNesting) throws Exception {