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/02/16 14:01:52 UTC

camel git commit: CAMEL-10842: Adjust connector to new JSon schema

Repository: camel
Updated Branches:
  refs/heads/master c4607e6c5 -> aea6e226b


CAMEL-10842: Adjust connector to new JSon schema


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

Branch: refs/heads/master
Commit: aea6e226b5177f3e476277822055df503ecabb32
Parents: c4607e6
Author: Claus Ibsen <da...@apache.org>
Authored: Thu Feb 16 14:41:03 2017 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Thu Feb 16 14:41:03 2017 +0100

----------------------------------------------------------------------
 .../maven/connector/CollectionStringBuffer.java |  58 ++
 .../camel/maven/connector/ConnectorMojo.java    |  70 ++-
 .../camel/maven/connector/JSonSchemaHelper.java | 552 ++++++++++---------
 .../camel/maven/connector/StringHelper.java     |  91 +++
 connectors/examples/bar-connector/pom.xml       |  32 +-
 .../main/resources/camel-connector-schema.json  |   7 +-
 .../src/main/resources/camel-connector.json     |   2 +-
 connectors/examples/foo-connector/pom.xml       |  32 +-
 .../main/resources/camel-connector-schema.json  |   7 +-
 .../src/main/resources/camel-connector.json     |   4 +-
 .../main/resources/camel-connector-schema.json  |  18 +-
 .../src/main/resources/camel-connector.json     |   2 +-
 .../examples/twitter-mention-connector/pom.xml  |  32 +-
 .../main/resources/camel-connector-schema.json  |  15 +-
 connectors/examples/wine-connector/pom.xml      |  32 +-
 .../main/resources/camel-connector-schema.json  |   5 +-
 connectors/pom.xml                              |   3 +-
 17 files changed, 608 insertions(+), 354 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/aea6e226/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/CollectionStringBuffer.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/CollectionStringBuffer.java b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/CollectionStringBuffer.java
new file mode 100644
index 0000000..d98779d
--- /dev/null
+++ b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/CollectionStringBuffer.java
@@ -0,0 +1,58 @@
+/**
+ * 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.maven.connector;
+
+/**
+ * A little helper class for converting a collection of values to a (usually comma separated) string.
+ */
+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;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/aea6e226/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/ConnectorMojo.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/ConnectorMojo.java b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/ConnectorMojo.java
index c5c6b2e..36d514f 100644
--- a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/ConnectorMojo.java
+++ b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/ConnectorMojo.java
@@ -23,8 +23,11 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
 import java.net.URLClassLoader;
+import java.util.Arrays;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
@@ -211,8 +214,6 @@ public class ConnectorMojo extends AbstractJarMojo {
         Map values = (Map) dto.get("componentValues");
         Map overrides = (Map) dto.get("componentOverrides");
 
-        ObjectMapper mapper = new ObjectMapper();
-
         StringBuilder sb = new StringBuilder();
         sb.append("  \"componentProperties\": {\n");
 
@@ -220,7 +221,6 @@ public class ConnectorMojo extends AbstractJarMojo {
         for (int i = 0; i < rows.size(); i++) {
             Map<String, String> row = rows.get(i);
             String key = row.get("name");
-            row.remove("name");
 
             if (options == null || !options.contains(key)) {
                 continue;
@@ -228,9 +228,10 @@ public class ConnectorMojo extends AbstractJarMojo {
 
             // do we have a new default value for this row?
             if (values != null && values.containsKey(key)) {
-                String newDefaultValue = (String) values.get(key);
+                // the value may be an integer so we need to use Object and toString when putting back in row
+                Object newDefaultValue = values.get(key);
                 if (newDefaultValue != null) {
-                    row.put("defaultValue", newDefaultValue);
+                    row.put("defaultValue", newDefaultValue.toString());
                 }
             }
 
@@ -244,13 +245,12 @@ public class ConnectorMojo extends AbstractJarMojo {
 
             // we should build the json as one-line which is how Camel does it today
             // which makes its internal json parser support loading our generated schema file
-            String line = mapper.writeValueAsString(row);
+            String line = buildJSonLineFromRow(row);
 
             if (!first) {
                 sb.append(",\n");
             }
-            sb.append("    \"" + key + "\": ");
-            sb.append(line);
+            sb.append("    ").append(line);
 
             first = false;
         }
@@ -277,7 +277,6 @@ public class ConnectorMojo extends AbstractJarMojo {
         for (int i = 0; i < rows.size(); i++) {
             Map<String, String> row = rows.get(i);
             String key = row.get("name");
-            row.remove("name");
 
             if (options == null || !options.contains(key)) {
                 continue;
@@ -285,9 +284,10 @@ public class ConnectorMojo extends AbstractJarMojo {
 
             // do we have a new default value for this row?
             if (values != null && values.containsKey(key)) {
-                String newDefaultValue = (String) values.get(key);
+                // the value may be an integer so we need to use Object and toString when putting back in row
+                Object newDefaultValue = values.get(key);
                 if (newDefaultValue != null) {
-                    row.put("defaultValue", newDefaultValue);
+                    row.put("defaultValue", newDefaultValue.toString());
                 }
             }
 
@@ -301,13 +301,12 @@ public class ConnectorMojo extends AbstractJarMojo {
 
             // we should build the json as one-line which is how Camel does it today
             // which makes its internal json parser support loading our generated schema file
-            String line = mapper.writeValueAsString(row);
+            String line = buildJSonLineFromRow(row);
 
             if (!first) {
                 sb.append(",\n");
             }
-            sb.append("    \"" + key + "\": ");
-            sb.append(line);
+            sb.append("    ").append(line);
 
             first = false;
         }
@@ -447,7 +446,40 @@ public class ConnectorMojo extends AbstractJarMojo {
         return null;
     }
 
-    private String extractClass(List<String> lines) {
+    /**
+     * Builds a JSon line of the given row
+     */
+    private static String buildJSonLineFromRow(Map<String, String> row) {
+        String name = row.get("name");
+        String kind = row.get("kind");
+        boolean required = Boolean.valueOf(row.getOrDefault("required", "false"));
+        String type = row.get("type");
+        String defaultValue = row.get("defaultValue");
+        String description = row.get("description");
+        boolean deprecated = Boolean.valueOf(row.getOrDefault("deprecated", "false"));
+        boolean secret = Boolean.valueOf(row.getOrDefault("secret", "false"));
+        String group = row.get("group");
+        String label = row.get("label");
+        // for enum we need to build it back as a set
+        Set<String> enums = null;
+        // the enum can either be a List or String
+        Object value = row.get("enum");
+        if (value != null && value instanceof List) {
+            enums = new LinkedHashSet<String>((List)value);
+        } else if (value != null && value instanceof String) {
+            String[] array = value.toString().split(",");
+            enums = Arrays.stream(array).collect(Collectors.toSet());
+        }
+        boolean enumType = enums != null;
+        String optionalPrefix = row.get("optionalPrefix");
+        String prefix = row.get("prefix");
+        boolean multiValue = Boolean.valueOf(row.getOrDefault("multiValue", "false"));
+
+        return JSonSchemaHelper.toJson(name, kind, required, type, defaultValue, description, deprecated, secret, group, label,
+            enumType, enums, false, null, false, optionalPrefix, prefix, multiValue);
+    }
+
+    private static String extractClass(List<String> lines) {
         for (String line : lines) {
             line = line.trim();
             if (line.startsWith("class=")) {
@@ -457,19 +489,19 @@ public class ConnectorMojo extends AbstractJarMojo {
         return null;
     }
 
-    private String extractScheme(Map map) {
+    private static String extractScheme(Map map) {
         return (String) map.get("baseScheme");
     }
 
-    private String extractGroupId(Map map) {
+    private static String extractGroupId(Map map) {
         return (String) map.get("baseGroupId");
     }
 
-    private String extractArtifactId(Map map) {
+    private static String extractArtifactId(Map map) {
         return (String) map.get("baseArtifactId");
     }
 
-    private String extractVersion(Map map) {
+    private static String extractVersion(Map map) {
         return (String) map.get("baseVersion");
     }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/aea6e226/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/JSonSchemaHelper.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/JSonSchemaHelper.java b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/JSonSchemaHelper.java
index 018d548..d778386 100644
--- a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/JSonSchemaHelper.java
+++ b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/JSonSchemaHelper.java
@@ -16,9 +16,12 @@
  */
 package org.apache.camel.maven.connector;
 
+import java.io.File;
+import java.net.URI;
+import java.net.URL;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -26,16 +29,284 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 /**
- * Basic JSon parser to read the Camel component JSon schema files.
+ * A helper class for <a href="http://json-schema.org/">JSON schema</a>.
  */
 public final class JSonSchemaHelper {
 
-    private static final Pattern PATTERN = Pattern.compile("\"(.+?)\"|\\[(.+)\\]");
+    private static final String VALID_CHARS = ".-='/\\!&():;";
+    // 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() {
     }
 
+    public static String toJson(String name, String kind, Boolean required, String type, String defaultValue, String description,
+                                Boolean deprecated, Boolean secret, String group, String label, boolean enumType, Set<String> enums,
+                                boolean oneOfType, Set<String> oneOffTypes, boolean asPredicate, String optionalPrefix, String prefix, boolean multiValue) {
+        String typeName = getType(type, enumType);
+
+        StringBuilder sb = new StringBuilder();
+        sb.append(StringHelper.doubleQuote(name));
+        sb.append(": { \"kind\": ");
+        sb.append(StringHelper.doubleQuote(kind));
+
+        // we want group early so its easier to spot
+        if (!StringHelper.isNullOrEmpty(group)) {
+            sb.append(", \"group\": ");
+            sb.append(StringHelper.doubleQuote(group));
+        }
+
+        // we want label early so its easier to spot
+        if (!StringHelper.isNullOrEmpty(label)) {
+            sb.append(", \"label\": ");
+            sb.append(StringHelper.doubleQuote(label));
+        }
+
+        if (required != null) {
+            // boolean type
+            sb.append(", \"required\": ");
+            sb.append(required.toString());
+        }
+
+        sb.append(", \"type\": ");
+        if ("enum".equals(typeName)) {
+            String actualType = getType(type, false);
+            sb.append(StringHelper.doubleQuote(actualType));
+            sb.append(", \"javaType\": \"" + type + "\"");
+            CollectionStringBuffer enumValues = new CollectionStringBuffer();
+            for (Object value : enums) {
+                enumValues.append(StringHelper.doubleQuote(value.toString()));
+            }
+            sb.append(", \"enum\": [ ");
+            sb.append(enumValues.toString());
+            sb.append(" ]");
+        } else if (oneOfType) {
+            sb.append(StringHelper.doubleQuote(typeName));
+            sb.append(", \"javaType\": \"" + type + "\"");
+            CollectionStringBuffer oneOfValues = new CollectionStringBuffer();
+            for (Object value : oneOffTypes) {
+                oneOfValues.append(StringHelper.doubleQuote(value.toString()));
+            }
+            sb.append(", \"oneOf\": [ ");
+            sb.append(oneOfValues.toString());
+            sb.append(" ]");
+        } else if ("array".equals(typeName)) {
+            sb.append(StringHelper.doubleQuote("array"));
+            sb.append(", \"javaType\": \"" + type + "\"");
+        } else {
+            sb.append(StringHelper.doubleQuote(typeName));
+            sb.append(", \"javaType\": \"" + type + "\"");
+        }
+
+        if (!StringHelper.isNullOrEmpty(optionalPrefix)) {
+            sb.append(", \"optionalPrefix\": ");
+            String text = safeDefaultValue(optionalPrefix);
+            sb.append(StringHelper.doubleQuote(text));
+        }
+
+        if (!StringHelper.isNullOrEmpty(prefix)) {
+            sb.append(", \"prefix\": ");
+            String text = safeDefaultValue(prefix);
+            sb.append(StringHelper.doubleQuote(text));
+        }
+        if (multiValue) {
+            // boolean value
+            sb.append(", \"multiValue\": true");
+        }
+
+        if (deprecated != null) {
+            sb.append(", \"deprecated\": ");
+            // boolean value
+            sb.append(deprecated.toString());
+        }
+
+        if (secret != null) {
+            sb.append(", \"secret\": ");
+            // boolean value
+            sb.append(secret.toString());
+        }
+
+        if (!StringHelper.isNullOrEmpty(defaultValue)) {
+            sb.append(", \"defaultValue\": ");
+            String text = safeDefaultValue(defaultValue);
+            // the type can either be boolean, integer, number or text based
+            if ("boolean".equals(typeName) || "integer".equals(typeName) || "number".equals(typeName)) {
+                sb.append(text);
+            } else {
+                // text should be quoted
+                sb.append(StringHelper.doubleQuote(text));
+            }
+        }
+
+        // for expressions we want to know if it must be used as predicate or not
+        boolean predicate = "expression".equals(kind) || asPredicate;
+        if (predicate) {
+            sb.append(", \"asPredicate\": ");
+            if (asPredicate) {
+                sb.append("true");
+            } else {
+                sb.append("false");
+            }
+        }
+
+        if (!StringHelper.isNullOrEmpty(description)) {
+            sb.append(", \"description\": ");
+            String text = sanitizeDescription(description, false);
+            sb.append(StringHelper.doubleQuote(text));
+        }
+
+        sb.append(" }");
+        return sb.toString();
+    }
+
+    /**
+     * Gets the JSon schema type.
+     *
+     * @param   type the java type
+     * @return  the json schema type, is never null, but returns <tt>object</tt> as the generic type
+     */
+    public static String getType(String type, boolean enumType) {
+        if (enumType) {
+            return "enum";
+        } else if (type == null) {
+            // return generic type for unknown type
+            return "object";
+        } else if (type.equals(URI.class.getName()) || type.equals(URL.class.getName())) {
+            return "string";
+        } else if (type.equals(File.class.getName())) {
+            return "string";
+        } else if (type.equals(Date.class.getName())) {
+            return "string";
+        } else if (type.startsWith("java.lang.Class")) {
+            return "string";
+        } else if (type.startsWith("java.util.List") || type.startsWith("java.util.Collection")) {
+            return "array";
+        }
+
+        String primitive = getPrimitiveType(type);
+        if (primitive != null) {
+            return primitive;
+        }
+
+        return "object";
+    }
+
+    /**
+     * Gets the JSon schema primitive type.
+     *
+     * @param   name the java type
+     * @return  the json schema primitive type, or <tt>null</tt> if not a primitive
+     */
+    public static String getPrimitiveType(String name) {
+
+        // special for byte[] or Object[] as its common to use
+        if ("java.lang.byte[]".equals(name) || "byte[]".equals(name)) {
+            return "string";
+        } else if ("java.lang.Byte[]".equals(name) || "Byte[]".equals(name)) {
+            return "array";
+        } else if ("java.lang.Object[]".equals(name) || "Object[]".equals(name)) {
+            return "array";
+        } else if ("java.lang.String[]".equals(name) || "String[]".equals(name)) {
+            return "array";
+        } else if ("java.lang.Character".equals(name) || "Character".equals(name) || "char".equals(name)) {
+            return "string";
+        } else if ("java.lang.String".equals(name) || "String".equals(name)) {
+            return "string";
+        } else if ("java.lang.Boolean".equals(name) || "Boolean".equals(name) || "boolean".equals(name)) {
+            return "boolean";
+        } else if ("java.lang.Integer".equals(name) || "Integer".equals(name) || "int".equals(name)) {
+            return "integer";
+        } else if ("java.lang.Long".equals(name) || "Long".equals(name) || "long".equals(name)) {
+            return "integer";
+        } else if ("java.lang.Short".equals(name) || "Short".equals(name) || "short".equals(name)) {
+            return "integer";
+        } else if ("java.lang.Byte".equals(name) || "Byte".equals(name) || "byte".equals(name)) {
+            return "integer";
+        } else if ("java.lang.Float".equals(name) || "Float".equals(name) || "float".equals(name)) {
+            return "number";
+        } else if ("java.lang.Double".equals(name) || "Double".equals(name) || "double".equals(name)) {
+            return "number";
+        }
+
+        return null;
+    }
+
+    /**
+     * Sanitizes the javadoc to removed invalid characters so it can be used as json description
+     *
+     * @param javadoc  the javadoc
+     * @return the text that is valid as json
+     */
+    public static String sanitizeDescription(String javadoc, boolean summary) {
+        if (StringHelper.isNullOrEmpty(javadoc)) {
+            return null;
+        }
+
+        // lets just use what java accepts as identifiers
+        StringBuilder sb = new StringBuilder();
+
+        // split into lines
+        String[] lines = javadoc.split("\n");
+
+        boolean first = true;
+        for (String line : lines) {
+            line = line.trim();
+
+            // terminate if we reach @param, @return or @deprecated as we only want the javadoc summary
+            if (line.startsWith("@param") || line.startsWith("@return") || line.startsWith("@deprecated")) {
+                break;
+            }
+
+            // skip lines that are javadoc references
+            if (line.startsWith("@")) {
+                continue;
+            }
+
+            // remove all XML tags
+            line = line.replaceAll("<.*?>", "");
+
+            // remove all inlined javadoc links, eg such as {@link org.apache.camel.spi.Registry}
+            line = line.replaceAll("\\{\\@\\w+\\s([\\w.]+)\\}", "$1");
+
+            // we are starting from a new line, so add a whitespace
+            if (!first) {
+                sb.append(' ');
+            }
+
+            // create a new line
+            StringBuilder cb = new StringBuilder();
+            for (char c : line.toCharArray()) {
+                if (Character.isJavaIdentifierPart(c) || VALID_CHARS.indexOf(c) != -1) {
+                    cb.append(c);
+                } else if (Character.isWhitespace(c)) {
+                    // always use space as whitespace, also for line feeds etc
+                    cb.append(' ');
+                }
+            }
+
+            // append data
+            String s = cb.toString().trim();
+            sb.append(s);
+
+            boolean empty = StringHelper.isNullOrEmpty(s);
+            boolean endWithDot = s.endsWith(".");
+            boolean haveText = sb.length() > 0;
+
+            if (haveText && summary && (empty || endWithDot)) {
+                // if we only want a summary, then skip at first empty line we encounter, or if the sentence ends with a dot
+                break;
+            }
+
+            first = false;
+        }
+
+        // remove double whitespaces, and trim
+        String s = sb.toString();
+        s = s.replaceAll("\\s+", " ");
+        return s.trim();
+    }
+
     /**
      * Parses the json schema to split it into a list or rows, where each row contains key value pairs with the metadata
      *
@@ -84,19 +355,34 @@ public final class JSonSchemaHelper {
                     key = matcher.group(1);
                 } else {
                     String value = matcher.group(1);
-                    if (value == null) {
-                        value = matcher.group(2);
-                        // its an enum so strip out " and trim spaces after comma
-                        value = value.replaceAll("\"", "");
-                        value = value.replaceAll(", ", ",");
-                    }
                     if (value != null) {
+                        // its text based
                         value = value.trim();
                         // decode
                         value = value.replaceAll(QUOT, "\"");
                         value = decodeJson(value);
                     }
-                    row.put(key, 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;
                 }
@@ -117,243 +403,17 @@ public final class JSonSchemaHelper {
         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 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"));
-            }
+    /**
+     * The default value may need to be escaped to be safe for json
+     */
+    private static String safeDefaultValue(String value) {
+        if ("\"".equals(value)) {
+            return "\\\"";
+        } else if ("\\".equals(value)) {
+            return "\\\\";
+        } else {
+            return value;
         }
-        return answer;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/aea6e226/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/StringHelper.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/StringHelper.java b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/StringHelper.java
index 10d514b..b3822a5 100644
--- a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/StringHelper.java
+++ b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/StringHelper.java
@@ -58,4 +58,95 @@ public final class StringHelper {
     public static String nullSafe(String text) {
         return text != null ? text : "";
     }
+
+    /**
+     * Returns true if the given text is null or empty string or has <tt>null</tt> as the value
+     */
+    public static boolean isNullOrEmpty(String text) {
+        return text == null || text.length() == 0 || "null".equals(text);
+    }
+
+    public static String safeNull(String text) {
+        if (isNullOrEmpty(text)) {
+            return "";
+        } else {
+            return text;
+        }
+    }
+
+    /**
+     * Returns the value or the defaultValue if it is null
+     */
+    public static String getOrElse(String text, String defaultValue) {
+        return (text != null) ? text : defaultValue;
+    }
+
+    /**
+     * 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 canonical class name by removing any generic type information.
+     */
+    public static String canonicalClassName(String className) {
+        // remove generics
+        int pos = className.indexOf('<');
+        if (pos != -1) {
+            return className.substring(0, pos);
+        } else {
+            return className;
+        }
+    }
+
+    /**
+     * Returns the text wrapped double quotes
+     */
+    public static String doubleQuote(String text) {
+        return quote(text, "\"");
+    }
+
+    /**
+     * Returns the text wrapped single quotes
+     */
+    public static String singleQuote(String text) {
+        return quote(text, "'");
+    }
+
+    /**
+     * Wraps the text in the given quote text
+     *
+     * @param text the text to wrap in quotes
+     * @param quote the quote text added to the prefix and postfix of the text
+     *
+     * @return the text wrapped in the given quotes
+     */
+    public static String quote(String text, String quote) {
+        return quote + text + quote;
+    }
+
+    /**
+     * Clips the text between the start and end markers
+     */
+    public static String between(String text, String start, String end) {
+        int pos = text.indexOf(start);
+        if (pos > 0) {
+            text = text.substring(pos + 1);
+        }
+        int pos2 = text.lastIndexOf(end);
+        if (pos2 > 0) {
+            text = text.substring(0, pos2);
+        }
+        return text;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/aea6e226/connectors/examples/bar-connector/pom.xml
----------------------------------------------------------------------
diff --git a/connectors/examples/bar-connector/pom.xml b/connectors/examples/bar-connector/pom.xml
index 7191e5c..feb962d 100644
--- a/connectors/examples/bar-connector/pom.xml
+++ b/connectors/examples/bar-connector/pom.xml
@@ -141,7 +141,20 @@
         </executions>
       </plugin>
 
-      <!-- generate connector -->
+      <!-- turn off jar plugin as we use connector plugin to jar instead -->
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <version>${maven-jar-plugin-version}</version>
+        <executions>
+          <execution>
+            <id>default-jar</id>
+            <phase/>
+          </execution>
+        </executions>
+      </plugin>
+
+      <!-- connector plugin will build the jar -->
       <plugin>
         <groupId>org.apache.camel</groupId>
         <artifactId>camel-connector-maven-plugin</artifactId>
@@ -149,24 +162,13 @@
         <executions>
           <execution>
             <id>connector</id>
+            <goals>
+              <goal>jar</goal>
+            </goals>
           </execution>
         </executions>
       </plugin>
 
-      <!-- to generate the MANIFEST-FILE of the bundle -->
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <version>${maven-bundle-plugin-version}</version>
-        <extensions>true</extensions>
-        <configuration>
-          <instructions>
-            <Bundle-SymbolicName>com.foo.bar</Bundle-SymbolicName>
-            <Export-Service>org.apache.camel.spi.ComponentResolver;component=bar</Export-Service>
-          </instructions>
-        </configuration>
-      </plugin>
-
     </plugins>
   </build>
 

http://git-wip-us.apache.org/repos/asf/camel/blob/aea6e226/connectors/examples/bar-connector/src/main/resources/camel-connector-schema.json
----------------------------------------------------------------------
diff --git a/connectors/examples/bar-connector/src/main/resources/camel-connector-schema.json b/connectors/examples/bar-connector/src/main/resources/camel-connector-schema.json
index 1c0dcdd..ff37add 100644
--- a/connectors/examples/bar-connector/src/main/resources/camel-connector-schema.json
+++ b/connectors/examples/bar-connector/src/main/resources/camel-connector-schema.json
@@ -10,6 +10,7 @@
     "deprecated": "false",
     "async": "false",
     "producerOnly": "true",
+    "lenientProperties": "false",
     "javaType": "org.foo.connector.BarComponent",
     "groupId": "org.foo",
     "artifactId": "bar-connector",
@@ -18,8 +19,8 @@
   "componentProperties": {
   },
   "properties": {
-    "drink": {"kind":"path","group":"producer","required":"true","type":"object","javaType":"org.beverage.Beverages","enum":"Beer,GinTonic,Wine","deprecated":"false","secret":"false","description":"What drink to order"},
-    "amount": {"kind":"parameter","group":"producer","type":"integer","javaType":"int","deprecated":"false","secret":"false","defaultValue":"2","description":"Number of drinks in the order"},
-    "celebrity": {"kind":"parameter","group":"producer","type":"boolean","javaType":"boolean","deprecated":"false","secret":"false","defaultValue":"false","description":"Is this a famous person ordering"}
+    "drink": { "kind": "path", "group": "producer", "required": true, "type": "object", "javaType": "object", "enum": [ "Wine", "GinTonic", "Beer" ], "deprecated": false, "secret": false, "description": "What drink to order" },
+    "amount": { "kind": "parameter", "group": "producer", "required": false, "type": "object", "javaType": "integer", "deprecated": false, "secret": false, "defaultValue": "2" },
+    "celebrity": { "kind": "parameter", "group": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "secret": false, "defaultValue": false, "description": "Is this a famous person ordering" }
   }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/aea6e226/connectors/examples/bar-connector/src/main/resources/camel-connector.json
----------------------------------------------------------------------
diff --git a/connectors/examples/bar-connector/src/main/resources/camel-connector.json b/connectors/examples/bar-connector/src/main/resources/camel-connector.json
index 50960df..e4062cc 100644
--- a/connectors/examples/bar-connector/src/main/resources/camel-connector.json
+++ b/connectors/examples/bar-connector/src/main/resources/camel-connector.json
@@ -15,6 +15,6 @@
   "pattern" : "To",
   "endpointOptions" : [ "drink", "amount", "celebrity" ],
   "endpointValues" : {
-    "amount" : "2"
+    "amount" : 2
   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/aea6e226/connectors/examples/foo-connector/pom.xml
----------------------------------------------------------------------
diff --git a/connectors/examples/foo-connector/pom.xml b/connectors/examples/foo-connector/pom.xml
index 0143208..3783ad2 100644
--- a/connectors/examples/foo-connector/pom.xml
+++ b/connectors/examples/foo-connector/pom.xml
@@ -141,7 +141,20 @@
         </executions>
       </plugin>
 
-      <!-- generate connector -->
+      <!-- turn off jar plugin as we use connector plugin to jar instead -->
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <version>${maven-jar-plugin-version}</version>
+        <executions>
+          <execution>
+            <id>default-jar</id>
+            <phase/>
+          </execution>
+        </executions>
+      </plugin>
+
+      <!-- connector plugin will build the jar -->
       <plugin>
         <groupId>org.apache.camel</groupId>
         <artifactId>camel-connector-maven-plugin</artifactId>
@@ -149,24 +162,13 @@
         <executions>
           <execution>
             <id>connector</id>
+            <goals>
+              <goal>jar</goal>
+            </goals>
           </execution>
         </executions>
       </plugin>
 
-      <!-- to generate the MANIFEST-FILE of the bundle -->
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <version>${maven-bundle-plugin-version}</version>
-        <extensions>true</extensions>
-        <configuration>
-          <instructions>
-            <Bundle-SymbolicName>org.foo.foo-connector</Bundle-SymbolicName>
-            <Export-Service>org.apache.camel.spi.ComponentResolver;component=foo</Export-Service>
-          </instructions>
-        </configuration>
-      </plugin>
-
     </plugins>
   </build>
 

http://git-wip-us.apache.org/repos/asf/camel/blob/aea6e226/connectors/examples/foo-connector/src/main/resources/camel-connector-schema.json
----------------------------------------------------------------------
diff --git a/connectors/examples/foo-connector/src/main/resources/camel-connector-schema.json b/connectors/examples/foo-connector/src/main/resources/camel-connector-schema.json
index eeca92c..24dd2c1 100644
--- a/connectors/examples/foo-connector/src/main/resources/camel-connector-schema.json
+++ b/connectors/examples/foo-connector/src/main/resources/camel-connector-schema.json
@@ -10,6 +10,7 @@
     "deprecated": "false",
     "async": "false",
     "consumerOnly": "true",
+    "lenientProperties": "false",
     "javaType": "org.foo.connector.FooComponent",
     "groupId": "org.foo",
     "artifactId": "foo-connector",
@@ -18,8 +19,8 @@
   "componentProperties": {
   },
   "properties": {
-    "timerName": {"kind":"path","group":"consumer","required":"true","type":"string","javaType":"java.lang.String","deprecated":"false","secret":"false","description":"The name of the timer"},
-    "period": {"kind":"parameter","group":"consumer","type":"integer","javaType":"long","deprecated":"false","secret":"false","defaultValue":"5000","description":"If greater than 0 generate periodic events every period milliseconds. The default value is 1000. You can also specify time values using units such as 60s (60 seconds) 5m30s (5 minutes and 30 seconds) and 1h (1 hour)."},
-    "repeatCount": {"kind":"parameter","group":"consumer","type":"integer","javaType":"long","deprecated":"false","secret":"false","defaultValue":"0","description":"Specifies a maximum limit of number of fires. So if you set it to 1 the timer will only fire once. If you set it to 5 it will only fire five times. A value of zero or negative means fire forever."}
+    "timerName": { "kind": "path", "group": "consumer", "required": true, "type": "object", "javaType": "string", "deprecated": false, "secret": false, "description": "The name of the timer" },
+    "period": { "kind": "parameter", "group": "consumer", "required": false, "type": "object", "javaType": "integer", "deprecated": false, "secret": false, "defaultValue": "5000", "description": "If greater than 0 generate periodic events every period milliseconds. The default value is 1000. You can also specify time values using units such as 60s (60 seconds) 5m30s (5 minutes and 30 seconds) and 1h (1 hour)." },
+    "repeatCount": { "kind": "parameter", "group": "consumer", "required": false, "type": "object", "javaType": "integer", "deprecated": false, "secret": false, "defaultValue": "description" }
   }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/aea6e226/connectors/examples/foo-connector/src/main/resources/camel-connector.json
----------------------------------------------------------------------
diff --git a/connectors/examples/foo-connector/src/main/resources/camel-connector.json b/connectors/examples/foo-connector/src/main/resources/camel-connector.json
index 31e81ea..0f6dec9 100644
--- a/connectors/examples/foo-connector/src/main/resources/camel-connector.json
+++ b/connectors/examples/foo-connector/src/main/resources/camel-connector.json
@@ -15,7 +15,7 @@
   "pattern" : "From",
   "endpointOptions" : [ "timerName", "period", "repeatCount" ],
   "endpointValues" : {
-    "fixedRate" : "true",
-    "period" : "5000"
+    "fixedRate" : true,
+    "period" : 5000
   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/aea6e226/connectors/examples/salesforce-upsert-contact-connector/src/main/resources/camel-connector-schema.json
----------------------------------------------------------------------
diff --git a/connectors/examples/salesforce-upsert-contact-connector/src/main/resources/camel-connector-schema.json b/connectors/examples/salesforce-upsert-contact-connector/src/main/resources/camel-connector-schema.json
index 2fc468e..a82c836 100644
--- a/connectors/examples/salesforce-upsert-contact-connector/src/main/resources/camel-connector-schema.json
+++ b/connectors/examples/salesforce-upsert-contact-connector/src/main/resources/camel-connector-schema.json
@@ -7,22 +7,22 @@
     "title": "SalesforceUpsertContact",
     "description": "Create or update Salesforce Contact SObject",
     "label": "salesforce",
-    "deprecated": "false",
-    "async": "false",
-    "producerOnly": "true",
+    "deprecated": false,
+    "async": false,
+    "producerOnly": true,
     "javaType": "org.foo.salesforce.contact.SalesforceUpsertContactComponent",
     "groupId": "org.foo",
     "artifactId": "salesforce-upsert-contact-connector",
     "version": "2.19.0-SNAPSHOT"
   },
   "componentProperties": {
-    "loginUrl": { "kind": "property", "group": "security", "label": "security", "required": "false", "type": "string", "javaType": "java.lang.String", "deprecated": "false", "secret": "false", "defaultValue": "https://login.salesforce.com", "description": "Salesforce login URL defaults to https://login.salesforce.com" },
-    "clientId": { "kind": "property", "group": "security", "label": "security", "required": "false", "type": "string", "javaType": "java.lang.String", "deprecated": "false", "secret": "true", "description": "Salesforce connected application Consumer Key" },
-    "clientSecret": { "kind": "property", "group": "security", "label": "security", "required": "false", "type": "string", "javaType": "java.lang.String", "deprecated": "false", "secret": "true", "description": "Salesforce connected application Consumer Secret" },
-    "refreshToken": { "kind": "property", "group": "security", "label": "security", "required": "false", "type": "string", "javaType": "java.lang.String", "deprecated": "false", "secret": "true", "description": "Salesforce connected application Consumer token" }
+    "loginUrl": { "kind": "property", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": false, "defaultValue": "https://login.salesforce.com", "description": "Salesforce login URL defaults to https://login.salesforce.com" },
+    "clientId": { "kind": "property", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": true, "description": "Salesforce connected application Consumer Key" },
+    "clientSecret": { "kind": "property", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": true, "description": "Salesforce connected application Consumer Secret" },
+    "refreshToken": { "kind": "property", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": true, "description": "Salesforce connected application Consumer token" }
   },
   "properties": {
-    "sObjectIdName": {"kind":"parameter","group":"common","type":"string","javaType":"java.lang.String","deprecated":"false","secret":"false","description":"SObject external ID field name","required":"true"},
-    "sObjectIdValue": {"kind":"parameter","group":"common","type":"string","javaType":"java.lang.String","deprecated":"false","secret":"false","description":"SObject external ID field value"}
+    "sObjectIdName": {"kind":"parameter","group":"common","type":"string","javaType":"java.lang.String","deprecated":false,"secret":false,"description":"SObject external ID field name","required":true},
+    "sObjectIdValue": {"kind":"parameter","group":"common","type":"string","javaType":"java.lang.String","deprecated":false,"secret":false,"description":"SObject external ID field value"}
   }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/aea6e226/connectors/examples/salesforce-upsert-contact-connector/src/main/resources/camel-connector.json
----------------------------------------------------------------------
diff --git a/connectors/examples/salesforce-upsert-contact-connector/src/main/resources/camel-connector.json b/connectors/examples/salesforce-upsert-contact-connector/src/main/resources/camel-connector.json
index 07aa0df..c1a26ec 100644
--- a/connectors/examples/salesforce-upsert-contact-connector/src/main/resources/camel-connector.json
+++ b/connectors/examples/salesforce-upsert-contact-connector/src/main/resources/camel-connector.json
@@ -17,7 +17,7 @@
     "operationName": "upsertSObject"
   },
   "endpointOverrides": {
-    "sObjectIdName": {"required":"true"}
+    "sObjectIdName": {"required": true}
   },
   "endpointOptions": [ "sObjectIdName", "sObjectIdValue" ]
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/aea6e226/connectors/examples/twitter-mention-connector/pom.xml
----------------------------------------------------------------------
diff --git a/connectors/examples/twitter-mention-connector/pom.xml b/connectors/examples/twitter-mention-connector/pom.xml
index dad717b..648d04a 100644
--- a/connectors/examples/twitter-mention-connector/pom.xml
+++ b/connectors/examples/twitter-mention-connector/pom.xml
@@ -147,7 +147,20 @@
         </executions>
       </plugin>
 
-      <!-- generate connector -->
+      <!-- turn off jar plugin as we use connector plugin to jar instead -->
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <version>${maven-jar-plugin-version}</version>
+        <executions>
+          <execution>
+            <id>default-jar</id>
+            <phase/>
+          </execution>
+        </executions>
+      </plugin>
+
+      <!-- connector plugin will build the jar -->
       <plugin>
         <groupId>org.apache.camel</groupId>
         <artifactId>camel-connector-maven-plugin</artifactId>
@@ -155,24 +168,13 @@
         <executions>
           <execution>
             <id>connector</id>
+            <goals>
+              <goal>jar</goal>
+            </goals>
           </execution>
         </executions>
       </plugin>
 
-      <!-- to generate the MANIFEST-FILE of the bundle -->
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <version>${maven-bundle-plugin-version}</version>
-        <extensions>true</extensions>
-        <configuration>
-          <instructions>
-            <Bundle-SymbolicName>org.foo.twitter-mention-connector</Bundle-SymbolicName>
-            <Export-Service>org.apache.camel.spi.ComponentResolver;component=twitter-mention</Export-Service>
-          </instructions>
-        </configuration>
-      </plugin>
-
     </plugins>
   </build>
 

http://git-wip-us.apache.org/repos/asf/camel/blob/aea6e226/connectors/examples/twitter-mention-connector/src/main/resources/camel-connector-schema.json
----------------------------------------------------------------------
diff --git a/connectors/examples/twitter-mention-connector/src/main/resources/camel-connector-schema.json b/connectors/examples/twitter-mention-connector/src/main/resources/camel-connector-schema.json
index 0cd1639..309f20c 100644
--- a/connectors/examples/twitter-mention-connector/src/main/resources/camel-connector-schema.json
+++ b/connectors/examples/twitter-mention-connector/src/main/resources/camel-connector-schema.json
@@ -7,19 +7,20 @@
     "title": "TwitterMention",
     "description": "Connection from twitter when anyone mention you",
     "label": "twitter",
-    "deprecated": "false",
-    "async": "false",
-    "consumerOnly": "true",
+    "deprecated": false,
+    "async": false,
+    "consumerOnly": true,
+    "lenientProperties": false,
     "javaType": "org.foo.mention.TwitterMentionComponent",
     "groupId": "org.foo",
     "artifactId": "twitter-mention-connector",
     "version": "2.19.0-SNAPSHOT"
   },
   "componentProperties": {
-    "accessToken": {"kind":"property","group":"security","label":"security","required":"false","type":"string","javaType":"java.lang.String","deprecated":"false","secret":"true","description":"The access token"},
-    "accessTokenSecret": {"kind":"property","group":"security","label":"security","required":"false","type":"string","javaType":"java.lang.String","deprecated":"false","secret":"true","description":"The access token secret"},
-    "consumerKey": {"kind":"property","group":"security","label":"security","required":"false","type":"string","javaType":"java.lang.String","deprecated":"false","secret":"true","description":"The consumer key"},
-    "consumerSecret": {"kind":"property","group":"security","label":"security","required":"false","type":"string","javaType":"java.lang.String","deprecated":"false","secret":"true","description":"The consumer secret"}
+    "accessToken": { "kind": "property", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "string", "deprecated": false, "secret": true, "description": "The access token" },
+    "accessTokenSecret": { "kind": "property", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "string", "deprecated": false, "secret": true, "description": "The access token secret" },
+    "consumerKey": { "kind": "property", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "string", "deprecated": false, "secret": true, "description": "The consumer key" },
+    "consumerSecret": { "kind": "property", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "string", "deprecated": false, "secret": true, "description": "The consumer secret" }
   },
   "properties": {
   }

http://git-wip-us.apache.org/repos/asf/camel/blob/aea6e226/connectors/examples/wine-connector/pom.xml
----------------------------------------------------------------------
diff --git a/connectors/examples/wine-connector/pom.xml b/connectors/examples/wine-connector/pom.xml
index d4d787c..b827538 100644
--- a/connectors/examples/wine-connector/pom.xml
+++ b/connectors/examples/wine-connector/pom.xml
@@ -141,7 +141,20 @@
         </executions>
       </plugin>
 
-      <!-- generate connector -->
+      <!-- turn off jar plugin as we use connector plugin to jar instead -->
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <version>${maven-jar-plugin-version}</version>
+        <executions>
+          <execution>
+            <id>default-jar</id>
+            <phase/>
+          </execution>
+        </executions>
+      </plugin>
+
+      <!-- connector plugin will build the jar -->
       <plugin>
         <groupId>org.apache.camel</groupId>
         <artifactId>camel-connector-maven-plugin</artifactId>
@@ -149,24 +162,13 @@
         <executions>
           <execution>
             <id>connector</id>
+            <goals>
+              <goal>jar</goal>
+            </goals>
           </execution>
         </executions>
       </plugin>
 
-      <!-- to generate the MANIFEST-FILE of the bundle -->
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <version>${maven-bundle-plugin-version}</version>
-        <extensions>true</extensions>
-        <configuration>
-          <instructions>
-            <Bundle-SymbolicName>com.foo.wine</Bundle-SymbolicName>
-            <Export-Service>org.apache.camel.spi.ComponentResolver;component=wine</Export-Service>
-          </instructions>
-        </configuration>
-      </plugin>
-
     </plugins>
   </build>
 

http://git-wip-us.apache.org/repos/asf/camel/blob/aea6e226/connectors/examples/wine-connector/src/main/resources/camel-connector-schema.json
----------------------------------------------------------------------
diff --git a/connectors/examples/wine-connector/src/main/resources/camel-connector-schema.json b/connectors/examples/wine-connector/src/main/resources/camel-connector-schema.json
index 4aff244..037edaf 100644
--- a/connectors/examples/wine-connector/src/main/resources/camel-connector-schema.json
+++ b/connectors/examples/wine-connector/src/main/resources/camel-connector-schema.json
@@ -10,6 +10,7 @@
     "deprecated": "false",
     "async": "false",
     "producerOnly": "true",
+    "lenientProperties": "false",
     "javaType": "org.foo.connector.WineComponent",
     "groupId": "org.foo",
     "artifactId": "wine-connector",
@@ -18,7 +19,7 @@
   "componentProperties": {
   },
   "properties": {
-    "drink": {"kind":"path","group":"producer","required":"true","type":"object","javaType":"org.beverage.Beverages","enum":["Wine"],"deprecated":"false","secret":"false","description":"You can only order wine","defaultValue":"Wine"},
-    "amount": {"kind":"parameter","group":"producer","type":"integer","javaType":"int","deprecated":"false","secret":"false","defaultValue":"1","description":"Number of drinks in the order"}
+    "drink": { "kind": "path", "group": "producer", "required": true, "type": "object", "javaType": "object", "enum": [ "Wine" ], "deprecated": false, "secret": false, "defaultValue": "Wine", "description": "You can only order wine" },
+    "amount": { "kind": "parameter", "group": "producer", "required": false, "type": "object", "javaType": "integer", "deprecated": false, "secret": false, "defaultValue": "description" }
   }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/aea6e226/connectors/pom.xml
----------------------------------------------------------------------
diff --git a/connectors/pom.xml b/connectors/pom.xml
index de66bc8..227673c 100644
--- a/connectors/pom.xml
+++ b/connectors/pom.xml
@@ -15,7 +15,8 @@
   See the License for the specific language governing permissions and
   limitations under the License.
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
   <modelVersion>4.0.0</modelVersion>