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 2017/04/14 10:52:55 UTC

[1/6] camel git commit: Rename catalog to runtimecatalog to avoid clash with same package name in camel-catalog.

Repository: camel
Updated Branches:
  refs/heads/master d72696455 -> 6b42a3534


Rename catalog to runtimecatalog to avoid clash with same package name in camel-catalog.


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/6b42a353
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/6b42a353
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/6b42a353

Branch: refs/heads/master
Commit: 6b42a3534120f58180e6194e6bf4f1a284707abc
Parents: c66be7a
Author: Claus Ibsen <da...@apache.org>
Authored: Fri Apr 14 12:17:14 2017 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Fri Apr 14 12:52:40 2017 +0200

----------------------------------------------------------------------
 platforms/camel-catalog/pom.xml | 40 ++++++++++++++++++++++++++++++++++--
 1 file changed, 38 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/6b42a353/platforms/camel-catalog/pom.xml
----------------------------------------------------------------------
diff --git a/platforms/camel-catalog/pom.xml b/platforms/camel-catalog/pom.xml
index 2be82e0..6c71fcb 100644
--- a/platforms/camel-catalog/pom.xml
+++ b/platforms/camel-catalog/pom.xml
@@ -92,7 +92,7 @@
         <executions>
           <execution>
             <id>copy-resources</id>
-            <phase>process-sources</phase>
+            <phase>generate-sources</phase>
             <goals>
               <goal>copy-resources</goal>
             </goals>
@@ -101,7 +101,7 @@
               <overwrite>true</overwrite>
               <resources>
                 <resource>
-                  <directory>../../camel-core/src/main/java/org/apache/camel/catalog</directory>
+                  <directory>../../camel-core/src/main/java/org/apache/camel/runtimecatalog</directory>
                   <!-- the following files are maintained in camel-core and not here, so they are copied over -->
                   <includes>
                     <include>AbstractCamelCatalog.java</include>
@@ -123,6 +123,42 @@
           </execution>
         </executions>
       </plugin>
+      <!-- rename runtimecatalog to catalog which is the package name we use here -->
+      <plugin>
+        <groupId>com.google.code.maven-replacer-plugin</groupId>
+        <artifactId>replacer</artifactId>
+        <version>1.5.3</version>
+        <executions>
+          <execution>
+            <phase>process-sources</phase>
+            <goals>
+              <goal>replace</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <includes>
+            <include>${basedir}/src/main/java/org/apache/camel/catalog/AbstractCamelCatalog.java</include>
+            <include>${basedir}/src/main/java/org/apache/camel/catalog/CatalogHelper.java</include>
+            <include>${basedir}/src/main/java/org/apache/camel/catalog/CollectionStringBuffer.java</include>
+            <include>${basedir}/src/main/java/org/apache/camel/catalog/EndpointValidationResult.java</include>
+            <include>${basedir}/src/main/java/org/apache/camel/catalog/JSonSchemaHelper.java</include>
+            <include>${basedir}/src/main/java/org/apache/camel/catalog/JSonSchemaResolver.java</include>
+            <include>${basedir}/src/main/java/org/apache/camel/catalog/LanguageValidationResult.java</include>
+            <include>${basedir}/src/main/java/org/apache/camel/catalog/SimpleValidationResult.java</include>
+            <include>${basedir}/src/main/java/org/apache/camel/catalog/SuggestionStrategy.java</include>
+            <include>${basedir}/src/main/java/org/apache/camel/catalog/TimePatternConverter.java</include>
+            <include>${basedir}/src/main/java/org/apache/camel/catalog/UnsafeUriCharactersEncoder.java</include>
+            <include>${basedir}/src/main/java/org/apache/camel/catalog/URISupport.java</include>
+          </includes>
+          <replacements>
+            <replacement>
+              <token>org.apache.camel.runtimecatalog</token>
+              <value>org.apache.camel.catalog</value>
+            </replacement>
+          </replacements>
+        </configuration>
+      </plugin>
 
       <!-- generate and include all components in the catalog -->
       <plugin>


[3/6] camel git commit: Rename catalog to runtimecatalog to avoid clash with same package name in camel-catalog.

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaHelper.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaHelper.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaHelper.java
new file mode 100644
index 0000000..1e69269
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaHelper.java
@@ -0,0 +1,424 @@
+/**
+ * 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;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public final class JSonSchemaHelper {
+
+    // 0 = text, 1 = enum, 2 = boolean, 3 = integer or number
+    private static final Pattern PATTERN = Pattern.compile("\"(.+?)\"|\\[(.+)\\]|(true|false)|(-?\\d+\\.?\\d*)");
+    private static final String QUOT = "&quot;";
+
+    private JSonSchemaHelper() {
+    }
+
+    /**
+     * 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>.
+     * @param json the json
+     * @return a list of all the rows, where each row is a set of key value pairs with metadata
+     */
+    public static List<Map<String, String>> parseJsonSchema(String group, String json, boolean parseProperties) {
+        List<Map<String, String>> answer = new ArrayList<Map<String, String>>();
+        if (json == null) {
+            return answer;
+        }
+
+        boolean found = false;
+
+        // parse line by line
+        String[] lines = json.split("\n");
+        for (String line : lines) {
+            // we need to find the group first
+            if (!found) {
+                String s = line.trim();
+                found = s.startsWith("\"" + group + "\":") && s.endsWith("{");
+                continue;
+            }
+
+            // we should stop when we end the group
+            if (line.equals("  },") || line.equals("  }")) {
+                break;
+            }
+
+            // need to safe encode \" so we can parse the line
+            line = line.replaceAll("\"\\\\\"\"", '"' + QUOT + '"');
+
+            Map<String, String> row = new LinkedHashMap<String, String>();
+            Matcher matcher = PATTERN.matcher(line);
+
+            String key;
+            if (parseProperties) {
+                // when parsing properties the first key is given as name, so the first parsed token is the value of the name
+                key = "name";
+            } else {
+                key = null;
+            }
+            while (matcher.find()) {
+                if (key == null) {
+                    key = matcher.group(1);
+                } else {
+                    String value = matcher.group(1);
+                    if (value != null) {
+                        // its text based
+                        value = value.trim();
+                        // decode
+                        value = value.replaceAll(QUOT, "\"");
+                        value = decodeJson(value);
+                    }
+                    if (value == null) {
+                        // not text then its maybe an enum?
+                        value = matcher.group(2);
+                        if (value != null) {
+                            // its an enum so strip out " and trim spaces after comma
+                            value = value.replaceAll("\"", "");
+                            value = value.replaceAll(", ", ",");
+                            value = value.trim();
+                        }
+                    }
+                    if (value == null) {
+                        // not text then its maybe a boolean?
+                        value = matcher.group(3);
+                    }
+                    if (value == null) {
+                        // not text then its maybe a integer?
+                        value = matcher.group(4);
+                    }
+                    if (value != null) {
+                        row.put(key, value);
+                    }
+                    // reset
+                    key = null;
+                }
+            }
+            if (!row.isEmpty()) {
+                answer.add(row);
+            }
+        }
+
+        return answer;
+    }
+
+    private static String decodeJson(String value) {
+        // json encodes a \ as \\ so we need to decode from \\ back to \
+        if ("\\\\".equals(value)) {
+            value = "\\";
+        }
+        return value;
+    }
+
+    public static boolean isComponentLenientProperties(List<Map<String, String>> rows) {
+        for (Map<String, String> row : rows) {
+            if (row.containsKey("lenientProperties")) {
+                return "true".equals(row.get("lenientProperties"));
+            }
+        }
+        return false;
+    }
+
+    public static boolean isComponentConsumerOnly(List<Map<String, String>> rows) {
+        for (Map<String, String> row : rows) {
+            if (row.containsKey("consumerOnly")) {
+                return "true".equals(row.get("consumerOnly"));
+            }
+        }
+        return false;
+    }
+
+    public static boolean isComponentProducerOnly(List<Map<String, String>> rows) {
+        for (Map<String, String> row : rows) {
+            if (row.containsKey("producerOnly")) {
+                return "true".equals(row.get("producerOnly"));
+            }
+        }
+        return false;
+    }
+
+    public static boolean isPropertyConsumerOnly(List<Map<String, String>> rows, String name) {
+        for (Map<String, String> row : rows) {
+            String labels = null;
+            boolean found = false;
+            if (row.containsKey("name")) {
+                found = name.equals(row.get("name"));
+            }
+            if (row.containsKey("label")) {
+                labels = row.get("label");
+            }
+            if (found) {
+                return labels != null && labels.contains("consumer");
+            }
+        }
+        return false;
+    }
+
+    public static boolean isPropertyProducerOnly(List<Map<String, String>> rows, String name) {
+        for (Map<String, String> row : rows) {
+            String labels = null;
+            boolean found = false;
+            if (row.containsKey("name")) {
+                found = name.equals(row.get("name"));
+            }
+            if (row.containsKey("label")) {
+                labels = row.get("label");
+            }
+            if (found) {
+                return labels != null && labels.contains("producer");
+            }
+        }
+        return false;
+    }
+
+    public static boolean isPropertyRequired(List<Map<String, String>> rows, String name) {
+        for (Map<String, String> row : rows) {
+            boolean required = false;
+            boolean found = false;
+            if (row.containsKey("name")) {
+                found = name.equals(row.get("name"));
+            }
+            if (row.containsKey("required")) {
+                required = "true".equals(row.get("required"));
+            }
+            if (found) {
+                return required;
+            }
+        }
+        return false;
+    }
+
+    public static String getPropertyKind(List<Map<String, String>> rows, String name) {
+        for (Map<String, String> row : rows) {
+            String kind = null;
+            boolean found = false;
+            if (row.containsKey("name")) {
+                found = name.equals(row.get("name"));
+            }
+            if (row.containsKey("kind")) {
+                kind = row.get("kind");
+            }
+            if (found) {
+                return kind;
+            }
+        }
+        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"));
+            }
+            if (row.containsKey("type")) {
+                type = row.get("type");
+            }
+            if (found) {
+                return "boolean".equals(type);
+            }
+        }
+        return false;
+    }
+
+    public static boolean isPropertyInteger(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"));
+            }
+            if (row.containsKey("type")) {
+                type = row.get("type");
+            }
+            if (found) {
+                return "integer".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"));
+            }
+            if (row.containsKey("type")) {
+                type = row.get("type");
+            }
+            if (found) {
+                return "number".equals(type);
+            }
+        }
+        return false;
+    }
+
+    public static boolean isPropertyObject(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"));
+            }
+            if (row.containsKey("type")) {
+                type = row.get("type");
+            }
+            if (found) {
+                return "object".equals(type);
+            }
+        }
+        return false;
+    }
+
+    public static String getPropertyDefaultValue(List<Map<String, String>> rows, String name) {
+        for (Map<String, String> row : rows) {
+            String defaultValue = null;
+            boolean found = false;
+            if (row.containsKey("name")) {
+                found = name.equals(row.get("name"));
+            }
+            if (row.containsKey("defaultValue")) {
+                defaultValue = row.get("defaultValue");
+            }
+            if (found) {
+                return defaultValue;
+            }
+        }
+        return null;
+    }
+
+    public static String stripOptionalPrefixFromName(List<Map<String, String>> rows, String name) {
+        for (Map<String, String> row : rows) {
+            String optionalPrefix = null;
+            boolean found = false;
+            if (row.containsKey("optionalPrefix")) {
+                optionalPrefix = row.get("optionalPrefix");
+            }
+            if (row.containsKey("name")) {
+                if (optionalPrefix != null && name.startsWith(optionalPrefix)) {
+                    name = name.substring(optionalPrefix.length());
+                    // try again
+                    return stripOptionalPrefixFromName(rows, name);
+                } else {
+                    found = name.equals(row.get("name"));
+                }
+            }
+            if (found) {
+                return name;
+            }
+        }
+        return name;
+    }
+
+    public static String getPropertyEnum(List<Map<String, String>> rows, String name) {
+        for (Map<String, String> row : rows) {
+            String enums = null;
+            boolean found = false;
+            if (row.containsKey("name")) {
+                found = name.equals(row.get("name"));
+            }
+            if (row.containsKey("enum")) {
+                enums = row.get("enum");
+            }
+            if (found) {
+                return enums;
+            }
+        }
+        return null;
+    }
+
+    public static String getPropertyPrefix(List<Map<String, String>> rows, String name) {
+        for (Map<String, String> row : rows) {
+            String prefix = null;
+            boolean found = false;
+            if (row.containsKey("name")) {
+                found = name.equals(row.get("name"));
+            }
+            if (row.containsKey("prefix")) {
+                prefix = row.get("prefix");
+            }
+            if (found) {
+                return prefix;
+            }
+        }
+        return null;
+    }
+
+    public static boolean isPropertyMultiValue(List<Map<String, String>> rows, String name) {
+        for (Map<String, String> row : rows) {
+            boolean multiValue = false;
+            boolean found = false;
+            if (row.containsKey("name")) {
+                found = name.equals(row.get("name"));
+            }
+            if (row.containsKey("multiValue")) {
+                multiValue = "true".equals(row.get("multiValue"));
+            }
+            if (found) {
+                return multiValue;
+            }
+        }
+        return false;
+    }
+
+    public static String getPropertyNameFromNameWithPrefix(List<Map<String, String>> rows, String name) {
+        for (Map<String, String> row : rows) {
+            String propertyName = null;
+            boolean found = false;
+            if (row.containsKey("name")) {
+                propertyName = row.get("name");
+            }
+            if (row.containsKey("prefix")) {
+                String preifx = row.get("prefix");
+                found = name.startsWith(preifx);
+            }
+            if (found) {
+                return propertyName;
+            }
+        }
+        return null;
+    }
+
+    public static Map<String, String> getRow(List<Map<String, String>> rows, String key) {
+        for (Map<String, String> row : rows) {
+            if (key.equals(row.get("name"))) {
+                return row;
+            }
+        }
+        return null;
+    }
+
+    public static Set<String> getNames(List<Map<String, String>> rows) {
+        Set<String> answer = new LinkedHashSet<String>();
+        for (Map<String, String> row : rows) {
+            if (row.containsKey("name")) {
+                answer.add(row.get("name"));
+            }
+        }
+        return answer;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaResolver.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaResolver.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaResolver.java
new file mode 100644
index 0000000..dbd6f45
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaResolver.java
@@ -0,0 +1,64 @@
+/**
+ * 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;
+
+/**
+ * Pluggable resolver to load JSon schema files for components, data formats, languages etc.
+ */
+public interface JSonSchemaResolver {
+
+    /**
+     * Returns the component information as JSon format.
+     *
+     * @param name the component name
+     * @return component details in JSon
+     */
+    String getComponentJSonSchema(String name);
+
+    /**
+     * Returns the data format information as JSon format.
+     *
+     * @param name the data format name
+     * @return data format details in JSon
+     */
+    String getDataFormatJSonSchema(String name);
+
+    /**
+     * Returns the language information as JSon format.
+     *
+     * @param name the language name
+     * @return language details in JSon
+     */
+    String getLanguageJSonSchema(String name);
+
+    /**
+     * Returns the other (miscellaneous) information as JSon format.
+     *
+     * @param name the other (miscellaneous) name
+     * @return other (miscellaneous) details in JSon
+     */
+    String getOtherJSonSchema(String name);
+
+    /**
+     * Returns the model information as JSon format.
+     *
+     * @param name the model name
+     * @return model details in JSon
+     */
+    String getModelJSonSchema(String name);
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/LanguageValidationResult.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/LanguageValidationResult.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/LanguageValidationResult.java
new file mode 100644
index 0000000..dbb5525
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/LanguageValidationResult.java
@@ -0,0 +1,65 @@
+/**
+ * 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;
+
+import java.io.Serializable;
+
+/**
+ * Validation result of parsing a language expression or predicate
+ */
+public class LanguageValidationResult implements Serializable {
+    private final String text;
+    private String error;
+    private String shortError;
+    private int index;
+
+    public LanguageValidationResult(String text) {
+        this.text = text;
+    }
+
+    public String getText() {
+        return text;
+    }
+
+    public boolean isSuccess() {
+        return error == null;
+    }
+
+    public void setError(String error) {
+        this.error = error;
+    }
+
+    public String getError() {
+        return error;
+    }
+
+    public String getShortError() {
+        return shortError;
+    }
+
+    public void setShortError(String shortError) {
+        this.shortError = shortError;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public void setIndex(int index) {
+        this.index = index;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/RuntimeCamelCatalog.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/RuntimeCamelCatalog.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/RuntimeCamelCatalog.java
new file mode 100644
index 0000000..86c4b53
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/RuntimeCamelCatalog.java
@@ -0,0 +1,234 @@
+/**
+ * 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;
+
+import java.net.URISyntaxException;
+import java.util.Map;
+
+import org.apache.camel.StaticService;
+
+/**
+ * Runtime based CamelCatalog which are included in camel-core that can provided limit CamelCatalog capabilities
+ */
+public interface RuntimeCamelCatalog extends StaticService {
+
+    /**
+     * Returns the component information as JSon format.
+     *
+     * @param name the component name
+     * @return component details in JSon
+     */
+    String componentJSonSchema(String name);
+
+    /**
+     * Returns the data format information as JSon format.
+     *
+     * @param name the data format name
+     * @return data format details in JSon
+     */
+    String dataFormatJSonSchema(String name);
+
+    /**
+     * Returns the language information as JSon format.
+     *
+     * @param name the language name
+     * @return language details in JSon
+     */
+    String languageJSonSchema(String name);
+
+    /**
+     * Returns the model information as JSon format.
+     *
+     * @param name the model name
+     * @return model details in JSon
+     */
+    String modelJSonSchema(String name);
+
+    /**
+     * Parses the endpoint uri and constructs a key/value properties of each option
+     *
+     * @param uri  the endpoint uri
+     * @return properties as key value pairs of each endpoint option
+     */
+    Map<String, String> endpointProperties(String uri) throws URISyntaxException;
+
+    /**
+     * Parses the endpoint uri and constructs a key/value properties of only the lenient properties (eg custom options)
+     * <p/>
+     * For example using the HTTP components to provide query parameters in the endpoint uri.
+     *
+     * @param uri  the endpoint uri
+     * @return properties as key value pairs of each lenient properties
+     */
+    Map<String, String> endpointLenientProperties(String uri) throws URISyntaxException;
+
+    /**
+     * Validates the pattern whether its a valid time pattern.
+     *
+     * @param pattern  the pattern such as 5000, 5s, 5sec, 4min, 4m30s, 1h, etc.
+     * @return <tt>true</tt> if valid, <tt>false</tt> if invalid
+     */
+    boolean validateTimePattern(String pattern);
+
+    /**
+     * Validates the properties for the given scheme against component and endpoint
+     *
+     * @param scheme  the endpoint scheme
+     * @param properties  the endpoint properties
+     * @return validation result
+     */
+    EndpointValidationResult validateProperties(String scheme, Map<String, String> properties);
+
+    /**
+     * Parses and validates the endpoint uri and constructs a key/value properties of each option.
+     *
+     * @param uri  the endpoint uri
+     * @return validation result
+     */
+    EndpointValidationResult validateEndpointProperties(String uri);
+
+    /**
+     * Parses and validates the endpoint uri and constructs a key/value properties of each option.
+     * <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
+     * but in the uri because of using lenient properties.
+     * For example using the HTTP components to provide query parameters in the endpoint uri.
+     *
+     * @param uri  the endpoint uri
+     * @param ignoreLenientProperties  whether to ignore components that uses lenient properties.
+     * @return validation result
+     */
+    EndpointValidationResult validateEndpointProperties(String uri, boolean ignoreLenientProperties);
+
+    /**
+     * Parses and validates the endpoint uri and constructs a key/value properties of each option.
+     * <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
+     * but in the uri because of using lenient properties.
+     * For example using the HTTP components to provide query parameters in the endpoint uri.
+     *
+     * @param uri  the endpoint uri
+     * @param ignoreLenientProperties  whether to ignore components that uses lenient properties.
+     * @param consumerOnly whether the endpoint is only used as a consumer
+     * @param producerOnly whether the endpoint is only used as a producer
+     * @return validation result
+     */
+    EndpointValidationResult validateEndpointProperties(String uri, boolean ignoreLenientProperties, boolean consumerOnly, boolean producerOnly);
+
+    /**
+     * Parses and validates the simple expression.
+     * <p/>
+     * <b>Important:</b> This requires having <tt>camel-core</tt> on the classpath
+     *
+     * @param simple  the simple expression
+     * @return validation result
+     * @deprecated use {@link #validateSimpleExpression(ClassLoader, String)}
+     */
+    @Deprecated
+    SimpleValidationResult validateSimpleExpression(String simple);
+
+    /**
+     * Parses and validates the simple expression.
+     * <p/>
+     * <b>Important:</b> This requires having <tt>camel-core</tt> on the classpath
+     *
+     * @param classLoader a custom classloader to use for loading the language from the classpath, or <tt>null</tt> for using default classloader
+     * @param simple  the simple expression
+     * @return validation result
+     */
+    SimpleValidationResult validateSimpleExpression(ClassLoader classLoader, String simple);
+
+    /**
+     * Parses and validates the simple predicate
+     * <p/>
+     * <b>Important:</b> This requires having <tt>camel-core</tt> on the classpath
+     *
+     * @param simple  the simple predicate
+     * @return validation result
+     * @deprecated use {@link #validateSimplePredicate(ClassLoader, String)}
+     */
+    @Deprecated
+    SimpleValidationResult validateSimplePredicate(String simple);
+
+    /**
+     * Parses and validates the simple predicate
+     * <p/>
+     * <b>Important:</b> This requires having <tt>camel-core</tt> on the classpath
+     *
+     * @param classLoader a custom classloader to use for loading the language from the classpath, or <tt>null</tt> for using default classloader
+     * @param simple  the simple predicate
+     * @return validation result
+     */
+    SimpleValidationResult validateSimplePredicate(ClassLoader classLoader, String simple);
+
+    /**
+     * Parses and validates the language as a predicate
+     * <p/>
+     * <b>Important:</b> This requires having <tt>camel-core</tt> and the language dependencies on the classpath
+     *
+     * @param classLoader a custom classloader to use for loading the language from the classpath, or <tt>null</tt> for using default classloader
+     * @param language the name of the language
+     * @param text  the predicate text
+     * @return validation result
+     */
+    LanguageValidationResult validateLanguagePredicate(ClassLoader classLoader, String language, String text);
+
+    /**
+     * Parses and validates the language as an expression
+     * <p/>
+     * <b>Important:</b> This requires having <tt>camel-core</tt> and the language dependencies on the classpath
+     *
+     * @param classLoader a custom classloader to use for loading the language from the classpath, or <tt>null</tt> for using default classloader
+     * @param language the name of the language
+     * @param text  the expression text
+     * @return validation result
+     */
+    LanguageValidationResult validateLanguageExpression(ClassLoader classLoader, String language, String text);
+
+    /**
+     * Returns the component name from the given endpoint uri
+     *
+     * @param uri  the endpoint uri
+     * @return the component name (aka scheme), or <tt>null</tt> if not possible to determine
+     */
+    String endpointComponentName(String uri);
+
+    /**
+     * Creates an endpoint uri in Java style from the information from the properties
+     *
+     * @param scheme the endpoint schema
+     * @param properties the properties as key value pairs
+     * @param encode whether to URL encode the returned uri or not
+     * @return the constructed endpoint uri
+     * @throws java.net.URISyntaxException is thrown if there is encoding error
+     */
+    String asEndpointUri(String scheme, Map<String, String> properties, boolean encode) throws URISyntaxException;
+
+    /**
+     * Creates an endpoint uri in XML style (eg escape & as &ampl;) from the information from the properties
+     *
+     * @param scheme the endpoint schema
+     * @param properties the properties as key value pairs
+     * @param encode whether to URL encode the returned uri or not
+     * @return the constructed endpoint uri
+     * @throws java.net.URISyntaxException is thrown if there is encoding error
+     */
+    String asEndpointUriXml(String scheme, Map<String, String> properties, boolean encode) throws URISyntaxException;
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/SimpleValidationResult.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/SimpleValidationResult.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/SimpleValidationResult.java
new file mode 100644
index 0000000..1b8dd0e
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/SimpleValidationResult.java
@@ -0,0 +1,32 @@
+/**
+ * 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;
+
+/**
+ * To be backwards compatible, but favor using {@link LanguageValidationResult} instead.
+ */
+public class SimpleValidationResult extends LanguageValidationResult {
+
+    public SimpleValidationResult(String text) {
+        super(text);
+    }
+
+    public String getSimple() {
+        return getText();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/SuggestionStrategy.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/SuggestionStrategy.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/SuggestionStrategy.java
new file mode 100644
index 0000000..e29afc6
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/SuggestionStrategy.java
@@ -0,0 +1,34 @@
+/**
+ * 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;
+
+import java.util.Set;
+
+/**
+ * Strategy to provide suggestions for unknown endpoint options
+ */
+public interface SuggestionStrategy {
+
+    /**
+     * Provides a list of valid option names for a did you mean function.
+     *
+     * @param names         valid names
+     * @param unknownOption unknown option name
+     * @return a list of suggested names (did you mean)
+     */
+    String[] suggestEndpointOptions(Set<String> names, String unknownOption);
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/TimePatternConverter.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/TimePatternConverter.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/TimePatternConverter.java
new file mode 100644
index 0000000..ed5585c
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/TimePatternConverter.java
@@ -0,0 +1,120 @@
+/**
+ * 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;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * This class is a copy from camel-core so we can use it independent to validate uris with time patterns
+ */
+public final class TimePatternConverter {
+    private static final Pattern NUMBERS_ONLY_STRING_PATTERN = Pattern.compile("^[-]?(\\d)+$", Pattern.CASE_INSENSITIVE);
+    private static final Pattern HOUR_REGEX_PATTERN = Pattern.compile("((\\d)*(\\d))h(our(s)?)?", Pattern.CASE_INSENSITIVE);
+    private static final Pattern MINUTES_REGEX_PATTERN = Pattern.compile("((\\d)*(\\d))m(in(ute(s)?)?)?", Pattern.CASE_INSENSITIVE);
+    private static final Pattern SECONDS_REGEX_PATTERN = Pattern.compile("((\\d)*(\\d))s(ec(ond)?(s)?)?", Pattern.CASE_INSENSITIVE);
+
+    /**
+     * Utility classes should not have a public constructor.
+     */
+    private TimePatternConverter() {
+    }
+
+    public static long toMilliSeconds(String source) throws IllegalArgumentException {
+        long milliseconds = 0;
+        boolean foundFlag = false;
+
+        checkCorrectnessOfPattern(source);
+        Matcher matcher;
+
+        matcher = createMatcher(NUMBERS_ONLY_STRING_PATTERN, source);
+        if (matcher.find()) {
+            // Note: This will also be used for regular numeric strings.
+            //       This String -> long converter will be used for all strings.
+            milliseconds = Long.valueOf(source);
+        } else {
+            matcher = createMatcher(HOUR_REGEX_PATTERN, source);
+            if (matcher.find()) {
+                milliseconds = milliseconds + (3600000 * Long.valueOf(matcher.group(1)));
+                foundFlag = true;
+            }
+
+            matcher = createMatcher(MINUTES_REGEX_PATTERN, source);
+            if (matcher.find()) {
+                long minutes = Long.valueOf(matcher.group(1));
+                if ((minutes > 59) && foundFlag) {
+                    throw new IllegalArgumentException("Minutes should contain a valid value between 0 and 59: " + source);
+                }
+                foundFlag = true;
+                milliseconds = milliseconds + (60000 * minutes);
+            }
+
+            matcher = createMatcher(SECONDS_REGEX_PATTERN, source);
+            if (matcher.find()) {
+                long seconds = Long.valueOf(matcher.group(1));
+                if ((seconds > 59) && foundFlag) {
+                    throw new IllegalArgumentException("Seconds should contain a valid value between 0 and 59: " + source);
+                }
+                foundFlag = true;
+                milliseconds = milliseconds + (1000 * seconds);
+            }
+
+            // No pattern matched... initiating fallback check and conversion (if required).
+            // The source at this point may contain illegal values or special characters
+            if (!foundFlag) {
+                milliseconds = Long.valueOf(source);
+            }
+        }
+
+        return milliseconds;
+    }
+
+    private static void checkCorrectnessOfPattern(String source) {
+        //replace only numbers once
+        Matcher matcher = createMatcher(NUMBERS_ONLY_STRING_PATTERN, source);
+        String replaceSource = matcher.replaceFirst("");
+
+        //replace hour string once
+        matcher = createMatcher(HOUR_REGEX_PATTERN, replaceSource);
+        if (matcher.find() && matcher.find()) {
+            throw new IllegalArgumentException("Hours should not be specified more then once: " + source);
+        }
+        replaceSource = matcher.replaceFirst("");
+
+        //replace minutes once
+        matcher = createMatcher(MINUTES_REGEX_PATTERN, replaceSource);
+        if (matcher.find() && matcher.find()) {
+            throw new IllegalArgumentException("Minutes should not be specified more then once: " + source);
+        }
+        replaceSource = matcher.replaceFirst("");
+
+        //replace seconds once
+        matcher = createMatcher(SECONDS_REGEX_PATTERN, replaceSource);
+        if (matcher.find() && matcher.find()) {
+            throw new IllegalArgumentException("Seconds should not be specified more then once: " + source);
+        }
+        replaceSource = matcher.replaceFirst("");
+
+        if (replaceSource.length() > 0) {
+            throw new IllegalArgumentException("Illegal characters: " + source);
+        }
+    }
+
+    private static Matcher createMatcher(Pattern pattern, String source) {
+        return pattern.matcher(source);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/URISupport.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/URISupport.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/URISupport.java
new file mode 100644
index 0000000..8389590
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/URISupport.java
@@ -0,0 +1,392 @@
+/**
+ * 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;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Copied from org.apache.camel.util.URISupport
+ */
+public final class URISupport {
+
+    public static final String RAW_TOKEN_START = "RAW(";
+    public static final String RAW_TOKEN_END = ")";
+
+    private static final String CHARSET = "UTF-8";
+
+    private URISupport() {
+        // Helper class
+    }
+
+    /**
+     * Normalizes the URI so unsafe characters is encoded
+     *
+     * @param uri the input uri
+     * @return as URI instance
+     * @throws URISyntaxException is thrown if syntax error in the input uri
+     */
+    public static URI normalizeUri(String uri) throws URISyntaxException {
+        return new URI(UnsafeUriCharactersEncoder.encode(uri, true));
+    }
+
+    public static Map<String, Object> extractProperties(Map<String, Object> properties, String optionPrefix) {
+        Map<String, Object> rc = new LinkedHashMap<String, Object>(properties.size());
+
+        for (Iterator<Map.Entry<String, Object>> it = properties.entrySet().iterator(); it.hasNext();) {
+            Map.Entry<String, Object> entry = it.next();
+            String name = entry.getKey();
+            if (name.startsWith(optionPrefix)) {
+                Object value = properties.get(name);
+                name = name.substring(optionPrefix.length());
+                rc.put(name, value);
+                it.remove();
+            }
+        }
+
+        return rc;
+    }
+
+    /**
+     * Strips the query parameters from the uri
+     *
+     * @param uri  the uri
+     * @return the uri without the query parameter
+     */
+    public static String stripQuery(String uri) {
+        int idx = uri.indexOf('?');
+        if (idx > -1) {
+            uri = uri.substring(0, idx);
+        }
+        return uri;
+    }
+
+    /**
+     * Parses the query parameters of the uri (eg the query part).
+     *
+     * @param uri the uri
+     * @return the parameters, or an empty map if no parameters (eg never null)
+     * @throws URISyntaxException is thrown if uri has invalid syntax.
+     */
+    public static Map<String, Object> parseParameters(URI uri) throws URISyntaxException {
+        String query = uri.getQuery();
+        if (query == null) {
+            String schemeSpecificPart = uri.getSchemeSpecificPart();
+            int idx = schemeSpecificPart.indexOf('?');
+            if (idx < 0) {
+                // return an empty map
+                return new LinkedHashMap<String, Object>(0);
+            } else {
+                query = schemeSpecificPart.substring(idx + 1);
+            }
+        } else {
+            query = stripPrefix(query, "?");
+        }
+        return parseQuery(query);
+    }
+
+    /**
+     * Strips the prefix from the value.
+     * <p/>
+     * Returns the value as-is if not starting with the prefix.
+     *
+     * @param value  the value
+     * @param prefix the prefix to remove from value
+     * @return the value without the prefix
+     */
+    public static String stripPrefix(String value, String prefix) {
+        if (value != null && value.startsWith(prefix)) {
+            return value.substring(prefix.length());
+        }
+        return value;
+    }
+
+    /**
+     * Parses the query part of the uri (eg the parameters).
+     * <p/>
+     * The URI parameters will by default be URI encoded. However you can define a parameter
+     * values with the syntax: <tt>key=RAW(value)</tt> which tells Camel to not encode the value,
+     * and use the value as is (eg key=value) and the value has <b>not</b> been encoded.
+     *
+     * @param uri the uri
+     * @return the parameters, or an empty map if no parameters (eg never null)
+     * @throws URISyntaxException is thrown if uri has invalid syntax.
+     * @see #RAW_TOKEN_START
+     * @see #RAW_TOKEN_END
+     */
+    public static Map<String, Object> parseQuery(String uri) throws URISyntaxException {
+        return parseQuery(uri, false);
+    }
+
+    /**
+     * Parses the query part of the uri (eg the parameters).
+     * <p/>
+     * The URI parameters will by default be URI encoded. However you can define a parameter
+     * values with the syntax: <tt>key=RAW(value)</tt> which tells Camel to not encode the value,
+     * and use the value as is (eg key=value) and the value has <b>not</b> been encoded.
+     *
+     * @param uri the uri
+     * @param useRaw whether to force using raw values
+     * @return the parameters, or an empty map if no parameters (eg never null)
+     * @throws URISyntaxException is thrown if uri has invalid syntax.
+     * @see #RAW_TOKEN_START
+     * @see #RAW_TOKEN_END
+     */
+    public static Map<String, Object> parseQuery(String uri, boolean useRaw) throws URISyntaxException {
+        // must check for trailing & as the uri.split("&") will ignore those
+        if (uri != null && uri.endsWith("&")) {
+            throw new URISyntaxException(uri, "Invalid uri syntax: Trailing & marker found. "
+                    + "Check the uri and remove the trailing & marker.");
+        }
+
+        if (isEmpty(uri)) {
+            // return an empty map
+            return new LinkedHashMap<String, Object>(0);
+        }
+
+        // need to parse the uri query parameters manually as we cannot rely on splitting by &,
+        // as & can be used in a parameter value as well.
+
+        try {
+            // use a linked map so the parameters is in the same order
+            Map<String, Object> rc = new LinkedHashMap<String, Object>();
+
+            boolean isKey = true;
+            boolean isValue = false;
+            boolean isRaw = false;
+            StringBuilder key = new StringBuilder();
+            StringBuilder value = new StringBuilder();
+
+            // parse the uri parameters char by char
+            for (int i = 0; i < uri.length(); i++) {
+                // current char
+                char ch = uri.charAt(i);
+                // look ahead of the next char
+                char next;
+                if (i <= uri.length() - 2) {
+                    next = uri.charAt(i + 1);
+                } else {
+                    next = '\u0000';
+                }
+
+                // are we a raw value
+                isRaw = value.toString().startsWith(RAW_TOKEN_START);
+
+                // if we are in raw mode, then we keep adding until we hit the end marker
+                if (isRaw) {
+                    if (isKey) {
+                        key.append(ch);
+                    } else if (isValue) {
+                        value.append(ch);
+                    }
+
+                    // we only end the raw marker if its )& or at the end of the value
+
+                    boolean end = ch == RAW_TOKEN_END.charAt(0) && (next == '&' || next == '\u0000');
+                    if (end) {
+                        // raw value end, so add that as a parameter, and reset flags
+                        addParameter(key.toString(), value.toString(), rc, useRaw || isRaw);
+                        key.setLength(0);
+                        value.setLength(0);
+                        isKey = true;
+                        isValue = false;
+                        isRaw = false;
+                        // skip to next as we are in raw mode and have already added the value
+                        i++;
+                    }
+                    continue;
+                }
+
+                // if its a key and there is a = sign then the key ends and we are in value mode
+                if (isKey && ch == '=') {
+                    isKey = false;
+                    isValue = true;
+                    isRaw = false;
+                    continue;
+                }
+
+                // the & denote parameter is ended
+                if (ch == '&') {
+                    // parameter is ended, as we hit & separator
+                    String aKey = key.toString();
+                    // the key may be a placeholder of options which we then do not know what is
+                    boolean validKey = !aKey.startsWith("{{") && !aKey.endsWith("}}");
+                    if (validKey) {
+                        addParameter(aKey, value.toString(), rc, useRaw || isRaw);
+                    }
+                    key.setLength(0);
+                    value.setLength(0);
+                    isKey = true;
+                    isValue = false;
+                    isRaw = false;
+                    continue;
+                }
+
+                // regular char so add it to the key or value
+                if (isKey) {
+                    key.append(ch);
+                } else if (isValue) {
+                    value.append(ch);
+                }
+            }
+
+            // any left over parameters, then add that
+            if (key.length() > 0) {
+                String aKey = key.toString();
+                // the key may be a placeholder of options which we then do not know what is
+                boolean validKey = !aKey.startsWith("{{") && !aKey.endsWith("}}");
+                if (validKey) {
+                    addParameter(aKey, value.toString(), rc, useRaw || isRaw);
+                }
+            }
+
+            return rc;
+
+        } catch (UnsupportedEncodingException e) {
+            URISyntaxException se = new URISyntaxException(e.toString(), "Invalid encoding");
+            se.initCause(e);
+            throw se;
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private static void addParameter(String name, String value, Map<String, Object> map, boolean isRaw) throws UnsupportedEncodingException {
+        name = URLDecoder.decode(name, CHARSET);
+        if (!isRaw) {
+            // need to replace % with %25
+            value = URLDecoder.decode(value.replaceAll("%", "%25"), CHARSET);
+        }
+
+        // does the key already exist?
+        if (map.containsKey(name)) {
+            // yes it does, so make sure we can support multiple values, but using a list
+            // to hold the multiple values
+            Object existing = map.get(name);
+            List<String> list;
+            if (existing instanceof List) {
+                list = (List<String>) existing;
+            } else {
+                // create a new list to hold the multiple values
+                list = new ArrayList<String>();
+                String s = existing != null ? existing.toString() : null;
+                if (s != null) {
+                    list.add(s);
+                }
+            }
+            list.add(value);
+            map.put(name, list);
+        } else {
+            map.put(name, value);
+        }
+    }
+
+    /**
+     * Assembles a query from the given map.
+     *
+     * @param options  the map with the options (eg key/value pairs)
+     * @param ampersand to use & for Java code, and &amp; for XML
+     * @return a query string with <tt>key1=value&key2=value2&...</tt>, or an empty string if there is no options.
+     * @throws URISyntaxException is thrown if uri has invalid syntax.
+     */
+    public static String createQueryString(Map<String, String> options, String ampersand, boolean encode) throws URISyntaxException {
+        try {
+            if (options.size() > 0) {
+                StringBuilder rc = new StringBuilder();
+                boolean first = true;
+                for (Object o : options.keySet()) {
+                    if (first) {
+                        first = false;
+                    } else {
+                        rc.append(ampersand);
+                    }
+
+                    String key = (String) o;
+                    Object value = options.get(key);
+
+                    // use the value as a String
+                    String s = value != null ? value.toString() : null;
+                    appendQueryStringParameter(key, s, rc, encode);
+                }
+                return rc.toString();
+            } else {
+                return "";
+            }
+        } catch (UnsupportedEncodingException e) {
+            URISyntaxException se = new URISyntaxException(e.toString(), "Invalid encoding");
+            se.initCause(e);
+            throw se;
+        }
+    }
+
+    private static void appendQueryStringParameter(String key, String value, StringBuilder rc, boolean encode) throws UnsupportedEncodingException {
+        if (encode) {
+            rc.append(URLEncoder.encode(key, CHARSET));
+        } else {
+            rc.append(key);
+        }
+        // only append if value is not null
+        if (value != null) {
+            rc.append("=");
+            if (value.startsWith(RAW_TOKEN_START) && value.endsWith(RAW_TOKEN_END)) {
+                // do not encode RAW parameters
+                rc.append(value);
+            } else {
+                if (encode) {
+                    rc.append(URLEncoder.encode(value, CHARSET));
+                } else {
+                    rc.append(value);
+                }
+            }
+        }
+    }
+
+    /**
+     * Tests whether the value is <tt>null</tt> or an empty string.
+     *
+     * @param value  the value, if its a String it will be tested for text length as well
+     * @return true if empty
+     */
+    public static boolean isEmpty(Object value) {
+        return !isNotEmpty(value);
+    }
+
+    /**
+     * Tests whether the value is <b>not</b> <tt>null</tt> or an empty string.
+     *
+     * @param value  the value, if its a String it will be tested for text length as well
+     * @return true if <b>not</b> empty
+     */
+    public static boolean isNotEmpty(Object value) {
+        if (value == null) {
+            return false;
+        } else if (value instanceof String) {
+            String text = (String) value;
+            return text.trim().length() > 0;
+        } else {
+            return true;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/UnsafeUriCharactersEncoder.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/UnsafeUriCharactersEncoder.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/UnsafeUriCharactersEncoder.java
new file mode 100644
index 0000000..a11c810
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/UnsafeUriCharactersEncoder.java
@@ -0,0 +1,206 @@
+/**
+ * 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;
+
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Encoder for unsafe URI characters.
+ * <p/>
+ * A good source for details is <a href="http://en.wikipedia.org/wiki/Url_encode">wikipedia url encode</a> article.
+ */
+public final class UnsafeUriCharactersEncoder {
+    private static BitSet unsafeCharactersRfc1738;
+    private static BitSet unsafeCharactersHttp;
+    private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
+        'D', 'E', 'F', 'a', 'b', 'c', 'd', 'e', 'f'};
+    private static final Pattern RAW_PATTERN = Pattern.compile("RAW\\([^\\)]+\\)");
+
+    static {
+        unsafeCharactersRfc1738 = new BitSet(256);
+        unsafeCharactersRfc1738.set(' ');
+        unsafeCharactersRfc1738.set('"');
+        unsafeCharactersRfc1738.set('<');
+        unsafeCharactersRfc1738.set('>');
+        unsafeCharactersRfc1738.set('#');
+        unsafeCharactersRfc1738.set('%');
+        unsafeCharactersRfc1738.set('{');
+        unsafeCharactersRfc1738.set('}');
+        unsafeCharactersRfc1738.set('|');
+        unsafeCharactersRfc1738.set('\\');
+        unsafeCharactersRfc1738.set('^');
+        unsafeCharactersRfc1738.set('~');
+        unsafeCharactersRfc1738.set('[');
+        unsafeCharactersRfc1738.set(']');
+        unsafeCharactersRfc1738.set('`');
+    }
+
+    static {
+        unsafeCharactersHttp = new BitSet(256);
+        unsafeCharactersHttp.set(' ');
+        unsafeCharactersHttp.set('"');
+        unsafeCharactersHttp.set('<');
+        unsafeCharactersHttp.set('>');
+        unsafeCharactersHttp.set('#');
+        unsafeCharactersHttp.set('%');
+        unsafeCharactersHttp.set('{');
+        unsafeCharactersHttp.set('}');
+        unsafeCharactersHttp.set('|');
+        unsafeCharactersHttp.set('\\');
+        unsafeCharactersHttp.set('^');
+        unsafeCharactersHttp.set('~');
+        unsafeCharactersHttp.set('`');
+    }
+
+    private UnsafeUriCharactersEncoder() {
+        // util class
+    }
+
+    public static String encode(String s) {
+        return encode(s, unsafeCharactersRfc1738);
+    }
+
+    public static String encodeHttpURI(String s) {
+        return encode(s, unsafeCharactersHttp);
+    }
+
+    public static String encode(String s, BitSet unsafeCharacters) {
+        return encode(s, unsafeCharacters, false);
+    }
+
+    public static String encode(String s, boolean checkRaw) {
+        return encode(s, unsafeCharactersRfc1738, checkRaw);
+    }
+
+    public static String encodeHttpURI(String s, boolean checkRaw) {
+        return encode(s, unsafeCharactersHttp, checkRaw);
+    }
+
+    private static List<Pair> checkRAW(String s) {
+        Matcher matcher = RAW_PATTERN.matcher(s);
+        List<Pair> answer = new ArrayList<Pair>();
+        // Check all occurrences
+        while (matcher.find()) {
+            answer.add(new Pair(matcher.start(), matcher.end()));
+        }
+        return answer;
+    }
+
+    private static boolean isRaw(int index, List<Pair> pairs) {
+        for (Pair pair : pairs) {
+            if (index < pair.left) {
+                return false;
+            } else {
+                if (index >= pair.left) {
+                    if (index <= pair.right) {
+                        return true;
+                    } else {
+                        continue;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    private static class Pair {
+        int left;
+        int right;
+
+        Pair(int left, int right) {
+            this.left = left;
+            this.right = right;
+        }
+    }
+
+    // Just skip the encode for isRAW part
+    public static String encode(String s, BitSet unsafeCharacters, boolean checkRaw) {
+        List<Pair> rawPairs;
+        if (checkRaw) {
+            rawPairs = checkRAW(s);
+        } else {
+            rawPairs = new ArrayList<Pair>();
+        }
+
+        int n = s == null ? 0 : s.length();
+        if (n == 0) {
+            return s;
+        }
+
+        // First check whether we actually need to encode
+        char chars[] = s.toCharArray();
+        for (int i = 0;;) {
+            // just deal with the ascii character
+            if (chars[i] > 0 && chars[i] < 128) {
+                if (unsafeCharacters.get(chars[i])) {
+                    break;
+                }
+            }
+            if (++i >= chars.length) {
+                return s;
+            }
+        }
+
+        // okay there are some unsafe characters so we do need to encode
+        // see details at: http://en.wikipedia.org/wiki/Url_encode
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < chars.length; i++) {
+            char ch = chars[i];
+            if (ch > 0 && ch < 128 && unsafeCharacters.get(ch)) {
+                // special for % sign as it may be a decimal encoded value
+                if (ch == '%') {
+                    char next = i + 1 < chars.length ? chars[i + 1] : ' ';
+                    char next2 = i + 2 < chars.length ? chars[i + 2] : ' ';
+
+                    if (isHexDigit(next) && isHexDigit(next2) && !isRaw(i, rawPairs)) {
+                        // its already encoded (decimal encoded) so just append as is
+                        sb.append(ch);
+                    } else {
+                        // must escape then, as its an unsafe character
+                        appendEscape(sb, (byte) ch);
+                    }
+                } else {
+                    // must escape then, as its an unsafe character
+                    appendEscape(sb, (byte) ch);
+                }
+            } else {
+                sb.append(ch);
+            }
+        }
+        return sb.toString();
+    }
+
+    private static void appendEscape(StringBuilder sb, byte b) {
+        sb.append('%');
+        sb.append(HEX_DIGITS[(b >> 4) & 0x0f]);
+        sb.append(HEX_DIGITS[(b >> 0) & 0x0f]);
+    }
+
+    private static boolean isHexDigit(char ch) {
+        for (char hex : HEX_DIGITS) {
+            if (hex == ch) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/package.html
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/package.html b/camel-core/src/main/java/org/apache/camel/runtimecatalog/package.html
new file mode 100644
index 0000000..2f15a04
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/package.html
@@ -0,0 +1,25 @@
+<!--
+    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.
+-->
+<html>
+<head>
+</head>
+<body>
+
+Runtime Camel Catalog
+
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/util/EndpointHelper.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/util/EndpointHelper.java b/camel-core/src/main/java/org/apache/camel/util/EndpointHelper.java
index fd22f55..a32c109 100644
--- a/camel-core/src/main/java/org/apache/camel/util/EndpointHelper.java
+++ b/camel-core/src/main/java/org/apache/camel/util/EndpointHelper.java
@@ -37,8 +37,8 @@ import org.apache.camel.PollingConsumer;
 import org.apache.camel.Processor;
 import org.apache.camel.ResolveEndpointFailedException;
 import org.apache.camel.Route;
-import org.apache.camel.catalog.DefaultRuntimeCamelCatalog;
-import org.apache.camel.catalog.RuntimeCamelCatalog;
+import org.apache.camel.runtimecatalog.DefaultRuntimeCamelCatalog;
+import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
 import org.apache.camel.spi.BrowsableEndpoint;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -523,7 +523,7 @@ public final class EndpointHelper {
      * @param uri          the endpoint uri
      * @return a map for each option in the uri with the corresponding information from the json
      * @throws Exception is thrown in case of error
-     * @deprecated use {@link org.apache.camel.catalog.RuntimeCamelCatalog#endpointProperties(String)}
+     * @deprecated use {@link org.apache.camel.runtimecatalog.RuntimeCamelCatalog#endpointProperties(String)}
      */
     @Deprecated
     public static Map<String, Object> endpointProperties(CamelContext camelContext, String uri) throws Exception {

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/test/java/org/apache/camel/catalog/AbstractCamelCatalogTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/catalog/AbstractCamelCatalogTest.java b/camel-core/src/test/java/org/apache/camel/catalog/AbstractCamelCatalogTest.java
deleted file mode 100644
index ed7e997..0000000
--- a/camel-core/src/test/java/org/apache/camel/catalog/AbstractCamelCatalogTest.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/**
- * 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.catalog;
-
-import java.net.URISyntaxException;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.mock;
-import static org.easymock.EasyMock.replay;
-import static org.junit.Assert.assertEquals;
-
-public class AbstractCamelCatalogTest {
-
-    AbstractCamelCatalog catalog = new AbstractCamelCatalog() {
-    };
-
-    JSonSchemaResolver resolver;
-
-    @Before
-    public void setupMockCatalog() {
-        resolver = mock(JSonSchemaResolver.class);
-
-        catalog.setJSonSchemaResolver(resolver);
-    }
-
-    @Test
-    public void shouldConstructEndpointUris() throws URISyntaxException {
-        expect(resolver.getComponentJSonSchema("comp")).andReturn("{\n"//
-            + "  \"component\": {\n"//
-            + "    \"syntax\": \"comp:param1:param2\"\n"//
-            + "  }\n"//
-            + "}");
-
-        replay(resolver);
-
-        final Map<String, String> properties = new HashMap<>();
-        properties.put("param1", "value1");
-        properties.put("param2", "value2");
-        properties.put("param3", "value3");
-
-        final String endpointUri = catalog.doAsEndpointUri("comp", properties, "&", false);
-
-        assertEquals("comp:value1:value2?param3=value3", endpointUri);
-    }
-
-    @Test
-    public void shouldConstructEndpointUrisWithPropertyPlaceholders() throws URISyntaxException {
-        expect(resolver.getComponentJSonSchema("comp")).andReturn("{\n"//
-            + "  \"component\": {\n"//
-            + "    \"syntax\": \"comp:param1:param2\"\n"//
-            + "  }\n"//
-            + "}");
-
-        replay(resolver);
-
-        final Map<String, String> properties = new HashMap<>();
-        properties.put("param1", "{{prop1}}");
-        properties.put("param2", "{{prop2}}");
-        properties.put("param3", "{{prop3}}");
-
-        final String endpointUri = catalog.doAsEndpointUri("comp", properties, "&", false);
-
-        assertEquals("comp:{{prop1}}:{{prop2}}?param3={{prop3}}", endpointUri);
-    }
-
-    @Test
-    public void shouldConstructEndpointUrisWhenValuesContainTokens() throws URISyntaxException {
-        expect(resolver.getComponentJSonSchema("comp")).andReturn("{\n"//
-            + "  \"component\": {\n"//
-            + "    \"syntax\": \"comp:param1:param2\"\n"//
-            + "  }\n"//
-            + "}");
-
-        replay(resolver);
-
-        final Map<String, String> properties = new HashMap<>();
-        properties.put("param1", "{value1}");
-        properties.put("param2", "/value2/");
-        properties.put("param3", "/value3/{param}");
-
-        final String endpointUri = catalog.doAsEndpointUri("comp", properties, "&", false);
-
-        assertEquals("comp:{value1}:/value2/?param3=/value3/{param}", endpointUri);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/test/java/org/apache/camel/catalog/RuntimeCamelCatalogTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/catalog/RuntimeCamelCatalogTest.java b/camel-core/src/test/java/org/apache/camel/catalog/RuntimeCamelCatalogTest.java
deleted file mode 100644
index 78e51a2..0000000
--- a/camel-core/src/test/java/org/apache/camel/catalog/RuntimeCamelCatalogTest.java
+++ /dev/null
@@ -1,393 +0,0 @@
-/**
- * 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.catalog;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.camel.impl.DefaultCamelContext;
-import org.junit.BeforeClass;
-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;
-
-public class RuntimeCamelCatalogTest {
-
-    static RuntimeCamelCatalog catalog;
-
-    private static final Logger LOG = LoggerFactory.getLogger(RuntimeCamelCatalogTest.class);
-
-    @BeforeClass
-    public static void createCamelCatalog() {
-        catalog = new DefaultRuntimeCamelCatalog(new DefaultCamelContext());
-    }
-
-    @Test
-    public void testFromCamelContext() throws Exception {
-        String schema = new DefaultCamelContext().getRuntimeCamelCatalog().modelJSonSchema("choice");
-        assertNotNull(schema);
-    }
-
-    @Test
-    public void testJsonSchema() throws Exception {
-        String schema = catalog.modelJSonSchema("aggregate");
-        assertNotNull(schema);
-
-        // lets make it possible to find bean/method using both names
-        schema = catalog.modelJSonSchema("method");
-        assertNotNull(schema);
-        schema = catalog.modelJSonSchema("bean");
-        assertNotNull(schema);
-    }
-
-    @Test
-    public void testAsEndpointUriMapFile() throws Exception {
-        Map<String, String> map = new HashMap<String, String>();
-        map.put("directoryName", "src/data/inbox");
-        map.put("noop", "true");
-        map.put("delay", "5000");
-
-        String uri = catalog.asEndpointUri("file", map, true);
-        assertEquals("file:src/data/inbox?delay=5000&noop=true", uri);
-
-        String uri2 = catalog.asEndpointUriXml("file", map, true);
-        assertEquals("file:src/data/inbox?delay=5000&amp;noop=true", uri2);
-    }
-
-    @Test
-    public void testAsEndpointUriTimer() throws Exception {
-        Map<String, String> map = new HashMap<String, String>();
-        map.put("timerName", "foo");
-        map.put("period", "5000");
-
-        String uri = catalog.asEndpointUri("timer", map, true);
-        assertEquals("timer:foo?period=5000", uri);
-    }
-
-    @Test
-    public void testAsEndpointUriPropertiesPlaceholders() throws Exception {
-        Map<String, String> map = new HashMap<String, String>();
-        map.put("timerName", "foo");
-        map.put("period", "{{howoften}}");
-        map.put("repeatCount", "5");
-
-        String uri = catalog.asEndpointUri("timer", map, true);
-        assertEquals("timer:foo?period=%7B%7Bhowoften%7D%7D&repeatCount=5", uri);
-
-        uri = catalog.asEndpointUri("timer", map, false);
-        assertEquals("timer:foo?period={{howoften}}&repeatCount=5", uri);
-    }
-
-    @Test
-    public void testAsEndpointUriBeanLookup() throws Exception {
-        Map<String, String> map = new HashMap<String, String>();
-        map.put("resourceUri", "foo.xslt");
-        map.put("converter", "#myConverter");
-
-        String uri = catalog.asEndpointUri("xslt", map, true);
-        assertEquals("xslt:foo.xslt?converter=%23myConverter", uri);
-
-        uri = catalog.asEndpointUri("xslt", map, false);
-        assertEquals("xslt:foo.xslt?converter=#myConverter", uri);
-    }
-
-    @Test
-    public void testEndpointPropertiesPlaceholders() throws Exception {
-        Map<String, String> map = catalog.endpointProperties("timer:foo?period={{howoften}}&repeatCount=5");
-        assertNotNull(map);
-        assertEquals(3, map.size());
-
-        assertEquals("foo", map.get("timerName"));
-        assertEquals("{{howoften}}", map.get("period"));
-        assertEquals("5", map.get("repeatCount"));
-    }
-
-    @Test
-    public void testAsEndpointUriLog() throws Exception {
-        Map<String, String> map = new HashMap<String, String>();
-        map.put("loggerName", "foo");
-        map.put("loggerLevel", "WARN");
-        map.put("multiline", "true");
-        map.put("showAll", "true");
-        map.put("showBody", "false");
-        map.put("showBodyType", "false");
-        map.put("showExchangePattern", "false");
-        map.put("style", "Tab");
-
-        assertEquals("log:foo?loggerLevel=WARN&multiline=true&showAll=true&style=Tab", catalog.asEndpointUri("log", map, false));
-    }
-
-    @Test
-    public void testAsEndpointUriLogShort() throws Exception {
-        Map<String, String> map = new HashMap<String, String>();
-        map.put("loggerName", "foo");
-        map.put("loggerLevel", "DEBUG");
-
-        assertEquals("log:foo?loggerLevel=DEBUG", catalog.asEndpointUri("log", map, false));
-    }
-
-    @Test
-    public void testAsEndpointUriWithplaceholder() throws Exception {
-        Map<String, String> map = new HashMap<String, String>();
-        map.put("name", "foo");
-        map.put("blockWhenFull", "{{block}}");
-        assertEquals("seda:foo?blockWhenFull={{block}}", catalog.asEndpointUri("seda", map, false));
-    }
-
-    @Test
-    public void testEndpointPropertiesSedaRequired() throws Exception {
-        Map<String, String> map = catalog.endpointProperties("seda:foo");
-        assertNotNull(map);
-        assertEquals(1, map.size());
-
-        assertEquals("foo", map.get("name"));
-
-        map = catalog.endpointProperties("seda:foo?blockWhenFull=true");
-        assertNotNull(map);
-        assertEquals(2, map.size());
-
-        assertEquals("foo", map.get("name"));
-        assertEquals("true", map.get("blockWhenFull"));
-    }
-
-    @Test
-    public void validateProperties() throws Exception {
-        // valid
-        EndpointValidationResult result = catalog.validateEndpointProperties("log:mylog");
-        assertTrue(result.isSuccess());
-
-        // unknown
-        result = catalog.validateEndpointProperties("log:mylog?level=WARN&foo=bar");
-        assertFalse(result.isSuccess());
-        assertTrue(result.getUnknown().contains("foo"));
-        assertEquals(1, result.getNumberOfErrors());
-
-        // enum
-        result = catalog.validateEndpointProperties("seda:foo?waitForTaskToComplete=blah");
-        assertFalse(result.isSuccess());
-        assertEquals("blah", result.getInvalidEnum().get("waitForTaskToComplete"));
-        assertEquals(1, result.getNumberOfErrors());
-
-        // reference okay
-        result = catalog.validateEndpointProperties("seda:foo?queue=#queue");
-        assertTrue(result.isSuccess());
-        assertEquals(0, result.getNumberOfErrors());
-
-        // unknown component
-        result = catalog.validateEndpointProperties("foo:bar?me=you");
-        assertFalse(result.isSuccess());
-        assertTrue(result.getUnknownComponent().equals("foo"));
-        assertEquals(1, result.getNumberOfErrors());
-
-        // invalid boolean but default value
-        result = catalog.validateEndpointProperties("log:output?showAll=ggg");
-        assertFalse(result.isSuccess());
-        assertEquals("ggg", result.getInvalidBoolean().get("showAll"));
-        assertEquals(1, result.getNumberOfErrors());
-
-        // dataset
-        result = catalog.validateEndpointProperties("dataset:foo?minRate=50");
-        assertTrue(result.isSuccess());
-
-        // time pattern
-        result = catalog.validateEndpointProperties("timer://foo?fixedRate=true&delay=0&period=2s");
-        assertTrue(result.isSuccess());
-
-        // reference lookup
-        result = catalog.validateEndpointProperties("timer://foo?fixedRate=#fixed&delay=#myDelay");
-        assertTrue(result.isSuccess());
-
-        // optional consumer. prefix
-        result = catalog.validateEndpointProperties("file:inbox?consumer.delay=5000&consumer.greedy=true");
-        assertTrue(result.isSuccess());
-
-        // optional without consumer. prefix
-        result = catalog.validateEndpointProperties("file:inbox?delay=5000&greedy=true");
-        assertTrue(result.isSuccess());
-
-        // mixed optional without consumer. prefix
-        result = catalog.validateEndpointProperties("file:inbox?delay=5000&consumer.greedy=true");
-        assertTrue(result.isSuccess());
-
-        // prefix
-        result = catalog.validateEndpointProperties("file:inbox?delay=5000&scheduler.foo=123&scheduler.bar=456");
-        assertTrue(result.isSuccess());
-
-        // stub
-        result = catalog.validateEndpointProperties("stub:foo?me=123&you=456");
-        assertTrue(result.isSuccess());
-
-        // lenient on
-        result = catalog.validateEndpointProperties("dataformat:string:marshal?foo=bar");
-        assertTrue(result.isSuccess());
-
-        // lenient off
-        result = catalog.validateEndpointProperties("dataformat:string:marshal?foo=bar", true);
-        assertFalse(result.isSuccess());
-        assertTrue(result.getUnknown().contains("foo"));
-
-        // data format
-        result = catalog.validateEndpointProperties("dataformat:string:marshal?charset=utf-8", true);
-        assertTrue(result.isSuccess());
-
-        // incapable to parse
-        result = catalog.validateEndpointProperties("{{getFtpUrl}}?recursive=true");
-        assertFalse(result.isSuccess());
-        assertTrue(result.getIncapable() != null);
-    }
-
-    @Test
-    public void validatePropertiesSummary() throws Exception {
-        EndpointValidationResult result = catalog.validateEndpointProperties("yammer:MESSAGES?blah=yada&accessToken=aaa&consumerKey=&useJson=no&initialDelay=five&pollStrategy=myStrategy");
-        assertFalse(result.isSuccess());
-        String reason = result.summaryErrorMessage(true);
-        LOG.info(reason);
-
-        result = catalog.validateEndpointProperties("jms:unknown:myqueue");
-        assertFalse(result.isSuccess());
-        reason = result.summaryErrorMessage(false);
-        LOG.info(reason);
-    }
-
-    @Test
-    public void validateTimePattern() throws Exception {
-        assertTrue(catalog.validateTimePattern("0"));
-        assertTrue(catalog.validateTimePattern("500"));
-        assertTrue(catalog.validateTimePattern("10000"));
-        assertTrue(catalog.validateTimePattern("5s"));
-        assertTrue(catalog.validateTimePattern("5sec"));
-        assertTrue(catalog.validateTimePattern("5secs"));
-        assertTrue(catalog.validateTimePattern("3m"));
-        assertTrue(catalog.validateTimePattern("3min"));
-        assertTrue(catalog.validateTimePattern("3minutes"));
-        assertTrue(catalog.validateTimePattern("5m15s"));
-        assertTrue(catalog.validateTimePattern("1h"));
-        assertTrue(catalog.validateTimePattern("1hour"));
-        assertTrue(catalog.validateTimePattern("2hours"));
-
-        assertFalse(catalog.validateTimePattern("bla"));
-        assertFalse(catalog.validateTimePattern("2year"));
-        assertFalse(catalog.validateTimePattern("60darn"));
-    }
-
-    @Test
-    public void testEndpointComponentName() throws Exception {
-        String name = catalog.endpointComponentName("jms:queue:foo");
-        assertEquals("jms", name);
-    }
-
-    @Test
-    public void testSimpleExpression() throws Exception {
-        SimpleValidationResult result = catalog.validateSimpleExpression(null, "${body}");
-        assertTrue(result.isSuccess());
-        assertEquals("${body}", result.getSimple());
-
-        result = catalog.validateSimpleExpression(null, "${body");
-        assertFalse(result.isSuccess());
-        assertEquals("${body", result.getSimple());
-        LOG.info(result.getError());
-        assertTrue(result.getError().startsWith("expected symbol functionEnd but was eol at location 5"));
-        assertEquals("expected symbol functionEnd but was eol", result.getShortError());
-        assertEquals(5, result.getIndex());
-    }
-
-    @Test
-    public void testSimplePredicate() throws Exception {
-        SimpleValidationResult result = catalog.validateSimplePredicate(null, "${body} == 'abc'");
-        assertTrue(result.isSuccess());
-        assertEquals("${body} == 'abc'", result.getSimple());
-
-        result = catalog.validateSimplePredicate(null, "${body} > ${header.size");
-        assertFalse(result.isSuccess());
-        assertEquals("${body} > ${header.size", result.getSimple());
-        LOG.info(result.getError());
-        assertTrue(result.getError().startsWith("expected symbol functionEnd but was eol at location 22"));
-        assertEquals("expected symbol functionEnd but was eol", result.getShortError());
-        assertEquals(22, result.getIndex());
-    }
-
-    @Test
-    public void testSimplePredicatePlaceholder() throws Exception {
-        SimpleValidationResult result = catalog.validateSimplePredicate(null, "${body} contains '{{danger}}'");
-        assertTrue(result.isSuccess());
-        assertEquals("${body} contains '{{danger}}'", result.getSimple());
-
-        result = catalog.validateSimplePredicate(null, "${bdy} contains '{{danger}}'");
-        assertFalse(result.isSuccess());
-        assertEquals("${bdy} contains '{{danger}}'", result.getSimple());
-        LOG.info(result.getError());
-        assertTrue(result.getError().startsWith("Unknown function: bdy at location 0"));
-        assertTrue(result.getError().contains("'{{danger}}'"));
-        assertEquals("Unknown function: bdy", result.getShortError());
-        assertEquals(0, result.getIndex());
-    }
-
-    @Test
-    public void testValidateLanguage() throws Exception {
-        LanguageValidationResult result = catalog.validateLanguageExpression(null, "simple", "${body}");
-        assertTrue(result.isSuccess());
-        assertEquals("${body}", result.getText());
-
-        result = catalog.validateLanguageExpression(null, "header", "foo");
-        assertTrue(result.isSuccess());
-        assertEquals("foo", result.getText());
-
-        result = catalog.validateLanguagePredicate(null, "simple", "${body} > 10");
-        assertTrue(result.isSuccess());
-        assertEquals("${body} > 10", result.getText());
-
-        result = catalog.validateLanguagePredicate(null, "header", "bar");
-        assertTrue(result.isSuccess());
-        assertEquals("bar", result.getText());
-
-        result = catalog.validateLanguagePredicate(null, "foobar", "bar");
-        assertFalse(result.isSuccess());
-        assertEquals("Unknown language foobar", result.getError());
-    }
-
-    @Test
-    public void testValidateEndpointConsumerOnly() throws Exception {
-        String uri = "file:inbox?bufferSize=4096&readLock=changed&delete=true";
-        EndpointValidationResult result = catalog.validateEndpointProperties(uri, false, true, false);
-        assertTrue(result.isSuccess());
-
-        uri = "file:inbox?bufferSize=4096&readLock=changed&delete=true&fileExist=Append";
-        result = catalog.validateEndpointProperties(uri, false, true, false);
-        assertFalse(result.isSuccess());
-
-        assertEquals("fileExist", result.getNotConsumerOnly().iterator().next());
-    }
-
-    @Test
-    public void testValidateEndpointProducerOnly() throws Exception {
-        String uri = "file:outbox?bufferSize=4096&fileExist=Append";
-        EndpointValidationResult result = catalog.validateEndpointProperties(uri, false, false, true);
-        assertTrue(result.isSuccess());
-
-        uri = "file:outbox?bufferSize=4096&fileExist=Append&delete=true";
-        result = catalog.validateEndpointProperties(uri, false, false, true);
-        assertFalse(result.isSuccess());
-
-        assertEquals("delete", result.getNotProducerOnly().iterator().next());
-    }
-
-}


[2/6] camel git commit: Rename catalog to runtimecatalog to avoid clash with same package name in camel-catalog.

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/test/java/org/apache/camel/runtimecatalog/AbstractCamelCatalogTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/runtimecatalog/AbstractCamelCatalogTest.java b/camel-core/src/test/java/org/apache/camel/runtimecatalog/AbstractCamelCatalogTest.java
new file mode 100644
index 0000000..309fb8e
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/runtimecatalog/AbstractCamelCatalogTest.java
@@ -0,0 +1,104 @@
+/**
+ * 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;
+
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.mock;
+import static org.easymock.EasyMock.replay;
+import static org.junit.Assert.assertEquals;
+
+public class AbstractCamelCatalogTest {
+
+    AbstractCamelCatalog catalog = new AbstractCamelCatalog() {
+    };
+
+    JSonSchemaResolver resolver;
+
+    @Before
+    public void setupMockCatalog() {
+        resolver = mock(JSonSchemaResolver.class);
+
+        catalog.setJSonSchemaResolver(resolver);
+    }
+
+    @Test
+    public void shouldConstructEndpointUris() throws URISyntaxException {
+        expect(resolver.getComponentJSonSchema("comp")).andReturn("{\n"//
+            + "  \"component\": {\n"//
+            + "    \"syntax\": \"comp:param1:param2\"\n"//
+            + "  }\n"//
+            + "}");
+
+        replay(resolver);
+
+        final Map<String, String> properties = new HashMap<>();
+        properties.put("param1", "value1");
+        properties.put("param2", "value2");
+        properties.put("param3", "value3");
+
+        final String endpointUri = catalog.doAsEndpointUri("comp", properties, "&", false);
+
+        assertEquals("comp:value1:value2?param3=value3", endpointUri);
+    }
+
+    @Test
+    public void shouldConstructEndpointUrisWithPropertyPlaceholders() throws URISyntaxException {
+        expect(resolver.getComponentJSonSchema("comp")).andReturn("{\n"//
+            + "  \"component\": {\n"//
+            + "    \"syntax\": \"comp:param1:param2\"\n"//
+            + "  }\n"//
+            + "}");
+
+        replay(resolver);
+
+        final Map<String, String> properties = new HashMap<>();
+        properties.put("param1", "{{prop1}}");
+        properties.put("param2", "{{prop2}}");
+        properties.put("param3", "{{prop3}}");
+
+        final String endpointUri = catalog.doAsEndpointUri("comp", properties, "&", false);
+
+        assertEquals("comp:{{prop1}}:{{prop2}}?param3={{prop3}}", endpointUri);
+    }
+
+    @Test
+    public void shouldConstructEndpointUrisWhenValuesContainTokens() throws URISyntaxException {
+        expect(resolver.getComponentJSonSchema("comp")).andReturn("{\n"//
+            + "  \"component\": {\n"//
+            + "    \"syntax\": \"comp:param1:param2\"\n"//
+            + "  }\n"//
+            + "}");
+
+        replay(resolver);
+
+        final Map<String, String> properties = new HashMap<>();
+        properties.put("param1", "{value1}");
+        properties.put("param2", "/value2/");
+        properties.put("param3", "/value3/{param}");
+
+        final String endpointUri = catalog.doAsEndpointUri("comp", properties, "&", false);
+
+        assertEquals("comp:{value1}:/value2/?param3=/value3/{param}", endpointUri);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/test/java/org/apache/camel/runtimecatalog/RuntimeCamelCatalogTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/runtimecatalog/RuntimeCamelCatalogTest.java b/camel-core/src/test/java/org/apache/camel/runtimecatalog/RuntimeCamelCatalogTest.java
new file mode 100644
index 0000000..dfdd5c5
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/runtimecatalog/RuntimeCamelCatalogTest.java
@@ -0,0 +1,393 @@
+/**
+ * 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;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.impl.DefaultCamelContext;
+import org.junit.BeforeClass;
+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;
+
+public class RuntimeCamelCatalogTest {
+
+    static RuntimeCamelCatalog catalog;
+
+    private static final Logger LOG = LoggerFactory.getLogger(RuntimeCamelCatalogTest.class);
+
+    @BeforeClass
+    public static void createCamelCatalog() {
+        catalog = new DefaultRuntimeCamelCatalog(new DefaultCamelContext());
+    }
+
+    @Test
+    public void testFromCamelContext() throws Exception {
+        String schema = new DefaultCamelContext().getRuntimeCamelCatalog().modelJSonSchema("choice");
+        assertNotNull(schema);
+    }
+
+    @Test
+    public void testJsonSchema() throws Exception {
+        String schema = catalog.modelJSonSchema("aggregate");
+        assertNotNull(schema);
+
+        // lets make it possible to find bean/method using both names
+        schema = catalog.modelJSonSchema("method");
+        assertNotNull(schema);
+        schema = catalog.modelJSonSchema("bean");
+        assertNotNull(schema);
+    }
+
+    @Test
+    public void testAsEndpointUriMapFile() throws Exception {
+        Map<String, String> map = new HashMap<String, String>();
+        map.put("directoryName", "src/data/inbox");
+        map.put("noop", "true");
+        map.put("delay", "5000");
+
+        String uri = catalog.asEndpointUri("file", map, true);
+        assertEquals("file:src/data/inbox?delay=5000&noop=true", uri);
+
+        String uri2 = catalog.asEndpointUriXml("file", map, true);
+        assertEquals("file:src/data/inbox?delay=5000&amp;noop=true", uri2);
+    }
+
+    @Test
+    public void testAsEndpointUriTimer() throws Exception {
+        Map<String, String> map = new HashMap<String, String>();
+        map.put("timerName", "foo");
+        map.put("period", "5000");
+
+        String uri = catalog.asEndpointUri("timer", map, true);
+        assertEquals("timer:foo?period=5000", uri);
+    }
+
+    @Test
+    public void testAsEndpointUriPropertiesPlaceholders() throws Exception {
+        Map<String, String> map = new HashMap<String, String>();
+        map.put("timerName", "foo");
+        map.put("period", "{{howoften}}");
+        map.put("repeatCount", "5");
+
+        String uri = catalog.asEndpointUri("timer", map, true);
+        assertEquals("timer:foo?period=%7B%7Bhowoften%7D%7D&repeatCount=5", uri);
+
+        uri = catalog.asEndpointUri("timer", map, false);
+        assertEquals("timer:foo?period={{howoften}}&repeatCount=5", uri);
+    }
+
+    @Test
+    public void testAsEndpointUriBeanLookup() throws Exception {
+        Map<String, String> map = new HashMap<String, String>();
+        map.put("resourceUri", "foo.xslt");
+        map.put("converter", "#myConverter");
+
+        String uri = catalog.asEndpointUri("xslt", map, true);
+        assertEquals("xslt:foo.xslt?converter=%23myConverter", uri);
+
+        uri = catalog.asEndpointUri("xslt", map, false);
+        assertEquals("xslt:foo.xslt?converter=#myConverter", uri);
+    }
+
+    @Test
+    public void testEndpointPropertiesPlaceholders() throws Exception {
+        Map<String, String> map = catalog.endpointProperties("timer:foo?period={{howoften}}&repeatCount=5");
+        assertNotNull(map);
+        assertEquals(3, map.size());
+
+        assertEquals("foo", map.get("timerName"));
+        assertEquals("{{howoften}}", map.get("period"));
+        assertEquals("5", map.get("repeatCount"));
+    }
+
+    @Test
+    public void testAsEndpointUriLog() throws Exception {
+        Map<String, String> map = new HashMap<String, String>();
+        map.put("loggerName", "foo");
+        map.put("loggerLevel", "WARN");
+        map.put("multiline", "true");
+        map.put("showAll", "true");
+        map.put("showBody", "false");
+        map.put("showBodyType", "false");
+        map.put("showExchangePattern", "false");
+        map.put("style", "Tab");
+
+        assertEquals("log:foo?loggerLevel=WARN&multiline=true&showAll=true&style=Tab", catalog.asEndpointUri("log", map, false));
+    }
+
+    @Test
+    public void testAsEndpointUriLogShort() throws Exception {
+        Map<String, String> map = new HashMap<String, String>();
+        map.put("loggerName", "foo");
+        map.put("loggerLevel", "DEBUG");
+
+        assertEquals("log:foo?loggerLevel=DEBUG", catalog.asEndpointUri("log", map, false));
+    }
+
+    @Test
+    public void testAsEndpointUriWithplaceholder() throws Exception {
+        Map<String, String> map = new HashMap<String, String>();
+        map.put("name", "foo");
+        map.put("blockWhenFull", "{{block}}");
+        assertEquals("seda:foo?blockWhenFull={{block}}", catalog.asEndpointUri("seda", map, false));
+    }
+
+    @Test
+    public void testEndpointPropertiesSedaRequired() throws Exception {
+        Map<String, String> map = catalog.endpointProperties("seda:foo");
+        assertNotNull(map);
+        assertEquals(1, map.size());
+
+        assertEquals("foo", map.get("name"));
+
+        map = catalog.endpointProperties("seda:foo?blockWhenFull=true");
+        assertNotNull(map);
+        assertEquals(2, map.size());
+
+        assertEquals("foo", map.get("name"));
+        assertEquals("true", map.get("blockWhenFull"));
+    }
+
+    @Test
+    public void validateProperties() throws Exception {
+        // valid
+        EndpointValidationResult result = catalog.validateEndpointProperties("log:mylog");
+        assertTrue(result.isSuccess());
+
+        // unknown
+        result = catalog.validateEndpointProperties("log:mylog?level=WARN&foo=bar");
+        assertFalse(result.isSuccess());
+        assertTrue(result.getUnknown().contains("foo"));
+        assertEquals(1, result.getNumberOfErrors());
+
+        // enum
+        result = catalog.validateEndpointProperties("seda:foo?waitForTaskToComplete=blah");
+        assertFalse(result.isSuccess());
+        assertEquals("blah", result.getInvalidEnum().get("waitForTaskToComplete"));
+        assertEquals(1, result.getNumberOfErrors());
+
+        // reference okay
+        result = catalog.validateEndpointProperties("seda:foo?queue=#queue");
+        assertTrue(result.isSuccess());
+        assertEquals(0, result.getNumberOfErrors());
+
+        // unknown component
+        result = catalog.validateEndpointProperties("foo:bar?me=you");
+        assertFalse(result.isSuccess());
+        assertTrue(result.getUnknownComponent().equals("foo"));
+        assertEquals(1, result.getNumberOfErrors());
+
+        // invalid boolean but default value
+        result = catalog.validateEndpointProperties("log:output?showAll=ggg");
+        assertFalse(result.isSuccess());
+        assertEquals("ggg", result.getInvalidBoolean().get("showAll"));
+        assertEquals(1, result.getNumberOfErrors());
+
+        // dataset
+        result = catalog.validateEndpointProperties("dataset:foo?minRate=50");
+        assertTrue(result.isSuccess());
+
+        // time pattern
+        result = catalog.validateEndpointProperties("timer://foo?fixedRate=true&delay=0&period=2s");
+        assertTrue(result.isSuccess());
+
+        // reference lookup
+        result = catalog.validateEndpointProperties("timer://foo?fixedRate=#fixed&delay=#myDelay");
+        assertTrue(result.isSuccess());
+
+        // optional consumer. prefix
+        result = catalog.validateEndpointProperties("file:inbox?consumer.delay=5000&consumer.greedy=true");
+        assertTrue(result.isSuccess());
+
+        // optional without consumer. prefix
+        result = catalog.validateEndpointProperties("file:inbox?delay=5000&greedy=true");
+        assertTrue(result.isSuccess());
+
+        // mixed optional without consumer. prefix
+        result = catalog.validateEndpointProperties("file:inbox?delay=5000&consumer.greedy=true");
+        assertTrue(result.isSuccess());
+
+        // prefix
+        result = catalog.validateEndpointProperties("file:inbox?delay=5000&scheduler.foo=123&scheduler.bar=456");
+        assertTrue(result.isSuccess());
+
+        // stub
+        result = catalog.validateEndpointProperties("stub:foo?me=123&you=456");
+        assertTrue(result.isSuccess());
+
+        // lenient on
+        result = catalog.validateEndpointProperties("dataformat:string:marshal?foo=bar");
+        assertTrue(result.isSuccess());
+
+        // lenient off
+        result = catalog.validateEndpointProperties("dataformat:string:marshal?foo=bar", true);
+        assertFalse(result.isSuccess());
+        assertTrue(result.getUnknown().contains("foo"));
+
+        // data format
+        result = catalog.validateEndpointProperties("dataformat:string:marshal?charset=utf-8", true);
+        assertTrue(result.isSuccess());
+
+        // incapable to parse
+        result = catalog.validateEndpointProperties("{{getFtpUrl}}?recursive=true");
+        assertFalse(result.isSuccess());
+        assertTrue(result.getIncapable() != null);
+    }
+
+    @Test
+    public void validatePropertiesSummary() throws Exception {
+        EndpointValidationResult result = catalog.validateEndpointProperties("yammer:MESSAGES?blah=yada&accessToken=aaa&consumerKey=&useJson=no&initialDelay=five&pollStrategy=myStrategy");
+        assertFalse(result.isSuccess());
+        String reason = result.summaryErrorMessage(true);
+        LOG.info(reason);
+
+        result = catalog.validateEndpointProperties("jms:unknown:myqueue");
+        assertFalse(result.isSuccess());
+        reason = result.summaryErrorMessage(false);
+        LOG.info(reason);
+    }
+
+    @Test
+    public void validateTimePattern() throws Exception {
+        assertTrue(catalog.validateTimePattern("0"));
+        assertTrue(catalog.validateTimePattern("500"));
+        assertTrue(catalog.validateTimePattern("10000"));
+        assertTrue(catalog.validateTimePattern("5s"));
+        assertTrue(catalog.validateTimePattern("5sec"));
+        assertTrue(catalog.validateTimePattern("5secs"));
+        assertTrue(catalog.validateTimePattern("3m"));
+        assertTrue(catalog.validateTimePattern("3min"));
+        assertTrue(catalog.validateTimePattern("3minutes"));
+        assertTrue(catalog.validateTimePattern("5m15s"));
+        assertTrue(catalog.validateTimePattern("1h"));
+        assertTrue(catalog.validateTimePattern("1hour"));
+        assertTrue(catalog.validateTimePattern("2hours"));
+
+        assertFalse(catalog.validateTimePattern("bla"));
+        assertFalse(catalog.validateTimePattern("2year"));
+        assertFalse(catalog.validateTimePattern("60darn"));
+    }
+
+    @Test
+    public void testEndpointComponentName() throws Exception {
+        String name = catalog.endpointComponentName("jms:queue:foo");
+        assertEquals("jms", name);
+    }
+
+    @Test
+    public void testSimpleExpression() throws Exception {
+        SimpleValidationResult result = catalog.validateSimpleExpression(null, "${body}");
+        assertTrue(result.isSuccess());
+        assertEquals("${body}", result.getSimple());
+
+        result = catalog.validateSimpleExpression(null, "${body");
+        assertFalse(result.isSuccess());
+        assertEquals("${body", result.getSimple());
+        LOG.info(result.getError());
+        assertTrue(result.getError().startsWith("expected symbol functionEnd but was eol at location 5"));
+        assertEquals("expected symbol functionEnd but was eol", result.getShortError());
+        assertEquals(5, result.getIndex());
+    }
+
+    @Test
+    public void testSimplePredicate() throws Exception {
+        SimpleValidationResult result = catalog.validateSimplePredicate(null, "${body} == 'abc'");
+        assertTrue(result.isSuccess());
+        assertEquals("${body} == 'abc'", result.getSimple());
+
+        result = catalog.validateSimplePredicate(null, "${body} > ${header.size");
+        assertFalse(result.isSuccess());
+        assertEquals("${body} > ${header.size", result.getSimple());
+        LOG.info(result.getError());
+        assertTrue(result.getError().startsWith("expected symbol functionEnd but was eol at location 22"));
+        assertEquals("expected symbol functionEnd but was eol", result.getShortError());
+        assertEquals(22, result.getIndex());
+    }
+
+    @Test
+    public void testSimplePredicatePlaceholder() throws Exception {
+        SimpleValidationResult result = catalog.validateSimplePredicate(null, "${body} contains '{{danger}}'");
+        assertTrue(result.isSuccess());
+        assertEquals("${body} contains '{{danger}}'", result.getSimple());
+
+        result = catalog.validateSimplePredicate(null, "${bdy} contains '{{danger}}'");
+        assertFalse(result.isSuccess());
+        assertEquals("${bdy} contains '{{danger}}'", result.getSimple());
+        LOG.info(result.getError());
+        assertTrue(result.getError().startsWith("Unknown function: bdy at location 0"));
+        assertTrue(result.getError().contains("'{{danger}}'"));
+        assertEquals("Unknown function: bdy", result.getShortError());
+        assertEquals(0, result.getIndex());
+    }
+
+    @Test
+    public void testValidateLanguage() throws Exception {
+        LanguageValidationResult result = catalog.validateLanguageExpression(null, "simple", "${body}");
+        assertTrue(result.isSuccess());
+        assertEquals("${body}", result.getText());
+
+        result = catalog.validateLanguageExpression(null, "header", "foo");
+        assertTrue(result.isSuccess());
+        assertEquals("foo", result.getText());
+
+        result = catalog.validateLanguagePredicate(null, "simple", "${body} > 10");
+        assertTrue(result.isSuccess());
+        assertEquals("${body} > 10", result.getText());
+
+        result = catalog.validateLanguagePredicate(null, "header", "bar");
+        assertTrue(result.isSuccess());
+        assertEquals("bar", result.getText());
+
+        result = catalog.validateLanguagePredicate(null, "foobar", "bar");
+        assertFalse(result.isSuccess());
+        assertEquals("Unknown language foobar", result.getError());
+    }
+
+    @Test
+    public void testValidateEndpointConsumerOnly() throws Exception {
+        String uri = "file:inbox?bufferSize=4096&readLock=changed&delete=true";
+        EndpointValidationResult result = catalog.validateEndpointProperties(uri, false, true, false);
+        assertTrue(result.isSuccess());
+
+        uri = "file:inbox?bufferSize=4096&readLock=changed&delete=true&fileExist=Append";
+        result = catalog.validateEndpointProperties(uri, false, true, false);
+        assertFalse(result.isSuccess());
+
+        assertEquals("fileExist", result.getNotConsumerOnly().iterator().next());
+    }
+
+    @Test
+    public void testValidateEndpointProducerOnly() throws Exception {
+        String uri = "file:outbox?bufferSize=4096&fileExist=Append";
+        EndpointValidationResult result = catalog.validateEndpointProperties(uri, false, false, true);
+        assertTrue(result.isSuccess());
+
+        uri = "file:outbox?bufferSize=4096&fileExist=Append&delete=true";
+        result = catalog.validateEndpointProperties(uri, false, false, true);
+        assertFalse(result.isSuccess());
+
+        assertEquals("delete", result.getNotProducerOnly().iterator().next());
+    }
+
+}


[4/6] camel git commit: Rename catalog to runtimecatalog to avoid clash with same package name in camel-catalog.

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/AbstractCamelCatalog.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/AbstractCamelCatalog.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/AbstractCamelCatalog.java
new file mode 100644
index 0000000..0420708
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/AbstractCamelCatalog.java
@@ -0,0 +1,1294 @@
+/**
+ * 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;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static org.apache.camel.runtimecatalog.CatalogHelper.after;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.getNames;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.getPropertyDefaultValue;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.getPropertyEnum;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.getPropertyKind;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.getPropertyNameFromNameWithPrefix;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.getPropertyPrefix;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.getRow;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.isComponentConsumerOnly;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.isComponentLenientProperties;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.isComponentProducerOnly;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.isPropertyBoolean;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.isPropertyConsumerOnly;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.isPropertyInteger;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.isPropertyMultiValue;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.isPropertyNumber;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.isPropertyObject;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.isPropertyProducerOnly;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.isPropertyRequired;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.stripOptionalPrefixFromName;
+import static org.apache.camel.runtimecatalog.URISupport.createQueryString;
+import static org.apache.camel.runtimecatalog.URISupport.isEmpty;
+import static org.apache.camel.runtimecatalog.URISupport.normalizeUri;
+import static org.apache.camel.runtimecatalog.URISupport.stripQuery;
+
+/**
+ * Base class for both the runtime RuntimeCamelCatalog from camel-core and the complete CamelCatalog from camel-catalog.
+ */
+public abstract class AbstractCamelCatalog {
+
+    // CHECKSTYLE:OFF
+
+    private static final Pattern SYNTAX_PATTERN = Pattern.compile("(\\w+)");
+
+    private SuggestionStrategy suggestionStrategy;
+    private JSonSchemaResolver jsonSchemaResolver;
+
+    public SuggestionStrategy getSuggestionStrategy() {
+        return suggestionStrategy;
+    }
+
+    public void setSuggestionStrategy(SuggestionStrategy suggestionStrategy) {
+        this.suggestionStrategy = suggestionStrategy;
+    }
+
+    public JSonSchemaResolver getJSonSchemaResolver() {
+        return jsonSchemaResolver;
+    }
+
+    public void setJSonSchemaResolver(JSonSchemaResolver resolver) {
+        this.jsonSchemaResolver = resolver;
+    }
+
+    public boolean validateTimePattern(String pattern) {
+        return validateInteger(pattern);
+    }
+
+    public EndpointValidationResult validateEndpointProperties(String uri) {
+        return validateEndpointProperties(uri, false, false, false);
+    }
+
+    public EndpointValidationResult validateEndpointProperties(String uri, boolean ignoreLenientProperties) {
+        return validateEndpointProperties(uri, ignoreLenientProperties, false, false);
+    }
+
+    public EndpointValidationResult validateProperties(String scheme, Map<String, String> properties) {
+        EndpointValidationResult result = new EndpointValidationResult(scheme);
+
+        String json = jsonSchemaResolver.getComponentJSonSchema(scheme);
+        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
+        List<Map<String, String>> componentProps = JSonSchemaHelper.parseJsonSchema("componentProperties", json, true);
+
+        // endpoint options have higher priority so remove those from component
+        // that may clash
+        componentProps.stream()
+            .filter(c -> rows.stream().noneMatch(e -> Objects.equals(e.get("name"), c.get("name"))))
+            .forEach(rows::add);
+
+        boolean lenient = Boolean.getBoolean(properties.getOrDefault("lenient", "false"));
+
+        // the dataformat component refers to a data format so lets add the properties for the selected
+        // data format to the list of rows
+        if ("dataformat".equals(scheme)) {
+            String dfName = properties.get("name");
+            if (dfName != null) {
+                String dfJson = jsonSchemaResolver.getDataFormatJSonSchema(dfName);
+                List<Map<String, String>> dfRows = JSonSchemaHelper.parseJsonSchema("properties", dfJson, true);
+                if (dfRows != null && !dfRows.isEmpty()) {
+                    rows.addAll(dfRows);
+                }
+            }
+        }
+
+        for (Map.Entry<String, String> property : properties.entrySet()) {
+            String value = property.getValue();
+            String originalName = property.getKey();
+            String name = property.getKey();
+            // the name may be using an optional prefix, so lets strip that because the options
+            // in the schema are listed without the prefix
+            name = stripOptionalPrefixFromName(rows, name);
+            // the name may be using a prefix, so lets see if we can find the real property name
+            String propertyName = getPropertyNameFromNameWithPrefix(rows, name);
+            if (propertyName != null) {
+                name = propertyName;
+            }
+
+            String prefix = getPropertyPrefix(rows, name);
+            String kind = getPropertyKind(rows, name);
+            boolean namePlaceholder = name.startsWith("{{") && name.endsWith("}}");
+            boolean valuePlaceholder = value.startsWith("{{") || value.startsWith("${") || value.startsWith("$simple{");
+            boolean lookup = value.startsWith("#") && value.length() > 1;
+            // we cannot evaluate multi values as strict as the others, as we don't know their expected types
+            boolean multiValue = prefix != null && originalName.startsWith(prefix) && isPropertyMultiValue(rows, name);
+
+            Map<String, String> row = getRow(rows, name);
+            if (row == null) {
+                // unknown option
+
+                // only add as error if the component is not lenient properties, or not stub component
+                // and the name is not a property placeholder for one or more values
+                if (!namePlaceholder && !"stub".equals(scheme)) {
+                    if (lenient) {
+                        // as if we are lenient then the option is a dynamic extra option which we cannot validate
+                        result.addLenient(name);
+                    } else {
+                        // its unknown
+                        result.addUnknown(name);
+                        if (suggestionStrategy != null) {
+                            String[] suggestions = suggestionStrategy.suggestEndpointOptions(getNames(rows), name);
+                            if (suggestions != null) {
+                                result.addUnknownSuggestions(name, suggestions);
+                            }
+                        }
+                    }
+                }
+            } else {
+                /* TODO: we may need to add something in the properties to know if they are related to a producer or consumer
+                if ("parameter".equals(kind)) {
+                    // consumer only or producer only mode for parameters
+                    if (consumerOnly) {
+                        boolean producer = isPropertyProducerOnly(rows, name);
+                        if (producer) {
+                            // the option is only for producer so you cannot use it in consumer mode
+                            result.addNotConsumerOnly(name);
+                        }
+                    } else if (producerOnly) {
+                        boolean consumer = isPropertyConsumerOnly(rows, name);
+                        if (consumer) {
+                            // the option is only for consumer so you cannot use it in producer mode
+                            result.addNotProducerOnly(name);
+                        }
+                    }
+                }
+                */
+
+                // default value
+                String defaultValue = getPropertyDefaultValue(rows, name);
+                if (defaultValue != null) {
+                    result.addDefaultValue(name, defaultValue);
+                }
+
+                // is required but the value is empty
+                boolean required = isPropertyRequired(rows, name);
+                if (required && isEmpty(value)) {
+                    result.addRequired(name);
+                }
+
+                // is enum but the value is not within the enum range
+                // but we can only check if the value is not a placeholder
+                String enums = getPropertyEnum(rows, name);
+                if (!multiValue && !valuePlaceholder && !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(name, value);
+                        result.addInvalidEnumChoices(name, 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(name, suggestions);
+                            }
+                        }
+
+                    }
+                }
+
+                // is reference lookup of bean (not applicable for @UriPath, enums, or multi-valued)
+                if (!multiValue && enums == null && !"path".equals(kind) && isPropertyObject(rows, name)) {
+                    // must start with # and be at least 2 characters
+                    if (!value.startsWith("#") || value.length() <= 1) {
+                        result.addInvalidReference(name, value);
+                    }
+                }
+
+                // is boolean
+                if (!multiValue && !valuePlaceholder && !lookup && isPropertyBoolean(rows, name)) {
+                    // value must be a boolean
+                    boolean bool = "true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value);
+                    if (!bool) {
+                        result.addInvalidBoolean(name, value);
+                    }
+                }
+
+                // is integer
+                if (!multiValue && !valuePlaceholder && !lookup && isPropertyInteger(rows, name)) {
+                    // value must be an integer
+                    boolean valid = validateInteger(value);
+                    if (!valid) {
+                        result.addInvalidInteger(name, value);
+                    }
+                }
+
+                // is number
+                if (!multiValue && !valuePlaceholder && !lookup && isPropertyNumber(rows, name)) {
+                    // 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(name, value);
+                    }
+                }
+            }
+        }
+
+        // now check if all required values are there, and that a default value does not exists
+        for (Map<String, String> row : rows) {
+            String name = row.get("name");
+            boolean required = isPropertyRequired(rows, name);
+            if (required) {
+                String value = properties.get(name);
+                if (isEmpty(value)) {
+                    value = getPropertyDefaultValue(rows, name);
+                }
+                if (isEmpty(value)) {
+                    result.addRequired(name);
+                }
+            }
+        }
+
+        return result;
+    }
+
+    public EndpointValidationResult validateEndpointProperties(String uri, boolean ignoreLenientProperties, boolean consumerOnly, boolean producerOnly) {
+        EndpointValidationResult result = new EndpointValidationResult(uri);
+
+        Map<String, String> properties;
+        List<Map<String, String>> rows;
+        boolean lenientProperties;
+        String scheme;
+
+        try {
+            String json = null;
+
+            // parse the uri
+            URI u = normalizeUri(uri);
+            scheme = u.getScheme();
+
+            if (scheme != null) {
+                json = jsonSchemaResolver.getComponentJSonSchema(scheme);
+            }
+            if (json == null) {
+                // if the uri starts with a placeholder then we are also incapable of parsing it as we wasn't able to resolve the component name
+                if (uri.startsWith("{{")) {
+                    result.addIncapable(uri);
+                } else if (scheme != null) {
+                    result.addUnknownComponent(scheme);
+                } else {
+                    result.addUnknownComponent(uri);
+                }
+                return result;
+            }
+
+            rows = JSonSchemaHelper.parseJsonSchema("component", json, false);
+
+            // is the component capable of both consumer and producer?
+            boolean canConsumeAndProduce = false;
+            if (!isComponentConsumerOnly(rows) && !isComponentProducerOnly(rows)) {
+                canConsumeAndProduce = true;
+            }
+
+            if (canConsumeAndProduce && consumerOnly) {
+                // lenient properties is not support in consumer only mode if the component can do both of them
+                lenientProperties = false;
+            } else {
+                // only enable lenient properties if we should not ignore
+                lenientProperties = !ignoreLenientProperties && isComponentLenientProperties(rows);
+            }
+            rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
+            properties = endpointProperties(uri);
+        } catch (URISyntaxException e) {
+            if (uri.startsWith("{{")) {
+                // if the uri starts with a placeholder then we are also incapable of parsing it as we wasn't able to resolve the component name
+                result.addIncapable(uri);
+            } else {
+                result.addSyntaxError(e.getMessage());
+            }
+
+            return result;
+        }
+
+        // the dataformat component refers to a data format so lets add the properties for the selected
+        // data format to the list of rows
+        if ("dataformat".equals(scheme)) {
+            String dfName = properties.get("name");
+            if (dfName != null) {
+                String dfJson = jsonSchemaResolver.getDataFormatJSonSchema(dfName);
+                List<Map<String, String>> dfRows = JSonSchemaHelper.parseJsonSchema("properties", dfJson, true);
+                if (dfRows != null && !dfRows.isEmpty()) {
+                    rows.addAll(dfRows);
+                }
+            }
+        }
+
+        for (Map.Entry<String, String> property : properties.entrySet()) {
+            String value = property.getValue();
+            String originalName = property.getKey();
+            String name = property.getKey();
+            // the name may be using an optional prefix, so lets strip that because the options
+            // in the schema are listed without the prefix
+            name = stripOptionalPrefixFromName(rows, name);
+            // the name may be using a prefix, so lets see if we can find the real property name
+            String propertyName = getPropertyNameFromNameWithPrefix(rows, name);
+            if (propertyName != null) {
+                name = propertyName;
+            }
+
+            String prefix = getPropertyPrefix(rows, name);
+            String kind = getPropertyKind(rows, name);
+            boolean namePlaceholder = name.startsWith("{{") && name.endsWith("}}");
+            boolean valuePlaceholder = value.startsWith("{{") || value.startsWith("${") || value.startsWith("$simple{");
+            boolean lookup = value.startsWith("#") && value.length() > 1;
+            // we cannot evaluate multi values as strict as the others, as we don't know their expected types
+            boolean mulitValue = prefix != null && originalName.startsWith(prefix) && isPropertyMultiValue(rows, name);
+
+            Map<String, String> row = getRow(rows, name);
+            if (row == null) {
+                // unknown option
+
+                // only add as error if the component is not lenient properties, or not stub component
+                // and the name is not a property placeholder for one or more values
+                if (!namePlaceholder && !"stub".equals(scheme)) {
+                    if (lenientProperties) {
+                        // as if we are lenient then the option is a dynamic extra option which we cannot validate
+                        result.addLenient(name);
+                    } else {
+                        // its unknown
+                        result.addUnknown(name);
+                        if (suggestionStrategy != null) {
+                            String[] suggestions = suggestionStrategy.suggestEndpointOptions(getNames(rows), name);
+                            if (suggestions != null) {
+                                result.addUnknownSuggestions(name, suggestions);
+                            }
+                        }
+                    }
+                }
+            } else {
+                if ("parameter".equals(kind)) {
+                    // consumer only or producer only mode for parameters
+                    if (consumerOnly) {
+                        boolean producer = isPropertyProducerOnly(rows, name);
+                        if (producer) {
+                            // the option is only for producer so you cannot use it in consumer mode
+                            result.addNotConsumerOnly(name);
+                        }
+                    } else if (producerOnly) {
+                        boolean consumer = isPropertyConsumerOnly(rows, name);
+                        if (consumer) {
+                            // the option is only for consumer so you cannot use it in producer mode
+                            result.addNotProducerOnly(name);
+                        }
+                    }
+                }
+
+                // default value
+                String defaultValue = getPropertyDefaultValue(rows, name);
+                if (defaultValue != null) {
+                    result.addDefaultValue(name, defaultValue);
+                }
+
+                // is required but the value is empty
+                boolean required = isPropertyRequired(rows, name);
+                if (required && isEmpty(value)) {
+                    result.addRequired(name);
+                }
+
+                // is enum but the value is not within the enum range
+                // but we can only check if the value is not a placeholder
+                String enums = getPropertyEnum(rows, name);
+                if (!mulitValue && !valuePlaceholder && !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(name, value);
+                        result.addInvalidEnumChoices(name, 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(name, suggestions);
+                            }
+                        }
+
+                    }
+                }
+
+                // is reference lookup of bean (not applicable for @UriPath, enums, or multi-valued)
+                if (!mulitValue && enums == null && !"path".equals(kind) && isPropertyObject(rows, name)) {
+                    // must start with # and be at least 2 characters
+                    if (!value.startsWith("#") || value.length() <= 1) {
+                        result.addInvalidReference(name, value);
+                    }
+                }
+
+                // is boolean
+                if (!mulitValue && !valuePlaceholder && !lookup && isPropertyBoolean(rows, name)) {
+                    // value must be a boolean
+                    boolean bool = "true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value);
+                    if (!bool) {
+                        result.addInvalidBoolean(name, value);
+                    }
+                }
+
+                // is integer
+                if (!mulitValue && !valuePlaceholder && !lookup && isPropertyInteger(rows, name)) {
+                    // value must be an integer
+                    boolean valid = validateInteger(value);
+                    if (!valid) {
+                        result.addInvalidInteger(name, value);
+                    }
+                }
+
+                // is number
+                if (!mulitValue && !valuePlaceholder && !lookup && isPropertyNumber(rows, name)) {
+                    // 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(name, value);
+                    }
+                }
+            }
+        }
+
+        // now check if all required values are there, and that a default value does not exists
+        for (Map<String, String> row : rows) {
+            String name = row.get("name");
+            boolean required = isPropertyRequired(rows, name);
+            if (required) {
+                String value = properties.get(name);
+                if (isEmpty(value)) {
+                    value = getPropertyDefaultValue(rows, name);
+                }
+                if (isEmpty(value)) {
+                    result.addRequired(name);
+                }
+            }
+        }
+
+        return result;
+    }
+
+    public Map<String, String> endpointProperties(String uri) throws URISyntaxException {
+        // need to normalize uri first
+        URI u = normalizeUri(uri);
+        String scheme = u.getScheme();
+
+        String json = jsonSchemaResolver.getComponentJSonSchema(scheme);
+        if (json == null) {
+            throw new IllegalArgumentException("Cannot find endpoint with scheme " + scheme);
+        }
+
+        // grab the syntax
+        String syntax = null;
+        String alternativeSyntax = null;
+        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("component", json, false);
+        for (Map<String, String> row : rows) {
+            if (row.containsKey("syntax")) {
+                syntax = row.get("syntax");
+            }
+            if (row.containsKey("alternativeSyntax")) {
+                alternativeSyntax = row.get("alternativeSyntax");
+            }
+        }
+        if (syntax == null) {
+            throw new IllegalArgumentException("Endpoint with scheme " + scheme + " has no syntax defined in the json schema");
+        }
+
+        // only if we support alternative syntax, and the uri contains the username and password in the authority
+        // part of the uri, then we would need some special logic to capture that information and strip those
+        // details from the uri, so we can continue parsing the uri using the normal syntax
+        Map<String, String> userInfoOptions = new LinkedHashMap<String, String>();
+        if (alternativeSyntax != null && alternativeSyntax.contains("@")) {
+            // clip the scheme from the syntax
+            alternativeSyntax = after(alternativeSyntax, ":");
+            // trim so only userinfo
+            int idx = alternativeSyntax.indexOf("@");
+            String fields = alternativeSyntax.substring(0, idx);
+            String[] names = fields.split(":");
+
+            // grab authority part and grab username and/or password
+            String authority = u.getAuthority();
+            if (authority != null && authority.contains("@")) {
+                String username = null;
+                String password = null;
+
+                // grab unserinfo part before @
+                String userInfo = authority.substring(0, authority.indexOf("@"));
+                String[] parts = userInfo.split(":");
+                if (parts.length == 2) {
+                    username = parts[0];
+                    password = parts[1];
+                } else {
+                    // only username
+                    username = userInfo;
+                }
+
+                // remember the username and/or password which we add later to the options
+                if (names.length == 2) {
+                    userInfoOptions.put(names[0], username);
+                    if (password != null) {
+                        // password is optional
+                        userInfoOptions.put(names[1], password);
+                    }
+                }
+            }
+        }
+
+        // clip the scheme from the syntax
+        syntax = after(syntax, ":");
+        // clip the scheme from the uri
+        uri = after(uri, ":");
+        String uriPath = stripQuery(uri);
+
+        // strip user info from uri path
+        if (!userInfoOptions.isEmpty()) {
+            int idx = uriPath.indexOf('@');
+            if (idx > -1) {
+                uriPath = uriPath.substring(idx + 1);
+            }
+        }
+
+        // strip double slash in the start
+        if (uriPath != null && uriPath.startsWith("//")) {
+            uriPath = uriPath.substring(2);
+        }
+
+        // parse the syntax and find the names of each option
+        Matcher matcher = SYNTAX_PATTERN.matcher(syntax);
+        List<String> word = new ArrayList<String>();
+        while (matcher.find()) {
+            String s = matcher.group(1);
+            if (!scheme.equals(s)) {
+                word.add(s);
+            }
+        }
+        // parse the syntax and find each token between each option
+        String[] tokens = SYNTAX_PATTERN.split(syntax);
+
+        // find the position where each option start/end
+        List<String> word2 = new ArrayList<String>();
+        int prev = 0;
+        int prevPath = 0;
+
+        // special for activemq/jms where the enum for destinationType causes a token issue as it includes a colon
+        // for 'temp:queue' and 'temp:topic' values
+        if ("activemq".equals(scheme) || "jms".equals(scheme)) {
+            if (uriPath.startsWith("temp:")) {
+                prevPath = 5;
+            }
+        }
+
+        for (String token : tokens) {
+            if (token.isEmpty()) {
+                continue;
+            }
+
+            // special for some tokens where :// can be used also, eg http://foo
+            int idx = -1;
+            int len = 0;
+            if (":".equals(token)) {
+                idx = uriPath.indexOf("://", prevPath);
+                len = 3;
+            }
+            if (idx == -1) {
+                idx = uriPath.indexOf(token, prevPath);
+                len = token.length();
+            }
+
+            if (idx > 0) {
+                String option = uriPath.substring(prev, idx);
+                word2.add(option);
+                prev = idx + len;
+                prevPath = prev;
+            }
+        }
+        // special for last or if we did not add anyone
+        if (prev > 0 || word2.isEmpty()) {
+            String option = uriPath.substring(prev);
+            word2.add(option);
+        }
+
+        rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
+
+        boolean defaultValueAdded = false;
+
+        // now parse the uri to know which part isw what
+        Map<String, String> options = new LinkedHashMap<String, String>();
+
+        // include the username and password from the userinfo section
+        if (!userInfoOptions.isEmpty()) {
+            options.putAll(userInfoOptions);
+        }
+
+        // word contains the syntax path elements
+        Iterator<String> it = word2.iterator();
+        for (int i = 0; i < word.size(); i++) {
+            String key = word.get(i);
+
+            boolean allOptions = word.size() == word2.size();
+            boolean required = isPropertyRequired(rows, key);
+            String defaultValue = getPropertyDefaultValue(rows, key);
+
+            // we have all options so no problem
+            if (allOptions) {
+                String value = it.next();
+                options.put(key, value);
+            } else {
+                // we have a little problem as we do not not have all options
+                if (!required) {
+                    String value = null;
+
+                    boolean last = i == word.size() - 1;
+                    if (last) {
+                        // if its the last value then use it instead of the default value
+                        value = it.hasNext() ? it.next() : null;
+                        if (value != null) {
+                            options.put(key, value);
+                        } else {
+                            value = defaultValue;
+                        }
+                    }
+                    if (value != null) {
+                        options.put(key, value);
+                        defaultValueAdded = true;
+                    }
+                } else {
+                    String value = it.hasNext() ? it.next() : null;
+                    if (value != null) {
+                        options.put(key, value);
+                    }
+                }
+            }
+        }
+
+        Map<String, String> answer = new LinkedHashMap<String, String>();
+
+        // remove all options which are using default values and are not required
+        for (Map.Entry<String, String> entry : options.entrySet()) {
+            String key = entry.getKey();
+            String value = entry.getValue();
+
+            if (defaultValueAdded) {
+                boolean required = isPropertyRequired(rows, key);
+                String defaultValue = getPropertyDefaultValue(rows, key);
+
+                if (!required && defaultValue != null) {
+                    if (defaultValue.equals(value)) {
+                        continue;
+                    }
+                }
+            }
+
+            // we should keep this in the answer
+            answer.put(key, value);
+        }
+
+        // now parse the uri parameters
+        Map<String, Object> parameters = URISupport.parseParameters(u);
+
+        // and covert the values to String so its JMX friendly
+        while (!parameters.isEmpty()) {
+            Map.Entry<String, Object> entry = parameters.entrySet().iterator().next();
+            String key = entry.getKey();
+            String value = entry.getValue() != null ? entry.getValue().toString() : "";
+
+            boolean multiValued = isPropertyMultiValue(rows, key);
+            if (multiValued) {
+                String prefix = getPropertyPrefix(rows, key);
+                // extra all the multi valued options
+                Map<String, Object> values = URISupport.extractProperties(parameters, prefix);
+                // build a string with the extra multi valued options with the prefix and & as separator
+                CollectionStringBuffer csb = new CollectionStringBuffer("&");
+                for (Map.Entry<String, Object> multi : values.entrySet()) {
+                    String line = prefix + multi.getKey() + "=" + (multi.getValue() != null ? multi.getValue().toString() : "");
+                    csb.append(line);
+                }
+                // append the extra multi-values to the existing (which contains the first multi value)
+                if (!csb.isEmpty()) {
+                    value = value + "&" + csb.toString();
+                }
+            }
+
+            answer.put(key, value);
+            // remove the parameter as we run in a while loop until no more parameters
+            parameters.remove(key);
+        }
+
+        return answer;
+    }
+
+    public Map<String, String> endpointLenientProperties(String uri) throws URISyntaxException {
+        // need to normalize uri first
+
+        // parse the uri
+        URI u = normalizeUri(uri);
+        String scheme = u.getScheme();
+
+        String json = jsonSchemaResolver.getComponentJSonSchema(scheme);
+        if (json == null) {
+            throw new IllegalArgumentException("Cannot find endpoint with scheme " + scheme);
+        }
+
+        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
+
+        // now parse the uri parameters
+        Map<String, Object> parameters = URISupport.parseParameters(u);
+
+        // all the known options
+        Set<String> names = getNames(rows);
+
+        Map<String, String> answer = new LinkedHashMap<>();
+
+        // and covert the values to String so its JMX friendly
+        parameters.forEach((k, v) -> {
+            String key = k;
+            String value = v != null ? v.toString() : "";
+
+            // is the key a prefix property
+            int dot = key.indexOf('.');
+            if (dot != -1) {
+                String prefix = key.substring(0, dot + 1); // include dot in prefix
+                String option = getPropertyNameFromNameWithPrefix(rows, prefix);
+                if (option == null || !isPropertyMultiValue(rows, option)) {
+                    answer.put(key, value);
+                }
+            } else if (!names.contains(key)) {
+                answer.put(key, value);
+            }
+        });
+
+        return answer;
+    }
+
+    public String endpointComponentName(String uri) {
+        if (uri != null) {
+            int idx = uri.indexOf(":");
+            if (idx > 0) {
+                return uri.substring(0, idx);
+            }
+        }
+        return null;
+    }
+
+    public String asEndpointUri(String scheme, String json, boolean encode) throws URISyntaxException {
+        return doAsEndpointUri(scheme, json, "&", encode);
+    }
+
+    public String asEndpointUriXml(String scheme, String json, boolean encode) throws URISyntaxException {
+        return doAsEndpointUri(scheme, json, "&amp;", encode);
+    }
+
+    private String doAsEndpointUri(String scheme, String json, String ampersand, boolean encode) throws URISyntaxException {
+        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
+
+        Map<String, String> copy = new HashMap<String, String>();
+        for (Map<String, String> row : rows) {
+            String name = row.get("name");
+            String required = row.get("required");
+            String value = row.get("value");
+            String defaultValue = row.get("defaultValue");
+
+            // only add if either required, or the value is != default value
+            String valueToAdd = null;
+            if ("true".equals(required)) {
+                valueToAdd = value != null ? value : defaultValue;
+                if (valueToAdd == null) {
+                    valueToAdd = "";
+                }
+            } else {
+                // if we have a value and no default then add it
+                if (value != null && defaultValue == null) {
+                    valueToAdd = value;
+                }
+                // otherwise only add if the value is != default value
+                if (value != null && defaultValue != null && !value.equals(defaultValue)) {
+                    valueToAdd = value;
+                }
+            }
+
+            if (valueToAdd != null) {
+                copy.put(name, valueToAdd);
+            }
+        }
+
+        return doAsEndpointUri(scheme, copy, ampersand, encode);
+    }
+
+    public String asEndpointUri(String scheme, Map<String, String> properties, boolean encode) throws URISyntaxException {
+        return doAsEndpointUri(scheme, properties, "&", encode);
+    }
+
+    public String asEndpointUriXml(String scheme, Map<String, String> properties, boolean encode) throws URISyntaxException {
+        return doAsEndpointUri(scheme, properties, "&amp;", encode);
+    }
+
+    String doAsEndpointUri(String scheme, Map<String, String> properties, String ampersand, boolean encode) throws URISyntaxException {
+        String json = jsonSchemaResolver.getComponentJSonSchema(scheme);
+        if (json == null) {
+            throw new IllegalArgumentException("Cannot find endpoint with scheme " + scheme);
+        }
+
+        // grab the syntax
+        String syntax = null;
+        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("component", json, false);
+        for (Map<String, String> row : rows) {
+            if (row.containsKey("syntax")) {
+                syntax = row.get("syntax");
+                break;
+            }
+        }
+        if (syntax == null) {
+            throw new IllegalArgumentException("Endpoint with scheme " + scheme + " has no syntax defined in the json schema");
+        }
+
+        // do any properties filtering which can be needed for some special components
+        properties = filterProperties(scheme, properties);
+
+        rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
+
+        // clip the scheme from the syntax
+        syntax = after(syntax, ":");
+
+        String originalSyntax = syntax;
+
+        // build at first according to syntax (use a tree map as we want the uri options sorted)
+        Map<String, String> copy = new TreeMap<String, String>();
+        for (Map.Entry<String, String> entry : properties.entrySet()) {
+            String key = entry.getKey();
+            String value = entry.getValue() != null ? entry.getValue() : "";
+            if (syntax != null && syntax.contains(key)) {
+                syntax = syntax.replace(key, value);
+            } else {
+                copy.put(key, value);
+            }
+        }
+
+        // do we have all the options the original syntax needs (easy way)
+        String[] keys = syntaxKeys(originalSyntax);
+        boolean hasAllKeys = properties.keySet().containsAll(Arrays.asList(keys));
+
+        // build endpoint uri
+        StringBuilder sb = new StringBuilder();
+        sb.append(scheme);
+        sb.append(":");
+
+        if (hasAllKeys) {
+            // we have all the keys for the syntax so we can build the uri the easy way
+            sb.append(syntax);
+
+            if (!copy.isEmpty()) {
+                boolean hasQuestionmark = sb.toString().contains("?");
+                // the last option may already contain a ? char, if so we should use & instead of ?
+                sb.append(hasQuestionmark ? ampersand : '?');
+                String query = createQueryString(copy, ampersand, encode);
+                sb.append(query);
+            }
+        } else {
+            // TODO: revisit this and see if we can do this in another way
+            // oh darn some options is missing, so we need a complex way of building the uri
+
+            // the tokens between the options in the path
+            String[] tokens = syntax.split("\\w+");
+
+            // parse the syntax into each options
+            Matcher matcher = SYNTAX_PATTERN.matcher(originalSyntax);
+            List<String> options = new ArrayList<String>();
+            while (matcher.find()) {
+                String s = matcher.group(1);
+                options.add(s);
+            }
+
+            // need to preserve {{ and }} from the syntax
+            // (we need to use words only as its provisional placeholders)
+            syntax = syntax.replaceAll("\\{\\{", "BEGINCAMELPLACEHOLDER");
+            syntax = syntax.replaceAll("\\}\\}", "ENDCAMELPLACEHOLDER");
+
+            // parse the syntax into each options
+            Matcher matcher2 = SYNTAX_PATTERN.matcher(syntax);
+            List<String> options2 = new ArrayList<String>();
+            while (matcher2.find()) {
+                String s = matcher2.group(1);
+                s = s.replaceAll("BEGINCAMELPLACEHOLDER", "\\{\\{");
+                s = s.replaceAll("ENDCAMELPLACEHOLDER", "\\}\\}");
+                options2.add(s);
+            }
+
+            // build the endpoint
+            int range = 0;
+            boolean first = true;
+            boolean hasQuestionmark = false;
+            for (int i = 0; i < options.size(); i++) {
+                String key = options.get(i);
+                String key2 = options2.get(i);
+                String token = null;
+                if (tokens.length > i) {
+                    token = tokens[i];
+                }
+
+                boolean contains = properties.containsKey(key);
+                if (!contains) {
+                    // if the key are similar we have no explicit value and can try to find a default value if the option is required
+                    if (isPropertyRequired(rows, key)) {
+                        String value = getPropertyDefaultValue(rows, key);
+                        if (value != null) {
+                            properties.put(key, value);
+                            key2 = value;
+                        }
+                    }
+                }
+
+                // was the option provided?
+                if (properties.containsKey(key)) {
+                    if (!first && token != null) {
+                        sb.append(token);
+                    }
+                    hasQuestionmark |= key.contains("?") || (token != null && token.contains("?"));
+                    sb.append(key2);
+                    first = false;
+                }
+                range++;
+            }
+            // append any extra options that was in surplus for the last
+            while (range < options2.size()) {
+                String token = null;
+                if (tokens.length > range) {
+                    token = tokens[range];
+                }
+                String key2 = options2.get(range);
+                sb.append(token);
+                sb.append(key2);
+                hasQuestionmark |= key2.contains("?") || (token != null && token.contains("?"));
+                range++;
+            }
+
+
+            if (!copy.isEmpty()) {
+                // the last option may already contain a ? char, if so we should use & instead of ?
+                sb.append(hasQuestionmark ? ampersand : '?');
+                String query = createQueryString(copy, ampersand, encode);
+                sb.append(query);
+            }
+        }
+
+        return sb.toString();
+    }
+
+    @Deprecated
+    private static String[] syntaxTokens(String syntax) {
+        // build tokens between the words
+        List<String> tokens = new ArrayList<>();
+        // preserve backwards behavior which had an empty token first
+        tokens.add("");
+
+        String current = "";
+        for (int i = 0; i < syntax.length(); i++) {
+            char ch = syntax.charAt(i);
+            if (Character.isLetterOrDigit(ch)) {
+                // reset for new current tokens
+                if (current.length() > 0) {
+                    tokens.add(current);
+                    current = "";
+                }
+            } else {
+                current += ch;
+            }
+        }
+        // anything left over?
+        if (current.length() > 0) {
+            tokens.add(current);
+        }
+
+        return tokens.toArray(new String[tokens.size()]);
+    }
+
+    private static String[] syntaxKeys(String syntax) {
+        // build tokens between the separators
+        List<String> tokens = new ArrayList<>();
+
+        String current = "";
+        for (int i = 0; i < syntax.length(); i++) {
+            char ch = syntax.charAt(i);
+            if (Character.isLetterOrDigit(ch)) {
+                current += ch;
+            } else {
+                // reset for new current tokens
+                if (current.length() > 0) {
+                    tokens.add(current);
+                    current = "";
+                }
+            }
+        }
+        // anything left over?
+        if (current.length() > 0) {
+            tokens.add(current);
+        }
+
+        return tokens.toArray(new String[tokens.size()]);
+    }
+
+    public SimpleValidationResult validateSimpleExpression(String simple) {
+        return doValidateSimple(null, simple, false);
+    }
+
+    public SimpleValidationResult validateSimpleExpression(ClassLoader classLoader, String simple) {
+        return doValidateSimple(classLoader, simple, false);
+    }
+
+    public SimpleValidationResult validateSimplePredicate(String simple) {
+        return doValidateSimple(null, simple, true);
+    }
+
+    public SimpleValidationResult validateSimplePredicate(ClassLoader classLoader, String simple) {
+        return doValidateSimple(classLoader, simple, true);
+    }
+
+    private SimpleValidationResult doValidateSimple(ClassLoader classLoader, String simple, boolean predicate) {
+        if (classLoader == null) {
+            classLoader = getClass().getClassLoader();
+        }
+
+        // if there are {{ }}} property placeholders then we need to resolve them to something else
+        // as the simple parse cannot resolve them before parsing as we dont run the actual Camel application
+        // with property placeholders setup so we need to dummy this by replace the {{ }} to something else
+        // therefore we use an more unlikely character: {{XXX}} to ~^XXX^~
+        String resolved = simple.replaceAll("\\{\\{(.+)\\}\\}", "~^$1^~");
+
+        SimpleValidationResult answer = new SimpleValidationResult(simple);
+
+        Object instance = null;
+        Class clazz = null;
+        try {
+            clazz = classLoader.loadClass("org.apache.camel.language.simple.SimpleLanguage");
+            instance = clazz.newInstance();
+        } catch (Exception e) {
+            // ignore
+        }
+
+        if (clazz != null && instance != null) {
+            Throwable cause = null;
+            try {
+                if (predicate) {
+                    instance.getClass().getMethod("createPredicate", String.class).invoke(instance, resolved);
+                } else {
+                    instance.getClass().getMethod("createExpression", String.class).invoke(instance, resolved);
+                }
+            } catch (InvocationTargetException e) {
+                cause = e.getTargetException();
+            } catch (Exception e) {
+                cause = e;
+            }
+
+            if (cause != null) {
+
+                // reverse ~^XXX^~ back to {{XXX}}
+                String errMsg = cause.getMessage();
+                errMsg = errMsg.replaceAll("\\~\\^(.+)\\^\\~", "{{$1}}");
+
+                answer.setError(errMsg);
+
+                // is it simple parser exception then we can grab the index where the problem is
+                if (cause.getClass().getName().equals("org.apache.camel.language.simple.types.SimpleIllegalSyntaxException")
+                    || cause.getClass().getName().equals("org.apache.camel.language.simple.types.SimpleParserException")) {
+                    try {
+                        // we need to grab the index field from those simple parser exceptions
+                        Method method = cause.getClass().getMethod("getIndex");
+                        Object result = method.invoke(cause);
+                        if (result != null) {
+                            int index = (int) result;
+                            answer.setIndex(index);
+                        }
+                    } catch (Throwable i) {
+                        // ignore
+                    }
+                }
+
+                // we need to grab the short message field from this simple syntax exception
+                if (cause.getClass().getName().equals("org.apache.camel.language.simple.types.SimpleIllegalSyntaxException")) {
+                    try {
+                        Method method = cause.getClass().getMethod("getShortMessage");
+                        Object result = method.invoke(cause);
+                        if (result != null) {
+                            String msg = (String) result;
+                            answer.setShortError(msg);
+                        }
+                    } catch (Throwable i) {
+                        // ignore
+                    }
+
+                    if (answer.getShortError() == null) {
+                        // fallback and try to make existing message short instead
+                        String msg = answer.getError();
+                        // grab everything before " at location " which would be regarded as the short message
+                        int idx = msg.indexOf(" at location ");
+                        if (idx > 0) {
+                            msg = msg.substring(0, idx);
+                            answer.setShortError(msg);
+                        }
+                    }
+                }
+            }
+        }
+
+        return answer;
+    }
+
+    public LanguageValidationResult validateLanguagePredicate(ClassLoader classLoader, String language, String text) {
+        return doValidateLanguage(classLoader, language, text, true);
+    }
+
+    public LanguageValidationResult validateLanguageExpression(ClassLoader classLoader, String language, String text) {
+        return doValidateLanguage(classLoader, language, text, false);
+    }
+
+    private LanguageValidationResult doValidateLanguage(ClassLoader classLoader, String language, String text, boolean predicate) {
+        if (classLoader == null) {
+            classLoader = getClass().getClassLoader();
+        }
+
+        SimpleValidationResult answer = new SimpleValidationResult(text);
+
+        String json = jsonSchemaResolver.getLanguageJSonSchema(language);
+        if (json == null) {
+            answer.setError("Unknown language " + language);
+            return answer;
+        }
+
+        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("language", json, false);
+        String className = null;
+        for (Map<String, String> row : rows) {
+            if (row.containsKey("javaType")) {
+                className = row.get("javaType");
+            }
+        }
+
+        if (className == null) {
+            answer.setError("Cannot find javaType for language " + language);
+            return answer;
+        }
+
+        Object instance = null;
+        Class clazz = null;
+        try {
+            clazz = classLoader.loadClass(className);
+            instance = clazz.newInstance();
+        } catch (Exception e) {
+            // ignore
+        }
+
+        if (clazz != null && instance != null) {
+            Throwable cause = null;
+            try {
+                if (predicate) {
+                    instance.getClass().getMethod("createPredicate", String.class).invoke(instance, text);
+                } else {
+                    instance.getClass().getMethod("createExpression", String.class).invoke(instance, text);
+                }
+            } catch (InvocationTargetException e) {
+                cause = e.getTargetException();
+            } catch (Exception e) {
+                cause = e;
+            }
+
+            if (cause != null) {
+                answer.setError(cause.getMessage());
+            }
+        }
+
+        return answer;
+    }
+
+    /**
+     * Special logic for log endpoints to deal when showAll=true
+     */
+    private Map<String, String> filterProperties(String scheme, Map<String, String> options) {
+        if ("log".equals(scheme)) {
+            String showAll = options.get("showAll");
+            if ("true".equals(showAll)) {
+                Map<String, String> filtered = new LinkedHashMap<String, String>();
+                // remove all the other showXXX options when showAll=true
+                for (Map.Entry<String, String> entry : options.entrySet()) {
+                    String key = entry.getKey();
+                    boolean skip = key.startsWith("show") && !key.equals("showAll");
+                    if (!skip) {
+                        filtered.put(key, entry.getValue());
+                    }
+                }
+                return filtered;
+            }
+        }
+        // use as-is
+        return options;
+    }
+
+    private static boolean validateInteger(String value) {
+        boolean valid = false;
+        try {
+            valid = Integer.valueOf(value) != null;
+        } catch (Exception e) {
+            // ignore
+        }
+        if (!valid) {
+            // it may be a time pattern, such as 5s for 5 seconds = 5000
+            try {
+                TimePatternConverter.toMilliSeconds(value);
+                valid = true;
+            } catch (Exception e) {
+                // ignore
+            }
+        }
+        return valid;
+    }
+
+    // CHECKSTYLE:ON
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/CamelContextJSonSchemaResolver.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/CamelContextJSonSchemaResolver.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/CamelContextJSonSchemaResolver.java
new file mode 100644
index 0000000..d3a448c
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/CamelContextJSonSchemaResolver.java
@@ -0,0 +1,80 @@
+/**
+ * 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;
+
+import java.io.IOException;
+
+import org.apache.camel.CamelContext;
+
+/**
+ * Uses runtime {@link CamelContext} to resolve the JSon schema files.
+ */
+public class CamelContextJSonSchemaResolver implements JSonSchemaResolver {
+
+    private final CamelContext camelContext;
+
+    public CamelContextJSonSchemaResolver(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public String getComponentJSonSchema(String name) {
+        try {
+            return camelContext.getComponentParameterJsonSchema(name);
+        } catch (IOException e) {
+            // ignore
+        }
+        return null;
+    }
+
+    @Override
+    public String getDataFormatJSonSchema(String name) {
+        try {
+            return camelContext.getDataFormatParameterJsonSchema(name);
+        } catch (IOException e) {
+            // ignore
+        }
+        return null;
+    }
+
+    @Override
+    public String getLanguageJSonSchema(String name) {
+        try {
+            return camelContext.getLanguageParameterJsonSchema(name);
+        } catch (IOException e) {
+            // ignore
+        }
+        return null;
+    }
+
+    @Override
+    public String getOtherJSonSchema(String name) {
+        // not supported
+        return null;
+    }
+
+    @Override
+    public String getModelJSonSchema(String name) {
+        try {
+            return camelContext.getEipParameterJsonSchema(name);
+        } catch (IOException e) {
+            // ignore
+        }
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/CatalogHelper.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/CatalogHelper.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/CatalogHelper.java
new file mode 100644
index 0000000..1b224df
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/CatalogHelper.java
@@ -0,0 +1,179 @@
+/**
+ * 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;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.util.List;
+
+public final class CatalogHelper {
+
+    private CatalogHelper() {
+    }
+
+    /**
+     * Loads the entire stream into memory as a String and returns it.
+     * <p/>
+     * <b>Notice:</b> This implementation appends a <tt>\n</tt> as line
+     * terminator at the of the text.
+     * <p/>
+     * Warning, don't use for crazy big streams :)
+     */
+    public static void loadLines(InputStream in, List<String> lines) throws IOException {
+        try (final InputStreamReader isr = new InputStreamReader(in);
+            final BufferedReader reader = new LineNumberReader(isr)) {
+            String line;
+            while ((line = reader.readLine()) != null) {
+                lines.add(line);
+            }
+        }
+    }
+
+    /**
+     * Loads the entire stream into memory as a String and returns it.
+     * <p/>
+     * <b>Notice:</b> This implementation appends a <tt>\n</tt> as line
+     * terminator at the of the text.
+     * <p/>
+     * Warning, don't use for crazy big streams :)
+     */
+    public static String loadText(InputStream in) throws IOException {
+        StringBuilder builder = new StringBuilder();
+        try (final InputStreamReader isr = new InputStreamReader(in);
+            final BufferedReader reader = new LineNumberReader(isr)) {
+            String line;
+            while ((line = reader.readLine()) != null) {
+                builder.append(line);
+                builder.append("\n");
+            }
+            return builder.toString();
+        }
+    }
+
+    /**
+     * Matches the name with the pattern.
+     *
+     * @param name  the name
+     * @param pattern the pattern
+     * @return <tt>true</tt> if matched, or <tt>false</tt> if not
+     */
+    public static boolean matchWildcard(String name, String pattern) {
+        // we have wildcard support in that hence you can match with: file* to match any file endpoints
+        if (pattern.endsWith("*") && name.startsWith(pattern.substring(0, pattern.length() - 1))) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Returns the string after the given token
+     *
+     * @param text  the text
+     * @param after the token
+     * @return the text after the token, or <tt>null</tt> if text does not contain the token
+     */
+    public static String after(String text, String after) {
+        if (!text.contains(after)) {
+            return null;
+        }
+        return text.substring(text.indexOf(after) + after.length());
+    }
+
+    /**
+     * Returns the string before the given token
+     *
+     * @param text  the text
+     * @param before the token
+     * @return the text before the token, or <tt>null</tt> if text does not contain the token
+     */
+    public static String before(String text, String before) {
+        if (!text.contains(before)) {
+            return null;
+        }
+        return text.substring(0, text.indexOf(before));
+    }
+
+    /**
+     * Returns the string between the given tokens
+     *
+     * @param text  the text
+     * @param after the before token
+     * @param before the after token
+     * @return the text between the tokens, or <tt>null</tt> if text does not contain the tokens
+     */
+    public static String between(String text, String after, String before) {
+        text = after(text, after);
+        if (text == null) {
+            return null;
+        }
+        return before(text, before);
+    }
+
+    /**
+     * Tests whether the value is <tt>null</tt> or an empty string.
+     *
+     * @param value  the value, if its a String it will be tested for text length as well
+     * @return true if empty
+     */
+    public static boolean isEmpty(Object value) {
+        return !isNotEmpty(value);
+    }
+
+    /**
+     * Tests whether the value is <b>not</b> <tt>null</tt> or an empty string.
+     *
+     * @param value  the value, if its a String it will be tested for text length as well
+     * @return true if <b>not</b> empty
+     */
+    public static boolean isNotEmpty(Object value) {
+        if (value == null) {
+            return false;
+        } else if (value instanceof String) {
+            String text = (String) value;
+            return text.trim().length() > 0;
+        } else {
+            return true;
+        }
+    }
+
+    /**
+     * Removes all leading and ending quotes (single and double) from the string
+     *
+     * @param s  the string
+     * @return the string without leading and ending quotes (single and double)
+     */
+    public static String removeLeadingAndEndingQuotes(String s) {
+        if (isEmpty(s)) {
+            return s;
+        }
+
+        String copy = s.trim();
+        if (copy.startsWith("'") && copy.endsWith("'")) {
+            return copy.substring(1, copy.length() - 1);
+        }
+        if (copy.startsWith("\"") && copy.endsWith("\"")) {
+            return copy.substring(1, copy.length() - 1);
+        }
+
+        // no quotes, so return as-is
+        return s;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/CollectionStringBuffer.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/CollectionStringBuffer.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/CollectionStringBuffer.java
new file mode 100644
index 0000000..f6484b8
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/CollectionStringBuffer.java
@@ -0,0 +1,57 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.runtimecatalog;
+
+public class CollectionStringBuffer {
+    private final StringBuilder buffer = new StringBuilder();
+    private String separator;
+    private boolean first = true;
+
+    public CollectionStringBuffer() {
+        this(", ");
+    }
+
+    public CollectionStringBuffer(String separator) {
+        this.separator = separator;
+    }
+
+    @Override
+    public String toString() {
+        return buffer.toString();
+    }
+
+    public void append(Object value) {
+        if (first) {
+            first = false;
+        } else {
+            buffer.append(separator);
+        }
+        buffer.append(value);
+    }
+
+    public String getSeparator() {
+        return separator;
+    }
+
+    public void setSeparator(String separator) {
+        this.separator = separator;
+    }
+
+    public boolean isEmpty() {
+        return first;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/DefaultRuntimeCamelCatalog.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/DefaultRuntimeCamelCatalog.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/DefaultRuntimeCamelCatalog.java
new file mode 100644
index 0000000..7648e64
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/DefaultRuntimeCamelCatalog.java
@@ -0,0 +1,136 @@
+/**
+ * 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;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+
+/**
+ * Default {@link RuntimeCamelCatalog}.
+ */
+public class DefaultRuntimeCamelCatalog extends AbstractCamelCatalog implements RuntimeCamelCatalog {
+
+    // cache of operation -> result
+    private final Map<String, Object> cache = new HashMap<String, Object>();
+    private boolean caching;
+
+    /**
+     * Creates the {@link RuntimeCamelCatalog} without caching enabled.
+     *
+     * @param camelContext  the camel context
+     */
+    public DefaultRuntimeCamelCatalog(CamelContext camelContext) {
+        this(camelContext, false);
+    }
+
+    /**
+     * Creates the {@link RuntimeCamelCatalog}
+     *
+     * @param camelContext  the camel context
+     * @param caching  whether to use cache
+     */
+    public DefaultRuntimeCamelCatalog(CamelContext camelContext, boolean caching) {
+        this.caching = caching;
+        setJSonSchemaResolver(new CamelContextJSonSchemaResolver(camelContext));
+    }
+
+    @Override
+    public void start() throws Exception {
+        // noop
+    }
+
+    @Override
+    public void stop() throws Exception {
+        cache.clear();
+    }
+
+    @Override
+    public String modelJSonSchema(String name) {
+        String answer = null;
+        if (caching) {
+            answer = (String) cache.get("model-" + name);
+        }
+
+        if (answer == null) {
+            answer = getJSonSchemaResolver().getModelJSonSchema(name);
+            if (caching) {
+                cache.put("model-" + name, answer);
+            }
+        }
+
+        return answer;
+    }
+
+    @Override
+    public String componentJSonSchema(String name) {
+        String answer = null;
+        if (caching) {
+            answer = (String) cache.get("component-" + name);
+        }
+
+        if (answer == null) {
+            answer = getJSonSchemaResolver().getComponentJSonSchema(name);
+            if (caching) {
+                cache.put("component-" + name, answer);
+            }
+        }
+
+        return answer;
+    }
+
+    @Override
+    public String dataFormatJSonSchema(String name) {
+        String answer = null;
+        if (caching) {
+            answer = (String) cache.get("dataformat-" + name);
+        }
+
+        if (answer == null) {
+            answer = getJSonSchemaResolver().getDataFormatJSonSchema(name);
+            if (caching) {
+                cache.put("dataformat-" + name, answer);
+            }
+        }
+
+        return answer;
+    }
+
+    @Override
+    public String languageJSonSchema(String name) {
+        // if we try to look method then its in the bean.json file
+        if ("method".equals(name)) {
+            name = "bean";
+        }
+
+        String answer = null;
+        if (caching) {
+            answer = (String) cache.get("language-" + name);
+        }
+
+        if (answer == null) {
+            answer = getJSonSchemaResolver().getLanguageJSonSchema(name);
+            if (caching) {
+                cache.put("language-" + name, answer);
+            }
+        }
+
+        return answer;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/EndpointValidationResult.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/EndpointValidationResult.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/EndpointValidationResult.java
new file mode 100644
index 0000000..7d1c657
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/EndpointValidationResult.java
@@ -0,0 +1,451 @@
+/**
+ * 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;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.apache.camel.runtimecatalog.URISupport.isEmpty;
+
+/**
+ * Details result of validating endpoint uri.
+ */
+public class EndpointValidationResult implements Serializable {
+
+    private final String uri;
+    private int errors;
+
+    // general
+    private String syntaxError;
+    private String unknownComponent;
+    private String incapable;
+
+    // options
+    private Set<String> unknown;
+    private Map<String, String[]> unknownSuggestions;
+    private Set<String> lenient;
+    private Set<String> notConsumerOnly;
+    private Set<String> notProducerOnly;
+    private Set<String> required;
+    private Map<String, String> invalidEnum;
+    private Map<String, String[]> invalidEnumChoices;
+    private Map<String, String[]> invalidEnumSuggestions;
+    private Map<String, String> invalidReference;
+    private Map<String, String> invalidBoolean;
+    private Map<String, String> invalidInteger;
+    private Map<String, String> invalidNumber;
+    private Map<String, String> defaultValues;
+
+    public EndpointValidationResult() {
+        this(null);
+    }
+
+    public EndpointValidationResult(String uri) {
+        this.uri = uri;
+    }
+
+    public String getUri() {
+        return uri;
+    }
+
+    public boolean hasErrors() {
+        return errors > 0;
+    }
+
+    public int getNumberOfErrors() {
+        return errors;
+    }
+
+    public boolean isSuccess() {
+        boolean ok = syntaxError == null && unknownComponent == null && incapable == null
+                && unknown == null && required == null;
+        if (ok) {
+            ok = notConsumerOnly == null && notProducerOnly == null;
+        }
+        if (ok) {
+            ok = invalidEnum == null && invalidEnumChoices == null && invalidReference == null
+                && invalidBoolean == null && invalidInteger == null && invalidNumber == null;
+        }
+        return ok;
+    }
+
+    public void addSyntaxError(String syntaxError) {
+        this.syntaxError = syntaxError;
+        errors++;
+    }
+
+    public void addIncapable(String uri) {
+        this.incapable = uri;
+        errors++;
+    }
+
+    public void addUnknownComponent(String name) {
+        this.unknownComponent = name;
+        errors++;
+    }
+
+    public void addUnknown(String name) {
+        if (unknown == null) {
+            unknown = new LinkedHashSet<String>();
+        }
+        if (!unknown.contains(name)) {
+            unknown.add(name);
+            errors++;
+        }
+    }
+
+    public void addUnknownSuggestions(String name, String[] suggestions) {
+        if (unknownSuggestions == null) {
+            unknownSuggestions = new LinkedHashMap<String, String[]>();
+        }
+        unknownSuggestions.put(name, suggestions);
+    }
+
+    public void addLenient(String name) {
+        if (lenient == null) {
+            lenient = new LinkedHashSet<String>();
+        }
+        if (!lenient.contains(name)) {
+            lenient.add(name);
+        }
+    }
+
+    public void addRequired(String name) {
+        if (required == null) {
+            required = new LinkedHashSet<String>();
+        }
+        if (!required.contains(name)) {
+            required.add(name);
+            errors++;
+        }
+    }
+
+    public void addInvalidEnum(String name, String value) {
+        if (invalidEnum == null) {
+            invalidEnum = new LinkedHashMap<String, String>();
+        }
+        if (!invalidEnum.containsKey(name)) {
+            invalidEnum.put(name, value);
+            errors++;
+        }
+    }
+
+    public void addInvalidEnumChoices(String name, String[] choices) {
+        if (invalidEnumChoices == null) {
+            invalidEnumChoices = new LinkedHashMap<String, String[]>();
+        }
+        invalidEnumChoices.put(name, choices);
+    }
+
+    public void addInvalidEnumSuggestions(String name, String[] suggestions) {
+        if (invalidEnumSuggestions == null) {
+            invalidEnumSuggestions = new LinkedHashMap<String, String[]>();
+        }
+        invalidEnumSuggestions.put(name, suggestions);
+    }
+
+    public void addInvalidReference(String name, String value) {
+        if (invalidReference == null) {
+            invalidReference = new LinkedHashMap<String, String>();
+        }
+        if (!invalidReference.containsKey(name)) {
+            invalidReference.put(name, value);
+            errors++;
+        }
+    }
+
+    public void addInvalidBoolean(String name, String value) {
+        if (invalidBoolean == null) {
+            invalidBoolean = new LinkedHashMap<String, String>();
+        }
+        if (!invalidBoolean.containsKey(name)) {
+            invalidBoolean.put(name, value);
+            errors++;
+        }
+    }
+
+    public void addInvalidInteger(String name, String value) {
+        if (invalidInteger == null) {
+            invalidInteger = new LinkedHashMap<String, String>();
+        }
+        if (!invalidInteger.containsKey(name)) {
+            invalidInteger.put(name, value);
+            errors++;
+        }
+    }
+
+    public void addInvalidNumber(String name, String value) {
+        if (invalidNumber == null) {
+            invalidNumber = new LinkedHashMap<String, String>();
+        }
+        if (!invalidNumber.containsKey(name)) {
+            invalidNumber.put(name, value);
+            errors++;
+        }
+    }
+
+    public void addDefaultValue(String name, String value)  {
+        if (defaultValues == null) {
+            defaultValues = new LinkedHashMap<String, String>();
+        }
+        defaultValues.put(name, value);
+    }
+
+    public void addNotConsumerOnly(String name) {
+        if (notConsumerOnly == null) {
+            notConsumerOnly = new LinkedHashSet<String>();
+        }
+        if (!notConsumerOnly.contains(name)) {
+            notConsumerOnly.add(name);
+            errors++;
+        }
+    }
+
+    public void addNotProducerOnly(String name) {
+        if (notProducerOnly == null) {
+            notProducerOnly = new LinkedHashSet<String>();
+        }
+        if (!notProducerOnly.contains(name)) {
+            notProducerOnly.add(name);
+            errors++;
+        }
+    }
+
+    public String getSyntaxError() {
+        return syntaxError;
+    }
+
+    public String getIncapable() {
+        return incapable;
+    }
+
+    public Set<String> getUnknown() {
+        return unknown;
+    }
+
+    public Set<String> getLenient() {
+        return lenient;
+    }
+
+    public Map<String, String[]> getUnknownSuggestions() {
+        return unknownSuggestions;
+    }
+
+    public String getUnknownComponent() {
+        return unknownComponent;
+    }
+
+    public Set<String> getRequired() {
+        return required;
+    }
+
+    public Map<String, String> getInvalidEnum() {
+        return invalidEnum;
+    }
+
+    public Map<String, String[]> getInvalidEnumChoices() {
+        return invalidEnumChoices;
+    }
+
+    public List<String> getEnumChoices(String optionName) {
+        if (invalidEnumChoices != null) {
+            String[] enums = invalidEnumChoices.get(optionName);
+            if (enums != null) {
+                return Arrays.asList(enums);
+            }
+        }
+
+        return Collections.emptyList();
+    }
+
+    public Map<String, String> getInvalidReference() {
+        return invalidReference;
+    }
+
+    public Map<String, String> getInvalidBoolean() {
+        return invalidBoolean;
+    }
+
+    public Map<String, String> getInvalidInteger() {
+        return invalidInteger;
+    }
+
+    public Map<String, String> getInvalidNumber() {
+        return invalidNumber;
+    }
+
+    public Map<String, String> getDefaultValues() {
+        return defaultValues;
+    }
+
+    public Set<String> getNotConsumerOnly() {
+        return notConsumerOnly;
+    }
+
+    public Set<String> getNotProducerOnly() {
+        return notProducerOnly;
+    }
+
+    /**
+     * A human readable summary of the validation errors.
+     *
+     * @param includeHeader whether to include a header
+     * @return the summary, or <tt>null</tt> if no validation errors
+     */
+    public String summaryErrorMessage(boolean includeHeader) {
+        if (isSuccess()) {
+            return null;
+        }
+
+        if (incapable != null) {
+            return "\tIncapable of parsing uri: " + incapable;
+        } else if (syntaxError != null) {
+            return "\tSyntax error: " + syntaxError;
+        } else if (unknownComponent != null) {
+            return "\tUnknown component: " + unknownComponent;
+        }
+
+        // for each invalid option build a reason message
+        Map<String, String> options = new LinkedHashMap<String, String>();
+        if (unknown != null) {
+            for (String name : unknown) {
+                if (unknownSuggestions != null && unknownSuggestions.containsKey(name)) {
+                    String[] suggestions = unknownSuggestions.get(name);
+                    if (suggestions != null && suggestions.length > 0) {
+                        String str = Arrays.asList(suggestions).toString();
+                        options.put(name, "Unknown option. Did you mean: " + str);
+                    } else {
+                        options.put(name, "Unknown option");
+                    }
+                } else {
+                    options.put(name, "Unknown option");
+                }
+            }
+        }
+        if (notConsumerOnly != null) {
+            for (String name : notConsumerOnly) {
+                options.put(name, "Option not applicable in consumer only mode");
+            }
+        }
+        if (notProducerOnly != null) {
+            for (String name : notProducerOnly) {
+                options.put(name, "Option not applicable in producer only mode");
+            }
+        }
+        if (required != null) {
+            for (String name : required) {
+                options.put(name, "Missing required option");
+            }
+        }
+        if (invalidEnum != null) {
+            for (Map.Entry<String, String> entry : invalidEnum.entrySet()) {
+                String name = entry.getKey();
+                String[] choices = invalidEnumChoices.get(name);
+                String defaultValue = defaultValues != null ? defaultValues.get(entry.getKey()) : null;
+                String str = Arrays.asList(choices).toString();
+                String msg = "Invalid enum value: " + entry.getValue() + ". Possible values: " + str;
+                if (invalidEnumSuggestions != null) {
+                    String[] suggestions = invalidEnumSuggestions.get(name);
+                    if (suggestions != null && suggestions.length > 0) {
+                        str = Arrays.asList(suggestions).toString();
+                        msg += ". Did you mean: " + str;
+                    }
+                }
+                if (defaultValue != null) {
+                    msg += ". Default value: " + defaultValue;
+                }
+
+                options.put(entry.getKey(), msg);
+            }
+        }
+        if (invalidReference != null) {
+            for (Map.Entry<String, String> entry : invalidReference.entrySet()) {
+                boolean empty = isEmpty(entry.getValue());
+                if (empty) {
+                    options.put(entry.getKey(), "Empty reference value");
+                } else if (!entry.getValue().startsWith("#")) {
+                    options.put(entry.getKey(), "Invalid reference value: " + entry.getValue() + " must start with #");
+                } else {
+                    options.put(entry.getKey(), "Invalid reference value: " + entry.getValue());
+                }
+            }
+        }
+        if (invalidBoolean != null) {
+            for (Map.Entry<String, String> entry : invalidBoolean.entrySet()) {
+                boolean empty = isEmpty(entry.getValue());
+                if (empty) {
+                    options.put(entry.getKey(), "Empty boolean value");
+                } else {
+                    options.put(entry.getKey(), "Invalid boolean value: " + entry.getValue());
+                }
+            }
+        }
+        if (invalidInteger != null) {
+            for (Map.Entry<String, String> entry : invalidInteger.entrySet()) {
+                boolean empty = isEmpty(entry.getValue());
+                if (empty) {
+                    options.put(entry.getKey(), "Empty integer value");
+                } else {
+                    options.put(entry.getKey(), "Invalid integer value: " + entry.getValue());
+                }
+            }
+        }
+        if (invalidNumber != null) {
+            for (Map.Entry<String, String> entry : invalidNumber.entrySet()) {
+                boolean empty = isEmpty(entry.getValue());
+                if (empty) {
+                    options.put(entry.getKey(), "Empty number value");
+                } else {
+                    options.put(entry.getKey(), "Invalid number value: " + entry.getValue());
+                }
+            }
+        }
+
+        // build a table with the error summary nicely formatted
+        // lets use 24 as min length
+        int maxLen = 24;
+        for (String key : options.keySet()) {
+            maxLen = Math.max(maxLen, key.length());
+        }
+        String format = "%" + maxLen + "s    %s";
+
+        // build the human error summary
+        StringBuilder sb = new StringBuilder();
+        if (includeHeader) {
+            sb.append("Endpoint validator error\n");
+            sb.append("---------------------------------------------------------------------------------------------------------------------------------------\n");
+            sb.append("\n");
+        }
+        if (uri != null) {
+            sb.append("\t").append(uri).append("\n");
+        } else {
+            sb.append("\n");
+        }
+        for (Map.Entry<String, String> option : options.entrySet()) {
+            String out = String.format(format, option.getKey(), option.getValue());
+            sb.append("\n\t").append(out);
+        }
+
+        return sb.toString();
+    }
+}


[5/6] camel git commit: Rename catalog to runtimecatalog to avoid clash with same package name in camel-catalog.

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/EndpointValidationResult.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/EndpointValidationResult.java b/camel-core/src/main/java/org/apache/camel/catalog/EndpointValidationResult.java
deleted file mode 100644
index 9bb98f0..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/EndpointValidationResult.java
+++ /dev/null
@@ -1,451 +0,0 @@
-/**
- * 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.catalog;
-
-import java.io.Serializable;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.apache.camel.catalog.URISupport.isEmpty;
-
-/**
- * Details result of validating endpoint uri.
- */
-public class EndpointValidationResult implements Serializable {
-
-    private final String uri;
-    private int errors;
-
-    // general
-    private String syntaxError;
-    private String unknownComponent;
-    private String incapable;
-
-    // options
-    private Set<String> unknown;
-    private Map<String, String[]> unknownSuggestions;
-    private Set<String> lenient;
-    private Set<String> notConsumerOnly;
-    private Set<String> notProducerOnly;
-    private Set<String> required;
-    private Map<String, String> invalidEnum;
-    private Map<String, String[]> invalidEnumChoices;
-    private Map<String, String[]> invalidEnumSuggestions;
-    private Map<String, String> invalidReference;
-    private Map<String, String> invalidBoolean;
-    private Map<String, String> invalidInteger;
-    private Map<String, String> invalidNumber;
-    private Map<String, String> defaultValues;
-
-    public EndpointValidationResult() {
-        this(null);
-    }
-
-    public EndpointValidationResult(String uri) {
-        this.uri = uri;
-    }
-
-    public String getUri() {
-        return uri;
-    }
-
-    public boolean hasErrors() {
-        return errors > 0;
-    }
-
-    public int getNumberOfErrors() {
-        return errors;
-    }
-
-    public boolean isSuccess() {
-        boolean ok = syntaxError == null && unknownComponent == null && incapable == null
-                && unknown == null && required == null;
-        if (ok) {
-            ok = notConsumerOnly == null && notProducerOnly == null;
-        }
-        if (ok) {
-            ok = invalidEnum == null && invalidEnumChoices == null && invalidReference == null
-                && invalidBoolean == null && invalidInteger == null && invalidNumber == null;
-        }
-        return ok;
-    }
-
-    public void addSyntaxError(String syntaxError) {
-        this.syntaxError = syntaxError;
-        errors++;
-    }
-
-    public void addIncapable(String uri) {
-        this.incapable = uri;
-        errors++;
-    }
-
-    public void addUnknownComponent(String name) {
-        this.unknownComponent = name;
-        errors++;
-    }
-
-    public void addUnknown(String name) {
-        if (unknown == null) {
-            unknown = new LinkedHashSet<String>();
-        }
-        if (!unknown.contains(name)) {
-            unknown.add(name);
-            errors++;
-        }
-    }
-
-    public void addUnknownSuggestions(String name, String[] suggestions) {
-        if (unknownSuggestions == null) {
-            unknownSuggestions = new LinkedHashMap<String, String[]>();
-        }
-        unknownSuggestions.put(name, suggestions);
-    }
-
-    public void addLenient(String name) {
-        if (lenient == null) {
-            lenient = new LinkedHashSet<String>();
-        }
-        if (!lenient.contains(name)) {
-            lenient.add(name);
-        }
-    }
-
-    public void addRequired(String name) {
-        if (required == null) {
-            required = new LinkedHashSet<String>();
-        }
-        if (!required.contains(name)) {
-            required.add(name);
-            errors++;
-        }
-    }
-
-    public void addInvalidEnum(String name, String value) {
-        if (invalidEnum == null) {
-            invalidEnum = new LinkedHashMap<String, String>();
-        }
-        if (!invalidEnum.containsKey(name)) {
-            invalidEnum.put(name, value);
-            errors++;
-        }
-    }
-
-    public void addInvalidEnumChoices(String name, String[] choices) {
-        if (invalidEnumChoices == null) {
-            invalidEnumChoices = new LinkedHashMap<String, String[]>();
-        }
-        invalidEnumChoices.put(name, choices);
-    }
-
-    public void addInvalidEnumSuggestions(String name, String[] suggestions) {
-        if (invalidEnumSuggestions == null) {
-            invalidEnumSuggestions = new LinkedHashMap<String, String[]>();
-        }
-        invalidEnumSuggestions.put(name, suggestions);
-    }
-
-    public void addInvalidReference(String name, String value) {
-        if (invalidReference == null) {
-            invalidReference = new LinkedHashMap<String, String>();
-        }
-        if (!invalidReference.containsKey(name)) {
-            invalidReference.put(name, value);
-            errors++;
-        }
-    }
-
-    public void addInvalidBoolean(String name, String value) {
-        if (invalidBoolean == null) {
-            invalidBoolean = new LinkedHashMap<String, String>();
-        }
-        if (!invalidBoolean.containsKey(name)) {
-            invalidBoolean.put(name, value);
-            errors++;
-        }
-    }
-
-    public void addInvalidInteger(String name, String value) {
-        if (invalidInteger == null) {
-            invalidInteger = new LinkedHashMap<String, String>();
-        }
-        if (!invalidInteger.containsKey(name)) {
-            invalidInteger.put(name, value);
-            errors++;
-        }
-    }
-
-    public void addInvalidNumber(String name, String value) {
-        if (invalidNumber == null) {
-            invalidNumber = new LinkedHashMap<String, String>();
-        }
-        if (!invalidNumber.containsKey(name)) {
-            invalidNumber.put(name, value);
-            errors++;
-        }
-    }
-
-    public void addDefaultValue(String name, String value)  {
-        if (defaultValues == null) {
-            defaultValues = new LinkedHashMap<String, String>();
-        }
-        defaultValues.put(name, value);
-    }
-
-    public void addNotConsumerOnly(String name) {
-        if (notConsumerOnly == null) {
-            notConsumerOnly = new LinkedHashSet<String>();
-        }
-        if (!notConsumerOnly.contains(name)) {
-            notConsumerOnly.add(name);
-            errors++;
-        }
-    }
-
-    public void addNotProducerOnly(String name) {
-        if (notProducerOnly == null) {
-            notProducerOnly = new LinkedHashSet<String>();
-        }
-        if (!notProducerOnly.contains(name)) {
-            notProducerOnly.add(name);
-            errors++;
-        }
-    }
-
-    public String getSyntaxError() {
-        return syntaxError;
-    }
-
-    public String getIncapable() {
-        return incapable;
-    }
-
-    public Set<String> getUnknown() {
-        return unknown;
-    }
-
-    public Set<String> getLenient() {
-        return lenient;
-    }
-
-    public Map<String, String[]> getUnknownSuggestions() {
-        return unknownSuggestions;
-    }
-
-    public String getUnknownComponent() {
-        return unknownComponent;
-    }
-
-    public Set<String> getRequired() {
-        return required;
-    }
-
-    public Map<String, String> getInvalidEnum() {
-        return invalidEnum;
-    }
-
-    public Map<String, String[]> getInvalidEnumChoices() {
-        return invalidEnumChoices;
-    }
-
-    public List<String> getEnumChoices(String optionName) {
-        if (invalidEnumChoices != null) {
-            String[] enums = invalidEnumChoices.get(optionName);
-            if (enums != null) {
-                return Arrays.asList(enums);
-            }
-        }
-
-        return Collections.emptyList();
-    }
-
-    public Map<String, String> getInvalidReference() {
-        return invalidReference;
-    }
-
-    public Map<String, String> getInvalidBoolean() {
-        return invalidBoolean;
-    }
-
-    public Map<String, String> getInvalidInteger() {
-        return invalidInteger;
-    }
-
-    public Map<String, String> getInvalidNumber() {
-        return invalidNumber;
-    }
-
-    public Map<String, String> getDefaultValues() {
-        return defaultValues;
-    }
-
-    public Set<String> getNotConsumerOnly() {
-        return notConsumerOnly;
-    }
-
-    public Set<String> getNotProducerOnly() {
-        return notProducerOnly;
-    }
-
-    /**
-     * A human readable summary of the validation errors.
-     *
-     * @param includeHeader whether to include a header
-     * @return the summary, or <tt>null</tt> if no validation errors
-     */
-    public String summaryErrorMessage(boolean includeHeader) {
-        if (isSuccess()) {
-            return null;
-        }
-
-        if (incapable != null) {
-            return "\tIncapable of parsing uri: " + incapable;
-        } else if (syntaxError != null) {
-            return "\tSyntax error: " + syntaxError;
-        } else if (unknownComponent != null) {
-            return "\tUnknown component: " + unknownComponent;
-        }
-
-        // for each invalid option build a reason message
-        Map<String, String> options = new LinkedHashMap<String, String>();
-        if (unknown != null) {
-            for (String name : unknown) {
-                if (unknownSuggestions != null && unknownSuggestions.containsKey(name)) {
-                    String[] suggestions = unknownSuggestions.get(name);
-                    if (suggestions != null && suggestions.length > 0) {
-                        String str = Arrays.asList(suggestions).toString();
-                        options.put(name, "Unknown option. Did you mean: " + str);
-                    } else {
-                        options.put(name, "Unknown option");
-                    }
-                } else {
-                    options.put(name, "Unknown option");
-                }
-            }
-        }
-        if (notConsumerOnly != null) {
-            for (String name : notConsumerOnly) {
-                options.put(name, "Option not applicable in consumer only mode");
-            }
-        }
-        if (notProducerOnly != null) {
-            for (String name : notProducerOnly) {
-                options.put(name, "Option not applicable in producer only mode");
-            }
-        }
-        if (required != null) {
-            for (String name : required) {
-                options.put(name, "Missing required option");
-            }
-        }
-        if (invalidEnum != null) {
-            for (Map.Entry<String, String> entry : invalidEnum.entrySet()) {
-                String name = entry.getKey();
-                String[] choices = invalidEnumChoices.get(name);
-                String defaultValue = defaultValues != null ? defaultValues.get(entry.getKey()) : null;
-                String str = Arrays.asList(choices).toString();
-                String msg = "Invalid enum value: " + entry.getValue() + ". Possible values: " + str;
-                if (invalidEnumSuggestions != null) {
-                    String[] suggestions = invalidEnumSuggestions.get(name);
-                    if (suggestions != null && suggestions.length > 0) {
-                        str = Arrays.asList(suggestions).toString();
-                        msg += ". Did you mean: " + str;
-                    }
-                }
-                if (defaultValue != null) {
-                    msg += ". Default value: " + defaultValue;
-                }
-
-                options.put(entry.getKey(), msg);
-            }
-        }
-        if (invalidReference != null) {
-            for (Map.Entry<String, String> entry : invalidReference.entrySet()) {
-                boolean empty = isEmpty(entry.getValue());
-                if (empty) {
-                    options.put(entry.getKey(), "Empty reference value");
-                } else if (!entry.getValue().startsWith("#")) {
-                    options.put(entry.getKey(), "Invalid reference value: " + entry.getValue() + " must start with #");
-                } else {
-                    options.put(entry.getKey(), "Invalid reference value: " + entry.getValue());
-                }
-            }
-        }
-        if (invalidBoolean != null) {
-            for (Map.Entry<String, String> entry : invalidBoolean.entrySet()) {
-                boolean empty = isEmpty(entry.getValue());
-                if (empty) {
-                    options.put(entry.getKey(), "Empty boolean value");
-                } else {
-                    options.put(entry.getKey(), "Invalid boolean value: " + entry.getValue());
-                }
-            }
-        }
-        if (invalidInteger != null) {
-            for (Map.Entry<String, String> entry : invalidInteger.entrySet()) {
-                boolean empty = isEmpty(entry.getValue());
-                if (empty) {
-                    options.put(entry.getKey(), "Empty integer value");
-                } else {
-                    options.put(entry.getKey(), "Invalid integer value: " + entry.getValue());
-                }
-            }
-        }
-        if (invalidNumber != null) {
-            for (Map.Entry<String, String> entry : invalidNumber.entrySet()) {
-                boolean empty = isEmpty(entry.getValue());
-                if (empty) {
-                    options.put(entry.getKey(), "Empty number value");
-                } else {
-                    options.put(entry.getKey(), "Invalid number value: " + entry.getValue());
-                }
-            }
-        }
-
-        // build a table with the error summary nicely formatted
-        // lets use 24 as min length
-        int maxLen = 24;
-        for (String key : options.keySet()) {
-            maxLen = Math.max(maxLen, key.length());
-        }
-        String format = "%" + maxLen + "s    %s";
-
-        // build the human error summary
-        StringBuilder sb = new StringBuilder();
-        if (includeHeader) {
-            sb.append("Endpoint validator error\n");
-            sb.append("---------------------------------------------------------------------------------------------------------------------------------------\n");
-            sb.append("\n");
-        }
-        if (uri != null) {
-            sb.append("\t").append(uri).append("\n");
-        } else {
-            sb.append("\n");
-        }
-        for (Map.Entry<String, String> option : options.entrySet()) {
-            String out = String.format(format, option.getKey(), option.getValue());
-            sb.append("\n\t").append(out);
-        }
-
-        return sb.toString();
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/JSonSchemaHelper.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/JSonSchemaHelper.java b/camel-core/src/main/java/org/apache/camel/catalog/JSonSchemaHelper.java
deleted file mode 100644
index 774facd..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/JSonSchemaHelper.java
+++ /dev/null
@@ -1,424 +0,0 @@
-/**
- * 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.catalog;
-
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public final class JSonSchemaHelper {
-
-    // 0 = text, 1 = enum, 2 = boolean, 3 = integer or number
-    private static final Pattern PATTERN = Pattern.compile("\"(.+?)\"|\\[(.+)\\]|(true|false)|(-?\\d+\\.?\\d*)");
-    private static final String QUOT = "&quot;";
-
-    private JSonSchemaHelper() {
-    }
-
-    /**
-     * 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>.
-     * @param json the json
-     * @return a list of all the rows, where each row is a set of key value pairs with metadata
-     */
-    public static List<Map<String, String>> parseJsonSchema(String group, String json, boolean parseProperties) {
-        List<Map<String, String>> answer = new ArrayList<Map<String, String>>();
-        if (json == null) {
-            return answer;
-        }
-
-        boolean found = false;
-
-        // parse line by line
-        String[] lines = json.split("\n");
-        for (String line : lines) {
-            // we need to find the group first
-            if (!found) {
-                String s = line.trim();
-                found = s.startsWith("\"" + group + "\":") && s.endsWith("{");
-                continue;
-            }
-
-            // we should stop when we end the group
-            if (line.equals("  },") || line.equals("  }")) {
-                break;
-            }
-
-            // need to safe encode \" so we can parse the line
-            line = line.replaceAll("\"\\\\\"\"", '"' + QUOT + '"');
-
-            Map<String, String> row = new LinkedHashMap<String, String>();
-            Matcher matcher = PATTERN.matcher(line);
-
-            String key;
-            if (parseProperties) {
-                // when parsing properties the first key is given as name, so the first parsed token is the value of the name
-                key = "name";
-            } else {
-                key = null;
-            }
-            while (matcher.find()) {
-                if (key == null) {
-                    key = matcher.group(1);
-                } else {
-                    String value = matcher.group(1);
-                    if (value != null) {
-                        // its text based
-                        value = value.trim();
-                        // decode
-                        value = value.replaceAll(QUOT, "\"");
-                        value = decodeJson(value);
-                    }
-                    if (value == null) {
-                        // not text then its maybe an enum?
-                        value = matcher.group(2);
-                        if (value != null) {
-                            // its an enum so strip out " and trim spaces after comma
-                            value = value.replaceAll("\"", "");
-                            value = value.replaceAll(", ", ",");
-                            value = value.trim();
-                        }
-                    }
-                    if (value == null) {
-                        // not text then its maybe a boolean?
-                        value = matcher.group(3);
-                    }
-                    if (value == null) {
-                        // not text then its maybe a integer?
-                        value = matcher.group(4);
-                    }
-                    if (value != null) {
-                        row.put(key, value);
-                    }
-                    // reset
-                    key = null;
-                }
-            }
-            if (!row.isEmpty()) {
-                answer.add(row);
-            }
-        }
-
-        return answer;
-    }
-
-    private static String decodeJson(String value) {
-        // json encodes a \ as \\ so we need to decode from \\ back to \
-        if ("\\\\".equals(value)) {
-            value = "\\";
-        }
-        return value;
-    }
-
-    public static boolean isComponentLenientProperties(List<Map<String, String>> rows) {
-        for (Map<String, String> row : rows) {
-            if (row.containsKey("lenientProperties")) {
-                return "true".equals(row.get("lenientProperties"));
-            }
-        }
-        return false;
-    }
-
-    public static boolean isComponentConsumerOnly(List<Map<String, String>> rows) {
-        for (Map<String, String> row : rows) {
-            if (row.containsKey("consumerOnly")) {
-                return "true".equals(row.get("consumerOnly"));
-            }
-        }
-        return false;
-    }
-
-    public static boolean isComponentProducerOnly(List<Map<String, String>> rows) {
-        for (Map<String, String> row : rows) {
-            if (row.containsKey("producerOnly")) {
-                return "true".equals(row.get("producerOnly"));
-            }
-        }
-        return false;
-    }
-
-    public static boolean isPropertyConsumerOnly(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            String labels = null;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                found = name.equals(row.get("name"));
-            }
-            if (row.containsKey("label")) {
-                labels = row.get("label");
-            }
-            if (found) {
-                return labels != null && labels.contains("consumer");
-            }
-        }
-        return false;
-    }
-
-    public static boolean isPropertyProducerOnly(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            String labels = null;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                found = name.equals(row.get("name"));
-            }
-            if (row.containsKey("label")) {
-                labels = row.get("label");
-            }
-            if (found) {
-                return labels != null && labels.contains("producer");
-            }
-        }
-        return false;
-    }
-
-    public static boolean isPropertyRequired(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            boolean required = false;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                found = name.equals(row.get("name"));
-            }
-            if (row.containsKey("required")) {
-                required = "true".equals(row.get("required"));
-            }
-            if (found) {
-                return required;
-            }
-        }
-        return false;
-    }
-
-    public static String getPropertyKind(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            String kind = null;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                found = name.equals(row.get("name"));
-            }
-            if (row.containsKey("kind")) {
-                kind = row.get("kind");
-            }
-            if (found) {
-                return kind;
-            }
-        }
-        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"));
-            }
-            if (row.containsKey("type")) {
-                type = row.get("type");
-            }
-            if (found) {
-                return "boolean".equals(type);
-            }
-        }
-        return false;
-    }
-
-    public static boolean isPropertyInteger(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"));
-            }
-            if (row.containsKey("type")) {
-                type = row.get("type");
-            }
-            if (found) {
-                return "integer".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"));
-            }
-            if (row.containsKey("type")) {
-                type = row.get("type");
-            }
-            if (found) {
-                return "number".equals(type);
-            }
-        }
-        return false;
-    }
-
-    public static boolean isPropertyObject(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"));
-            }
-            if (row.containsKey("type")) {
-                type = row.get("type");
-            }
-            if (found) {
-                return "object".equals(type);
-            }
-        }
-        return false;
-    }
-
-    public static String getPropertyDefaultValue(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            String defaultValue = null;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                found = name.equals(row.get("name"));
-            }
-            if (row.containsKey("defaultValue")) {
-                defaultValue = row.get("defaultValue");
-            }
-            if (found) {
-                return defaultValue;
-            }
-        }
-        return null;
-    }
-
-    public static String stripOptionalPrefixFromName(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            String optionalPrefix = null;
-            boolean found = false;
-            if (row.containsKey("optionalPrefix")) {
-                optionalPrefix = row.get("optionalPrefix");
-            }
-            if (row.containsKey("name")) {
-                if (optionalPrefix != null && name.startsWith(optionalPrefix)) {
-                    name = name.substring(optionalPrefix.length());
-                    // try again
-                    return stripOptionalPrefixFromName(rows, name);
-                } else {
-                    found = name.equals(row.get("name"));
-                }
-            }
-            if (found) {
-                return name;
-            }
-        }
-        return name;
-    }
-
-    public static String getPropertyEnum(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            String enums = null;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                found = name.equals(row.get("name"));
-            }
-            if (row.containsKey("enum")) {
-                enums = row.get("enum");
-            }
-            if (found) {
-                return enums;
-            }
-        }
-        return null;
-    }
-
-    public static String getPropertyPrefix(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            String prefix = null;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                found = name.equals(row.get("name"));
-            }
-            if (row.containsKey("prefix")) {
-                prefix = row.get("prefix");
-            }
-            if (found) {
-                return prefix;
-            }
-        }
-        return null;
-    }
-
-    public static boolean isPropertyMultiValue(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            boolean multiValue = false;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                found = name.equals(row.get("name"));
-            }
-            if (row.containsKey("multiValue")) {
-                multiValue = "true".equals(row.get("multiValue"));
-            }
-            if (found) {
-                return multiValue;
-            }
-        }
-        return false;
-    }
-
-    public static String getPropertyNameFromNameWithPrefix(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            String propertyName = null;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                propertyName = row.get("name");
-            }
-            if (row.containsKey("prefix")) {
-                String preifx = row.get("prefix");
-                found = name.startsWith(preifx);
-            }
-            if (found) {
-                return propertyName;
-            }
-        }
-        return null;
-    }
-
-    public static Map<String, String> getRow(List<Map<String, String>> rows, String key) {
-        for (Map<String, String> row : rows) {
-            if (key.equals(row.get("name"))) {
-                return row;
-            }
-        }
-        return null;
-    }
-
-    public static Set<String> getNames(List<Map<String, String>> rows) {
-        Set<String> answer = new LinkedHashSet<String>();
-        for (Map<String, String> row : rows) {
-            if (row.containsKey("name")) {
-                answer.add(row.get("name"));
-            }
-        }
-        return answer;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/JSonSchemaResolver.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/JSonSchemaResolver.java b/camel-core/src/main/java/org/apache/camel/catalog/JSonSchemaResolver.java
deleted file mode 100644
index 9bf09cc..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/JSonSchemaResolver.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * 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.catalog;
-
-/**
- * Pluggable resolver to load JSon schema files for components, data formats, languages etc.
- */
-public interface JSonSchemaResolver {
-
-    /**
-     * Returns the component information as JSon format.
-     *
-     * @param name the component name
-     * @return component details in JSon
-     */
-    String getComponentJSonSchema(String name);
-
-    /**
-     * Returns the data format information as JSon format.
-     *
-     * @param name the data format name
-     * @return data format details in JSon
-     */
-    String getDataFormatJSonSchema(String name);
-
-    /**
-     * Returns the language information as JSon format.
-     *
-     * @param name the language name
-     * @return language details in JSon
-     */
-    String getLanguageJSonSchema(String name);
-
-    /**
-     * Returns the other (miscellaneous) information as JSon format.
-     *
-     * @param name the other (miscellaneous) name
-     * @return other (miscellaneous) details in JSon
-     */
-    String getOtherJSonSchema(String name);
-
-    /**
-     * Returns the model information as JSon format.
-     *
-     * @param name the model name
-     * @return model details in JSon
-     */
-    String getModelJSonSchema(String name);
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/LanguageValidationResult.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/LanguageValidationResult.java b/camel-core/src/main/java/org/apache/camel/catalog/LanguageValidationResult.java
deleted file mode 100644
index 4a977eb..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/LanguageValidationResult.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * 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.catalog;
-
-import java.io.Serializable;
-
-/**
- * Validation result of parsing a language expression or predicate
- */
-public class LanguageValidationResult implements Serializable {
-    private final String text;
-    private String error;
-    private String shortError;
-    private int index;
-
-    public LanguageValidationResult(String text) {
-        this.text = text;
-    }
-
-    public String getText() {
-        return text;
-    }
-
-    public boolean isSuccess() {
-        return error == null;
-    }
-
-    public void setError(String error) {
-        this.error = error;
-    }
-
-    public String getError() {
-        return error;
-    }
-
-    public String getShortError() {
-        return shortError;
-    }
-
-    public void setShortError(String shortError) {
-        this.shortError = shortError;
-    }
-
-    public int getIndex() {
-        return index;
-    }
-
-    public void setIndex(int index) {
-        this.index = index;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/RuntimeCamelCatalog.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/RuntimeCamelCatalog.java b/camel-core/src/main/java/org/apache/camel/catalog/RuntimeCamelCatalog.java
deleted file mode 100644
index b46edab..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/RuntimeCamelCatalog.java
+++ /dev/null
@@ -1,234 +0,0 @@
-/**
- * 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.catalog;
-
-import java.net.URISyntaxException;
-import java.util.Map;
-
-import org.apache.camel.StaticService;
-
-/**
- * Runtime based CamelCatalog which are included in camel-core that can provided limit CamelCatalog capabilities
- */
-public interface RuntimeCamelCatalog extends StaticService {
-
-    /**
-     * Returns the component information as JSon format.
-     *
-     * @param name the component name
-     * @return component details in JSon
-     */
-    String componentJSonSchema(String name);
-
-    /**
-     * Returns the data format information as JSon format.
-     *
-     * @param name the data format name
-     * @return data format details in JSon
-     */
-    String dataFormatJSonSchema(String name);
-
-    /**
-     * Returns the language information as JSon format.
-     *
-     * @param name the language name
-     * @return language details in JSon
-     */
-    String languageJSonSchema(String name);
-
-    /**
-     * Returns the model information as JSon format.
-     *
-     * @param name the model name
-     * @return model details in JSon
-     */
-    String modelJSonSchema(String name);
-
-    /**
-     * Parses the endpoint uri and constructs a key/value properties of each option
-     *
-     * @param uri  the endpoint uri
-     * @return properties as key value pairs of each endpoint option
-     */
-    Map<String, String> endpointProperties(String uri) throws URISyntaxException;
-
-    /**
-     * Parses the endpoint uri and constructs a key/value properties of only the lenient properties (eg custom options)
-     * <p/>
-     * For example using the HTTP components to provide query parameters in the endpoint uri.
-     *
-     * @param uri  the endpoint uri
-     * @return properties as key value pairs of each lenient properties
-     */
-    Map<String, String> endpointLenientProperties(String uri) throws URISyntaxException;
-
-    /**
-     * Validates the pattern whether its a valid time pattern.
-     *
-     * @param pattern  the pattern such as 5000, 5s, 5sec, 4min, 4m30s, 1h, etc.
-     * @return <tt>true</tt> if valid, <tt>false</tt> if invalid
-     */
-    boolean validateTimePattern(String pattern);
-
-    /**
-     * Validates the properties for the given scheme against component and endpoint
-     *
-     * @param scheme  the endpoint scheme
-     * @param properties  the endpoint properties
-     * @return validation result
-     */
-    EndpointValidationResult validateProperties(String scheme, Map<String, String> properties);
-
-    /**
-     * Parses and validates the endpoint uri and constructs a key/value properties of each option.
-     *
-     * @param uri  the endpoint uri
-     * @return validation result
-     */
-    EndpointValidationResult validateEndpointProperties(String uri);
-
-    /**
-     * Parses and validates the endpoint uri and constructs a key/value properties of each option.
-     * <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
-     * but in the uri because of using lenient properties.
-     * For example using the HTTP components to provide query parameters in the endpoint uri.
-     *
-     * @param uri  the endpoint uri
-     * @param ignoreLenientProperties  whether to ignore components that uses lenient properties.
-     * @return validation result
-     */
-    EndpointValidationResult validateEndpointProperties(String uri, boolean ignoreLenientProperties);
-
-    /**
-     * Parses and validates the endpoint uri and constructs a key/value properties of each option.
-     * <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
-     * but in the uri because of using lenient properties.
-     * For example using the HTTP components to provide query parameters in the endpoint uri.
-     *
-     * @param uri  the endpoint uri
-     * @param ignoreLenientProperties  whether to ignore components that uses lenient properties.
-     * @param consumerOnly whether the endpoint is only used as a consumer
-     * @param producerOnly whether the endpoint is only used as a producer
-     * @return validation result
-     */
-    EndpointValidationResult validateEndpointProperties(String uri, boolean ignoreLenientProperties, boolean consumerOnly, boolean producerOnly);
-
-    /**
-     * Parses and validates the simple expression.
-     * <p/>
-     * <b>Important:</b> This requires having <tt>camel-core</tt> on the classpath
-     *
-     * @param simple  the simple expression
-     * @return validation result
-     * @deprecated use {@link #validateSimpleExpression(ClassLoader, String)}
-     */
-    @Deprecated
-    SimpleValidationResult validateSimpleExpression(String simple);
-
-    /**
-     * Parses and validates the simple expression.
-     * <p/>
-     * <b>Important:</b> This requires having <tt>camel-core</tt> on the classpath
-     *
-     * @param classLoader a custom classloader to use for loading the language from the classpath, or <tt>null</tt> for using default classloader
-     * @param simple  the simple expression
-     * @return validation result
-     */
-    SimpleValidationResult validateSimpleExpression(ClassLoader classLoader, String simple);
-
-    /**
-     * Parses and validates the simple predicate
-     * <p/>
-     * <b>Important:</b> This requires having <tt>camel-core</tt> on the classpath
-     *
-     * @param simple  the simple predicate
-     * @return validation result
-     * @deprecated use {@link #validateSimplePredicate(ClassLoader, String)}
-     */
-    @Deprecated
-    SimpleValidationResult validateSimplePredicate(String simple);
-
-    /**
-     * Parses and validates the simple predicate
-     * <p/>
-     * <b>Important:</b> This requires having <tt>camel-core</tt> on the classpath
-     *
-     * @param classLoader a custom classloader to use for loading the language from the classpath, or <tt>null</tt> for using default classloader
-     * @param simple  the simple predicate
-     * @return validation result
-     */
-    SimpleValidationResult validateSimplePredicate(ClassLoader classLoader, String simple);
-
-    /**
-     * Parses and validates the language as a predicate
-     * <p/>
-     * <b>Important:</b> This requires having <tt>camel-core</tt> and the language dependencies on the classpath
-     *
-     * @param classLoader a custom classloader to use for loading the language from the classpath, or <tt>null</tt> for using default classloader
-     * @param language the name of the language
-     * @param text  the predicate text
-     * @return validation result
-     */
-    LanguageValidationResult validateLanguagePredicate(ClassLoader classLoader, String language, String text);
-
-    /**
-     * Parses and validates the language as an expression
-     * <p/>
-     * <b>Important:</b> This requires having <tt>camel-core</tt> and the language dependencies on the classpath
-     *
-     * @param classLoader a custom classloader to use for loading the language from the classpath, or <tt>null</tt> for using default classloader
-     * @param language the name of the language
-     * @param text  the expression text
-     * @return validation result
-     */
-    LanguageValidationResult validateLanguageExpression(ClassLoader classLoader, String language, String text);
-
-    /**
-     * Returns the component name from the given endpoint uri
-     *
-     * @param uri  the endpoint uri
-     * @return the component name (aka scheme), or <tt>null</tt> if not possible to determine
-     */
-    String endpointComponentName(String uri);
-
-    /**
-     * Creates an endpoint uri in Java style from the information from the properties
-     *
-     * @param scheme the endpoint schema
-     * @param properties the properties as key value pairs
-     * @param encode whether to URL encode the returned uri or not
-     * @return the constructed endpoint uri
-     * @throws java.net.URISyntaxException is thrown if there is encoding error
-     */
-    String asEndpointUri(String scheme, Map<String, String> properties, boolean encode) throws URISyntaxException;
-
-    /**
-     * Creates an endpoint uri in XML style (eg escape & as &ampl;) from the information from the properties
-     *
-     * @param scheme the endpoint schema
-     * @param properties the properties as key value pairs
-     * @param encode whether to URL encode the returned uri or not
-     * @return the constructed endpoint uri
-     * @throws java.net.URISyntaxException is thrown if there is encoding error
-     */
-    String asEndpointUriXml(String scheme, Map<String, String> properties, boolean encode) throws URISyntaxException;
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/SimpleValidationResult.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/SimpleValidationResult.java b/camel-core/src/main/java/org/apache/camel/catalog/SimpleValidationResult.java
deleted file mode 100644
index 5c86f23..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/SimpleValidationResult.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * 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.catalog;
-
-/**
- * To be backwards compatible, but favor using {@link LanguageValidationResult} instead.
- */
-public class SimpleValidationResult extends LanguageValidationResult {
-
-    public SimpleValidationResult(String text) {
-        super(text);
-    }
-
-    public String getSimple() {
-        return getText();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/SuggestionStrategy.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/SuggestionStrategy.java b/camel-core/src/main/java/org/apache/camel/catalog/SuggestionStrategy.java
deleted file mode 100644
index 057d372..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/SuggestionStrategy.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * 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.catalog;
-
-import java.util.Set;
-
-/**
- * Strategy to provide suggestions for unknown endpoint options
- */
-public interface SuggestionStrategy {
-
-    /**
-     * Provides a list of valid option names for a did you mean function.
-     *
-     * @param names         valid names
-     * @param unknownOption unknown option name
-     * @return a list of suggested names (did you mean)
-     */
-    String[] suggestEndpointOptions(Set<String> names, String unknownOption);
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/TimePatternConverter.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/TimePatternConverter.java b/camel-core/src/main/java/org/apache/camel/catalog/TimePatternConverter.java
deleted file mode 100644
index 4ed843a..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/TimePatternConverter.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/**
- * 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.catalog;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * This class is a copy from camel-core so we can use it independent to validate uris with time patterns
- */
-public final class TimePatternConverter {
-    private static final Pattern NUMBERS_ONLY_STRING_PATTERN = Pattern.compile("^[-]?(\\d)+$", Pattern.CASE_INSENSITIVE);
-    private static final Pattern HOUR_REGEX_PATTERN = Pattern.compile("((\\d)*(\\d))h(our(s)?)?", Pattern.CASE_INSENSITIVE);
-    private static final Pattern MINUTES_REGEX_PATTERN = Pattern.compile("((\\d)*(\\d))m(in(ute(s)?)?)?", Pattern.CASE_INSENSITIVE);
-    private static final Pattern SECONDS_REGEX_PATTERN = Pattern.compile("((\\d)*(\\d))s(ec(ond)?(s)?)?", Pattern.CASE_INSENSITIVE);
-
-    /**
-     * Utility classes should not have a public constructor.
-     */
-    private TimePatternConverter() {
-    }
-
-    public static long toMilliSeconds(String source) throws IllegalArgumentException {
-        long milliseconds = 0;
-        boolean foundFlag = false;
-
-        checkCorrectnessOfPattern(source);
-        Matcher matcher;
-
-        matcher = createMatcher(NUMBERS_ONLY_STRING_PATTERN, source);
-        if (matcher.find()) {
-            // Note: This will also be used for regular numeric strings.
-            //       This String -> long converter will be used for all strings.
-            milliseconds = Long.valueOf(source);
-        } else {
-            matcher = createMatcher(HOUR_REGEX_PATTERN, source);
-            if (matcher.find()) {
-                milliseconds = milliseconds + (3600000 * Long.valueOf(matcher.group(1)));
-                foundFlag = true;
-            }
-
-            matcher = createMatcher(MINUTES_REGEX_PATTERN, source);
-            if (matcher.find()) {
-                long minutes = Long.valueOf(matcher.group(1));
-                if ((minutes > 59) && foundFlag) {
-                    throw new IllegalArgumentException("Minutes should contain a valid value between 0 and 59: " + source);
-                }
-                foundFlag = true;
-                milliseconds = milliseconds + (60000 * minutes);
-            }
-
-            matcher = createMatcher(SECONDS_REGEX_PATTERN, source);
-            if (matcher.find()) {
-                long seconds = Long.valueOf(matcher.group(1));
-                if ((seconds > 59) && foundFlag) {
-                    throw new IllegalArgumentException("Seconds should contain a valid value between 0 and 59: " + source);
-                }
-                foundFlag = true;
-                milliseconds = milliseconds + (1000 * seconds);
-            }
-
-            // No pattern matched... initiating fallback check and conversion (if required).
-            // The source at this point may contain illegal values or special characters
-            if (!foundFlag) {
-                milliseconds = Long.valueOf(source);
-            }
-        }
-
-        return milliseconds;
-    }
-
-    private static void checkCorrectnessOfPattern(String source) {
-        //replace only numbers once
-        Matcher matcher = createMatcher(NUMBERS_ONLY_STRING_PATTERN, source);
-        String replaceSource = matcher.replaceFirst("");
-
-        //replace hour string once
-        matcher = createMatcher(HOUR_REGEX_PATTERN, replaceSource);
-        if (matcher.find() && matcher.find()) {
-            throw new IllegalArgumentException("Hours should not be specified more then once: " + source);
-        }
-        replaceSource = matcher.replaceFirst("");
-
-        //replace minutes once
-        matcher = createMatcher(MINUTES_REGEX_PATTERN, replaceSource);
-        if (matcher.find() && matcher.find()) {
-            throw new IllegalArgumentException("Minutes should not be specified more then once: " + source);
-        }
-        replaceSource = matcher.replaceFirst("");
-
-        //replace seconds once
-        matcher = createMatcher(SECONDS_REGEX_PATTERN, replaceSource);
-        if (matcher.find() && matcher.find()) {
-            throw new IllegalArgumentException("Seconds should not be specified more then once: " + source);
-        }
-        replaceSource = matcher.replaceFirst("");
-
-        if (replaceSource.length() > 0) {
-            throw new IllegalArgumentException("Illegal characters: " + source);
-        }
-    }
-
-    private static Matcher createMatcher(Pattern pattern, String source) {
-        return pattern.matcher(source);
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/URISupport.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/URISupport.java b/camel-core/src/main/java/org/apache/camel/catalog/URISupport.java
deleted file mode 100644
index ea1ecd5..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/URISupport.java
+++ /dev/null
@@ -1,392 +0,0 @@
-/**
- * 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.catalog;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URLDecoder;
-import java.net.URLEncoder;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Copied from org.apache.camel.util.URISupport
- */
-public final class URISupport {
-
-    public static final String RAW_TOKEN_START = "RAW(";
-    public static final String RAW_TOKEN_END = ")";
-
-    private static final String CHARSET = "UTF-8";
-
-    private URISupport() {
-        // Helper class
-    }
-
-    /**
-     * Normalizes the URI so unsafe characters is encoded
-     *
-     * @param uri the input uri
-     * @return as URI instance
-     * @throws URISyntaxException is thrown if syntax error in the input uri
-     */
-    public static URI normalizeUri(String uri) throws URISyntaxException {
-        return new URI(UnsafeUriCharactersEncoder.encode(uri, true));
-    }
-
-    public static Map<String, Object> extractProperties(Map<String, Object> properties, String optionPrefix) {
-        Map<String, Object> rc = new LinkedHashMap<String, Object>(properties.size());
-
-        for (Iterator<Map.Entry<String, Object>> it = properties.entrySet().iterator(); it.hasNext();) {
-            Map.Entry<String, Object> entry = it.next();
-            String name = entry.getKey();
-            if (name.startsWith(optionPrefix)) {
-                Object value = properties.get(name);
-                name = name.substring(optionPrefix.length());
-                rc.put(name, value);
-                it.remove();
-            }
-        }
-
-        return rc;
-    }
-
-    /**
-     * Strips the query parameters from the uri
-     *
-     * @param uri  the uri
-     * @return the uri without the query parameter
-     */
-    public static String stripQuery(String uri) {
-        int idx = uri.indexOf('?');
-        if (idx > -1) {
-            uri = uri.substring(0, idx);
-        }
-        return uri;
-    }
-
-    /**
-     * Parses the query parameters of the uri (eg the query part).
-     *
-     * @param uri the uri
-     * @return the parameters, or an empty map if no parameters (eg never null)
-     * @throws URISyntaxException is thrown if uri has invalid syntax.
-     */
-    public static Map<String, Object> parseParameters(URI uri) throws URISyntaxException {
-        String query = uri.getQuery();
-        if (query == null) {
-            String schemeSpecificPart = uri.getSchemeSpecificPart();
-            int idx = schemeSpecificPart.indexOf('?');
-            if (idx < 0) {
-                // return an empty map
-                return new LinkedHashMap<String, Object>(0);
-            } else {
-                query = schemeSpecificPart.substring(idx + 1);
-            }
-        } else {
-            query = stripPrefix(query, "?");
-        }
-        return parseQuery(query);
-    }
-
-    /**
-     * Strips the prefix from the value.
-     * <p/>
-     * Returns the value as-is if not starting with the prefix.
-     *
-     * @param value  the value
-     * @param prefix the prefix to remove from value
-     * @return the value without the prefix
-     */
-    public static String stripPrefix(String value, String prefix) {
-        if (value != null && value.startsWith(prefix)) {
-            return value.substring(prefix.length());
-        }
-        return value;
-    }
-
-    /**
-     * Parses the query part of the uri (eg the parameters).
-     * <p/>
-     * The URI parameters will by default be URI encoded. However you can define a parameter
-     * values with the syntax: <tt>key=RAW(value)</tt> which tells Camel to not encode the value,
-     * and use the value as is (eg key=value) and the value has <b>not</b> been encoded.
-     *
-     * @param uri the uri
-     * @return the parameters, or an empty map if no parameters (eg never null)
-     * @throws URISyntaxException is thrown if uri has invalid syntax.
-     * @see #RAW_TOKEN_START
-     * @see #RAW_TOKEN_END
-     */
-    public static Map<String, Object> parseQuery(String uri) throws URISyntaxException {
-        return parseQuery(uri, false);
-    }
-
-    /**
-     * Parses the query part of the uri (eg the parameters).
-     * <p/>
-     * The URI parameters will by default be URI encoded. However you can define a parameter
-     * values with the syntax: <tt>key=RAW(value)</tt> which tells Camel to not encode the value,
-     * and use the value as is (eg key=value) and the value has <b>not</b> been encoded.
-     *
-     * @param uri the uri
-     * @param useRaw whether to force using raw values
-     * @return the parameters, or an empty map if no parameters (eg never null)
-     * @throws URISyntaxException is thrown if uri has invalid syntax.
-     * @see #RAW_TOKEN_START
-     * @see #RAW_TOKEN_END
-     */
-    public static Map<String, Object> parseQuery(String uri, boolean useRaw) throws URISyntaxException {
-        // must check for trailing & as the uri.split("&") will ignore those
-        if (uri != null && uri.endsWith("&")) {
-            throw new URISyntaxException(uri, "Invalid uri syntax: Trailing & marker found. "
-                    + "Check the uri and remove the trailing & marker.");
-        }
-
-        if (isEmpty(uri)) {
-            // return an empty map
-            return new LinkedHashMap<String, Object>(0);
-        }
-
-        // need to parse the uri query parameters manually as we cannot rely on splitting by &,
-        // as & can be used in a parameter value as well.
-
-        try {
-            // use a linked map so the parameters is in the same order
-            Map<String, Object> rc = new LinkedHashMap<String, Object>();
-
-            boolean isKey = true;
-            boolean isValue = false;
-            boolean isRaw = false;
-            StringBuilder key = new StringBuilder();
-            StringBuilder value = new StringBuilder();
-
-            // parse the uri parameters char by char
-            for (int i = 0; i < uri.length(); i++) {
-                // current char
-                char ch = uri.charAt(i);
-                // look ahead of the next char
-                char next;
-                if (i <= uri.length() - 2) {
-                    next = uri.charAt(i + 1);
-                } else {
-                    next = '\u0000';
-                }
-
-                // are we a raw value
-                isRaw = value.toString().startsWith(RAW_TOKEN_START);
-
-                // if we are in raw mode, then we keep adding until we hit the end marker
-                if (isRaw) {
-                    if (isKey) {
-                        key.append(ch);
-                    } else if (isValue) {
-                        value.append(ch);
-                    }
-
-                    // we only end the raw marker if its )& or at the end of the value
-
-                    boolean end = ch == RAW_TOKEN_END.charAt(0) && (next == '&' || next == '\u0000');
-                    if (end) {
-                        // raw value end, so add that as a parameter, and reset flags
-                        addParameter(key.toString(), value.toString(), rc, useRaw || isRaw);
-                        key.setLength(0);
-                        value.setLength(0);
-                        isKey = true;
-                        isValue = false;
-                        isRaw = false;
-                        // skip to next as we are in raw mode and have already added the value
-                        i++;
-                    }
-                    continue;
-                }
-
-                // if its a key and there is a = sign then the key ends and we are in value mode
-                if (isKey && ch == '=') {
-                    isKey = false;
-                    isValue = true;
-                    isRaw = false;
-                    continue;
-                }
-
-                // the & denote parameter is ended
-                if (ch == '&') {
-                    // parameter is ended, as we hit & separator
-                    String aKey = key.toString();
-                    // the key may be a placeholder of options which we then do not know what is
-                    boolean validKey = !aKey.startsWith("{{") && !aKey.endsWith("}}");
-                    if (validKey) {
-                        addParameter(aKey, value.toString(), rc, useRaw || isRaw);
-                    }
-                    key.setLength(0);
-                    value.setLength(0);
-                    isKey = true;
-                    isValue = false;
-                    isRaw = false;
-                    continue;
-                }
-
-                // regular char so add it to the key or value
-                if (isKey) {
-                    key.append(ch);
-                } else if (isValue) {
-                    value.append(ch);
-                }
-            }
-
-            // any left over parameters, then add that
-            if (key.length() > 0) {
-                String aKey = key.toString();
-                // the key may be a placeholder of options which we then do not know what is
-                boolean validKey = !aKey.startsWith("{{") && !aKey.endsWith("}}");
-                if (validKey) {
-                    addParameter(aKey, value.toString(), rc, useRaw || isRaw);
-                }
-            }
-
-            return rc;
-
-        } catch (UnsupportedEncodingException e) {
-            URISyntaxException se = new URISyntaxException(e.toString(), "Invalid encoding");
-            se.initCause(e);
-            throw se;
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    private static void addParameter(String name, String value, Map<String, Object> map, boolean isRaw) throws UnsupportedEncodingException {
-        name = URLDecoder.decode(name, CHARSET);
-        if (!isRaw) {
-            // need to replace % with %25
-            value = URLDecoder.decode(value.replaceAll("%", "%25"), CHARSET);
-        }
-
-        // does the key already exist?
-        if (map.containsKey(name)) {
-            // yes it does, so make sure we can support multiple values, but using a list
-            // to hold the multiple values
-            Object existing = map.get(name);
-            List<String> list;
-            if (existing instanceof List) {
-                list = (List<String>) existing;
-            } else {
-                // create a new list to hold the multiple values
-                list = new ArrayList<String>();
-                String s = existing != null ? existing.toString() : null;
-                if (s != null) {
-                    list.add(s);
-                }
-            }
-            list.add(value);
-            map.put(name, list);
-        } else {
-            map.put(name, value);
-        }
-    }
-
-    /**
-     * Assembles a query from the given map.
-     *
-     * @param options  the map with the options (eg key/value pairs)
-     * @param ampersand to use & for Java code, and &amp; for XML
-     * @return a query string with <tt>key1=value&key2=value2&...</tt>, or an empty string if there is no options.
-     * @throws URISyntaxException is thrown if uri has invalid syntax.
-     */
-    public static String createQueryString(Map<String, String> options, String ampersand, boolean encode) throws URISyntaxException {
-        try {
-            if (options.size() > 0) {
-                StringBuilder rc = new StringBuilder();
-                boolean first = true;
-                for (Object o : options.keySet()) {
-                    if (first) {
-                        first = false;
-                    } else {
-                        rc.append(ampersand);
-                    }
-
-                    String key = (String) o;
-                    Object value = options.get(key);
-
-                    // use the value as a String
-                    String s = value != null ? value.toString() : null;
-                    appendQueryStringParameter(key, s, rc, encode);
-                }
-                return rc.toString();
-            } else {
-                return "";
-            }
-        } catch (UnsupportedEncodingException e) {
-            URISyntaxException se = new URISyntaxException(e.toString(), "Invalid encoding");
-            se.initCause(e);
-            throw se;
-        }
-    }
-
-    private static void appendQueryStringParameter(String key, String value, StringBuilder rc, boolean encode) throws UnsupportedEncodingException {
-        if (encode) {
-            rc.append(URLEncoder.encode(key, CHARSET));
-        } else {
-            rc.append(key);
-        }
-        // only append if value is not null
-        if (value != null) {
-            rc.append("=");
-            if (value.startsWith(RAW_TOKEN_START) && value.endsWith(RAW_TOKEN_END)) {
-                // do not encode RAW parameters
-                rc.append(value);
-            } else {
-                if (encode) {
-                    rc.append(URLEncoder.encode(value, CHARSET));
-                } else {
-                    rc.append(value);
-                }
-            }
-        }
-    }
-
-    /**
-     * Tests whether the value is <tt>null</tt> or an empty string.
-     *
-     * @param value  the value, if its a String it will be tested for text length as well
-     * @return true if empty
-     */
-    public static boolean isEmpty(Object value) {
-        return !isNotEmpty(value);
-    }
-
-    /**
-     * Tests whether the value is <b>not</b> <tt>null</tt> or an empty string.
-     *
-     * @param value  the value, if its a String it will be tested for text length as well
-     * @return true if <b>not</b> empty
-     */
-    public static boolean isNotEmpty(Object value) {
-        if (value == null) {
-            return false;
-        } else if (value instanceof String) {
-            String text = (String) value;
-            return text.trim().length() > 0;
-        } else {
-            return true;
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/UnsafeUriCharactersEncoder.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/UnsafeUriCharactersEncoder.java b/camel-core/src/main/java/org/apache/camel/catalog/UnsafeUriCharactersEncoder.java
deleted file mode 100644
index 563bac2..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/UnsafeUriCharactersEncoder.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/**
- * 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.catalog;
-
-import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Encoder for unsafe URI characters.
- * <p/>
- * A good source for details is <a href="http://en.wikipedia.org/wiki/Url_encode">wikipedia url encode</a> article.
- */
-public final class UnsafeUriCharactersEncoder {
-    private static BitSet unsafeCharactersRfc1738;
-    private static BitSet unsafeCharactersHttp;
-    private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
-        'D', 'E', 'F', 'a', 'b', 'c', 'd', 'e', 'f'};
-    private static final Pattern RAW_PATTERN = Pattern.compile("RAW\\([^\\)]+\\)");
-
-    static {
-        unsafeCharactersRfc1738 = new BitSet(256);
-        unsafeCharactersRfc1738.set(' ');
-        unsafeCharactersRfc1738.set('"');
-        unsafeCharactersRfc1738.set('<');
-        unsafeCharactersRfc1738.set('>');
-        unsafeCharactersRfc1738.set('#');
-        unsafeCharactersRfc1738.set('%');
-        unsafeCharactersRfc1738.set('{');
-        unsafeCharactersRfc1738.set('}');
-        unsafeCharactersRfc1738.set('|');
-        unsafeCharactersRfc1738.set('\\');
-        unsafeCharactersRfc1738.set('^');
-        unsafeCharactersRfc1738.set('~');
-        unsafeCharactersRfc1738.set('[');
-        unsafeCharactersRfc1738.set(']');
-        unsafeCharactersRfc1738.set('`');
-    }
-
-    static {
-        unsafeCharactersHttp = new BitSet(256);
-        unsafeCharactersHttp.set(' ');
-        unsafeCharactersHttp.set('"');
-        unsafeCharactersHttp.set('<');
-        unsafeCharactersHttp.set('>');
-        unsafeCharactersHttp.set('#');
-        unsafeCharactersHttp.set('%');
-        unsafeCharactersHttp.set('{');
-        unsafeCharactersHttp.set('}');
-        unsafeCharactersHttp.set('|');
-        unsafeCharactersHttp.set('\\');
-        unsafeCharactersHttp.set('^');
-        unsafeCharactersHttp.set('~');
-        unsafeCharactersHttp.set('`');
-    }
-
-    private UnsafeUriCharactersEncoder() {
-        // util class
-    }
-
-    public static String encode(String s) {
-        return encode(s, unsafeCharactersRfc1738);
-    }
-
-    public static String encodeHttpURI(String s) {
-        return encode(s, unsafeCharactersHttp);
-    }
-
-    public static String encode(String s, BitSet unsafeCharacters) {
-        return encode(s, unsafeCharacters, false);
-    }
-
-    public static String encode(String s, boolean checkRaw) {
-        return encode(s, unsafeCharactersRfc1738, checkRaw);
-    }
-
-    public static String encodeHttpURI(String s, boolean checkRaw) {
-        return encode(s, unsafeCharactersHttp, checkRaw);
-    }
-
-    private static List<Pair> checkRAW(String s) {
-        Matcher matcher = RAW_PATTERN.matcher(s);
-        List<Pair> answer = new ArrayList<Pair>();
-        // Check all occurrences
-        while (matcher.find()) {
-            answer.add(new Pair(matcher.start(), matcher.end()));
-        }
-        return answer;
-    }
-
-    private static boolean isRaw(int index, List<Pair> pairs) {
-        for (Pair pair : pairs) {
-            if (index < pair.left) {
-                return false;
-            } else {
-                if (index >= pair.left) {
-                    if (index <= pair.right) {
-                        return true;
-                    } else {
-                        continue;
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
-    private static class Pair {
-        int left;
-        int right;
-
-        Pair(int left, int right) {
-            this.left = left;
-            this.right = right;
-        }
-    }
-
-    // Just skip the encode for isRAW part
-    public static String encode(String s, BitSet unsafeCharacters, boolean checkRaw) {
-        List<Pair> rawPairs;
-        if (checkRaw) {
-            rawPairs = checkRAW(s);
-        } else {
-            rawPairs = new ArrayList<Pair>();
-        }
-
-        int n = s == null ? 0 : s.length();
-        if (n == 0) {
-            return s;
-        }
-
-        // First check whether we actually need to encode
-        char chars[] = s.toCharArray();
-        for (int i = 0;;) {
-            // just deal with the ascii character
-            if (chars[i] > 0 && chars[i] < 128) {
-                if (unsafeCharacters.get(chars[i])) {
-                    break;
-                }
-            }
-            if (++i >= chars.length) {
-                return s;
-            }
-        }
-
-        // okay there are some unsafe characters so we do need to encode
-        // see details at: http://en.wikipedia.org/wiki/Url_encode
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < chars.length; i++) {
-            char ch = chars[i];
-            if (ch > 0 && ch < 128 && unsafeCharacters.get(ch)) {
-                // special for % sign as it may be a decimal encoded value
-                if (ch == '%') {
-                    char next = i + 1 < chars.length ? chars[i + 1] : ' ';
-                    char next2 = i + 2 < chars.length ? chars[i + 2] : ' ';
-
-                    if (isHexDigit(next) && isHexDigit(next2) && !isRaw(i, rawPairs)) {
-                        // its already encoded (decimal encoded) so just append as is
-                        sb.append(ch);
-                    } else {
-                        // must escape then, as its an unsafe character
-                        appendEscape(sb, (byte) ch);
-                    }
-                } else {
-                    // must escape then, as its an unsafe character
-                    appendEscape(sb, (byte) ch);
-                }
-            } else {
-                sb.append(ch);
-            }
-        }
-        return sb.toString();
-    }
-
-    private static void appendEscape(StringBuilder sb, byte b) {
-        sb.append('%');
-        sb.append(HEX_DIGITS[(b >> 4) & 0x0f]);
-        sb.append(HEX_DIGITS[(b >> 0) & 0x0f]);
-    }
-
-    private static boolean isHexDigit(char ch) {
-        for (char hex : HEX_DIGITS) {
-            if (hex == ch) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/package.html
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/package.html b/camel-core/src/main/java/org/apache/camel/catalog/package.html
deleted file mode 100644
index 98786d1..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/package.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-    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.
--->
-<html>
-<head>
-</head>
-<body>
-
-Camel Catalog
-
-</body>
-</html>

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/component/rest/RestComponentVerifier.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/rest/RestComponentVerifier.java b/camel-core/src/main/java/org/apache/camel/component/rest/RestComponentVerifier.java
index 5d19e0d..4013e5f 100644
--- a/camel-core/src/main/java/org/apache/camel/component/rest/RestComponentVerifier.java
+++ b/camel-core/src/main/java/org/apache/camel/component/rest/RestComponentVerifier.java
@@ -22,12 +22,12 @@ import java.util.Map;
 import org.apache.camel.Component;
 import org.apache.camel.ComponentVerifier;
 import org.apache.camel.VerifiableComponent;
-import org.apache.camel.catalog.JSonSchemaHelper;
-import org.apache.camel.catalog.RuntimeCamelCatalog;
 import org.apache.camel.impl.verifier.CatalogVerifierCustomizer;
 import org.apache.camel.impl.verifier.DefaultComponentVerifier;
 import org.apache.camel.impl.verifier.ResultBuilder;
 import org.apache.camel.impl.verifier.ResultErrorBuilder;
+import org.apache.camel.runtimecatalog.JSonSchemaHelper;
+import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
 import org.apache.camel.spi.RestConsumerFactory;
 import org.apache.camel.spi.RestProducerFactory;
 import org.apache.camel.util.ObjectHelper;

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
index c85ce8c..b53efc8 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
@@ -26,7 +26,6 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.Date;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
@@ -87,8 +86,6 @@ import org.apache.camel.api.management.mbean.ManagedRouteMBean;
 import org.apache.camel.builder.DefaultFluentProducerTemplate;
 import org.apache.camel.builder.ErrorHandlerBuilder;
 import org.apache.camel.builder.ErrorHandlerBuilderSupport;
-import org.apache.camel.catalog.DefaultRuntimeCamelCatalog;
-import org.apache.camel.catalog.RuntimeCamelCatalog;
 import org.apache.camel.component.properties.PropertiesComponent;
 import org.apache.camel.impl.converter.BaseTypeConverterRegistry;
 import org.apache.camel.impl.converter.DefaultTypeConverter;
@@ -121,6 +118,8 @@ import org.apache.camel.processor.interceptor.Delayer;
 import org.apache.camel.processor.interceptor.HandleFault;
 import org.apache.camel.processor.interceptor.StreamCaching;
 import org.apache.camel.processor.interceptor.Tracer;
+import org.apache.camel.runtimecatalog.DefaultRuntimeCamelCatalog;
+import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
 import org.apache.camel.spi.AsyncProcessorAwaitManager;
 import org.apache.camel.spi.CamelContextNameStrategy;
 import org.apache.camel.spi.ClassResolver;

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultComponentVerifier.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultComponentVerifier.java b/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultComponentVerifier.java
index b9d9998..f05cdb1 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultComponentVerifier.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultComponentVerifier.java
@@ -25,8 +25,8 @@ import org.apache.camel.CamelContext;
 import org.apache.camel.ComponentVerifier;
 import org.apache.camel.NoSuchOptionException;
 import org.apache.camel.TypeConverter;
-import org.apache.camel.catalog.EndpointValidationResult;
-import org.apache.camel.catalog.RuntimeCamelCatalog;
+import org.apache.camel.runtimecatalog.EndpointValidationResult;
+import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
 import org.apache.camel.util.CamelContextHelper;
 import org.apache.camel.util.EndpointHelper;
 import org.apache.camel.util.IntrospectionSupport;

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java b/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java
index a09ff7d..9a70390 100644
--- a/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java
+++ b/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java
@@ -46,12 +46,9 @@ import org.apache.camel.StartupListener;
 import org.apache.camel.TimerListener;
 import org.apache.camel.VetoCamelContextStartException;
 import org.apache.camel.api.management.PerformanceCounter;
-import org.apache.camel.catalog.RuntimeCamelCatalog;
 import org.apache.camel.impl.ConsumerCache;
 import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.impl.DefaultEndpointRegistry;
-import org.apache.camel.impl.DefaultTransformerRegistry;
-import org.apache.camel.impl.DefaultValidatorRegistry;
 import org.apache.camel.impl.EventDrivenConsumerRoute;
 import org.apache.camel.impl.ProducerCache;
 import org.apache.camel.impl.ThrottlingExceptionRoutePolicy;
@@ -89,6 +86,7 @@ import org.apache.camel.processor.CamelInternalProcessor;
 import org.apache.camel.processor.interceptor.BacklogDebugger;
 import org.apache.camel.processor.interceptor.BacklogTracer;
 import org.apache.camel.processor.interceptor.Tracer;
+import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
 import org.apache.camel.spi.AsyncProcessorAwaitManager;
 import org.apache.camel.spi.DataFormat;
 import org.apache.camel.spi.EventNotifier;

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedRuntimeCamelCatalog.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedRuntimeCamelCatalog.java b/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedRuntimeCamelCatalog.java
index 20d3f28..6a99656 100644
--- a/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedRuntimeCamelCatalog.java
+++ b/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedRuntimeCamelCatalog.java
@@ -19,7 +19,7 @@ package org.apache.camel.management.mbean;
 import org.apache.camel.CamelContext;
 import org.apache.camel.api.management.ManagedResource;
 import org.apache.camel.api.management.mbean.ManagedRuntimeCamelCatalogMBean;
-import org.apache.camel.catalog.RuntimeCamelCatalog;
+import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
 import org.apache.camel.spi.ManagementStrategy;
 
 /**


[6/6] camel git commit: Rename catalog to runtimecatalog to avoid clash with same package name in camel-catalog.

Posted by da...@apache.org.
Rename catalog to runtimecatalog to avoid clash with same package name in camel-catalog.


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/c66be7a8
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/c66be7a8
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/c66be7a8

Branch: refs/heads/master
Commit: c66be7a8c21de8944fd86888a2cf039eb97a2ff1
Parents: d726964
Author: Claus Ibsen <da...@apache.org>
Authored: Fri Apr 14 12:08:59 2017 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Fri Apr 14 12:52:40 2017 +0200

----------------------------------------------------------------------
 .../java/org/apache/camel/CamelContext.java     |    2 +-
 .../camel/catalog/AbstractCamelCatalog.java     | 1294 ------------------
 .../catalog/CamelContextJSonSchemaResolver.java |   80 --
 .../org/apache/camel/catalog/CatalogHelper.java |  179 ---
 .../camel/catalog/CollectionStringBuffer.java   |   57 -
 .../catalog/DefaultRuntimeCamelCatalog.java     |  136 --
 .../camel/catalog/EndpointValidationResult.java |  451 ------
 .../apache/camel/catalog/JSonSchemaHelper.java  |  424 ------
 .../camel/catalog/JSonSchemaResolver.java       |   64 -
 .../camel/catalog/LanguageValidationResult.java |   65 -
 .../camel/catalog/RuntimeCamelCatalog.java      |  234 ----
 .../camel/catalog/SimpleValidationResult.java   |   32 -
 .../camel/catalog/SuggestionStrategy.java       |   34 -
 .../camel/catalog/TimePatternConverter.java     |  120 --
 .../org/apache/camel/catalog/URISupport.java    |  392 ------
 .../catalog/UnsafeUriCharactersEncoder.java     |  206 ---
 .../java/org/apache/camel/catalog/package.html  |   25 -
 .../component/rest/RestComponentVerifier.java   |    4 +-
 .../apache/camel/impl/DefaultCamelContext.java  |    5 +-
 .../impl/verifier/DefaultComponentVerifier.java |    4 +-
 .../DefaultManagementLifecycleStrategy.java     |    4 +-
 .../mbean/ManagedRuntimeCamelCatalog.java       |    2 +-
 .../runtimecatalog/AbstractCamelCatalog.java    | 1294 ++++++++++++++++++
 .../CamelContextJSonSchemaResolver.java         |   80 ++
 .../camel/runtimecatalog/CatalogHelper.java     |  179 +++
 .../runtimecatalog/CollectionStringBuffer.java  |   57 +
 .../DefaultRuntimeCamelCatalog.java             |  136 ++
 .../EndpointValidationResult.java               |  451 ++++++
 .../camel/runtimecatalog/JSonSchemaHelper.java  |  424 ++++++
 .../runtimecatalog/JSonSchemaResolver.java      |   64 +
 .../LanguageValidationResult.java               |   65 +
 .../runtimecatalog/RuntimeCamelCatalog.java     |  234 ++++
 .../runtimecatalog/SimpleValidationResult.java  |   32 +
 .../runtimecatalog/SuggestionStrategy.java      |   34 +
 .../runtimecatalog/TimePatternConverter.java    |  120 ++
 .../apache/camel/runtimecatalog/URISupport.java |  392 ++++++
 .../UnsafeUriCharactersEncoder.java             |  206 +++
 .../apache/camel/runtimecatalog/package.html    |   25 +
 .../org/apache/camel/util/EndpointHelper.java   |    6 +-
 .../camel/catalog/AbstractCamelCatalogTest.java |  104 --
 .../camel/catalog/RuntimeCamelCatalogTest.java  |  393 ------
 .../AbstractCamelCatalogTest.java               |  104 ++
 .../runtimecatalog/RuntimeCamelCatalogTest.java |  393 ++++++
 43 files changed, 4302 insertions(+), 4305 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/CamelContext.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/CamelContext.java b/camel-core/src/main/java/org/apache/camel/CamelContext.java
index d4fd6ae..00702d1 100644
--- a/camel-core/src/main/java/org/apache/camel/CamelContext.java
+++ b/camel-core/src/main/java/org/apache/camel/CamelContext.java
@@ -30,7 +30,6 @@ import org.apache.camel.api.management.mbean.ManagedCamelContextMBean;
 import org.apache.camel.api.management.mbean.ManagedProcessorMBean;
 import org.apache.camel.api.management.mbean.ManagedRouteMBean;
 import org.apache.camel.builder.ErrorHandlerBuilder;
-import org.apache.camel.catalog.RuntimeCamelCatalog;
 import org.apache.camel.model.DataFormatDefinition;
 import org.apache.camel.model.HystrixConfigurationDefinition;
 import org.apache.camel.model.ProcessorDefinition;
@@ -41,6 +40,7 @@ import org.apache.camel.model.rest.RestDefinition;
 import org.apache.camel.model.rest.RestsDefinition;
 import org.apache.camel.model.transformer.TransformerDefinition;
 import org.apache.camel.model.validator.ValidatorDefinition;
+import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
 import org.apache.camel.spi.AsyncProcessorAwaitManager;
 import org.apache.camel.spi.CamelContextNameStrategy;
 import org.apache.camel.spi.ClassResolver;

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/AbstractCamelCatalog.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/AbstractCamelCatalog.java b/camel-core/src/main/java/org/apache/camel/catalog/AbstractCamelCatalog.java
deleted file mode 100644
index 6511eff..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/AbstractCamelCatalog.java
+++ /dev/null
@@ -1,1294 +0,0 @@
-/**
- * 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.catalog;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import static org.apache.camel.catalog.CatalogHelper.after;
-import static org.apache.camel.catalog.JSonSchemaHelper.getNames;
-import static org.apache.camel.catalog.JSonSchemaHelper.getPropertyDefaultValue;
-import static org.apache.camel.catalog.JSonSchemaHelper.getPropertyEnum;
-import static org.apache.camel.catalog.JSonSchemaHelper.getPropertyKind;
-import static org.apache.camel.catalog.JSonSchemaHelper.getPropertyNameFromNameWithPrefix;
-import static org.apache.camel.catalog.JSonSchemaHelper.getPropertyPrefix;
-import static org.apache.camel.catalog.JSonSchemaHelper.getRow;
-import static org.apache.camel.catalog.JSonSchemaHelper.isComponentConsumerOnly;
-import static org.apache.camel.catalog.JSonSchemaHelper.isComponentLenientProperties;
-import static org.apache.camel.catalog.JSonSchemaHelper.isComponentProducerOnly;
-import static org.apache.camel.catalog.JSonSchemaHelper.isPropertyBoolean;
-import static org.apache.camel.catalog.JSonSchemaHelper.isPropertyConsumerOnly;
-import static org.apache.camel.catalog.JSonSchemaHelper.isPropertyInteger;
-import static org.apache.camel.catalog.JSonSchemaHelper.isPropertyMultiValue;
-import static org.apache.camel.catalog.JSonSchemaHelper.isPropertyNumber;
-import static org.apache.camel.catalog.JSonSchemaHelper.isPropertyObject;
-import static org.apache.camel.catalog.JSonSchemaHelper.isPropertyProducerOnly;
-import static org.apache.camel.catalog.JSonSchemaHelper.isPropertyRequired;
-import static org.apache.camel.catalog.JSonSchemaHelper.stripOptionalPrefixFromName;
-import static org.apache.camel.catalog.URISupport.createQueryString;
-import static org.apache.camel.catalog.URISupport.isEmpty;
-import static org.apache.camel.catalog.URISupport.normalizeUri;
-import static org.apache.camel.catalog.URISupport.stripQuery;
-
-/**
- * Base class for both the runtime RuntimeCamelCatalog from camel-core and the complete CamelCatalog from camel-catalog.
- */
-public abstract class AbstractCamelCatalog {
-
-    // CHECKSTYLE:OFF
-
-    private static final Pattern SYNTAX_PATTERN = Pattern.compile("(\\w+)");
-
-    private SuggestionStrategy suggestionStrategy;
-    private JSonSchemaResolver jsonSchemaResolver;
-
-    public SuggestionStrategy getSuggestionStrategy() {
-        return suggestionStrategy;
-    }
-
-    public void setSuggestionStrategy(SuggestionStrategy suggestionStrategy) {
-        this.suggestionStrategy = suggestionStrategy;
-    }
-
-    public JSonSchemaResolver getJSonSchemaResolver() {
-        return jsonSchemaResolver;
-    }
-
-    public void setJSonSchemaResolver(JSonSchemaResolver resolver) {
-        this.jsonSchemaResolver = resolver;
-    }
-
-    public boolean validateTimePattern(String pattern) {
-        return validateInteger(pattern);
-    }
-
-    public EndpointValidationResult validateEndpointProperties(String uri) {
-        return validateEndpointProperties(uri, false, false, false);
-    }
-
-    public EndpointValidationResult validateEndpointProperties(String uri, boolean ignoreLenientProperties) {
-        return validateEndpointProperties(uri, ignoreLenientProperties, false, false);
-    }
-
-    public EndpointValidationResult validateProperties(String scheme, Map<String, String> properties) {
-        EndpointValidationResult result = new EndpointValidationResult(scheme);
-
-        String json = jsonSchemaResolver.getComponentJSonSchema(scheme);
-        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
-        List<Map<String, String>> componentProps = JSonSchemaHelper.parseJsonSchema("componentProperties", json, true);
-
-        // endpoint options have higher priority so remove those from component
-        // that may clash
-        componentProps.stream()
-            .filter(c -> rows.stream().noneMatch(e -> Objects.equals(e.get("name"), c.get("name"))))
-            .forEach(rows::add);
-
-        boolean lenient = Boolean.getBoolean(properties.getOrDefault("lenient", "false"));
-
-        // the dataformat component refers to a data format so lets add the properties for the selected
-        // data format to the list of rows
-        if ("dataformat".equals(scheme)) {
-            String dfName = properties.get("name");
-            if (dfName != null) {
-                String dfJson = jsonSchemaResolver.getDataFormatJSonSchema(dfName);
-                List<Map<String, String>> dfRows = JSonSchemaHelper.parseJsonSchema("properties", dfJson, true);
-                if (dfRows != null && !dfRows.isEmpty()) {
-                    rows.addAll(dfRows);
-                }
-            }
-        }
-
-        for (Map.Entry<String, String> property : properties.entrySet()) {
-            String value = property.getValue();
-            String originalName = property.getKey();
-            String name = property.getKey();
-            // the name may be using an optional prefix, so lets strip that because the options
-            // in the schema are listed without the prefix
-            name = stripOptionalPrefixFromName(rows, name);
-            // the name may be using a prefix, so lets see if we can find the real property name
-            String propertyName = getPropertyNameFromNameWithPrefix(rows, name);
-            if (propertyName != null) {
-                name = propertyName;
-            }
-
-            String prefix = getPropertyPrefix(rows, name);
-            String kind = getPropertyKind(rows, name);
-            boolean namePlaceholder = name.startsWith("{{") && name.endsWith("}}");
-            boolean valuePlaceholder = value.startsWith("{{") || value.startsWith("${") || value.startsWith("$simple{");
-            boolean lookup = value.startsWith("#") && value.length() > 1;
-            // we cannot evaluate multi values as strict as the others, as we don't know their expected types
-            boolean multiValue = prefix != null && originalName.startsWith(prefix) && isPropertyMultiValue(rows, name);
-
-            Map<String, String> row = getRow(rows, name);
-            if (row == null) {
-                // unknown option
-
-                // only add as error if the component is not lenient properties, or not stub component
-                // and the name is not a property placeholder for one or more values
-                if (!namePlaceholder && !"stub".equals(scheme)) {
-                    if (lenient) {
-                        // as if we are lenient then the option is a dynamic extra option which we cannot validate
-                        result.addLenient(name);
-                    } else {
-                        // its unknown
-                        result.addUnknown(name);
-                        if (suggestionStrategy != null) {
-                            String[] suggestions = suggestionStrategy.suggestEndpointOptions(getNames(rows), name);
-                            if (suggestions != null) {
-                                result.addUnknownSuggestions(name, suggestions);
-                            }
-                        }
-                    }
-                }
-            } else {
-                /* TODO: we may need to add something in the properties to know if they are related to a producer or consumer
-                if ("parameter".equals(kind)) {
-                    // consumer only or producer only mode for parameters
-                    if (consumerOnly) {
-                        boolean producer = isPropertyProducerOnly(rows, name);
-                        if (producer) {
-                            // the option is only for producer so you cannot use it in consumer mode
-                            result.addNotConsumerOnly(name);
-                        }
-                    } else if (producerOnly) {
-                        boolean consumer = isPropertyConsumerOnly(rows, name);
-                        if (consumer) {
-                            // the option is only for consumer so you cannot use it in producer mode
-                            result.addNotProducerOnly(name);
-                        }
-                    }
-                }
-                */
-
-                // default value
-                String defaultValue = getPropertyDefaultValue(rows, name);
-                if (defaultValue != null) {
-                    result.addDefaultValue(name, defaultValue);
-                }
-
-                // is required but the value is empty
-                boolean required = isPropertyRequired(rows, name);
-                if (required && isEmpty(value)) {
-                    result.addRequired(name);
-                }
-
-                // is enum but the value is not within the enum range
-                // but we can only check if the value is not a placeholder
-                String enums = getPropertyEnum(rows, name);
-                if (!multiValue && !valuePlaceholder && !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(name, value);
-                        result.addInvalidEnumChoices(name, 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(name, suggestions);
-                            }
-                        }
-
-                    }
-                }
-
-                // is reference lookup of bean (not applicable for @UriPath, enums, or multi-valued)
-                if (!multiValue && enums == null && !"path".equals(kind) && isPropertyObject(rows, name)) {
-                    // must start with # and be at least 2 characters
-                    if (!value.startsWith("#") || value.length() <= 1) {
-                        result.addInvalidReference(name, value);
-                    }
-                }
-
-                // is boolean
-                if (!multiValue && !valuePlaceholder && !lookup && isPropertyBoolean(rows, name)) {
-                    // value must be a boolean
-                    boolean bool = "true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value);
-                    if (!bool) {
-                        result.addInvalidBoolean(name, value);
-                    }
-                }
-
-                // is integer
-                if (!multiValue && !valuePlaceholder && !lookup && isPropertyInteger(rows, name)) {
-                    // value must be an integer
-                    boolean valid = validateInteger(value);
-                    if (!valid) {
-                        result.addInvalidInteger(name, value);
-                    }
-                }
-
-                // is number
-                if (!multiValue && !valuePlaceholder && !lookup && isPropertyNumber(rows, name)) {
-                    // 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(name, value);
-                    }
-                }
-            }
-        }
-
-        // now check if all required values are there, and that a default value does not exists
-        for (Map<String, String> row : rows) {
-            String name = row.get("name");
-            boolean required = isPropertyRequired(rows, name);
-            if (required) {
-                String value = properties.get(name);
-                if (isEmpty(value)) {
-                    value = getPropertyDefaultValue(rows, name);
-                }
-                if (isEmpty(value)) {
-                    result.addRequired(name);
-                }
-            }
-        }
-
-        return result;
-    }
-
-    public EndpointValidationResult validateEndpointProperties(String uri, boolean ignoreLenientProperties, boolean consumerOnly, boolean producerOnly) {
-        EndpointValidationResult result = new EndpointValidationResult(uri);
-
-        Map<String, String> properties;
-        List<Map<String, String>> rows;
-        boolean lenientProperties;
-        String scheme;
-
-        try {
-            String json = null;
-
-            // parse the uri
-            URI u = normalizeUri(uri);
-            scheme = u.getScheme();
-
-            if (scheme != null) {
-                json = jsonSchemaResolver.getComponentJSonSchema(scheme);
-            }
-            if (json == null) {
-                // if the uri starts with a placeholder then we are also incapable of parsing it as we wasn't able to resolve the component name
-                if (uri.startsWith("{{")) {
-                    result.addIncapable(uri);
-                } else if (scheme != null) {
-                    result.addUnknownComponent(scheme);
-                } else {
-                    result.addUnknownComponent(uri);
-                }
-                return result;
-            }
-
-            rows = JSonSchemaHelper.parseJsonSchema("component", json, false);
-
-            // is the component capable of both consumer and producer?
-            boolean canConsumeAndProduce = false;
-            if (!isComponentConsumerOnly(rows) && !isComponentProducerOnly(rows)) {
-                canConsumeAndProduce = true;
-            }
-
-            if (canConsumeAndProduce && consumerOnly) {
-                // lenient properties is not support in consumer only mode if the component can do both of them
-                lenientProperties = false;
-            } else {
-                // only enable lenient properties if we should not ignore
-                lenientProperties = !ignoreLenientProperties && isComponentLenientProperties(rows);
-            }
-            rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
-            properties = endpointProperties(uri);
-        } catch (URISyntaxException e) {
-            if (uri.startsWith("{{")) {
-                // if the uri starts with a placeholder then we are also incapable of parsing it as we wasn't able to resolve the component name
-                result.addIncapable(uri);
-            } else {
-                result.addSyntaxError(e.getMessage());
-            }
-
-            return result;
-        }
-
-        // the dataformat component refers to a data format so lets add the properties for the selected
-        // data format to the list of rows
-        if ("dataformat".equals(scheme)) {
-            String dfName = properties.get("name");
-            if (dfName != null) {
-                String dfJson = jsonSchemaResolver.getDataFormatJSonSchema(dfName);
-                List<Map<String, String>> dfRows = JSonSchemaHelper.parseJsonSchema("properties", dfJson, true);
-                if (dfRows != null && !dfRows.isEmpty()) {
-                    rows.addAll(dfRows);
-                }
-            }
-        }
-
-        for (Map.Entry<String, String> property : properties.entrySet()) {
-            String value = property.getValue();
-            String originalName = property.getKey();
-            String name = property.getKey();
-            // the name may be using an optional prefix, so lets strip that because the options
-            // in the schema are listed without the prefix
-            name = stripOptionalPrefixFromName(rows, name);
-            // the name may be using a prefix, so lets see if we can find the real property name
-            String propertyName = getPropertyNameFromNameWithPrefix(rows, name);
-            if (propertyName != null) {
-                name = propertyName;
-            }
-
-            String prefix = getPropertyPrefix(rows, name);
-            String kind = getPropertyKind(rows, name);
-            boolean namePlaceholder = name.startsWith("{{") && name.endsWith("}}");
-            boolean valuePlaceholder = value.startsWith("{{") || value.startsWith("${") || value.startsWith("$simple{");
-            boolean lookup = value.startsWith("#") && value.length() > 1;
-            // we cannot evaluate multi values as strict as the others, as we don't know their expected types
-            boolean mulitValue = prefix != null && originalName.startsWith(prefix) && isPropertyMultiValue(rows, name);
-
-            Map<String, String> row = getRow(rows, name);
-            if (row == null) {
-                // unknown option
-
-                // only add as error if the component is not lenient properties, or not stub component
-                // and the name is not a property placeholder for one or more values
-                if (!namePlaceholder && !"stub".equals(scheme)) {
-                    if (lenientProperties) {
-                        // as if we are lenient then the option is a dynamic extra option which we cannot validate
-                        result.addLenient(name);
-                    } else {
-                        // its unknown
-                        result.addUnknown(name);
-                        if (suggestionStrategy != null) {
-                            String[] suggestions = suggestionStrategy.suggestEndpointOptions(getNames(rows), name);
-                            if (suggestions != null) {
-                                result.addUnknownSuggestions(name, suggestions);
-                            }
-                        }
-                    }
-                }
-            } else {
-                if ("parameter".equals(kind)) {
-                    // consumer only or producer only mode for parameters
-                    if (consumerOnly) {
-                        boolean producer = isPropertyProducerOnly(rows, name);
-                        if (producer) {
-                            // the option is only for producer so you cannot use it in consumer mode
-                            result.addNotConsumerOnly(name);
-                        }
-                    } else if (producerOnly) {
-                        boolean consumer = isPropertyConsumerOnly(rows, name);
-                        if (consumer) {
-                            // the option is only for consumer so you cannot use it in producer mode
-                            result.addNotProducerOnly(name);
-                        }
-                    }
-                }
-
-                // default value
-                String defaultValue = getPropertyDefaultValue(rows, name);
-                if (defaultValue != null) {
-                    result.addDefaultValue(name, defaultValue);
-                }
-
-                // is required but the value is empty
-                boolean required = isPropertyRequired(rows, name);
-                if (required && isEmpty(value)) {
-                    result.addRequired(name);
-                }
-
-                // is enum but the value is not within the enum range
-                // but we can only check if the value is not a placeholder
-                String enums = getPropertyEnum(rows, name);
-                if (!mulitValue && !valuePlaceholder && !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(name, value);
-                        result.addInvalidEnumChoices(name, 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(name, suggestions);
-                            }
-                        }
-
-                    }
-                }
-
-                // is reference lookup of bean (not applicable for @UriPath, enums, or multi-valued)
-                if (!mulitValue && enums == null && !"path".equals(kind) && isPropertyObject(rows, name)) {
-                    // must start with # and be at least 2 characters
-                    if (!value.startsWith("#") || value.length() <= 1) {
-                        result.addInvalidReference(name, value);
-                    }
-                }
-
-                // is boolean
-                if (!mulitValue && !valuePlaceholder && !lookup && isPropertyBoolean(rows, name)) {
-                    // value must be a boolean
-                    boolean bool = "true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value);
-                    if (!bool) {
-                        result.addInvalidBoolean(name, value);
-                    }
-                }
-
-                // is integer
-                if (!mulitValue && !valuePlaceholder && !lookup && isPropertyInteger(rows, name)) {
-                    // value must be an integer
-                    boolean valid = validateInteger(value);
-                    if (!valid) {
-                        result.addInvalidInteger(name, value);
-                    }
-                }
-
-                // is number
-                if (!mulitValue && !valuePlaceholder && !lookup && isPropertyNumber(rows, name)) {
-                    // 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(name, value);
-                    }
-                }
-            }
-        }
-
-        // now check if all required values are there, and that a default value does not exists
-        for (Map<String, String> row : rows) {
-            String name = row.get("name");
-            boolean required = isPropertyRequired(rows, name);
-            if (required) {
-                String value = properties.get(name);
-                if (isEmpty(value)) {
-                    value = getPropertyDefaultValue(rows, name);
-                }
-                if (isEmpty(value)) {
-                    result.addRequired(name);
-                }
-            }
-        }
-
-        return result;
-    }
-
-    public Map<String, String> endpointProperties(String uri) throws URISyntaxException {
-        // need to normalize uri first
-        URI u = normalizeUri(uri);
-        String scheme = u.getScheme();
-
-        String json = jsonSchemaResolver.getComponentJSonSchema(scheme);
-        if (json == null) {
-            throw new IllegalArgumentException("Cannot find endpoint with scheme " + scheme);
-        }
-
-        // grab the syntax
-        String syntax = null;
-        String alternativeSyntax = null;
-        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("component", json, false);
-        for (Map<String, String> row : rows) {
-            if (row.containsKey("syntax")) {
-                syntax = row.get("syntax");
-            }
-            if (row.containsKey("alternativeSyntax")) {
-                alternativeSyntax = row.get("alternativeSyntax");
-            }
-        }
-        if (syntax == null) {
-            throw new IllegalArgumentException("Endpoint with scheme " + scheme + " has no syntax defined in the json schema");
-        }
-
-        // only if we support alternative syntax, and the uri contains the username and password in the authority
-        // part of the uri, then we would need some special logic to capture that information and strip those
-        // details from the uri, so we can continue parsing the uri using the normal syntax
-        Map<String, String> userInfoOptions = new LinkedHashMap<String, String>();
-        if (alternativeSyntax != null && alternativeSyntax.contains("@")) {
-            // clip the scheme from the syntax
-            alternativeSyntax = after(alternativeSyntax, ":");
-            // trim so only userinfo
-            int idx = alternativeSyntax.indexOf("@");
-            String fields = alternativeSyntax.substring(0, idx);
-            String[] names = fields.split(":");
-
-            // grab authority part and grab username and/or password
-            String authority = u.getAuthority();
-            if (authority != null && authority.contains("@")) {
-                String username = null;
-                String password = null;
-
-                // grab unserinfo part before @
-                String userInfo = authority.substring(0, authority.indexOf("@"));
-                String[] parts = userInfo.split(":");
-                if (parts.length == 2) {
-                    username = parts[0];
-                    password = parts[1];
-                } else {
-                    // only username
-                    username = userInfo;
-                }
-
-                // remember the username and/or password which we add later to the options
-                if (names.length == 2) {
-                    userInfoOptions.put(names[0], username);
-                    if (password != null) {
-                        // password is optional
-                        userInfoOptions.put(names[1], password);
-                    }
-                }
-            }
-        }
-
-        // clip the scheme from the syntax
-        syntax = after(syntax, ":");
-        // clip the scheme from the uri
-        uri = after(uri, ":");
-        String uriPath = stripQuery(uri);
-
-        // strip user info from uri path
-        if (!userInfoOptions.isEmpty()) {
-            int idx = uriPath.indexOf('@');
-            if (idx > -1) {
-                uriPath = uriPath.substring(idx + 1);
-            }
-        }
-
-        // strip double slash in the start
-        if (uriPath != null && uriPath.startsWith("//")) {
-            uriPath = uriPath.substring(2);
-        }
-
-        // parse the syntax and find the names of each option
-        Matcher matcher = SYNTAX_PATTERN.matcher(syntax);
-        List<String> word = new ArrayList<String>();
-        while (matcher.find()) {
-            String s = matcher.group(1);
-            if (!scheme.equals(s)) {
-                word.add(s);
-            }
-        }
-        // parse the syntax and find each token between each option
-        String[] tokens = SYNTAX_PATTERN.split(syntax);
-
-        // find the position where each option start/end
-        List<String> word2 = new ArrayList<String>();
-        int prev = 0;
-        int prevPath = 0;
-
-        // special for activemq/jms where the enum for destinationType causes a token issue as it includes a colon
-        // for 'temp:queue' and 'temp:topic' values
-        if ("activemq".equals(scheme) || "jms".equals(scheme)) {
-            if (uriPath.startsWith("temp:")) {
-                prevPath = 5;
-            }
-        }
-
-        for (String token : tokens) {
-            if (token.isEmpty()) {
-                continue;
-            }
-
-            // special for some tokens where :// can be used also, eg http://foo
-            int idx = -1;
-            int len = 0;
-            if (":".equals(token)) {
-                idx = uriPath.indexOf("://", prevPath);
-                len = 3;
-            }
-            if (idx == -1) {
-                idx = uriPath.indexOf(token, prevPath);
-                len = token.length();
-            }
-
-            if (idx > 0) {
-                String option = uriPath.substring(prev, idx);
-                word2.add(option);
-                prev = idx + len;
-                prevPath = prev;
-            }
-        }
-        // special for last or if we did not add anyone
-        if (prev > 0 || word2.isEmpty()) {
-            String option = uriPath.substring(prev);
-            word2.add(option);
-        }
-
-        rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
-
-        boolean defaultValueAdded = false;
-
-        // now parse the uri to know which part isw what
-        Map<String, String> options = new LinkedHashMap<String, String>();
-
-        // include the username and password from the userinfo section
-        if (!userInfoOptions.isEmpty()) {
-            options.putAll(userInfoOptions);
-        }
-
-        // word contains the syntax path elements
-        Iterator<String> it = word2.iterator();
-        for (int i = 0; i < word.size(); i++) {
-            String key = word.get(i);
-
-            boolean allOptions = word.size() == word2.size();
-            boolean required = isPropertyRequired(rows, key);
-            String defaultValue = getPropertyDefaultValue(rows, key);
-
-            // we have all options so no problem
-            if (allOptions) {
-                String value = it.next();
-                options.put(key, value);
-            } else {
-                // we have a little problem as we do not not have all options
-                if (!required) {
-                    String value = null;
-
-                    boolean last = i == word.size() - 1;
-                    if (last) {
-                        // if its the last value then use it instead of the default value
-                        value = it.hasNext() ? it.next() : null;
-                        if (value != null) {
-                            options.put(key, value);
-                        } else {
-                            value = defaultValue;
-                        }
-                    }
-                    if (value != null) {
-                        options.put(key, value);
-                        defaultValueAdded = true;
-                    }
-                } else {
-                    String value = it.hasNext() ? it.next() : null;
-                    if (value != null) {
-                        options.put(key, value);
-                    }
-                }
-            }
-        }
-
-        Map<String, String> answer = new LinkedHashMap<String, String>();
-
-        // remove all options which are using default values and are not required
-        for (Map.Entry<String, String> entry : options.entrySet()) {
-            String key = entry.getKey();
-            String value = entry.getValue();
-
-            if (defaultValueAdded) {
-                boolean required = isPropertyRequired(rows, key);
-                String defaultValue = getPropertyDefaultValue(rows, key);
-
-                if (!required && defaultValue != null) {
-                    if (defaultValue.equals(value)) {
-                        continue;
-                    }
-                }
-            }
-
-            // we should keep this in the answer
-            answer.put(key, value);
-        }
-
-        // now parse the uri parameters
-        Map<String, Object> parameters = URISupport.parseParameters(u);
-
-        // and covert the values to String so its JMX friendly
-        while (!parameters.isEmpty()) {
-            Map.Entry<String, Object> entry = parameters.entrySet().iterator().next();
-            String key = entry.getKey();
-            String value = entry.getValue() != null ? entry.getValue().toString() : "";
-
-            boolean multiValued = isPropertyMultiValue(rows, key);
-            if (multiValued) {
-                String prefix = getPropertyPrefix(rows, key);
-                // extra all the multi valued options
-                Map<String, Object> values = URISupport.extractProperties(parameters, prefix);
-                // build a string with the extra multi valued options with the prefix and & as separator
-                CollectionStringBuffer csb = new CollectionStringBuffer("&");
-                for (Map.Entry<String, Object> multi : values.entrySet()) {
-                    String line = prefix + multi.getKey() + "=" + (multi.getValue() != null ? multi.getValue().toString() : "");
-                    csb.append(line);
-                }
-                // append the extra multi-values to the existing (which contains the first multi value)
-                if (!csb.isEmpty()) {
-                    value = value + "&" + csb.toString();
-                }
-            }
-
-            answer.put(key, value);
-            // remove the parameter as we run in a while loop until no more parameters
-            parameters.remove(key);
-        }
-
-        return answer;
-    }
-
-    public Map<String, String> endpointLenientProperties(String uri) throws URISyntaxException {
-        // need to normalize uri first
-
-        // parse the uri
-        URI u = normalizeUri(uri);
-        String scheme = u.getScheme();
-
-        String json = jsonSchemaResolver.getComponentJSonSchema(scheme);
-        if (json == null) {
-            throw new IllegalArgumentException("Cannot find endpoint with scheme " + scheme);
-        }
-
-        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
-
-        // now parse the uri parameters
-        Map<String, Object> parameters = URISupport.parseParameters(u);
-
-        // all the known options
-        Set<String> names = getNames(rows);
-
-        Map<String, String> answer = new LinkedHashMap<>();
-
-        // and covert the values to String so its JMX friendly
-        parameters.forEach((k, v) -> {
-            String key = k;
-            String value = v != null ? v.toString() : "";
-
-            // is the key a prefix property
-            int dot = key.indexOf('.');
-            if (dot != -1) {
-                String prefix = key.substring(0, dot + 1); // include dot in prefix
-                String option = getPropertyNameFromNameWithPrefix(rows, prefix);
-                if (option == null || !isPropertyMultiValue(rows, option)) {
-                    answer.put(key, value);
-                }
-            } else if (!names.contains(key)) {
-                answer.put(key, value);
-            }
-        });
-
-        return answer;
-    }
-
-    public String endpointComponentName(String uri) {
-        if (uri != null) {
-            int idx = uri.indexOf(":");
-            if (idx > 0) {
-                return uri.substring(0, idx);
-            }
-        }
-        return null;
-    }
-
-    public String asEndpointUri(String scheme, String json, boolean encode) throws URISyntaxException {
-        return doAsEndpointUri(scheme, json, "&", encode);
-    }
-
-    public String asEndpointUriXml(String scheme, String json, boolean encode) throws URISyntaxException {
-        return doAsEndpointUri(scheme, json, "&amp;", encode);
-    }
-
-    private String doAsEndpointUri(String scheme, String json, String ampersand, boolean encode) throws URISyntaxException {
-        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
-
-        Map<String, String> copy = new HashMap<String, String>();
-        for (Map<String, String> row : rows) {
-            String name = row.get("name");
-            String required = row.get("required");
-            String value = row.get("value");
-            String defaultValue = row.get("defaultValue");
-
-            // only add if either required, or the value is != default value
-            String valueToAdd = null;
-            if ("true".equals(required)) {
-                valueToAdd = value != null ? value : defaultValue;
-                if (valueToAdd == null) {
-                    valueToAdd = "";
-                }
-            } else {
-                // if we have a value and no default then add it
-                if (value != null && defaultValue == null) {
-                    valueToAdd = value;
-                }
-                // otherwise only add if the value is != default value
-                if (value != null && defaultValue != null && !value.equals(defaultValue)) {
-                    valueToAdd = value;
-                }
-            }
-
-            if (valueToAdd != null) {
-                copy.put(name, valueToAdd);
-            }
-        }
-
-        return doAsEndpointUri(scheme, copy, ampersand, encode);
-    }
-
-    public String asEndpointUri(String scheme, Map<String, String> properties, boolean encode) throws URISyntaxException {
-        return doAsEndpointUri(scheme, properties, "&", encode);
-    }
-
-    public String asEndpointUriXml(String scheme, Map<String, String> properties, boolean encode) throws URISyntaxException {
-        return doAsEndpointUri(scheme, properties, "&amp;", encode);
-    }
-
-    String doAsEndpointUri(String scheme, Map<String, String> properties, String ampersand, boolean encode) throws URISyntaxException {
-        String json = jsonSchemaResolver.getComponentJSonSchema(scheme);
-        if (json == null) {
-            throw new IllegalArgumentException("Cannot find endpoint with scheme " + scheme);
-        }
-
-        // grab the syntax
-        String syntax = null;
-        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("component", json, false);
-        for (Map<String, String> row : rows) {
-            if (row.containsKey("syntax")) {
-                syntax = row.get("syntax");
-                break;
-            }
-        }
-        if (syntax == null) {
-            throw new IllegalArgumentException("Endpoint with scheme " + scheme + " has no syntax defined in the json schema");
-        }
-
-        // do any properties filtering which can be needed for some special components
-        properties = filterProperties(scheme, properties);
-
-        rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
-
-        // clip the scheme from the syntax
-        syntax = after(syntax, ":");
-
-        String originalSyntax = syntax;
-
-        // build at first according to syntax (use a tree map as we want the uri options sorted)
-        Map<String, String> copy = new TreeMap<String, String>();
-        for (Map.Entry<String, String> entry : properties.entrySet()) {
-            String key = entry.getKey();
-            String value = entry.getValue() != null ? entry.getValue() : "";
-            if (syntax != null && syntax.contains(key)) {
-                syntax = syntax.replace(key, value);
-            } else {
-                copy.put(key, value);
-            }
-        }
-
-        // do we have all the options the original syntax needs (easy way)
-        String[] keys = syntaxKeys(originalSyntax);
-        boolean hasAllKeys = properties.keySet().containsAll(Arrays.asList(keys));
-
-        // build endpoint uri
-        StringBuilder sb = new StringBuilder();
-        sb.append(scheme);
-        sb.append(":");
-
-        if (hasAllKeys) {
-            // we have all the keys for the syntax so we can build the uri the easy way
-            sb.append(syntax);
-
-            if (!copy.isEmpty()) {
-                boolean hasQuestionmark = sb.toString().contains("?");
-                // the last option may already contain a ? char, if so we should use & instead of ?
-                sb.append(hasQuestionmark ? ampersand : '?');
-                String query = createQueryString(copy, ampersand, encode);
-                sb.append(query);
-            }
-        } else {
-            // TODO: revisit this and see if we can do this in another way
-            // oh darn some options is missing, so we need a complex way of building the uri
-
-            // the tokens between the options in the path
-            String[] tokens = syntax.split("\\w+");
-
-            // parse the syntax into each options
-            Matcher matcher = SYNTAX_PATTERN.matcher(originalSyntax);
-            List<String> options = new ArrayList<String>();
-            while (matcher.find()) {
-                String s = matcher.group(1);
-                options.add(s);
-            }
-
-            // need to preserve {{ and }} from the syntax
-            // (we need to use words only as its provisional placeholders)
-            syntax = syntax.replaceAll("\\{\\{", "BEGINCAMELPLACEHOLDER");
-            syntax = syntax.replaceAll("\\}\\}", "ENDCAMELPLACEHOLDER");
-
-            // parse the syntax into each options
-            Matcher matcher2 = SYNTAX_PATTERN.matcher(syntax);
-            List<String> options2 = new ArrayList<String>();
-            while (matcher2.find()) {
-                String s = matcher2.group(1);
-                s = s.replaceAll("BEGINCAMELPLACEHOLDER", "\\{\\{");
-                s = s.replaceAll("ENDCAMELPLACEHOLDER", "\\}\\}");
-                options2.add(s);
-            }
-
-            // build the endpoint
-            int range = 0;
-            boolean first = true;
-            boolean hasQuestionmark = false;
-            for (int i = 0; i < options.size(); i++) {
-                String key = options.get(i);
-                String key2 = options2.get(i);
-                String token = null;
-                if (tokens.length > i) {
-                    token = tokens[i];
-                }
-
-                boolean contains = properties.containsKey(key);
-                if (!contains) {
-                    // if the key are similar we have no explicit value and can try to find a default value if the option is required
-                    if (isPropertyRequired(rows, key)) {
-                        String value = getPropertyDefaultValue(rows, key);
-                        if (value != null) {
-                            properties.put(key, value);
-                            key2 = value;
-                        }
-                    }
-                }
-
-                // was the option provided?
-                if (properties.containsKey(key)) {
-                    if (!first && token != null) {
-                        sb.append(token);
-                    }
-                    hasQuestionmark |= key.contains("?") || (token != null && token.contains("?"));
-                    sb.append(key2);
-                    first = false;
-                }
-                range++;
-            }
-            // append any extra options that was in surplus for the last
-            while (range < options2.size()) {
-                String token = null;
-                if (tokens.length > range) {
-                    token = tokens[range];
-                }
-                String key2 = options2.get(range);
-                sb.append(token);
-                sb.append(key2);
-                hasQuestionmark |= key2.contains("?") || (token != null && token.contains("?"));
-                range++;
-            }
-
-
-            if (!copy.isEmpty()) {
-                // the last option may already contain a ? char, if so we should use & instead of ?
-                sb.append(hasQuestionmark ? ampersand : '?');
-                String query = createQueryString(copy, ampersand, encode);
-                sb.append(query);
-            }
-        }
-
-        return sb.toString();
-    }
-
-    @Deprecated
-    private static String[] syntaxTokens(String syntax) {
-        // build tokens between the words
-        List<String> tokens = new ArrayList<>();
-        // preserve backwards behavior which had an empty token first
-        tokens.add("");
-
-        String current = "";
-        for (int i = 0; i < syntax.length(); i++) {
-            char ch = syntax.charAt(i);
-            if (Character.isLetterOrDigit(ch)) {
-                // reset for new current tokens
-                if (current.length() > 0) {
-                    tokens.add(current);
-                    current = "";
-                }
-            } else {
-                current += ch;
-            }
-        }
-        // anything left over?
-        if (current.length() > 0) {
-            tokens.add(current);
-        }
-
-        return tokens.toArray(new String[tokens.size()]);
-    }
-
-    private static String[] syntaxKeys(String syntax) {
-        // build tokens between the separators
-        List<String> tokens = new ArrayList<>();
-
-        String current = "";
-        for (int i = 0; i < syntax.length(); i++) {
-            char ch = syntax.charAt(i);
-            if (Character.isLetterOrDigit(ch)) {
-                current += ch;
-            } else {
-                // reset for new current tokens
-                if (current.length() > 0) {
-                    tokens.add(current);
-                    current = "";
-                }
-            }
-        }
-        // anything left over?
-        if (current.length() > 0) {
-            tokens.add(current);
-        }
-
-        return tokens.toArray(new String[tokens.size()]);
-    }
-
-    public SimpleValidationResult validateSimpleExpression(String simple) {
-        return doValidateSimple(null, simple, false);
-    }
-
-    public SimpleValidationResult validateSimpleExpression(ClassLoader classLoader, String simple) {
-        return doValidateSimple(classLoader, simple, false);
-    }
-
-    public SimpleValidationResult validateSimplePredicate(String simple) {
-        return doValidateSimple(null, simple, true);
-    }
-
-    public SimpleValidationResult validateSimplePredicate(ClassLoader classLoader, String simple) {
-        return doValidateSimple(classLoader, simple, true);
-    }
-
-    private SimpleValidationResult doValidateSimple(ClassLoader classLoader, String simple, boolean predicate) {
-        if (classLoader == null) {
-            classLoader = getClass().getClassLoader();
-        }
-
-        // if there are {{ }}} property placeholders then we need to resolve them to something else
-        // as the simple parse cannot resolve them before parsing as we dont run the actual Camel application
-        // with property placeholders setup so we need to dummy this by replace the {{ }} to something else
-        // therefore we use an more unlikely character: {{XXX}} to ~^XXX^~
-        String resolved = simple.replaceAll("\\{\\{(.+)\\}\\}", "~^$1^~");
-
-        SimpleValidationResult answer = new SimpleValidationResult(simple);
-
-        Object instance = null;
-        Class clazz = null;
-        try {
-            clazz = classLoader.loadClass("org.apache.camel.language.simple.SimpleLanguage");
-            instance = clazz.newInstance();
-        } catch (Exception e) {
-            // ignore
-        }
-
-        if (clazz != null && instance != null) {
-            Throwable cause = null;
-            try {
-                if (predicate) {
-                    instance.getClass().getMethod("createPredicate", String.class).invoke(instance, resolved);
-                } else {
-                    instance.getClass().getMethod("createExpression", String.class).invoke(instance, resolved);
-                }
-            } catch (InvocationTargetException e) {
-                cause = e.getTargetException();
-            } catch (Exception e) {
-                cause = e;
-            }
-
-            if (cause != null) {
-
-                // reverse ~^XXX^~ back to {{XXX}}
-                String errMsg = cause.getMessage();
-                errMsg = errMsg.replaceAll("\\~\\^(.+)\\^\\~", "{{$1}}");
-
-                answer.setError(errMsg);
-
-                // is it simple parser exception then we can grab the index where the problem is
-                if (cause.getClass().getName().equals("org.apache.camel.language.simple.types.SimpleIllegalSyntaxException")
-                    || cause.getClass().getName().equals("org.apache.camel.language.simple.types.SimpleParserException")) {
-                    try {
-                        // we need to grab the index field from those simple parser exceptions
-                        Method method = cause.getClass().getMethod("getIndex");
-                        Object result = method.invoke(cause);
-                        if (result != null) {
-                            int index = (int) result;
-                            answer.setIndex(index);
-                        }
-                    } catch (Throwable i) {
-                        // ignore
-                    }
-                }
-
-                // we need to grab the short message field from this simple syntax exception
-                if (cause.getClass().getName().equals("org.apache.camel.language.simple.types.SimpleIllegalSyntaxException")) {
-                    try {
-                        Method method = cause.getClass().getMethod("getShortMessage");
-                        Object result = method.invoke(cause);
-                        if (result != null) {
-                            String msg = (String) result;
-                            answer.setShortError(msg);
-                        }
-                    } catch (Throwable i) {
-                        // ignore
-                    }
-
-                    if (answer.getShortError() == null) {
-                        // fallback and try to make existing message short instead
-                        String msg = answer.getError();
-                        // grab everything before " at location " which would be regarded as the short message
-                        int idx = msg.indexOf(" at location ");
-                        if (idx > 0) {
-                            msg = msg.substring(0, idx);
-                            answer.setShortError(msg);
-                        }
-                    }
-                }
-            }
-        }
-
-        return answer;
-    }
-
-    public LanguageValidationResult validateLanguagePredicate(ClassLoader classLoader, String language, String text) {
-        return doValidateLanguage(classLoader, language, text, true);
-    }
-
-    public LanguageValidationResult validateLanguageExpression(ClassLoader classLoader, String language, String text) {
-        return doValidateLanguage(classLoader, language, text, false);
-    }
-
-    private LanguageValidationResult doValidateLanguage(ClassLoader classLoader, String language, String text, boolean predicate) {
-        if (classLoader == null) {
-            classLoader = getClass().getClassLoader();
-        }
-
-        SimpleValidationResult answer = new SimpleValidationResult(text);
-
-        String json = jsonSchemaResolver.getLanguageJSonSchema(language);
-        if (json == null) {
-            answer.setError("Unknown language " + language);
-            return answer;
-        }
-
-        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("language", json, false);
-        String className = null;
-        for (Map<String, String> row : rows) {
-            if (row.containsKey("javaType")) {
-                className = row.get("javaType");
-            }
-        }
-
-        if (className == null) {
-            answer.setError("Cannot find javaType for language " + language);
-            return answer;
-        }
-
-        Object instance = null;
-        Class clazz = null;
-        try {
-            clazz = classLoader.loadClass(className);
-            instance = clazz.newInstance();
-        } catch (Exception e) {
-            // ignore
-        }
-
-        if (clazz != null && instance != null) {
-            Throwable cause = null;
-            try {
-                if (predicate) {
-                    instance.getClass().getMethod("createPredicate", String.class).invoke(instance, text);
-                } else {
-                    instance.getClass().getMethod("createExpression", String.class).invoke(instance, text);
-                }
-            } catch (InvocationTargetException e) {
-                cause = e.getTargetException();
-            } catch (Exception e) {
-                cause = e;
-            }
-
-            if (cause != null) {
-                answer.setError(cause.getMessage());
-            }
-        }
-
-        return answer;
-    }
-
-    /**
-     * Special logic for log endpoints to deal when showAll=true
-     */
-    private Map<String, String> filterProperties(String scheme, Map<String, String> options) {
-        if ("log".equals(scheme)) {
-            String showAll = options.get("showAll");
-            if ("true".equals(showAll)) {
-                Map<String, String> filtered = new LinkedHashMap<String, String>();
-                // remove all the other showXXX options when showAll=true
-                for (Map.Entry<String, String> entry : options.entrySet()) {
-                    String key = entry.getKey();
-                    boolean skip = key.startsWith("show") && !key.equals("showAll");
-                    if (!skip) {
-                        filtered.put(key, entry.getValue());
-                    }
-                }
-                return filtered;
-            }
-        }
-        // use as-is
-        return options;
-    }
-
-    private static boolean validateInteger(String value) {
-        boolean valid = false;
-        try {
-            valid = Integer.valueOf(value) != null;
-        } catch (Exception e) {
-            // ignore
-        }
-        if (!valid) {
-            // it may be a time pattern, such as 5s for 5 seconds = 5000
-            try {
-                TimePatternConverter.toMilliSeconds(value);
-                valid = true;
-            } catch (Exception e) {
-                // ignore
-            }
-        }
-        return valid;
-    }
-
-    // CHECKSTYLE:ON
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/CamelContextJSonSchemaResolver.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/CamelContextJSonSchemaResolver.java b/camel-core/src/main/java/org/apache/camel/catalog/CamelContextJSonSchemaResolver.java
deleted file mode 100644
index 8d95488..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/CamelContextJSonSchemaResolver.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * 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.catalog;
-
-import java.io.IOException;
-
-import org.apache.camel.CamelContext;
-
-/**
- * Uses runtime {@link CamelContext} to resolve the JSon schema files.
- */
-public class CamelContextJSonSchemaResolver implements JSonSchemaResolver {
-
-    private final CamelContext camelContext;
-
-    public CamelContextJSonSchemaResolver(CamelContext camelContext) {
-        this.camelContext = camelContext;
-    }
-
-    @Override
-    public String getComponentJSonSchema(String name) {
-        try {
-            return camelContext.getComponentParameterJsonSchema(name);
-        } catch (IOException e) {
-            // ignore
-        }
-        return null;
-    }
-
-    @Override
-    public String getDataFormatJSonSchema(String name) {
-        try {
-            return camelContext.getDataFormatParameterJsonSchema(name);
-        } catch (IOException e) {
-            // ignore
-        }
-        return null;
-    }
-
-    @Override
-    public String getLanguageJSonSchema(String name) {
-        try {
-            return camelContext.getLanguageParameterJsonSchema(name);
-        } catch (IOException e) {
-            // ignore
-        }
-        return null;
-    }
-
-    @Override
-    public String getOtherJSonSchema(String name) {
-        // not supported
-        return null;
-    }
-
-    @Override
-    public String getModelJSonSchema(String name) {
-        try {
-            return camelContext.getEipParameterJsonSchema(name);
-        } catch (IOException e) {
-            // ignore
-        }
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/CatalogHelper.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/CatalogHelper.java b/camel-core/src/main/java/org/apache/camel/catalog/CatalogHelper.java
deleted file mode 100644
index caba4a3..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/CatalogHelper.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/**
- * 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.catalog;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.LineNumberReader;
-import java.util.List;
-
-public final class CatalogHelper {
-
-    private CatalogHelper() {
-    }
-
-    /**
-     * Loads the entire stream into memory as a String and returns it.
-     * <p/>
-     * <b>Notice:</b> This implementation appends a <tt>\n</tt> as line
-     * terminator at the of the text.
-     * <p/>
-     * Warning, don't use for crazy big streams :)
-     */
-    public static void loadLines(InputStream in, List<String> lines) throws IOException {
-        try (final InputStreamReader isr = new InputStreamReader(in);
-            final BufferedReader reader = new LineNumberReader(isr)) {
-            String line;
-            while ((line = reader.readLine()) != null) {
-                lines.add(line);
-            }
-        }
-    }
-
-    /**
-     * Loads the entire stream into memory as a String and returns it.
-     * <p/>
-     * <b>Notice:</b> This implementation appends a <tt>\n</tt> as line
-     * terminator at the of the text.
-     * <p/>
-     * Warning, don't use for crazy big streams :)
-     */
-    public static String loadText(InputStream in) throws IOException {
-        StringBuilder builder = new StringBuilder();
-        try (final InputStreamReader isr = new InputStreamReader(in);
-            final BufferedReader reader = new LineNumberReader(isr)) {
-            String line;
-            while ((line = reader.readLine()) != null) {
-                builder.append(line);
-                builder.append("\n");
-            }
-            return builder.toString();
-        }
-    }
-
-    /**
-     * Matches the name with the pattern.
-     *
-     * @param name  the name
-     * @param pattern the pattern
-     * @return <tt>true</tt> if matched, or <tt>false</tt> if not
-     */
-    public static boolean matchWildcard(String name, String pattern) {
-        // we have wildcard support in that hence you can match with: file* to match any file endpoints
-        if (pattern.endsWith("*") && name.startsWith(pattern.substring(0, pattern.length() - 1))) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Returns the string after the given token
-     *
-     * @param text  the text
-     * @param after the token
-     * @return the text after the token, or <tt>null</tt> if text does not contain the token
-     */
-    public static String after(String text, String after) {
-        if (!text.contains(after)) {
-            return null;
-        }
-        return text.substring(text.indexOf(after) + after.length());
-    }
-
-    /**
-     * Returns the string before the given token
-     *
-     * @param text  the text
-     * @param before the token
-     * @return the text before the token, or <tt>null</tt> if text does not contain the token
-     */
-    public static String before(String text, String before) {
-        if (!text.contains(before)) {
-            return null;
-        }
-        return text.substring(0, text.indexOf(before));
-    }
-
-    /**
-     * Returns the string between the given tokens
-     *
-     * @param text  the text
-     * @param after the before token
-     * @param before the after token
-     * @return the text between the tokens, or <tt>null</tt> if text does not contain the tokens
-     */
-    public static String between(String text, String after, String before) {
-        text = after(text, after);
-        if (text == null) {
-            return null;
-        }
-        return before(text, before);
-    }
-
-    /**
-     * Tests whether the value is <tt>null</tt> or an empty string.
-     *
-     * @param value  the value, if its a String it will be tested for text length as well
-     * @return true if empty
-     */
-    public static boolean isEmpty(Object value) {
-        return !isNotEmpty(value);
-    }
-
-    /**
-     * Tests whether the value is <b>not</b> <tt>null</tt> or an empty string.
-     *
-     * @param value  the value, if its a String it will be tested for text length as well
-     * @return true if <b>not</b> empty
-     */
-    public static boolean isNotEmpty(Object value) {
-        if (value == null) {
-            return false;
-        } else if (value instanceof String) {
-            String text = (String) value;
-            return text.trim().length() > 0;
-        } else {
-            return true;
-        }
-    }
-
-    /**
-     * Removes all leading and ending quotes (single and double) from the string
-     *
-     * @param s  the string
-     * @return the string without leading and ending quotes (single and double)
-     */
-    public static String removeLeadingAndEndingQuotes(String s) {
-        if (isEmpty(s)) {
-            return s;
-        }
-
-        String copy = s.trim();
-        if (copy.startsWith("'") && copy.endsWith("'")) {
-            return copy.substring(1, copy.length() - 1);
-        }
-        if (copy.startsWith("\"") && copy.endsWith("\"")) {
-            return copy.substring(1, copy.length() - 1);
-        }
-
-        // no quotes, so return as-is
-        return s;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/CollectionStringBuffer.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/CollectionStringBuffer.java b/camel-core/src/main/java/org/apache/camel/catalog/CollectionStringBuffer.java
deleted file mode 100644
index 2844ca9..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/CollectionStringBuffer.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * 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.catalog;
-
-public class CollectionStringBuffer {
-    private final StringBuilder buffer = new StringBuilder();
-    private String separator;
-    private boolean first = true;
-
-    public CollectionStringBuffer() {
-        this(", ");
-    }
-
-    public CollectionStringBuffer(String separator) {
-        this.separator = separator;
-    }
-
-    @Override
-    public String toString() {
-        return buffer.toString();
-    }
-
-    public void append(Object value) {
-        if (first) {
-            first = false;
-        } else {
-            buffer.append(separator);
-        }
-        buffer.append(value);
-    }
-
-    public String getSeparator() {
-        return separator;
-    }
-
-    public void setSeparator(String separator) {
-        this.separator = separator;
-    }
-
-    public boolean isEmpty() {
-        return first;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/DefaultRuntimeCamelCatalog.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/DefaultRuntimeCamelCatalog.java b/camel-core/src/main/java/org/apache/camel/catalog/DefaultRuntimeCamelCatalog.java
deleted file mode 100644
index dd66c55..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/DefaultRuntimeCamelCatalog.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/**
- * 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.catalog;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.camel.CamelContext;
-
-/**
- * Default {@link RuntimeCamelCatalog}.
- */
-public class DefaultRuntimeCamelCatalog extends AbstractCamelCatalog implements RuntimeCamelCatalog {
-
-    // cache of operation -> result
-    private final Map<String, Object> cache = new HashMap<String, Object>();
-    private boolean caching;
-
-    /**
-     * Creates the {@link RuntimeCamelCatalog} without caching enabled.
-     *
-     * @param camelContext  the camel context
-     */
-    public DefaultRuntimeCamelCatalog(CamelContext camelContext) {
-        this(camelContext, false);
-    }
-
-    /**
-     * Creates the {@link RuntimeCamelCatalog}
-     *
-     * @param camelContext  the camel context
-     * @param caching  whether to use cache
-     */
-    public DefaultRuntimeCamelCatalog(CamelContext camelContext, boolean caching) {
-        this.caching = caching;
-        setJSonSchemaResolver(new CamelContextJSonSchemaResolver(camelContext));
-    }
-
-    @Override
-    public void start() throws Exception {
-        // noop
-    }
-
-    @Override
-    public void stop() throws Exception {
-        cache.clear();
-    }
-
-    @Override
-    public String modelJSonSchema(String name) {
-        String answer = null;
-        if (caching) {
-            answer = (String) cache.get("model-" + name);
-        }
-
-        if (answer == null) {
-            answer = getJSonSchemaResolver().getModelJSonSchema(name);
-            if (caching) {
-                cache.put("model-" + name, answer);
-            }
-        }
-
-        return answer;
-    }
-
-    @Override
-    public String componentJSonSchema(String name) {
-        String answer = null;
-        if (caching) {
-            answer = (String) cache.get("component-" + name);
-        }
-
-        if (answer == null) {
-            answer = getJSonSchemaResolver().getComponentJSonSchema(name);
-            if (caching) {
-                cache.put("component-" + name, answer);
-            }
-        }
-
-        return answer;
-    }
-
-    @Override
-    public String dataFormatJSonSchema(String name) {
-        String answer = null;
-        if (caching) {
-            answer = (String) cache.get("dataformat-" + name);
-        }
-
-        if (answer == null) {
-            answer = getJSonSchemaResolver().getDataFormatJSonSchema(name);
-            if (caching) {
-                cache.put("dataformat-" + name, answer);
-            }
-        }
-
-        return answer;
-    }
-
-    @Override
-    public String languageJSonSchema(String name) {
-        // if we try to look method then its in the bean.json file
-        if ("method".equals(name)) {
-            name = "bean";
-        }
-
-        String answer = null;
-        if (caching) {
-            answer = (String) cache.get("language-" + name);
-        }
-
-        if (answer == null) {
-            answer = getJSonSchemaResolver().getLanguageJSonSchema(name);
-            if (caching) {
-                cache.put("language-" + name, answer);
-            }
-        }
-
-        return answer;
-    }
-
-}