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/12/21 07:28:21 UTC

[camel] branch master updated (e694b13 -> 77661bb)

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 e694b13  camel-directvm: Remove unused camel-direct dependency. (#3434)
     new 1400650  CAMEL-14311: Add validate configuration properties to camel-catalog.
     new 77661bb  Regen

The 2 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:
 catalog/camel-catalog/pom.xml                      |   1 +
 .../org/apache/camel/catalog/CamelCatalog.java     |   8 +
 .../catalog/CamelCatalogJSonSchemaResolver.java    |   7 +
 .../org/apache/camel/catalog/CamelCatalogTest.java | 234 +++++++++++++++++++
 .../src/main/docs/elytron-component.adoc           |   8 +-
 .../ConfigurationPropertiesValidationResult.java   |  19 +-
 .../runtimecatalog/EndpointValidationResult.java   |  33 +++
 .../camel/runtimecatalog/JSonSchemaResolver.java   |   7 +
 .../camel/runtimecatalog/RuntimeCamelCatalog.java  |  14 +-
 .../runtimecatalog/impl/AbstractCamelCatalog.java  | 250 +++++++++++++++++++--
 .../impl/CamelContextJSonSchemaResolver.java       |  19 ++
 .../impl/RuntimeCamelCatalogTest.java              |  53 ++++-
 .../dsl/ElytronEndpointBuilderFactory.java         |   6 +-
 .../org/apache/camel/support/JSonSchemaHelper.java | 157 +++++++++++--
 .../camel/support/PropertyBindingSupport.java      |   2 +-
 docs/components/modules/ROOT/nav.adoc              |   1 +
 .../modules/ROOT/pages}/elytron-component.adoc     |   9 +-
 docs/components/modules/ROOT/pages/index.adoc      |   4 +-
 18 files changed, 765 insertions(+), 67 deletions(-)
 copy catalog/camel-main-maven-plugin/src/main/java/org/apache/camel/maven/model/AutowireData.java => core/camel-api/src/main/java/org/apache/camel/runtimecatalog/ConfigurationPropertiesValidationResult.java (71%)
 copy {components/camel-elytron/src/main/docs => docs/components/modules/ROOT/pages}/elytron-component.adoc (95%)


[camel] 02/02: Regen

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 77661bb7c3e58ff572adb54ee75095d96c4e76fc
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Sat Dec 21 08:23:16 2019 +0100

    Regen
---
 components/camel-elytron/src/main/docs/elytron-component.adoc    | 8 ++++----
 .../builder/endpoint/dsl/ElytronEndpointBuilderFactory.java      | 6 +++---
 docs/components/modules/ROOT/nav.adoc                            | 1 +
 .../components/modules/ROOT/pages}/elytron-component.adoc        | 9 +++++----
 docs/components/modules/ROOT/pages/index.adoc                    | 4 +++-
 5 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/components/camel-elytron/src/main/docs/elytron-component.adoc b/components/camel-elytron/src/main/docs/elytron-component.adoc
index ad85ff8..fca83a5 100644
--- a/components/camel-elytron/src/main/docs/elytron-component.adoc
+++ b/components/camel-elytron/src/main/docs/elytron-component.adoc
@@ -56,9 +56,9 @@ The Elytron component supports 11 options, which are listed below.
 [width="100%",cols="2,5,^1,2",options="header"]
 |===
 | Name | Description | Default | Type
-| *securityDomainBuilder* (elytron) | *Required* Definition of Builder, which will be used for creation of security domain. |  | Builder
-| *mechanismName* (elytron) | Name of the mechanism, which will be used for selection of authentication mechanism. | BEARER_TOKEN | String
-| *elytronProvider* (elytron) | Elytron security provider, has to support mechanism from parameter mechanismName. | instance of WildFlyElytronHttpBearerProvider | WildFlyElytronBaseProvider
+| *securityDomainBuilder* (advanced) | *Required* Definition of Builder, which will be used for creation of security domain. |  | Builder
+| *mechanismName* (advanced) | Name of the mechanism, which will be used for selection of authentication mechanism. | BEARER_TOKEN | String
+| *elytronProvider* (advanced) | Elytron security provider, has to support mechanism from parameter mechanismName. | instance of WildFlyElytronHttpBearerProvider | WildFlyElytronBaseProvider
 | *undertowHttpBinding* (advanced) | To use a custom HttpBinding to control the mapping between Camel message and HttpClient. |  | UndertowHttpBinding
 | *sslContextParameters* (security) | To configure security using SSLContextParameters |  | SSLContextParameters
 | *useGlobalSslContext Parameters* (security) | Enable usage of global SSL context parameters. | false | boolean
@@ -96,7 +96,7 @@ with the following path and query parameters:
 [width="100%",cols="2,5,^1,2",options="header"]
 |===
 | Name | Description | Default | Type
-| *allowedRoles* (allowedRoles) | Comma separated list of allowed roles. |  | String
+| *allowedRoles* (common) | Comma separated list of allowed roles. |  | String
 | *useStreaming* (common) | For HTTP endpoint: if true, text and binary messages will be wrapped as java.io.InputStream before they are passed to an Exchange; otherwise they will be passed as byte. For WebSocket endpoint: if true, text and binary messages will be wrapped as java.io.Reader and java.io.InputStream respectively before they are passed to an Exchange; otherwise they will be passed as String and byte respectively. | false | boolean
 | *accessLog* (consumer) | Whether or not the consumer should write access log | false | Boolean
 | *bridgeErrorHandler* (consumer) | Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored. | false | boolean
diff --git a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/ElytronEndpointBuilderFactory.java b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/ElytronEndpointBuilderFactory.java
index b958a2f..b2bf109 100644
--- a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/ElytronEndpointBuilderFactory.java
+++ b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/ElytronEndpointBuilderFactory.java
@@ -49,7 +49,7 @@ public interface ElytronEndpointBuilderFactory {
          * 
          * The option is a: <code>java.lang.String</code> type.
          * 
-         * Group: allowedRoles
+         * Group: common
          */
         default ElytronEndpointConsumerBuilder allowedRoles(String allowedRoles) {
             doSetProperty("allowedRoles", allowedRoles);
@@ -556,7 +556,7 @@ public interface ElytronEndpointBuilderFactory {
          * 
          * The option is a: <code>java.lang.String</code> type.
          * 
-         * Group: allowedRoles
+         * Group: common
          */
         default ElytronEndpointProducerBuilder allowedRoles(String allowedRoles) {
             doSetProperty("allowedRoles", allowedRoles);
@@ -1112,7 +1112,7 @@ public interface ElytronEndpointBuilderFactory {
          * 
          * The option is a: <code>java.lang.String</code> type.
          * 
-         * Group: allowedRoles
+         * Group: common
          */
         default ElytronEndpointBuilder allowedRoles(String allowedRoles) {
             doSetProperty("allowedRoles", allowedRoles);
diff --git a/docs/components/modules/ROOT/nav.adoc b/docs/components/modules/ROOT/nav.adoc
index ee5e565..0b5c531 100644
--- a/docs/components/modules/ROOT/nav.adoc
+++ b/docs/components/modules/ROOT/nav.adoc
@@ -103,6 +103,7 @@
 * xref:ehcache-component.adoc[Ehcache Component]
 * xref:elasticsearch-rest-component.adoc[Elastichsearch Rest Component]
 * xref:elsql-component.adoc[ElSQL Component]
+* xref:elytron-component.adoc[Elytron Component]
 * xref:etcd-component.adoc[Etcd Component]
 * xref:eventadmin-component.adoc[OSGi EventAdmin Component]
 * xref:exec-component.adoc[Exec Component]
diff --git a/components/camel-elytron/src/main/docs/elytron-component.adoc b/docs/components/modules/ROOT/pages/elytron-component.adoc
similarity index 95%
copy from components/camel-elytron/src/main/docs/elytron-component.adoc
copy to docs/components/modules/ROOT/pages/elytron-component.adoc
index ad85ff8..4c97074 100644
--- a/components/camel-elytron/src/main/docs/elytron-component.adoc
+++ b/docs/components/modules/ROOT/pages/elytron-component.adoc
@@ -1,5 +1,6 @@
 [[elytron-component]]
 = Elytron Component
+:page-source: components/camel-elytron/src/main/docs/elytron-component.adoc
 
 *Since Camel 3.1*
 
@@ -56,9 +57,9 @@ The Elytron component supports 11 options, which are listed below.
 [width="100%",cols="2,5,^1,2",options="header"]
 |===
 | Name | Description | Default | Type
-| *securityDomainBuilder* (elytron) | *Required* Definition of Builder, which will be used for creation of security domain. |  | Builder
-| *mechanismName* (elytron) | Name of the mechanism, which will be used for selection of authentication mechanism. | BEARER_TOKEN | String
-| *elytronProvider* (elytron) | Elytron security provider, has to support mechanism from parameter mechanismName. | instance of WildFlyElytronHttpBearerProvider | WildFlyElytronBaseProvider
+| *securityDomainBuilder* (advanced) | *Required* Definition of Builder, which will be used for creation of security domain. |  | Builder
+| *mechanismName* (advanced) | Name of the mechanism, which will be used for selection of authentication mechanism. | BEARER_TOKEN | String
+| *elytronProvider* (advanced) | Elytron security provider, has to support mechanism from parameter mechanismName. | instance of WildFlyElytronHttpBearerProvider | WildFlyElytronBaseProvider
 | *undertowHttpBinding* (advanced) | To use a custom HttpBinding to control the mapping between Camel message and HttpClient. |  | UndertowHttpBinding
 | *sslContextParameters* (security) | To configure security using SSLContextParameters |  | SSLContextParameters
 | *useGlobalSslContext Parameters* (security) | Enable usage of global SSL context parameters. | false | boolean
@@ -96,7 +97,7 @@ with the following path and query parameters:
 [width="100%",cols="2,5,^1,2",options="header"]
 |===
 | Name | Description | Default | Type
-| *allowedRoles* (allowedRoles) | Comma separated list of allowed roles. |  | String
+| *allowedRoles* (common) | Comma separated list of allowed roles. |  | String
 | *useStreaming* (common) | For HTTP endpoint: if true, text and binary messages will be wrapped as java.io.InputStream before they are passed to an Exchange; otherwise they will be passed as byte. For WebSocket endpoint: if true, text and binary messages will be wrapped as java.io.Reader and java.io.InputStream respectively before they are passed to an Exchange; otherwise they will be passed as String and byte respectively. | false | boolean
 | *accessLog* (consumer) | Whether or not the consumer should write access log | false | Boolean
 | *bridgeErrorHandler* (consumer) | Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored. | false | boolean
diff --git a/docs/components/modules/ROOT/pages/index.adoc b/docs/components/modules/ROOT/pages/index.adoc
index 92215ca..57e606f 100644
--- a/docs/components/modules/ROOT/pages/index.adoc
+++ b/docs/components/modules/ROOT/pages/index.adoc
@@ -6,7 +6,7 @@ The following Apache Camel artifacts are provided:
 == Components
 
 // components: START
-Number of Components: 306 in 244 JAR artifacts (1 deprecated)
+Number of Components: 307 in 245 JAR artifacts (1 deprecated)
 
 [width="100%",cols="4,1,5",options="header"]
 |===
@@ -180,6 +180,8 @@ Number of Components: 306 in 244 JAR artifacts (1 deprecated)
 
 | xref:elsql-component.adoc[ElSQL] (camel-elsql) | 2.16 | The elsql component is an extension to the existing SQL Component that uses ElSql to define the SQL queries.
 
+| xref:elytron-component.adoc[Elytron] (camel-elytron) | 3.1 | Endpoint
+
 | xref:etcd-component.adoc[Etcd] (camel-etcd) | 2.18 | The camel etcd component allows you to work with Etcd, a distributed reliable key-value store.
 
 | xref:exec-component.adoc[Exec] (camel-exec) | 2.3 | The exec component can be used to execute OS system commands.


[camel] 01/02: CAMEL-14311: Add validate configuration properties to camel-catalog.

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 1400650f37f6e11047fbeeaa15861b853952bdfa
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri Dec 20 19:41:03 2019 +0100

    CAMEL-14311: Add validate configuration properties to camel-catalog.
---
 catalog/camel-catalog/pom.xml                      |   1 +
 .../org/apache/camel/catalog/CamelCatalog.java     |   8 +
 .../catalog/CamelCatalogJSonSchemaResolver.java    |   7 +
 .../org/apache/camel/catalog/CamelCatalogTest.java | 234 +++++++++++++++++++
 .../ConfigurationPropertiesValidationResult.java   |  41 ++++
 .../runtimecatalog/EndpointValidationResult.java   |  33 +++
 .../camel/runtimecatalog/JSonSchemaResolver.java   |   7 +
 .../camel/runtimecatalog/RuntimeCamelCatalog.java  |  14 +-
 .../runtimecatalog/impl/AbstractCamelCatalog.java  | 250 +++++++++++++++++++--
 .../impl/CamelContextJSonSchemaResolver.java       |  19 ++
 .../impl/RuntimeCamelCatalogTest.java              |  53 ++++-
 .../org/apache/camel/support/JSonSchemaHelper.java | 157 +++++++++++--
 .../camel/support/PropertyBindingSupport.java      |   2 +-
 13 files changed, 782 insertions(+), 44 deletions(-)

diff --git a/catalog/camel-catalog/pom.xml b/catalog/camel-catalog/pom.xml
index 4c3e8a1..ba9a7ca 100644
--- a/catalog/camel-catalog/pom.xml
+++ b/catalog/camel-catalog/pom.xml
@@ -125,6 +125,7 @@
                                     </directory>
                                     <!-- the following files are maintained in camel-api and not here, so they are copied over -->
                                     <includes>
+                                        <include>ConfigurationPropertiesValidationResult.java</include>
                                         <include>EndpointValidationResult.java</include>
                                         <include>JSonSchemaResolver.java</include>
                                         <include>LanguageValidationResult.java</include>
diff --git a/catalog/camel-catalog/src/main/java/org/apache/camel/catalog/CamelCatalog.java b/catalog/camel-catalog/src/main/java/org/apache/camel/catalog/CamelCatalog.java
index 3bcef3d..bbba0f8 100644
--- a/catalog/camel-catalog/src/main/java/org/apache/camel/catalog/CamelCatalog.java
+++ b/catalog/camel-catalog/src/main/java/org/apache/camel/catalog/CamelCatalog.java
@@ -474,6 +474,14 @@ public interface CamelCatalog {
     LanguageValidationResult validateLanguageExpression(ClassLoader classLoader, String language, String text);
 
     /**
+     * Parses and validates the configuration property
+     *
+     * @param text  the configuration text
+     * @return validation result
+     */
+    ConfigurationPropertiesValidationResult validateConfigurationProperty(String text);
+
+    /**
      * Returns the component name from the given endpoint uri
      *
      * @param uri  the endpoint uri
diff --git a/catalog/camel-catalog/src/main/java/org/apache/camel/catalog/CamelCatalogJSonSchemaResolver.java b/catalog/camel-catalog/src/main/java/org/apache/camel/catalog/CamelCatalogJSonSchemaResolver.java
index eb49604..a43c4e2 100644
--- a/catalog/camel-catalog/src/main/java/org/apache/camel/catalog/CamelCatalogJSonSchemaResolver.java
+++ b/catalog/camel-catalog/src/main/java/org/apache/camel/catalog/CamelCatalogJSonSchemaResolver.java
@@ -105,6 +105,13 @@ public class CamelCatalogJSonSchemaResolver implements JSonSchemaResolver {
     }
 
     @Override
+    public String getMainJsonSchema() {
+        final String file = "META-INF/camel-main-configuration-metadata.json";
+
+        return loadResourceFromVersionManager(file);
+    }
+
+    @Override
     public String getOtherJSonSchema(String name) {
         final String file = camelCatalog.getRuntimeProvider().getOtherJSonSchemaDirectory() + "/" + name + ".json";
 
diff --git a/catalog/camel-catalog/src/test/java/org/apache/camel/catalog/CamelCatalogTest.java b/catalog/camel-catalog/src/test/java/org/apache/camel/catalog/CamelCatalogTest.java
index 79864a6..ddc9c84 100644
--- a/catalog/camel-catalog/src/test/java/org/apache/camel/catalog/CamelCatalogTest.java
+++ b/catalog/camel-catalog/src/test/java/org/apache/camel/catalog/CamelCatalogTest.java
@@ -1301,4 +1301,238 @@ public class CamelCatalogTest {
         assertEquals("Kerberos Renew Jitter", row.get("displayName"));
     }
 
+    @Test
+    public void testValidateConfigurationPropertyComponent() throws Exception {
+        String text = "camel.component.seda.queueSize=1234";
+        ConfigurationPropertiesValidationResult result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.component.seda.queue-size=1234";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.component.seda.queuesize=1234";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.component.seda.queueSize=abc";
+        result = catalog.validateConfigurationProperty(text);
+        assertFalse(result.isSuccess());
+        assertEquals("abc", result.getInvalidInteger().get("camel.component.seda.queueSize"));
+
+        text = "camel.component.seda.foo=abc";
+        result = catalog.validateConfigurationProperty(text);
+        assertFalse(result.isSuccess());
+        assertTrue(result.getUnknown().contains("camel.component.seda.foo"));
+
+        text = "camel.component.jms.acknowledgementModeName=abc";
+        result = catalog.validateConfigurationProperty(text);
+        assertFalse(result.isSuccess());
+        assertEquals("abc", result.getInvalidEnum().get("camel.component.jms.acknowledgementModeName"));
+        List<String> list = result.getEnumChoices("camel.component.jms.acknowledgementModeName");
+        assertEquals(4, list.size());
+        assertEquals("SESSION_TRANSACTED", list.get(0));
+        assertEquals("CLIENT_ACKNOWLEDGE", list.get(1));
+        assertEquals("AUTO_ACKNOWLEDGE", list.get(2));
+        assertEquals("DUPS_OK_ACKNOWLEDGE", list.get(3));
+    }
+
+    @Test
+    public void testValidateConfigurationPropertyLanguage() throws Exception {
+        String text = "camel.language.tokenize.token=;";
+        ConfigurationPropertiesValidationResult result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.language.tokenize.regex=true";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.language.tokenize.regex=abc";
+        result = catalog.validateConfigurationProperty(text);
+        assertFalse(result.isSuccess());
+        assertEquals("abc", result.getInvalidBoolean().get("camel.language.tokenize.regex"));
+
+        text = "camel.language.tokenize.foo=abc";
+        result = catalog.validateConfigurationProperty(text);
+        assertFalse(result.isSuccess());
+        assertTrue(result.getUnknown().contains("camel.language.tokenize.foo"));
+    }
+
+    @Test
+    public void testValidateConfigurationPropertyDataformat() throws Exception {
+        String text = "camel.dataformat.bindy-csv.type=csv";
+        ConfigurationPropertiesValidationResult result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.dataformat.bindy-csv.locale=us";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.dataformat.bindy-csv.allowEmptyStream=abc";
+        result = catalog.validateConfigurationProperty(text);
+        assertFalse(result.isSuccess());
+        assertEquals("abc", result.getInvalidBoolean().get("camel.dataformat.bindy-csv.allowEmptyStream"));
+
+        text = "camel.dataformat.bindy-csv.foo=abc";
+        result = catalog.validateConfigurationProperty(text);
+        assertFalse(result.isSuccess());
+        assertTrue(result.getUnknown().contains("camel.dataformat.bindy-csv.foo"));
+
+        text = "camel.dataformat.bindy-csv.type=abc";
+        result = catalog.validateConfigurationProperty(text);
+        assertFalse(result.isSuccess());
+        assertEquals("abc", result.getInvalidEnum().get("camel.dataformat.bindy-csv.type"));
+        List<String> list = result.getEnumChoices("camel.dataformat.bindy-csv.type");
+        assertEquals(3, list.size());
+        assertEquals("Csv", list.get(0));
+        assertEquals("Fixed", list.get(1));
+        assertEquals("KeyValue", list.get(2));
+    }
+
+    @Test
+    public void testValidateConfigurationPropertyComponentQuartz() throws Exception {
+        String text = "camel.component.quartz.auto-start-scheduler=true";
+        ConfigurationPropertiesValidationResult result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.component.quartz.properties=#myProp";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.component.quartz.properties=123";
+        result = catalog.validateConfigurationProperty(text);
+        assertFalse(result.isSuccess());
+
+        text = "camel.component.quartz.properties.foo=123";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.component.quartz.properties.bar=true";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.component.quartz.properties[0]=yes";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.component.quartz.properties[1]=no";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.component.quartz.properties[foo]=abc";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.component.quartz.properties[foo].beer=yes";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.component.quartz.properties[foo].drink=no";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+    }
+
+    @Test
+    public void testValidateConfigurationPropertyComponentJClouds() throws Exception {
+        String text = "camel.component.jclouds.basicPropertyBinding=true";
+        ConfigurationPropertiesValidationResult result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.component.jclouds.blobStores=#myStores";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.component.jclouds.blobStores=foo";
+        result = catalog.validateConfigurationProperty(text);
+        assertFalse(result.isSuccess());
+        assertTrue(result.getInvalidArray().containsKey("camel.component.jclouds.blobStores"));
+
+        text = "camel.component.jclouds.blobStores[0]=foo";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.component.jclouds.blobStores[1]=bar";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.component.jclouds.blobStores[foo]=123";
+        result = catalog.validateConfigurationProperty(text);
+        assertFalse(result.isSuccess());
+        assertEquals("foo", result.getInvalidInteger().get("camel.component.jclouds.blobStores[foo]"));
+
+        text = "camel.component.jclouds.blobStores[0].beer=yes";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.component.jclouds.blobStores[1].drink=no";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.component.jclouds.blobStores[foo].beer=yes";
+        result = catalog.validateConfigurationProperty(text);
+        assertFalse(result.isSuccess());
+        assertEquals("foo", result.getInvalidInteger().get("camel.component.jclouds.blobStores[foo].beer"));
+    }
+
+    @Test
+    public void testValidateConfigurationPropertyMain() throws Exception {
+        String text = "camel.main.allow-use-original-message=true";
+        ConfigurationPropertiesValidationResult result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.main.allow-use-original-message=abc";
+        result = catalog.validateConfigurationProperty(text);
+        assertFalse(result.isSuccess());
+        assertEquals("abc", result.getInvalidBoolean().get("camel.main.allow-use-original-message"));
+
+        text = "camel.main.foo=abc";
+        result = catalog.validateConfigurationProperty(text);
+        assertFalse(result.isSuccess());
+        assertTrue(result.getUnknown().contains("camel.main.foo"));
+
+        text = "camel.resilience4j.minimum-number-of-calls=123";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.resilience4j.minimum-number-of-calls=abc";
+        result = catalog.validateConfigurationProperty(text);
+        assertFalse(result.isSuccess());
+        assertEquals("abc", result.getInvalidInteger().get("camel.resilience4j.minimum-number-of-calls"));
+
+        text = "camel.resilience4j.slow-call-rate-threshold=12.5";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.resilience4j.slow-call-rate-threshold=12x5";
+        result = catalog.validateConfigurationProperty(text);
+        assertFalse(result.isSuccess());
+        assertEquals("12x5", result.getInvalidNumber().get("camel.resilience4j.slow-call-rate-threshold"));
+
+        text = "camel.rest.api-properties=#foo";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.rest.api-properties=bar";
+        result = catalog.validateConfigurationProperty(text);
+        assertFalse(result.isSuccess());
+        assertEquals("bar", result.getInvalidMap().get("camel.rest.api-properties"));
+
+        text = "camel.rest.api-properties.foo=abc";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.rest.api-properties.bar=123";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.rest.api-properties.beer=yes";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        // TODO: add support for [] maps for main
+//        text = "camel.rest.api-properties[drink]=no";
+//        result = catalog.validateConfigurationProperty(text);
+//        assertTrue(result.isSuccess());
+    }
+
 }
diff --git a/core/camel-api/src/main/java/org/apache/camel/runtimecatalog/ConfigurationPropertiesValidationResult.java b/core/camel-api/src/main/java/org/apache/camel/runtimecatalog/ConfigurationPropertiesValidationResult.java
new file mode 100644
index 0000000..14047b1
--- /dev/null
+++ b/core/camel-api/src/main/java/org/apache/camel/runtimecatalog/ConfigurationPropertiesValidationResult.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.runtimecatalog;
+
+/**
+ * Details result of validating configuration properties (eg application.properties for camel-main).
+ */
+public class ConfigurationPropertiesValidationResult extends EndpointValidationResult {
+
+    // TODO: Move stuff to base class for EndpointValidationResult so they can share code
+
+    private String key;
+    private String value;
+
+    public ConfigurationPropertiesValidationResult(String key, String value) {
+        this.key = key;
+        this.value = value;
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    public String getValue() {
+        return value;
+    }
+}
diff --git a/core/camel-api/src/main/java/org/apache/camel/runtimecatalog/EndpointValidationResult.java b/core/camel-api/src/main/java/org/apache/camel/runtimecatalog/EndpointValidationResult.java
index 091820a..6070f1d 100644
--- a/core/camel-api/src/main/java/org/apache/camel/runtimecatalog/EndpointValidationResult.java
+++ b/core/camel-api/src/main/java/org/apache/camel/runtimecatalog/EndpointValidationResult.java
@@ -51,6 +51,8 @@ public class EndpointValidationResult implements Serializable {
     private Map<String, String> invalidEnum;
     private Map<String, String[]> invalidEnumChoices;
     private Map<String, String[]> invalidEnumSuggestions;
+    private Map<String, String> invalidMap;
+    private Map<String, String> invalidArray;
     private Map<String, String> invalidReference;
     private Map<String, String> invalidBoolean;
     private Map<String, String> invalidInteger;
@@ -94,6 +96,9 @@ public class EndpointValidationResult implements Serializable {
             ok = invalidEnum == null && invalidEnumChoices == null && invalidReference == null
                 && invalidBoolean == null && invalidInteger == null && invalidNumber == null;
         }
+        if (ok) {
+           ok = invalidMap == null && invalidArray == null;
+        }
         return ok;
     }
 
@@ -191,6 +196,26 @@ public class EndpointValidationResult implements Serializable {
         }
     }
 
+    public void addInvalidMap(String name, String value) {
+        if (invalidMap == null) {
+            invalidMap = new LinkedHashMap<>();
+        }
+        if (!invalidMap.containsKey(name)) {
+            invalidMap.put(name, value);
+            errors++;
+        }
+    }
+
+    public void addInvalidArray(String name, String value) {
+        if (invalidArray == null) {
+            invalidArray = new LinkedHashMap<>();
+        }
+        if (!invalidArray.containsKey(name)) {
+            invalidArray.put(name, value);
+            errors++;
+        }
+    }
+
     public void addInvalidBoolean(String name, String value) {
         if (invalidBoolean == null) {
             invalidBoolean = new LinkedHashMap<>();
@@ -303,6 +328,14 @@ public class EndpointValidationResult implements Serializable {
         return invalidReference;
     }
 
+    public Map<String, String> getInvalidMap() {
+        return invalidMap;
+    }
+
+    public Map<String, String> getInvalidArray() {
+        return invalidArray;
+    }
+
     public Map<String, String> getInvalidBoolean() {
         return invalidBoolean;
     }
diff --git a/core/camel-api/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaResolver.java b/core/camel-api/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaResolver.java
index a6a8fc5..a849b0b 100644
--- a/core/camel-api/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaResolver.java
+++ b/core/camel-api/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaResolver.java
@@ -61,4 +61,11 @@ public interface JSonSchemaResolver {
      */
     String getModelJSonSchema(String name);
 
+    /**
+     * Returns the camel-main json schema
+     *
+     * @return the camel-main json schema
+     */
+    String getMainJsonSchema();
+
 }
diff --git a/core/camel-api/src/main/java/org/apache/camel/runtimecatalog/RuntimeCamelCatalog.java b/core/camel-api/src/main/java/org/apache/camel/runtimecatalog/RuntimeCamelCatalog.java
index 57bcda7..8228595 100644
--- a/core/camel-api/src/main/java/org/apache/camel/runtimecatalog/RuntimeCamelCatalog.java
+++ b/core/camel-api/src/main/java/org/apache/camel/runtimecatalog/RuntimeCamelCatalog.java
@@ -108,7 +108,7 @@ public interface RuntimeCamelCatalog extends StaticService {
     EndpointValidationResult validateProperties(String scheme, Map<String, String> properties);
 
     /**
-     * Parses and validates the endpoint uri and constructs a key/value properties of each option.
+     * Parses and validates the endpoint uri
      *
      * @param uri  the endpoint uri
      * @return validation result
@@ -116,7 +116,7 @@ public interface RuntimeCamelCatalog extends StaticService {
     EndpointValidationResult validateEndpointProperties(String uri);
 
     /**
-     * Parses and validates the endpoint uri and constructs a key/value properties of each option.
+     * Parses and validates the endpoint uri
      * <p/>
      * The option ignoreLenientProperties can be used to ignore components that uses lenient properties.
      * When this is true, then the uri validation is stricter but would fail on properties that are not part of the component
@@ -130,7 +130,7 @@ public interface RuntimeCamelCatalog extends StaticService {
     EndpointValidationResult validateEndpointProperties(String uri, boolean ignoreLenientProperties);
 
     /**
-     * Parses and validates the endpoint uri and constructs a key/value properties of each option.
+     * Parses and validates the endpoint uri
      * <p/>
      * The option ignoreLenientProperties can be used to ignore components that uses lenient properties.
      * When this is true, then the uri validation is stricter but would fail on properties that are not part of the component
@@ -170,6 +170,14 @@ public interface RuntimeCamelCatalog extends StaticService {
     LanguageValidationResult validateLanguageExpression(ClassLoader classLoader, String language, String text);
 
     /**
+     * Parses and validates the configuration property
+     *
+     * @param text  the configuration text
+     * @return validation result
+     */
+    ConfigurationPropertiesValidationResult validateConfigurationProperty(String text);
+
+    /**
      * Returns the component name from the given endpoint uri
      *
      * @param uri  the endpoint uri
diff --git a/core/camel-base/src/main/java/org/apache/camel/runtimecatalog/impl/AbstractCamelCatalog.java b/core/camel-base/src/main/java/org/apache/camel/runtimecatalog/impl/AbstractCamelCatalog.java
index fe32e5b..2e06468 100644
--- a/core/camel-base/src/main/java/org/apache/camel/runtimecatalog/impl/AbstractCamelCatalog.java
+++ b/core/camel-base/src/main/java/org/apache/camel/runtimecatalog/impl/AbstractCamelCatalog.java
@@ -26,6 +26,7 @@ import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
@@ -34,36 +35,18 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
+import org.apache.camel.runtimecatalog.ConfigurationPropertiesValidationResult;
 import org.apache.camel.runtimecatalog.EndpointValidationResult;
 import org.apache.camel.runtimecatalog.JSonSchemaResolver;
 import org.apache.camel.runtimecatalog.LanguageValidationResult;
 
 import static org.apache.camel.runtimecatalog.impl.CatalogHelper.after;
+import static org.apache.camel.runtimecatalog.impl.CatalogHelper.before;
 import static org.apache.camel.runtimecatalog.impl.URISupport.createQueryString;
 import static org.apache.camel.runtimecatalog.impl.URISupport.isEmpty;
 import static org.apache.camel.runtimecatalog.impl.URISupport.normalizeUri;
 import static org.apache.camel.runtimecatalog.impl.URISupport.stripQuery;
-import static org.apache.camel.support.JSonSchemaHelper.getNames;
-import static org.apache.camel.support.JSonSchemaHelper.getPropertyDefaultValue;
-import static org.apache.camel.support.JSonSchemaHelper.getPropertyEnum;
-import static org.apache.camel.support.JSonSchemaHelper.getPropertyKind;
-import static org.apache.camel.support.JSonSchemaHelper.getPropertyNameFromNameWithPrefix;
-import static org.apache.camel.support.JSonSchemaHelper.getPropertyPrefix;
-import static org.apache.camel.support.JSonSchemaHelper.getRow;
-import static org.apache.camel.support.JSonSchemaHelper.isComponentConsumerOnly;
-import static org.apache.camel.support.JSonSchemaHelper.isComponentLenientProperties;
-import static org.apache.camel.support.JSonSchemaHelper.isComponentProducerOnly;
-import static org.apache.camel.support.JSonSchemaHelper.isPropertyBoolean;
-import static org.apache.camel.support.JSonSchemaHelper.isPropertyConsumerOnly;
-import static org.apache.camel.support.JSonSchemaHelper.isPropertyDeprecated;
-import static org.apache.camel.support.JSonSchemaHelper.isPropertyInteger;
-import static org.apache.camel.support.JSonSchemaHelper.isPropertyMultiValue;
-import static org.apache.camel.support.JSonSchemaHelper.isPropertyNumber;
-import static org.apache.camel.support.JSonSchemaHelper.isPropertyObject;
-import static org.apache.camel.support.JSonSchemaHelper.isPropertyProducerOnly;
-import static org.apache.camel.support.JSonSchemaHelper.isPropertyRequired;
-import static org.apache.camel.support.JSonSchemaHelper.parseJsonSchema;
-import static org.apache.camel.support.JSonSchemaHelper.stripOptionalPrefixFromName;
+import static org.apache.camel.support.JSonSchemaHelper.*;
 
 /**
  * Base class for both the runtime RuntimeCamelCatalog from camel-core and the complete CamelCatalog from camel-catalog.
@@ -1036,6 +1019,228 @@ public abstract class AbstractCamelCatalog {
         return tokens.toArray(new String[tokens.size()]);
     }
 
+    public ConfigurationPropertiesValidationResult validateConfigurationProperty(String text) {
+        String longKey = before(text, "=");
+        String key = longKey;
+        String value = after(text, "=");
+
+        ConfigurationPropertiesValidationResult result = new ConfigurationPropertiesValidationResult(key, value);
+        boolean accept = acceptConfigurationPropertyKey(key);
+        if (!accept) {
+            result.addUnknown(key);
+            return result;
+        }
+
+        boolean component = key.startsWith("camel.component.");
+        boolean dataformat = key.startsWith("camel.dataformat.");
+        boolean language = key.startsWith("camel.language.");
+        boolean main = key.startsWith("camel.main.") || key.startsWith("camel.hystrix.") | key.startsWith("camel.resilience4j.") || key.startsWith("camel.rest.");
+        if (component || dataformat || language) {
+            String group;
+            if (component) {
+                key = key.substring(16);
+                group = "componentProperties";
+            } else if (dataformat) {
+                key = key.substring(17);
+                group = "properties";
+            } else {
+                key = key.substring(15);
+                group = "properties";
+            }
+            if (!key.contains(".")) {
+                result.addIncapable(key);
+                return result;
+            }
+            String name = before(key, ".");
+            String option = after(key, ".");
+            if (name != null && option != null && value != null) {
+                String json;
+                if (component) {
+                    json = jsonSchemaResolver.getComponentJSonSchema(name);
+                } else if (dataformat) {
+                    json = jsonSchemaResolver.getDataFormatJSonSchema(name);
+                } else {
+                    json = jsonSchemaResolver.getLanguageJSonSchema(name);
+                }
+                if (json == null) {
+                    result.addUnknownComponent(name);
+                    return result;
+                }
+                List<Map<String, String>> rows = parseJsonSchema(group, json, true);
+
+                // lower case option and remove dash
+                String nOption = option.replaceAll("-", "").toLowerCase(Locale.US);
+                String suffix = null;
+                int posDot = nOption.indexOf('.');
+                int posBracket = nOption.indexOf('[');
+                if (posDot > 0 && posBracket > 0) {
+                    int first = Math.min(posDot, posBracket);
+                    suffix = nOption.substring(first);
+                    nOption = nOption.substring(0, first);
+                } else if (posDot > 0) {
+                    suffix = nOption.substring(posDot);
+                    nOption = nOption.substring(0, posDot);
+                } else if (posBracket > 0) {
+                    suffix = nOption.substring(posBracket);
+                    nOption = nOption.substring(0, posBracket);
+                }
+                doValidateConfigurationProperty(result, rows, name, value, longKey, nOption, suffix);
+            }
+        } else if (main) {
+            // skip camel.
+            key = key.substring(6);
+            String name = before(key, ".");
+            String option = after(key, ".");
+            if (name != null && option != null && value != null) {
+                String json = jsonSchemaResolver.getMainJsonSchema();
+                if (json == null) {
+                    result.addIncapable("camel-main not detected on classpath");
+                    return result;
+                }
+                List<Map<String, String>> rows = parseMainJsonSchema(json);
+
+                // lower case option and remove dash
+                String lookupKey = longKey.replaceAll("-", "").toLowerCase(Locale.US);
+                String suffix = null;
+                int pos = option.indexOf('.');
+                // TODO: add support for [] maps for main
+                if (pos > 0 && option.length() > pos) {
+                    suffix = option.substring(pos + 1);
+                    // remove .suffix from lookup key
+                    int len = lookupKey.length() - suffix.length() - 1;
+                    lookupKey = lookupKey.substring(0, len);
+                }
+                doValidateConfigurationProperty(result, rows, name, value, longKey, lookupKey, suffix);
+            }
+        }
+
+        return result;
+    }
+
+    private void doValidateConfigurationProperty(ConfigurationPropertiesValidationResult result, List<Map<String, String>> rows,
+                                                 String name, String value, String longKey,
+                                                 String lookupKey, String suffix) {
+
+        // find option
+        String rowKey = rows.stream()
+                .map(e -> e.get("name"))
+                .filter(n -> n.toLowerCase(Locale.US).equals(lookupKey)).findFirst().orElse(null);
+        if (rowKey == null) {
+            // unknown option
+            result.addUnknown(longKey);
+            if (suggestionStrategy != null) {
+                String[] suggestions = suggestionStrategy.suggestEndpointOptions(getNames(rows), name);
+                if (suggestions != null) {
+                    result.addUnknownSuggestions(name, suggestions);
+                }
+            }
+        } else {
+            boolean optionPlaceholder = value.startsWith("{{") || value.startsWith("${") || value.startsWith("$simple{");
+            boolean lookup = value.startsWith("#") && value.length() > 1;
+
+            // deprecated
+            if (!optionPlaceholder && !lookup && isPropertyDeprecated(rows, rowKey)) {
+                result.addDeprecated(longKey);
+            }
+
+            // is boolean
+            if (!optionPlaceholder && !lookup && isPropertyBoolean(rows, rowKey)) {
+                // value must be a boolean
+                boolean bool = "true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value);
+                if (!bool) {
+                    result.addInvalidBoolean(longKey, value);
+                }
+            }
+
+            // is integer
+            if (!optionPlaceholder && !lookup && isPropertyInteger(rows, rowKey)) {
+                // value must be an integer
+                boolean valid = validateInteger(value);
+                if (!valid) {
+                    result.addInvalidInteger(longKey, value);
+                }
+            }
+
+            // is number
+            if (!optionPlaceholder && !lookup && isPropertyNumber(rows, rowKey)) {
+                // value must be an number
+                boolean valid = false;
+                try {
+                    valid = !Double.valueOf(value).isNaN() || !Float.valueOf(value).isNaN();
+                } catch (Exception e) {
+                    // ignore
+                }
+                if (!valid) {
+                    result.addInvalidNumber(longKey, value);
+                }
+            }
+
+            // is enum
+            String enums = getPropertyEnum(rows, rowKey);
+            if (!optionPlaceholder && !lookup && enums != null) {
+                String[] choices = enums.split(",");
+                boolean found = false;
+                for (String s : choices) {
+                    if (value.equalsIgnoreCase(s)) {
+                        found = true;
+                        break;
+                    }
+                }
+                if (!found) {
+                    result.addInvalidEnum(longKey, value);
+                    result.addInvalidEnumChoices(longKey, choices);
+                    if (suggestionStrategy != null) {
+                        Set<String> names = new LinkedHashSet<>();
+                        names.addAll(Arrays.asList(choices));
+                        String[] suggestions = suggestionStrategy.suggestEndpointOptions(names, value);
+                        if (suggestions != null) {
+                            result.addInvalidEnumSuggestions(longKey, suggestions);
+                        }
+                    }
+                }
+            }
+
+            String javaType = getPropertyJavaType(rows, rowKey);
+            if (!optionPlaceholder && !lookup && javaType != null
+                    && (javaType.startsWith("java.util.Map") || javaType.startsWith("java.util.Properties"))) {
+                // there must be a valid suffix
+                if (suffix == null || suffix.isEmpty() || suffix.equals(".")) {
+                    result.addInvalidMap(longKey, value);
+                } else if (suffix.startsWith("[") && !suffix.contains("]")) {
+                    result.addInvalidMap(longKey, value);
+                }
+            }
+            if (!optionPlaceholder && !lookup && javaType != null && isPropertyArray(rows, rowKey)) {
+                // there must be a suffix and it must be using [] style
+                if (suffix == null || suffix.isEmpty() || suffix.equals(".")) {
+                    result.addInvalidArray(longKey, value);
+                } else if (!suffix.startsWith("[") && !suffix.contains("]")) {
+                    result.addInvalidArray(longKey, value);
+                } else {
+                    String index = before(suffix.substring(1), "]");
+                    // value must be an integer
+                    boolean valid = validateInteger(index);
+                    if (!valid) {
+                        result.addInvalidInteger(longKey, index);
+                    }
+                }
+            }
+        }
+    }
+
+    private static boolean acceptConfigurationPropertyKey(String key) {
+        if (key == null) {
+            return false;
+        }
+        return key.startsWith("camel.component.")
+                || key.startsWith("camel.dataformat.")
+                || key.startsWith("camel.language.")
+                || key.startsWith("camel.main.")
+                || key.startsWith("camel.hystrix.")
+                || key.startsWith("camel.resilience4j.")
+                || key.startsWith("camel.rest.");
+    }
+
     private LanguageValidationResult doValidateSimple(ClassLoader classLoader, String simple, boolean predicate) {
         if (classLoader == null) {
             classLoader = getClass().getClassLoader();
@@ -1225,7 +1430,8 @@ public abstract class AbstractCamelCatalog {
     private static boolean validateInteger(String value) {
         boolean valid = false;
         try {
-            valid = Integer.valueOf(value) != null;
+            Integer.parseInt(value);
+            valid = true;
         } catch (Exception e) {
             // ignore
         }
diff --git a/core/camel-base/src/main/java/org/apache/camel/runtimecatalog/impl/CamelContextJSonSchemaResolver.java b/core/camel-base/src/main/java/org/apache/camel/runtimecatalog/impl/CamelContextJSonSchemaResolver.java
index ac8f092..9e92aa5 100644
--- a/core/camel-base/src/main/java/org/apache/camel/runtimecatalog/impl/CamelContextJSonSchemaResolver.java
+++ b/core/camel-base/src/main/java/org/apache/camel/runtimecatalog/impl/CamelContextJSonSchemaResolver.java
@@ -17,10 +17,13 @@
 package org.apache.camel.runtimecatalog.impl;
 
 import java.io.IOException;
+import java.io.InputStream;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.CatalogCamelContext;
 import org.apache.camel.runtimecatalog.JSonSchemaResolver;
+import org.apache.camel.spi.ClassResolver;
+import org.apache.camel.util.IOHelper;
 
 /**
  * Uses runtime {@link CamelContext} to resolve the JSon schema files.
@@ -79,4 +82,20 @@ public class CamelContextJSonSchemaResolver implements JSonSchemaResolver {
         return null;
     }
 
+    @Override
+    public String getMainJsonSchema() {
+        String path = "META-INF/camel-main-configuration-metadata.json";
+        ClassResolver resolver = camelContext.getClassResolver();
+        InputStream inputStream = resolver.loadResourceAsStream(path);
+        if (inputStream != null) {
+            try {
+                return IOHelper.loadText(inputStream);
+            } catch (IOException e) {
+                // ignore
+            } finally {
+                IOHelper.close(inputStream);
+            }
+        }
+        return null;
+    }
 }
diff --git a/core/camel-core/src/test/java/org/apache/camel/runtimecatalog/impl/RuntimeCamelCatalogTest.java b/core/camel-core/src/test/java/org/apache/camel/runtimecatalog/impl/RuntimeCamelCatalogTest.java
index 37d79a8..93693f3 100644
--- a/core/camel-core/src/test/java/org/apache/camel/runtimecatalog/impl/RuntimeCamelCatalogTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/runtimecatalog/impl/RuntimeCamelCatalogTest.java
@@ -20,6 +20,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.runtimecatalog.ConfigurationPropertiesValidationResult;
 import org.apache.camel.runtimecatalog.EndpointValidationResult;
 import org.apache.camel.runtimecatalog.LanguageValidationResult;
 import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
@@ -28,10 +29,8 @@ import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+
+import static org.junit.Assert.*;
 
 public class RuntimeCamelCatalogTest {
 
@@ -376,4 +375,50 @@ public class RuntimeCamelCatalogTest {
         assertEquals("delete", result.getNotProducerOnly().iterator().next());
     }
 
+    @Test
+    public void testValidateConfigurationPropertyComponent() throws Exception {
+        String text = "camel.component.seda.queueSize=1234";
+        ConfigurationPropertiesValidationResult result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.component.seda.queue-size=1234";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.component.seda.queuesize=1234";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.component.seda.queueSize=abc";
+        result = catalog.validateConfigurationProperty(text);
+        assertFalse(result.isSuccess());
+        assertEquals("abc", result.getInvalidInteger().get("camel.component.seda.queueSize"));
+
+        text = "camel.component.seda.foo=abc";
+        result = catalog.validateConfigurationProperty(text);
+        assertFalse(result.isSuccess());
+        assertTrue(result.getUnknown().contains("camel.component.seda.foo"));
+    }
+
+    @Test
+    public void testValidateConfigurationPropertyLanguage() throws Exception {
+        String text = "camel.language.tokenize.token=;";
+        ConfigurationPropertiesValidationResult result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.language.tokenize.regex=true";
+        result = catalog.validateConfigurationProperty(text);
+        assertTrue(result.isSuccess());
+
+        text = "camel.language.tokenize.regex=abc";
+        result = catalog.validateConfigurationProperty(text);
+        assertFalse(result.isSuccess());
+        assertEquals("abc", result.getInvalidBoolean().get("camel.language.tokenize.regex"));
+
+        text = "camel.language.tokenize.foo=abc";
+        result = catalog.validateConfigurationProperty(text);
+        assertFalse(result.isSuccess());
+        assertTrue(result.getUnknown().contains("camel.language.tokenize.foo"));
+    }
+
 }
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/JSonSchemaHelper.java b/core/camel-support/src/main/java/org/apache/camel/support/JSonSchemaHelper.java
index 6c77d3f..fc90ac9 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/JSonSchemaHelper.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/JSonSchemaHelper.java
@@ -24,6 +24,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 
+import org.apache.camel.util.json.JsonArray;
 import org.apache.camel.util.json.JsonObject;
 import org.apache.camel.util.json.Jsoner;
 
@@ -36,6 +37,69 @@ public final class JSonSchemaHelper {
     }
 
     /**
+     * Parses the camel-main json schema to split it into a list or rows, where each row contains key value pairs with the metadata
+     *
+     * @param json the main configuration json
+     * @return a list of all the rows, where each row is a set of key value pairs with metadata
+     * @throws RuntimeException is thrown if error parsing the json data
+     */
+    @SuppressWarnings("unchecked")
+    public static List<Map<String, String>> parseMainJsonSchema(String json) {
+        List<Map<String, String>> answer = new ArrayList<>();
+        if (json == null) {
+            return answer;
+        }
+
+        // convert into a List<Map<String, String>> structure which is expected as output from this parser
+        try {
+            JsonObject output = (JsonObject) Jsoner.deserialize(json);
+            for (String key : output.keySet()) {
+                JsonArray array = (JsonArray) output.get(key);
+                if (key.equals("properties")) {
+                    // flattern each entry in the row with name as they key, and its value as the content (its a map also)
+                    for (Object obj : array) {
+                        Map entry = (Map) obj;
+                        Map<String, String> newRow = new LinkedHashMap();
+                        newRow.putAll(entry);
+                        answer.add(newRow);
+                        String name = ((Map) obj).get("name").toString();
+                        // use naming style with camel case
+                        String lookupKey = dashToCamelCase(name);
+                        newRow.put("name", lookupKey);
+                        // its the java type
+                        String type = newRow.get("type");
+                        newRow.put("javaType", type);
+                        newRow.put("type", fromMainToType(type));
+                    }
+                }
+            }
+        } catch (Exception e) {
+            // wrap parsing exceptions as runtime
+            throw new RuntimeException("Cannot parse json", e);
+        }
+
+        return answer;
+    }
+
+    private static String fromMainToType(String type) {
+        if ("boolean".equals(type) || "java.lang.Boolean".equals(type)) {
+            return "boolean";
+        } else if ("int".equals(type) || "java.lang.Integer".equals(type)) {
+            return "integer";
+        } else if ("long".equals(type) || "java.lang.Long".equals(type)) {
+            return "integer";
+        } else if ("float".equals(type) || "java.lang.Float".equals(type)) {
+            return "number";
+        } else if ("double".equals(type) || "java.lang.Double".equals(type)) {
+            return "number";
+        } else if ("string".equals(type) || "java.lang.String".equals(type)) {
+            return "string";
+        } else {
+            return "object";
+        }
+    }
+
+    /**
      * Parses the json schema to split it into a list or rows, where each row contains key value pairs with the metadata
      *
      * @param group the group to parse from such as <tt>component</tt>, <tt>componentProperties</tt>, or <tt>properties</tt>.
@@ -150,7 +214,7 @@ public final class JSonSchemaHelper {
             String labels = null;
             boolean found = false;
             if (row.containsKey("name")) {
-                found = name.equals(row.get("name"));
+                found = name.equalsIgnoreCase(row.get("name"));
             }
             if (row.containsKey("label")) {
                 labels = row.get("label");
@@ -167,7 +231,7 @@ public final class JSonSchemaHelper {
             String labels = null;
             boolean found = false;
             if (row.containsKey("name")) {
-                found = name.equals(row.get("name"));
+                found = name.equalsIgnoreCase(row.get("name"));
             }
             if (row.containsKey("label")) {
                 labels = row.get("label");
@@ -184,7 +248,7 @@ public final class JSonSchemaHelper {
             boolean required = false;
             boolean found = false;
             if (row.containsKey("name")) {
-                found = name.equals(row.get("name"));
+                found = name.equalsIgnoreCase(row.get("name"));
             }
             if (row.containsKey("required")) {
                 required = "true".equals(row.get("required"));
@@ -201,7 +265,7 @@ public final class JSonSchemaHelper {
             boolean deprecated = false;
             boolean found = false;
             if (row.containsKey("name")) {
-                found = name.equals(row.get("name"));
+                found = name.equalsIgnoreCase(row.get("name"));
             }
             if (row.containsKey("deprecated")) {
                 deprecated = "true".equals(row.get("deprecated"));
@@ -218,7 +282,7 @@ public final class JSonSchemaHelper {
             String kind = null;
             boolean found = false;
             if (row.containsKey("name")) {
-                found = name.equals(row.get("name"));
+                found = name.equalsIgnoreCase(row.get("name"));
             }
             if (row.containsKey("kind")) {
                 kind = row.get("kind");
@@ -230,12 +294,29 @@ public final class JSonSchemaHelper {
         return null;
     }
 
+    public static String getPropertyJavaType(List<Map<String, String>> rows, String name) {
+        for (Map<String, String> row : rows) {
+            String javaType = null;
+            boolean found = false;
+            if (row.containsKey("name")) {
+                found = name.equalsIgnoreCase(row.get("name"));
+            }
+            if (row.containsKey("javaType")) {
+                javaType = row.get("javaType");
+            }
+            if (found) {
+                return javaType;
+            }
+        }
+        return null;
+    }
+
     public static boolean isPropertyBoolean(List<Map<String, String>> rows, String name) {
         for (Map<String, String> row : rows) {
             String type = null;
             boolean found = false;
             if (row.containsKey("name")) {
-                found = name.equals(row.get("name"));
+                found = name.equalsIgnoreCase(row.get("name"));
             }
             if (row.containsKey("type")) {
                 type = row.get("type");
@@ -252,7 +333,7 @@ public final class JSonSchemaHelper {
             String type = null;
             boolean found = false;
             if (row.containsKey("name")) {
-                found = name.equals(row.get("name"));
+                found = name.equalsIgnoreCase(row.get("name"));
             }
             if (row.containsKey("type")) {
                 type = row.get("type");
@@ -264,12 +345,29 @@ public final class JSonSchemaHelper {
         return false;
     }
 
+    public static boolean isPropertyArray(List<Map<String, String>> rows, String name) {
+        for (Map<String, String> row : rows) {
+            String type = null;
+            boolean found = false;
+            if (row.containsKey("name")) {
+                found = name.equalsIgnoreCase(row.get("name"));
+            }
+            if (row.containsKey("type")) {
+                type = row.get("type");
+            }
+            if (found) {
+                return "array".equals(type);
+            }
+        }
+        return false;
+    }
+
     public static boolean isPropertyNumber(List<Map<String, String>> rows, String name) {
         for (Map<String, String> row : rows) {
             String type = null;
             boolean found = false;
             if (row.containsKey("name")) {
-                found = name.equals(row.get("name"));
+                found = name.equalsIgnoreCase(row.get("name"));
             }
             if (row.containsKey("type")) {
                 type = row.get("type");
@@ -286,7 +384,7 @@ public final class JSonSchemaHelper {
             String type = null;
             boolean found = false;
             if (row.containsKey("name")) {
-                found = name.equals(row.get("name"));
+                found = name.equalsIgnoreCase(row.get("name"));
             }
             if (row.containsKey("type")) {
                 type = row.get("type");
@@ -303,7 +401,7 @@ public final class JSonSchemaHelper {
             String defaultValue = null;
             boolean found = false;
             if (row.containsKey("name")) {
-                found = name.equals(row.get("name"));
+                found = name.equalsIgnoreCase(row.get("name"));
             }
             if (row.containsKey("defaultValue")) {
                 defaultValue = row.get("defaultValue");
@@ -328,7 +426,7 @@ public final class JSonSchemaHelper {
                     // try again
                     return stripOptionalPrefixFromName(rows, name);
                 } else {
-                    found = name.equals(row.get("name"));
+                    found = name.equalsIgnoreCase(row.get("name"));
                 }
             }
             if (found) {
@@ -343,7 +441,7 @@ public final class JSonSchemaHelper {
             String enums = null;
             boolean found = false;
             if (row.containsKey("name")) {
-                found = name.equals(row.get("name"));
+                found = name.equalsIgnoreCase(row.get("name"));
             }
             if (row.containsKey("enum")) {
                 enums = row.get("enum");
@@ -360,7 +458,7 @@ public final class JSonSchemaHelper {
             String prefix = null;
             boolean found = false;
             if (row.containsKey("name")) {
-                found = name.equals(row.get("name"));
+                found = name.equalsIgnoreCase(row.get("name"));
             }
             if (row.containsKey("prefix")) {
                 prefix = row.get("prefix");
@@ -377,7 +475,7 @@ public final class JSonSchemaHelper {
             boolean multiValue = false;
             boolean found = false;
             if (row.containsKey("name")) {
-                found = name.equals(row.get("name"));
+                found = name.equalsIgnoreCase(row.get("name"));
             }
             if (row.containsKey("multiValue")) {
                 multiValue = "true".equals(row.get("multiValue"));
@@ -426,4 +524,35 @@ public final class JSonSchemaHelper {
         return answer;
     }
 
+    /**
+     * Converts the string from dash format into camel case (hello-great-world -> helloGreatWorld)
+     *
+     * @param text  the string
+     * @return the string camel cased
+     */
+    private static String dashToCamelCase(String text) {
+        if (text == null) {
+            return null;
+        }
+        int length = text.length();
+        if (length == 0) {
+            return text;
+        }
+        if (text.indexOf('-') == -1) {
+            return text;
+        }
+
+        StringBuilder sb = new StringBuilder();
+
+        for (int i = 0; i < text.length(); i++) {
+            char c = text.charAt(i);
+            if (c == '-') {
+                i++;
+                sb.append(Character.toUpperCase(text.charAt(i)));
+            } else {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
 }
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 25d5bd8..1a09199 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
@@ -713,7 +713,7 @@ public final class PropertyBindingSupport {
         } else if (answer instanceof List) {
             List list = (List) answer;
             if (isNotEmpty(lookupKey)) {
-                int idx = Integer.valueOf(lookupKey);
+                int idx = Integer.parseInt(lookupKey);
                 answer = list.get(idx);
             } else {
                 if (list.isEmpty()) {