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:22 UTC
[camel] 01/02: CAMEL-14311: Add validate configuration properties
to camel-catalog.
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()) {