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/03/15 21:41:02 UTC

[1/3] camel git commit: CAMEL-10799: camel-connector - Generate spring boot auto configuration

Repository: camel
Updated Branches:
  refs/heads/master 7aeb3b769 -> 12ddb0fc8


CAMEL-10799: camel-connector - Generate spring boot auto configuration


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

Branch: refs/heads/master
Commit: f897d46870baf9eacf8d32d704f4bfaf13df3fd9
Parents: 7aeb3b7
Author: Claus Ibsen <da...@apache.org>
Authored: Wed Mar 15 20:15:44 2017 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Wed Mar 15 20:33:49 2017 +0100

----------------------------------------------------------------------
 connectors/camel-connector-maven-plugin/pom.xml |  22 +
 .../camel/maven/connector/ConnectorMojo.java    |   2 -
 .../SpringBootAutoConfigurationMojo.java        | 416 +++++++++++++++++++
 .../camel/maven/connector/StringHelper.java     |  27 ++
 .../maven/connector/model/ComponentModel.java   | 201 +++++++++
 .../connector/model/ComponentOptionModel.java   | 146 +++++++
 .../src/main/resources/license-header-java.txt  |  16 +
 .../src/main/resources/license-header.txt       |  16 +
 connectors/camel-connector/pom.xml              |  15 +
 9 files changed, 859 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/f897d468/connectors/camel-connector-maven-plugin/pom.xml
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/pom.xml b/connectors/camel-connector-maven-plugin/pom.xml
index 524b1be..48a8bc8 100644
--- a/connectors/camel-connector-maven-plugin/pom.xml
+++ b/connectors/camel-connector-maven-plugin/pom.xml
@@ -61,6 +61,28 @@
       <version>${jackson2-version}</version>
     </dependency>
 
+    <!-- roaster to create java source for Spring Boot auto configuration support -->
+    <dependency>
+      <groupId>org.jboss.forge.roaster</groupId>
+      <artifactId>roaster-api</artifactId>
+      <version>${roaster-version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.forge.roaster</groupId>
+      <artifactId>roaster-jdt</artifactId>
+      <version>${roaster-version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot</artifactId>
+      <version>${spring-boot-version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-autoconfigure</artifactId>
+      <version>${spring-boot-version}</version>
+    </dependency>
+
     <!-- logging -->
     <dependency>
       <groupId>org.slf4j</groupId>

http://git-wip-us.apache.org/repos/asf/camel/blob/f897d468/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 ce089d8..a9958a6 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
@@ -268,8 +268,6 @@ public class ConnectorMojo extends AbstractJarMojo {
         Map values = (Map) dto.get("endpointValues");
         Map overrides = (Map) dto.get("endpointOverrides");
 
-        ObjectMapper mapper = new ObjectMapper();
-
         StringBuilder sb = new StringBuilder();
         sb.append("  \"properties\": {\n");
 

http://git-wip-us.apache.org/repos/asf/camel/blob/f897d468/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java
new file mode 100644
index 0000000..a6dbd84
--- /dev/null
+++ b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java
@@ -0,0 +1,416 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.camel.maven.connector.model.ComponentModel;
+import org.apache.camel.maven.connector.model.ComponentOptionModel;
+import org.apache.commons.io.FileUtils;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.jboss.forge.roaster.Roaster;
+import org.jboss.forge.roaster.model.source.AnnotationSource;
+import org.jboss.forge.roaster.model.source.Import;
+import org.jboss.forge.roaster.model.source.JavaClassSource;
+import org.jboss.forge.roaster.model.source.MethodSource;
+import org.jboss.forge.roaster.model.source.PropertySource;
+import org.jboss.forge.roaster.model.util.Formatter;
+import org.jboss.forge.roaster.model.util.Strings;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.context.properties.DeprecatedConfigurationProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import static org.apache.camel.maven.connector.FileHelper.loadText;
+import static org.apache.camel.maven.connector.StringHelper.getSafeValue;
+
+/**
+ * Generate Spring Boot auto configuration files for Camel connectors.
+ */
+@Mojo(name = "prepare-spring-boot-auto-configuration",
+    defaultPhase = LifecyclePhase.PACKAGE,
+    requiresProject = true, threadSafe = true)
+public class SpringBootAutoConfigurationMojo extends AbstractMojo {
+
+    @Parameter(defaultValue = "${project.build.outputDirectory}", required = true)
+    private File classesDirectory;
+
+    @Parameter(defaultValue = "${basedir}", required = true)
+    private File baseDir;
+
+    @Parameter(defaultValue = "true")
+    private boolean includeLicenseHeader;
+
+    @Override
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        try {
+            executeConnector();
+        } catch (Exception e) {
+            throw new MojoFailureException("Error generating Spring-Boot auto configuration for connector", e);
+        }
+    }
+
+    private void executeConnector() throws Exception {
+
+        String javaType = null;
+        String connectorScheme = null;
+
+        File file = new File(classesDirectory, "camel-connector.json");
+        if (file.exists()) {
+            ObjectMapper mapper = new ObjectMapper();
+            Map dto = mapper.readValue(file, Map.class);
+
+            javaType = (String) dto.get("javaType");
+            connectorScheme = (String) dto.get("scheme");
+        }
+
+        // find the component dependency and get its .json file
+        file = new File(classesDirectory, "camel-component-schema.json");
+        if (file.exists() && javaType != null && connectorScheme != null) {
+            String json = loadText(new FileInputStream(file));
+            ComponentModel model = generateComponentModel(json);
+
+            // resolvePropertyPlaceholders is an option which only make sense to use if the component has other options
+            boolean hasOptions = model.getComponentOptions().stream().anyMatch(o -> !o.getName().equals("resolvePropertyPlaceholders"));
+
+            // use springboot as sub package name so the code is not in normal
+            // package so the Spring Boot JARs can be optional at runtime
+            int pos = javaType.lastIndexOf(".");
+            String pkg = javaType.substring(0, pos) + ".springboot";
+
+            getLog().info("Generating Spring Boot AutoConfiguration for Connector: " + model.getScheme());
+
+            if (hasOptions) {
+                createConnectorConfigurationSource(pkg, model, javaType, connectorScheme);
+            }
+            createConnectorAutoConfigurationSource(pkg, model, hasOptions, javaType, connectorScheme);
+            createConnectorSpringFactorySource(pkg, model);
+        } else {
+            getLog().warn("Cannot generate Spring Boot AutoConfiguration as camel-component-schema.json file missing");
+        }
+    }
+
+    private void createConnectorSpringFactorySource(String packageName, ComponentModel model) throws MojoFailureException {
+        int pos = model.getJavaType().lastIndexOf(".");
+        String name = model.getJavaType().substring(pos + 1);
+        name = name.replace("Component", "ConnectorAutoConfiguration");
+
+        writeComponentSpringFactorySource(packageName, name);
+    }
+
+    private void writeComponentSpringFactorySource(String packageName, String name) throws MojoFailureException {
+        StringBuilder sb = new StringBuilder();
+        sb.append("org.springframework.boot.autoconfigure.EnableAutoConfiguration=\\\n");
+
+        String lineToAdd = packageName + "." + name + "\n";
+        sb.append(lineToAdd);
+
+        String fileName = "src/main/resources/META-INF/spring.factories";
+        File target = new File(baseDir, fileName);
+
+        // create new file
+        try {
+            String header = "";
+            if (includeLicenseHeader) {
+                InputStream is = getClass().getClassLoader().getResourceAsStream("license-header.txt");
+                header = loadText(is);
+            }
+            String code = sb.toString();
+            // add empty new line after header
+            code = header + "\n" + code;
+            getLog().debug("Source code generated:\n" + code);
+
+            FileUtils.write(target, code);
+            getLog().info("Created file: " + target);
+        } catch (Exception e) {
+            throw new MojoFailureException("IOError with file " + target, e);
+        }
+    }
+
+    private void createConnectorConfigurationSource(String packageName, ComponentModel model, String javaType, String connectorScheme) throws MojoFailureException {
+        final JavaClassSource javaClass = Roaster.create(JavaClassSource.class);
+
+        int pos = javaType.lastIndexOf(".");
+        String name = javaType.substring(pos + 1);
+        name = name.replace("Component", "ConnectorConfiguration");
+        javaClass.setPackage(packageName).setName(name);
+
+        String doc = "Generated by camel-connector-maven-plugin - do not edit this file!";
+        if (!Strings.isBlank(model.getDescription())) {
+            doc = model.getDescription() + "\n\n" + doc;
+        }
+        // replace Component with Connector
+        doc = doc.replaceAll("Component", "Connector");
+        doc = doc.replaceAll("component", "connector");
+        javaClass.getJavaDoc().setFullText(doc);
+
+        String prefix = "camel.connector." + model.getScheme();
+        // make sure prefix is in lower case
+        prefix = connectorScheme.toLowerCase(Locale.US);
+        javaClass.addAnnotation("org.springframework.boot.context.properties.ConfigurationProperties").setStringValue("prefix", prefix);
+
+        for (ComponentOptionModel option : model.getComponentOptions()) {
+            String type = option.getJavaType();
+            PropertySource<JavaClassSource> prop = javaClass.addProperty(type, option.getName());
+
+            // TODO: only include the global options so we can configure them
+
+            if ("true".equals(option.getDeprecated())) {
+                prop.getField().addAnnotation(Deprecated.class);
+                prop.getAccessor().addAnnotation(Deprecated.class);
+                prop.getMutator().addAnnotation(Deprecated.class);
+                // DeprecatedConfigurationProperty must be on getter when deprecated
+                prop.getAccessor().addAnnotation(DeprecatedConfigurationProperty.class);
+            }
+            if (!Strings.isBlank(option.getDescription())) {
+                prop.getField().getJavaDoc().setFullText(option.getDescription());
+            }
+            if (!Strings.isBlank(option.getDefaultValue())) {
+                if ("java.lang.String".equals(option.getJavaType())) {
+                    prop.getField().setStringInitializer(option.getDefaultValue());
+                } else if ("long".equals(option.getJavaType()) || "java.lang.Long".equals(option.getJavaType())) {
+                    // the value should be a Long number
+                    String value = option.getDefaultValue() + "L";
+                    prop.getField().setLiteralInitializer(value);
+                } else if ("integer".equals(option.getType()) || "boolean".equals(option.getType())) {
+                    prop.getField().setLiteralInitializer(option.getDefaultValue());
+                } else if (!Strings.isBlank(option.getEnums())) {
+                    String enumShortName = type.substring(type.lastIndexOf(".") + 1);
+                    prop.getField().setLiteralInitializer(enumShortName + "." + option.getDefaultValue());
+                    javaClass.addImport(model.getJavaType());
+                }
+            }
+        }
+
+
+        sortImports(javaClass);
+
+        String fileName = packageName.replaceAll("\\.", "\\/") + "/" + name + ".java";
+
+        writeSourceIfChanged(javaClass, fileName);
+    }
+
+    private void createConnectorAutoConfigurationSource(String packageName, ComponentModel model, boolean hasOptions,
+                                                        String javaType, String connectorScheme) throws MojoFailureException {
+
+        final JavaClassSource javaClass = Roaster.create(JavaClassSource.class);
+
+        int pos = javaType.lastIndexOf(".");
+        String name = javaType.substring(pos + 1);
+        name = name.replace("Component", "ConnectorAutoConfiguration");
+
+        javaClass.setPackage(packageName).setName(name);
+
+        String doc = "Generated by camel-connector-maven-plugin - do not edit this file!";
+        javaClass.getJavaDoc().setFullText(doc);
+
+        javaClass.addAnnotation(Configuration.class);
+        javaClass.addAnnotation(ConditionalOnBean.class).setStringValue("type", "org.apache.camel.spring.boot.CamelAutoConfiguration");
+        javaClass.addAnnotation(AutoConfigureAfter.class).setStringValue("name", "org.apache.camel.spring.boot.CamelAutoConfiguration");
+
+        String configurationName = name.replace("ConnectorAutoConfiguration", "ConnectorConfiguration");
+        if (hasOptions) {
+            AnnotationSource<JavaClassSource> ann = javaClass.addAnnotation(EnableConfigurationProperties.class);
+            ann.setLiteralValue("value", configurationName + ".class");
+
+            javaClass.addImport("java.util.HashMap");
+            javaClass.addImport("java.util.Map");
+            javaClass.addImport("org.apache.camel.util.IntrospectionSupport");
+        }
+
+        javaClass.addImport(model.getJavaType());
+        javaClass.addImport("org.apache.camel.CamelContext");
+
+        // add method for auto configure
+        String body = createComponentBody(model.getShortJavaType(), hasOptions);
+        String methodName = "configure" + model.getShortJavaType();
+
+        MethodSource<JavaClassSource> method = javaClass.addMethod()
+            .setName(methodName)
+            .setPublic()
+            .setBody(body)
+            .setReturnType(model.getShortJavaType())
+            .addThrows(Exception.class);
+
+        method.addParameter("CamelContext", "camelContext");
+
+        if (hasOptions) {
+            method.addParameter(configurationName, "configuration");
+        }
+
+        method.addAnnotation(Bean.class).setStringValue("name", connectorScheme.toLowerCase(Locale.US) + "-connector");
+        method.addAnnotation(ConditionalOnClass.class).setLiteralValue("value", "CamelContext.class");
+        method.addAnnotation(ConditionalOnMissingBean.class).setLiteralValue("value", model.getShortJavaType() + ".class");
+
+        sortImports(javaClass);
+
+        String fileName = packageName.replaceAll("\\.", "\\/") + "/" + name + ".java";
+        writeSourceIfChanged(javaClass, fileName);
+    }
+
+    private void writeSourceIfChanged(JavaClassSource source, String fileName) throws MojoFailureException {
+        File target = new File(".", "src/main/java/" + fileName);
+
+        try {
+            String header = "";
+            if (includeLicenseHeader) {
+                InputStream is = getClass().getClassLoader().getResourceAsStream("license-header-java.txt");
+                header = loadText(is);
+            }
+            String code = sourceToString(source);
+            code = header + code;
+            getLog().debug("Source code generated:\n" + code);
+
+            if (target.exists()) {
+                String existing = FileUtils.readFileToString(target);
+                if (!code.equals(existing)) {
+                    FileUtils.write(target, code, false);
+                    getLog().info("Updated existing file: " + target);
+                } else {
+                    getLog().debug("No changes to existing file: " + target);
+                }
+            } else {
+                FileUtils.write(target, code);
+                getLog().info("Created file: " + target);
+            }
+        } catch (Exception e) {
+            throw new MojoFailureException("IOError with file " + target, e);
+        }
+    }
+
+    private static String createComponentBody(String shortJavaType, boolean hasOptions) {
+        StringBuilder sb = new StringBuilder();
+        sb.append(shortJavaType).append(" connector = new ").append(shortJavaType).append("();").append("\n");
+        sb.append("connector.setCamelContext(camelContext);\n");
+        sb.append("\n");
+        if (hasOptions) {
+            sb.append("Map<String, Object> parameters = new HashMap<>();\n");
+            sb.append("IntrospectionSupport.getProperties(configuration, parameters, null, false);\n");
+            sb.append("IntrospectionSupport.setProperties(camelContext, camelContext.getTypeConverter(), connector, parameters);\n");
+        }
+        sb.append("\n");
+        sb.append("return connector;");
+        return sb.toString();
+    }
+
+    private static void sortImports(JavaClassSource javaClass) {
+        // sort imports
+        List<Import> imports = javaClass.getImports();
+
+        // sort imports
+        List<String> names = new ArrayList<>();
+        for (Import imp : imports) {
+            names.add(imp.getQualifiedName());
+        }
+        // sort
+        Collections.sort(names, (s1, s2) -> {
+            // java comes first
+            if (s1.startsWith("java.")) {
+                s1 = "___" + s1;
+            }
+            if (s2.startsWith("java.")) {
+                s2 = "___" + s2;
+            }
+            // then javax comes next
+            if (s1.startsWith("javax.")) {
+                s1 = "__" + s1;
+            }
+            if (s2.startsWith("javax.")) {
+                s2 = "__" + s2;
+            }
+            // org.w3c is for some odd reason also before others
+            if (s1.startsWith("org.w3c.")) {
+                s1 = "_" + s1;
+            }
+            if (s2.startsWith("org.w3c.")) {
+                s2 = "_" + s2;
+            }
+            return s1.compareTo(s2);
+        });
+
+        // remove all imports first
+        for (String name : names) {
+            javaClass.removeImport(name);
+        }
+        // and add them back in correct order
+        for (String name : names) {
+            javaClass.addImport(name);
+        }
+    }
+
+    private static String sourceToString(JavaClassSource javaClass) {
+        String code = Formatter.format(javaClass);
+        // convert tabs to 4 spaces
+        code = code.replaceAll("\\t", "    ");
+        return code;
+    }
+
+    private static ComponentModel generateComponentModel(String json) {
+        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("component", json, false);
+
+        ComponentModel component = new ComponentModel(true);
+        component.setScheme(getSafeValue("scheme", rows));
+        component.setSyntax(getSafeValue("syntax", rows));
+        component.setAlternativeSyntax(getSafeValue("alternativeSyntax", rows));
+        component.setTitle(getSafeValue("title", rows));
+        component.setDescription(getSafeValue("description", rows));
+        component.setFirstVersion(getSafeValue("firstVersion", rows));
+        component.setLabel(getSafeValue("label", rows));
+        component.setDeprecated(getSafeValue("deprecated", rows));
+        component.setConsumerOnly(getSafeValue("consumerOnly", rows));
+        component.setProducerOnly(getSafeValue("producerOnly", rows));
+        component.setJavaType(getSafeValue("javaType", rows));
+        component.setGroupId(getSafeValue("groupId", rows));
+        component.setArtifactId(getSafeValue("artifactId", rows));
+        component.setVersion(getSafeValue("version", rows));
+
+        rows = JSonSchemaHelper.parseJsonSchema("componentProperties", json, true);
+        for (Map<String, String> row : rows) {
+            ComponentOptionModel option = new ComponentOptionModel();
+            option.setName(getSafeValue("name", row));
+            option.setDisplayName(getSafeValue("displayName", row));
+            option.setKind(getSafeValue("kind", row));
+            option.setType(getSafeValue("type", row));
+            option.setJavaType(getSafeValue("javaType", row));
+            option.setDeprecated(getSafeValue("deprecated", row));
+            option.setDescription(getSafeValue("description", row));
+            option.setDefaultValue(getSafeValue("defaultValue", row));
+            option.setEnums(getSafeValue("enum", row));
+            component.addComponentOption(option);
+        }
+
+        return component;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/f897d468/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 b69de06..556cc59 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
@@ -16,6 +16,9 @@
  */
 package org.apache.camel.maven.connector;
 
+import java.util.List;
+import java.util.Map;
+
 /**
  * Utility methods for String.
  */
@@ -172,4 +175,28 @@ public final class StringHelper {
         return sb.toString().trim();
     }
 
+    /**
+     * Gets the value with the key in a safe way, eg returning an empty string if there was no value for the key.
+     */
+    public static String getSafeValue(String key, List<Map<String, String>> rows) {
+        for (Map<String, String> row : rows) {
+            String value = row.get(key);
+            if (value != null) {
+                return value;
+            }
+        }
+        return "";
+    }
+
+    /**
+     * Gets the value with the key in a safe way, eg returning an empty string if there was no value for the key.
+     */
+    public static String getSafeValue(String key, Map<String, String> rows) {
+        String value = rows.get(key);
+        if (value != null) {
+            return value;
+        }
+        return "";
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/f897d468/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/ComponentModel.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/ComponentModel.java b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/ComponentModel.java
new file mode 100644
index 0000000..126ffb2
--- /dev/null
+++ b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/ComponentModel.java
@@ -0,0 +1,201 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ComponentModel {
+
+    private final boolean coreOnly;
+
+    private String kind;
+    private String scheme;
+    private String syntax;
+    private String alternativeSyntax;
+    private String alternativeSchemes;
+    private String title;
+    private String description;
+    private String firstVersion;
+    private String label;
+    private String deprecated;
+    private String consumerOnly;
+    private String producerOnly;
+    private String javaType;
+    private String groupId;
+    private String artifactId;
+    private String version;
+    private final List<ComponentOptionModel> componentOptions = new ArrayList<ComponentOptionModel>();
+
+    public ComponentModel(boolean coreOnly) {
+        this.coreOnly = coreOnly;
+    }
+
+    public String getKind() {
+        return kind;
+    }
+
+    public void setKind(String kind) {
+        this.kind = kind;
+    }
+
+    public String getScheme() {
+        return scheme;
+    }
+
+    public void setScheme(String scheme) {
+        this.scheme = scheme;
+    }
+
+    public String getSyntax() {
+        return syntax;
+    }
+
+    public void setSyntax(String syntax) {
+        this.syntax = syntax;
+    }
+
+    public String getAlternativeSyntax() {
+        return alternativeSyntax;
+    }
+
+    public void setAlternativeSyntax(String alternativeSyntax) {
+        this.alternativeSyntax = alternativeSyntax;
+    }
+
+    public String getAlternativeSchemes() {
+        return alternativeSchemes;
+    }
+
+    public void setAlternativeSchemes(String alternativeSchemes) {
+        this.alternativeSchemes = alternativeSchemes;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getFirstVersion() {
+        return firstVersion;
+    }
+
+    public void setFirstVersion(String firstVersion) {
+        this.firstVersion = firstVersion;
+    }
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    public String getDeprecated() {
+        return deprecated;
+    }
+
+    public void setDeprecated(String deprecated) {
+        this.deprecated = deprecated;
+    }
+
+    public String getConsumerOnly() {
+        return consumerOnly;
+    }
+
+    public void setConsumerOnly(String consumerOnly) {
+        this.consumerOnly = consumerOnly;
+    }
+
+    public String getProducerOnly() {
+        return producerOnly;
+    }
+
+    public void setProducerOnly(String producerOnly) {
+        this.producerOnly = producerOnly;
+    }
+
+    public String getJavaType() {
+        return javaType;
+    }
+
+    public void setJavaType(String javaType) {
+        this.javaType = javaType;
+    }
+
+    public String getGroupId() {
+        return groupId;
+    }
+
+    public void setGroupId(String groupId) {
+        this.groupId = groupId;
+    }
+
+    public String getArtifactId() {
+        return artifactId;
+    }
+
+    public void setArtifactId(String artifactId) {
+        this.artifactId = artifactId;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    public List<ComponentOptionModel> getComponentOptions() {
+        return componentOptions;
+    }
+
+    public void addComponentOption(ComponentOptionModel option) {
+        componentOptions.add(option);
+    }
+
+    public String getShortJavaType() {
+        if (javaType.startsWith("java.util.Map")) {
+            return "Map";
+        } else if (javaType.startsWith("java.util.Set")) {
+            return "Set";
+        } else if (javaType.startsWith("java.util.List")) {
+            return "List";
+        }
+        int pos = javaType.lastIndexOf(".");
+        if (pos != -1) {
+            return javaType.substring(pos + 1);
+        } else {
+            return javaType;
+        }
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/f897d468/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/ComponentOptionModel.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/ComponentOptionModel.java b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/ComponentOptionModel.java
new file mode 100644
index 0000000..2a717ab
--- /dev/null
+++ b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/ComponentOptionModel.java
@@ -0,0 +1,146 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.model;
+
+public class ComponentOptionModel {
+
+    private String name;
+    private String displayName;
+    private String kind;
+    private String group;
+    private String required;
+    private String type;
+    private String javaType;
+    private String deprecated;
+    private String secret;
+    private String description;
+    private String defaultValue;
+    private String enums;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDisplayName() {
+        return displayName;
+    }
+
+    public void setDisplayName(String displayName) {
+        this.displayName = displayName;
+    }
+
+    public String getKind() {
+        return kind;
+    }
+
+    public void setKind(String kind) {
+        this.kind = kind;
+    }
+
+    public String getGroup() {
+        return group;
+    }
+
+    public void setGroup(String group) {
+        this.group = group;
+    }
+
+    public String getRequired() {
+        return required;
+    }
+
+    public void setRequired(String required) {
+        this.required = required;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getJavaType() {
+        return javaType;
+    }
+
+    public void setJavaType(String javaType) {
+        this.javaType = javaType;
+    }
+
+    public String getDeprecated() {
+        return deprecated;
+    }
+
+    public void setDeprecated(String deprecated) {
+        this.deprecated = deprecated;
+    }
+
+    public String getSecret() {
+        return secret;
+    }
+
+    public void setSecret(String secret) {
+        this.secret = secret;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getDefaultValue() {
+        return defaultValue;
+    }
+
+    public void setDefaultValue(String defaultValue) {
+        this.defaultValue = defaultValue;
+    }
+
+    public String getEnums() {
+        return enums;
+    }
+
+    public void setEnums(String enums) {
+        this.enums = enums;
+    }
+
+    public String getShortJavaType() {
+        if (javaType.startsWith("java.util.Map")) {
+            return "Map";
+        } else if (javaType.startsWith("java.util.Set")) {
+            return "Set";
+        } else if (javaType.startsWith("java.util.List")) {
+            return "List";
+        }
+        int pos = javaType.lastIndexOf(".");
+        if (pos != -1) {
+            return javaType.substring(pos + 1);
+        } else {
+            return javaType;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/f897d468/connectors/camel-connector-maven-plugin/src/main/resources/license-header-java.txt
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/resources/license-header-java.txt b/connectors/camel-connector-maven-plugin/src/main/resources/license-header-java.txt
new file mode 100644
index 0000000..0f49ea9
--- /dev/null
+++ b/connectors/camel-connector-maven-plugin/src/main/resources/license-header-java.txt
@@ -0,0 +1,16 @@
+/**
+ * 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.
+ */
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/f897d468/connectors/camel-connector-maven-plugin/src/main/resources/license-header.txt
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/resources/license-header.txt b/connectors/camel-connector-maven-plugin/src/main/resources/license-header.txt
new file mode 100644
index 0000000..12bdf0d
--- /dev/null
+++ b/connectors/camel-connector-maven-plugin/src/main/resources/license-header.txt
@@ -0,0 +1,16 @@
+#
+# 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.
+#

http://git-wip-us.apache.org/repos/asf/camel/blob/f897d468/connectors/camel-connector/pom.xml
----------------------------------------------------------------------
diff --git a/connectors/camel-connector/pom.xml b/connectors/camel-connector/pom.xml
index 6f99578..e709823 100644
--- a/connectors/camel-connector/pom.xml
+++ b/connectors/camel-connector/pom.xml
@@ -35,6 +35,8 @@
   </properties>
 
   <dependencies>
+
+    <!-- camel -->
     <dependency>
       <groupId>org.apache.camel</groupId>
       <artifactId>camel-core</artifactId>
@@ -43,6 +45,19 @@
       <groupId>org.apache.camel</groupId>
       <artifactId>camel-catalog</artifactId>
     </dependency>
+
+    <!-- to support spring-boot auto configuration in the connectors -->
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot</artifactId>
+      <version>${spring-boot-version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-autoconfigure</artifactId>
+      <version>${spring-boot-version}</version>
+    </dependency>
+
   </dependencies>
 
 </project>


[2/3] camel git commit: CAMEL-10799: camel-connector - Generate spring boot auto configuration

Posted by da...@apache.org.
CAMEL-10799: camel-connector - Generate spring boot auto configuration


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

Branch: refs/heads/master
Commit: 788572aac3a0a83947dc81d82e991ee404115272
Parents: f897d46
Author: Claus Ibsen <da...@apache.org>
Authored: Wed Mar 15 20:49:03 2017 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Wed Mar 15 21:15:41 2017 +0100

----------------------------------------------------------------------
 .../maven/connector/CollectionStringBuffer.java |  58 ---
 .../camel/maven/connector/ConnectorMojo.java    |   4 +
 .../camel/maven/connector/FileHelper.java       | 140 ------
 .../apache/camel/maven/connector/GitHelper.java | 132 ------
 .../camel/maven/connector/JSonSchemaHelper.java | 427 -------------------
 .../SpringBootAutoConfigurationMojo.java        |  43 +-
 .../camel/maven/connector/StringHelper.java     | 202 ---------
 .../maven/connector/model/ComponentModel.java   |   1 -
 .../connector/util/CollectionStringBuffer.java  |  58 +++
 .../camel/maven/connector/util/FileHelper.java  | 140 ++++++
 .../camel/maven/connector/util/GitHelper.java   | 132 ++++++
 .../maven/connector/util/JSonSchemaHelper.java  | 427 +++++++++++++++++++
 .../maven/connector/util/StringHelper.java      | 219 ++++++++++
 13 files changed, 1003 insertions(+), 980 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/788572aa/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
deleted file mode 100644
index d98779d..0000000
--- a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/CollectionStringBuffer.java
+++ /dev/null
@@ -1,58 +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.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/788572aa/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 a9958a6..59c91d8 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
@@ -32,6 +32,10 @@ import java.util.stream.Collectors;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.camel.maven.connector.util.FileHelper;
+import org.apache.camel.maven.connector.util.GitHelper;
+import org.apache.camel.maven.connector.util.JSonSchemaHelper;
+import org.apache.camel.maven.connector.util.StringHelper;
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugins.annotations.LifecyclePhase;

http://git-wip-us.apache.org/repos/asf/camel/blob/788572aa/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/FileHelper.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/FileHelper.java b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/FileHelper.java
deleted file mode 100644
index ae01138..0000000
--- a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/FileHelper.java
+++ /dev/null
@@ -1,140 +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.maven.connector;
-
-import java.io.BufferedReader;
-import java.io.Closeable;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.LineNumberReader;
-import java.nio.channels.FileChannel;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Utility methods for files.
- */
-public final class FileHelper {
-
-    private FileHelper() {
-    }
-
-    /**
-     * 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();
-        InputStreamReader isr = new InputStreamReader(in);
-        try {
-            BufferedReader reader = new LineNumberReader(isr);
-            while (true) {
-                String line = reader.readLine();
-                if (line != null) {
-                    builder.append(line);
-                    builder.append("\n");
-                } else {
-                    break;
-                }
-            }
-            return builder.toString();
-        } finally {
-            isr.close();
-            in.close();
-        }
-    }
-
-    /**
-     * Loads the file
-     */
-    public static List<String> loadFile(File file) throws Exception {
-        List<String> lines = new ArrayList<>();
-        LineNumberReader reader = new LineNumberReader(new FileReader(file));
-
-        String line;
-        do {
-            line = reader.readLine();
-            if (line != null) {
-                lines.add(line);
-            }
-        } while (line != null);
-        reader.close();
-
-        return lines;
-    }
-
-    /**
-     * Loads the file
-     */
-    public static List<String> loadFile(InputStream fis) throws Exception {
-        List<String> lines = new ArrayList<>();
-        LineNumberReader reader = new LineNumberReader(new InputStreamReader(fis));
-
-        String line;
-        do {
-            line = reader.readLine();
-            if (line != null) {
-                lines.add(line);
-            }
-        } while (line != null);
-        reader.close();
-
-        return lines;
-    }
-
-    public static void copyFile(File from, File to) throws IOException {
-        FileChannel in = null;
-        FileChannel out = null;
-        try {
-            in = new FileInputStream(from).getChannel();
-            out = new FileOutputStream(to).getChannel();
-
-            long size = in.size();
-            long position = 0;
-            while (position < size) {
-                position += in.transferTo(position, 4096, out);
-            }
-        } finally {
-            close(in);
-            close(out);
-        }
-    }
-
-    /**
-     * Closes the given resource if it is available, logging any closing exceptions to the given log.
-     */
-    public static void close(Closeable closeable) {
-        if (closeable != null) {
-            try {
-                closeable.close();
-            } catch (IOException e) {
-                // ignore
-            }
-        }
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/788572aa/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/GitHelper.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/GitHelper.java b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/GitHelper.java
deleted file mode 100644
index bd879f7..0000000
--- a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/GitHelper.java
+++ /dev/null
@@ -1,132 +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.maven.connector;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.StringReader;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Utility methods for git.
- */
-public final class GitHelper {
-
-    private GitHelper() {
-    }
-
-    /**
-     * Finds the folder where <tt>.git</tt> is located in the project
-     */
-    public static File findGitFolder() {
-        File baseDir = new File("").getAbsoluteFile();
-        return findGitFolder(baseDir);
-    }
-
-    private static File findGitFolder(File basedir) {
-        File gitDir = new File(basedir, ".git");
-        if (gitDir.exists() && gitDir.isDirectory()) {
-            return gitDir;
-        }
-
-        File parent = basedir.getParentFile();
-        if (parent != null) {
-            return findGitFolder(parent);
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Returns the remote git URL for the given folder; looking for the .git/config file in the current directory or a parent directory
-     */
-    public static String extractGitUrl(File basedir) throws IOException {
-        if (basedir == null) {
-            return null;
-        }
-        if (basedir.exists() && basedir.isDirectory()) {
-            File gitConfig = new File(basedir, ".git/config");
-            if (gitConfig.isFile() && gitConfig.exists()) {
-                String text = FileHelper.loadText(new FileInputStream(gitConfig));
-                return extractGitUrl(text);
-            }
-        }
-        File parentFile = basedir.getParentFile();
-        if (parentFile != null) {
-            return extractGitUrl(parentFile);
-        }
-        return null;
-    }
-
-    /**
-     * Returns the remote git URL for the given git config file text lets extract the
-     */
-    private static String extractGitUrl(String configText) {
-        String remote = null;
-        String lastUrl = null;
-        String firstUrl = null;
-        BufferedReader reader = new BufferedReader(new StringReader(configText));
-        Map<String, String> remoteUrls = new HashMap<>();
-        while (true) {
-            String line = null;
-            try {
-                line = reader.readLine();
-            } catch (IOException e) {
-                // ignore should never happen!
-            }
-            if (line == null) {
-                break;
-            }
-            if (line.startsWith("[remote ")) {
-                String[] parts = line.split("\"");
-                if (parts.length > 1) {
-                    remote = parts[1];
-                }
-            } else if (line.startsWith("[")) {
-                remote = null;
-            } else if (remote != null && line.length() > 0 && Character.isWhitespace(line.charAt(0))) {
-                String trimmed = line.trim();
-                if (trimmed.startsWith("url ")) {
-                    String[] parts = trimmed.split("=", 2);
-                    if (parts.length > 1) {
-                        lastUrl = parts[1].trim();
-                        if (firstUrl == null) {
-                            firstUrl = lastUrl;
-                        }
-                        remoteUrls.put(remote, lastUrl);
-                    }
-                }
-
-            }
-        }
-        String answer = null;
-        if (remoteUrls.size() == 1) {
-            return lastUrl;
-        } else if (remoteUrls.size() > 1) {
-            answer = remoteUrls.get("origin");
-            if (answer == null) {
-                answer = firstUrl;
-            }
-        }
-        return answer;
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/788572aa/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
deleted file mode 100644
index c78d79c..0000000
--- a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/JSonSchemaHelper.java
+++ /dev/null
@@ -1,427 +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.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.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * A helper class for <a href="http://json-schema.org/">JSON schema</a>.
- */
-public final class JSonSchemaHelper {
-
-    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 displayName, 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));
-
-        // compute a display name if we don't have anything
-        if (StringHelper.isNullOrEmpty(displayName)) {
-            displayName = StringHelper.asTitle(name);
-        }
-        // we want display name early so its easier to spot
-        sb.append(", \"displayName\": ");
-        sb.append(StringHelper.doubleQuote(displayName));
-
-        // 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
-     *
-     * @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;
-    }
-
-    /**
-     * 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;
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/788572aa/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java
index a6dbd84..e276992 100644
--- a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java
+++ b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java
@@ -28,6 +28,7 @@ import java.util.Map;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.camel.maven.connector.model.ComponentModel;
 import org.apache.camel.maven.connector.model.ComponentOptionModel;
+import org.apache.camel.maven.connector.util.JSonSchemaHelper;
 import org.apache.commons.io.FileUtils;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
@@ -52,8 +53,9 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 
-import static org.apache.camel.maven.connector.FileHelper.loadText;
-import static org.apache.camel.maven.connector.StringHelper.getSafeValue;
+import static org.apache.camel.maven.connector.util.FileHelper.loadText;
+import static org.apache.camel.maven.connector.util.StringHelper.getSafeValue;
+import static org.apache.camel.maven.connector.util.StringHelper.getShortJavaType;
 
 /**
  * Generate Spring Boot auto configuration files for Camel connectors.
@@ -66,9 +68,6 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo {
     @Parameter(defaultValue = "${project.build.outputDirectory}", required = true)
     private File classesDirectory;
 
-    @Parameter(defaultValue = "${basedir}", required = true)
-    private File baseDir;
-
     @Parameter(defaultValue = "true")
     private boolean includeLicenseHeader;
 
@@ -114,16 +113,16 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo {
             if (hasOptions) {
                 createConnectorConfigurationSource(pkg, model, javaType, connectorScheme);
             }
-            createConnectorAutoConfigurationSource(pkg, model, hasOptions, javaType, connectorScheme);
-            createConnectorSpringFactorySource(pkg, model);
+            createConnectorAutoConfigurationSource(pkg, hasOptions, javaType, connectorScheme);
+            createConnectorSpringFactorySource(pkg, javaType);
         } else {
             getLog().warn("Cannot generate Spring Boot AutoConfiguration as camel-component-schema.json file missing");
         }
     }
 
-    private void createConnectorSpringFactorySource(String packageName, ComponentModel model) throws MojoFailureException {
-        int pos = model.getJavaType().lastIndexOf(".");
-        String name = model.getJavaType().substring(pos + 1);
+    private void createConnectorSpringFactorySource(String packageName, String javaType) throws MojoFailureException {
+        int pos = javaType.lastIndexOf(".");
+        String name = javaType.substring(pos + 1);
         name = name.replace("Component", "ConnectorAutoConfiguration");
 
         writeComponentSpringFactorySource(packageName, name);
@@ -136,8 +135,10 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo {
         String lineToAdd = packageName + "." + name + "\n";
         sb.append(lineToAdd);
 
+        // project root folder
+        File root = classesDirectory.getParentFile().getParentFile();
         String fileName = "src/main/resources/META-INF/spring.factories";
-        File target = new File(baseDir, fileName);
+        File target = new File(root, fileName);
 
         // create new file
         try {
@@ -177,7 +178,7 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo {
 
         String prefix = "camel.connector." + model.getScheme();
         // make sure prefix is in lower case
-        prefix = connectorScheme.toLowerCase(Locale.US);
+        prefix = "camel.connector." + connectorScheme.toLowerCase(Locale.US);
         javaClass.addAnnotation("org.springframework.boot.context.properties.ConfigurationProperties").setStringValue("prefix", prefix);
 
         for (ComponentOptionModel option : model.getComponentOptions()) {
@@ -217,11 +218,10 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo {
         sortImports(javaClass);
 
         String fileName = packageName.replaceAll("\\.", "\\/") + "/" + name + ".java";
-
         writeSourceIfChanged(javaClass, fileName);
     }
 
-    private void createConnectorAutoConfigurationSource(String packageName, ComponentModel model, boolean hasOptions,
+    private void createConnectorAutoConfigurationSource(String packageName, boolean hasOptions,
                                                         String javaType, String connectorScheme) throws MojoFailureException {
 
         final JavaClassSource javaClass = Roaster.create(JavaClassSource.class);
@@ -249,18 +249,19 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo {
             javaClass.addImport("org.apache.camel.util.IntrospectionSupport");
         }
 
-        javaClass.addImport(model.getJavaType());
+        javaClass.addImport(javaType);
         javaClass.addImport("org.apache.camel.CamelContext");
 
         // add method for auto configure
-        String body = createComponentBody(model.getShortJavaType(), hasOptions);
-        String methodName = "configure" + model.getShortJavaType();
+        String shortJavaType = getShortJavaType(javaType);
+        String body = createComponentBody(shortJavaType, hasOptions);
+        String methodName = "configure" + shortJavaType;
 
         MethodSource<JavaClassSource> method = javaClass.addMethod()
             .setName(methodName)
             .setPublic()
             .setBody(body)
-            .setReturnType(model.getShortJavaType())
+            .setReturnType(shortJavaType)
             .addThrows(Exception.class);
 
         method.addParameter("CamelContext", "camelContext");
@@ -271,7 +272,7 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo {
 
         method.addAnnotation(Bean.class).setStringValue("name", connectorScheme.toLowerCase(Locale.US) + "-connector");
         method.addAnnotation(ConditionalOnClass.class).setLiteralValue("value", "CamelContext.class");
-        method.addAnnotation(ConditionalOnMissingBean.class).setLiteralValue("value", model.getShortJavaType() + ".class");
+        method.addAnnotation(ConditionalOnMissingBean.class).setLiteralValue("value", javaType + ".class");
 
         sortImports(javaClass);
 
@@ -280,7 +281,9 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo {
     }
 
     private void writeSourceIfChanged(JavaClassSource source, String fileName) throws MojoFailureException {
-        File target = new File(".", "src/main/java/" + fileName);
+        // project root folder
+        File root = classesDirectory.getParentFile().getParentFile();
+        File target = new File(root, "src/main/java/" + fileName);
 
         try {
             String header = "";

http://git-wip-us.apache.org/repos/asf/camel/blob/788572aa/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
deleted file mode 100644
index 556cc59..0000000
--- a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/StringHelper.java
+++ /dev/null
@@ -1,202 +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.maven.connector;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * Utility methods for String.
- */
-public final class StringHelper {
-
-    private StringHelper() {
-    }
-
-    /**
-     * Converts the value to use dash style instead of upper cased
-     */
-    public static String camelCaseToDash(String value) {
-        StringBuilder sb = new StringBuilder(value.length());
-        boolean dash = false;
-
-        for (char c : value.toCharArray()) {
-            // skip dash in start
-            if (sb.length() > 0 & Character.isUpperCase(c)) {
-                dash = true;
-            }
-            if (dash) {
-                sb.append('-');
-                sb.append(Character.toLowerCase(c));
-            } else {
-                // lower case first
-                if (sb.length() == 0) {
-                    sb.append(Character.toLowerCase(c));
-                } else {
-                    sb.append(c);
-                }
-            }
-            dash = false;
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Returns the string value (uses empty string for <tt>null</tt> values)
-     */
-    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;
-    }
-
-    /**
-     * Capitalizes the name as a title
-     *
-     * @param name  the name
-     * @return as a title
-     */
-    public static String asTitle(String name) {
-        StringBuilder sb = new StringBuilder();
-        for (char c : name.toCharArray()) {
-            boolean upper = Character.isUpperCase(c);
-            boolean first = sb.length() == 0;
-            if (first) {
-                sb.append(Character.toUpperCase(c));
-            } else if (upper) {
-                sb.append(' ');
-                sb.append(c);
-            } else {
-                sb.append(Character.toLowerCase(c));
-            }
-        }
-        return sb.toString().trim();
-    }
-
-    /**
-     * Gets the value with the key in a safe way, eg returning an empty string if there was no value for the key.
-     */
-    public static String getSafeValue(String key, List<Map<String, String>> rows) {
-        for (Map<String, String> row : rows) {
-            String value = row.get(key);
-            if (value != null) {
-                return value;
-            }
-        }
-        return "";
-    }
-
-    /**
-     * Gets the value with the key in a safe way, eg returning an empty string if there was no value for the key.
-     */
-    public static String getSafeValue(String key, Map<String, String> rows) {
-        String value = rows.get(key);
-        if (value != null) {
-            return value;
-        }
-        return "";
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/788572aa/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/ComponentModel.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/ComponentModel.java b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/ComponentModel.java
index 126ffb2..fad13aa 100644
--- a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/ComponentModel.java
+++ b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/ComponentModel.java
@@ -197,5 +197,4 @@ public class ComponentModel {
         }
     }
 
-
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/788572aa/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/util/CollectionStringBuffer.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/util/CollectionStringBuffer.java b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/util/CollectionStringBuffer.java
new file mode 100644
index 0000000..e4c88e2
--- /dev/null
+++ b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/util/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.util;
+
+/**
+ * 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/788572aa/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/util/FileHelper.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/util/FileHelper.java b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/util/FileHelper.java
new file mode 100644
index 0000000..5e974d1
--- /dev/null
+++ b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/util/FileHelper.java
@@ -0,0 +1,140 @@
+/**
+ * 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.util;
+
+import java.io.BufferedReader;
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.nio.channels.FileChannel;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Utility methods for files.
+ */
+public final class FileHelper {
+
+    private FileHelper() {
+    }
+
+    /**
+     * 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();
+        InputStreamReader isr = new InputStreamReader(in);
+        try {
+            BufferedReader reader = new LineNumberReader(isr);
+            while (true) {
+                String line = reader.readLine();
+                if (line != null) {
+                    builder.append(line);
+                    builder.append("\n");
+                } else {
+                    break;
+                }
+            }
+            return builder.toString();
+        } finally {
+            isr.close();
+            in.close();
+        }
+    }
+
+    /**
+     * Loads the file
+     */
+    public static List<String> loadFile(File file) throws Exception {
+        List<String> lines = new ArrayList<>();
+        LineNumberReader reader = new LineNumberReader(new FileReader(file));
+
+        String line;
+        do {
+            line = reader.readLine();
+            if (line != null) {
+                lines.add(line);
+            }
+        } while (line != null);
+        reader.close();
+
+        return lines;
+    }
+
+    /**
+     * Loads the file
+     */
+    public static List<String> loadFile(InputStream fis) throws Exception {
+        List<String> lines = new ArrayList<>();
+        LineNumberReader reader = new LineNumberReader(new InputStreamReader(fis));
+
+        String line;
+        do {
+            line = reader.readLine();
+            if (line != null) {
+                lines.add(line);
+            }
+        } while (line != null);
+        reader.close();
+
+        return lines;
+    }
+
+    public static void copyFile(File from, File to) throws IOException {
+        FileChannel in = null;
+        FileChannel out = null;
+        try {
+            in = new FileInputStream(from).getChannel();
+            out = new FileOutputStream(to).getChannel();
+
+            long size = in.size();
+            long position = 0;
+            while (position < size) {
+                position += in.transferTo(position, 4096, out);
+            }
+        } finally {
+            close(in);
+            close(out);
+        }
+    }
+
+    /**
+     * Closes the given resource if it is available, logging any closing exceptions to the given log.
+     */
+    public static void close(Closeable closeable) {
+        if (closeable != null) {
+            try {
+                closeable.close();
+            } catch (IOException e) {
+                // ignore
+            }
+        }
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/788572aa/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/util/GitHelper.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/util/GitHelper.java b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/util/GitHelper.java
new file mode 100644
index 0000000..7b2fdb6
--- /dev/null
+++ b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/util/GitHelper.java
@@ -0,0 +1,132 @@
+/**
+ * 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.util;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Utility methods for git.
+ */
+public final class GitHelper {
+
+    private GitHelper() {
+    }
+
+    /**
+     * Finds the folder where <tt>.git</tt> is located in the project
+     */
+    public static File findGitFolder() {
+        File baseDir = new File("").getAbsoluteFile();
+        return findGitFolder(baseDir);
+    }
+
+    private static File findGitFolder(File basedir) {
+        File gitDir = new File(basedir, ".git");
+        if (gitDir.exists() && gitDir.isDirectory()) {
+            return gitDir;
+        }
+
+        File parent = basedir.getParentFile();
+        if (parent != null) {
+            return findGitFolder(parent);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Returns the remote git URL for the given folder; looking for the .git/config file in the current directory or a parent directory
+     */
+    public static String extractGitUrl(File basedir) throws IOException {
+        if (basedir == null) {
+            return null;
+        }
+        if (basedir.exists() && basedir.isDirectory()) {
+            File gitConfig = new File(basedir, ".git/config");
+            if (gitConfig.isFile() && gitConfig.exists()) {
+                String text = FileHelper.loadText(new FileInputStream(gitConfig));
+                return extractGitUrl(text);
+            }
+        }
+        File parentFile = basedir.getParentFile();
+        if (parentFile != null) {
+            return extractGitUrl(parentFile);
+        }
+        return null;
+    }
+
+    /**
+     * Returns the remote git URL for the given git config file text lets extract the
+     */
+    private static String extractGitUrl(String configText) {
+        String remote = null;
+        String lastUrl = null;
+        String firstUrl = null;
+        BufferedReader reader = new BufferedReader(new StringReader(configText));
+        Map<String, String> remoteUrls = new HashMap<>();
+        while (true) {
+            String line = null;
+            try {
+                line = reader.readLine();
+            } catch (IOException e) {
+                // ignore should never happen!
+            }
+            if (line == null) {
+                break;
+            }
+            if (line.startsWith("[remote ")) {
+                String[] parts = line.split("\"");
+                if (parts.length > 1) {
+                    remote = parts[1];
+                }
+            } else if (line.startsWith("[")) {
+                remote = null;
+            } else if (remote != null && line.length() > 0 && Character.isWhitespace(line.charAt(0))) {
+                String trimmed = line.trim();
+                if (trimmed.startsWith("url ")) {
+                    String[] parts = trimmed.split("=", 2);
+                    if (parts.length > 1) {
+                        lastUrl = parts[1].trim();
+                        if (firstUrl == null) {
+                            firstUrl = lastUrl;
+                        }
+                        remoteUrls.put(remote, lastUrl);
+                    }
+                }
+
+            }
+        }
+        String answer = null;
+        if (remoteUrls.size() == 1) {
+            return lastUrl;
+        } else if (remoteUrls.size() > 1) {
+            answer = remoteUrls.get("origin");
+            if (answer == null) {
+                answer = firstUrl;
+            }
+        }
+        return answer;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/788572aa/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/util/JSonSchemaHelper.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/util/JSonSchemaHelper.java b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/util/JSonSchemaHelper.java
new file mode 100644
index 0000000..2bc95b7
--- /dev/null
+++ b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/util/JSonSchemaHelper.java
@@ -0,0 +1,427 @@
+/**
+ * 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.util;
+
+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.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * A helper class for <a href="http://json-schema.org/">JSON schema</a>.
+ */
+public final class JSonSchemaHelper {
+
+    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 displayName, 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));
+
+        // compute a display name if we don't have anything
+        if (StringHelper.isNullOrEmpty(displayName)) {
+            displayName = StringHelper.asTitle(name);
+        }
+        // we want display name early so its easier to spot
+        sb.append(", \"displayName\": ");
+        sb.append(StringHelper.doubleQuote(displayName));
+
+        // 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
+     *
+     * @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;
+    }
+
+    /**
+     * 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;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/788572aa/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/util/StringHelper.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/util/StringHelper.java b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/util/StringHelper.java
new file mode 100644
index 0000000..5aa8542
--- /dev/null
+++ b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/util/StringHelper.java
@@ -0,0 +1,219 @@
+/**
+ * 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.util;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Utility methods for String.
+ */
+public final class StringHelper {
+
+    private StringHelper() {
+    }
+
+    /**
+     * Converts the value to use dash style instead of upper cased
+     */
+    public static String camelCaseToDash(String value) {
+        StringBuilder sb = new StringBuilder(value.length());
+        boolean dash = false;
+
+        for (char c : value.toCharArray()) {
+            // skip dash in start
+            if (sb.length() > 0 & Character.isUpperCase(c)) {
+                dash = true;
+            }
+            if (dash) {
+                sb.append('-');
+                sb.append(Character.toLowerCase(c));
+            } else {
+                // lower case first
+                if (sb.length() == 0) {
+                    sb.append(Character.toLowerCase(c));
+                } else {
+                    sb.append(c);
+                }
+            }
+            dash = false;
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Returns the string value (uses empty string for <tt>null</tt> values)
+     */
+    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;
+    }
+
+    /**
+     * Capitalizes the name as a title
+     *
+     * @param name  the name
+     * @return as a title
+     */
+    public static String asTitle(String name) {
+        StringBuilder sb = new StringBuilder();
+        for (char c : name.toCharArray()) {
+            boolean upper = Character.isUpperCase(c);
+            boolean first = sb.length() == 0;
+            if (first) {
+                sb.append(Character.toUpperCase(c));
+            } else if (upper) {
+                sb.append(' ');
+                sb.append(c);
+            } else {
+                sb.append(Character.toLowerCase(c));
+            }
+        }
+        return sb.toString().trim();
+    }
+
+    /**
+     * Gets the value with the key in a safe way, eg returning an empty string if there was no value for the key.
+     */
+    public static String getSafeValue(String key, List<Map<String, String>> rows) {
+        for (Map<String, String> row : rows) {
+            String value = row.get(key);
+            if (value != null) {
+                return value;
+            }
+        }
+        return "";
+    }
+
+    /**
+     * Gets the value with the key in a safe way, eg returning an empty string if there was no value for the key.
+     */
+    public static String getSafeValue(String key, Map<String, String> rows) {
+        String value = rows.get(key);
+        if (value != null) {
+            return value;
+        }
+        return "";
+    }
+
+    public static String getShortJavaType(String javaType) {
+        if (javaType.startsWith("java.util.Map")) {
+            return "Map";
+        } else if (javaType.startsWith("java.util.Set")) {
+            return "Set";
+        } else if (javaType.startsWith("java.util.List")) {
+            return "List";
+        }
+        int pos = javaType.lastIndexOf(".");
+        if (pos != -1) {
+            return javaType.substring(pos + 1);
+        } else {
+            return javaType;
+        }
+    }
+
+
+}


[3/3] camel git commit: CAMEL-10799: camel-connector - Generate spring boot auto configuration

Posted by da...@apache.org.
CAMEL-10799: camel-connector - Generate spring boot auto configuration


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

Branch: refs/heads/master
Commit: 12ddb0fc8147b0e5491134a078f3e44579a7651c
Parents: 788572a
Author: Claus Ibsen <da...@apache.org>
Authored: Wed Mar 15 21:56:47 2017 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Wed Mar 15 22:40:48 2017 +0100

----------------------------------------------------------------------
 .../SpringBootAutoConfigurationMojo.java        | 18 +++++---
 .../component/connector/ConnectorComponent.java | 10 +++++
 .../connector/DefaultConnectorComponent.java    | 47 ++++++++++++++++++++
 3 files changed, 68 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/12ddb0fc/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java
index e276992..1529696 100644
--- a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java
+++ b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java
@@ -52,6 +52,7 @@ import org.springframework.boot.context.properties.DeprecatedConfigurationProper
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Lazy;
 
 import static org.apache.camel.maven.connector.util.FileHelper.loadText;
 import static org.apache.camel.maven.connector.util.StringHelper.getSafeValue;
@@ -108,15 +109,14 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo {
             int pos = javaType.lastIndexOf(".");
             String pkg = javaType.substring(0, pos) + ".springboot";
 
-            getLog().info("Generating Spring Boot AutoConfiguration for Connector: " + model.getScheme());
-
+            // we only create spring boot auto configuration if there is options to configure
             if (hasOptions) {
+                getLog().info("Generating Spring Boot AutoConfiguration for Connector: " + model.getScheme());
+
                 createConnectorConfigurationSource(pkg, model, javaType, connectorScheme);
+                createConnectorAutoConfigurationSource(pkg, hasOptions, javaType, connectorScheme);
+                createConnectorSpringFactorySource(pkg, javaType);
             }
-            createConnectorAutoConfigurationSource(pkg, hasOptions, javaType, connectorScheme);
-            createConnectorSpringFactorySource(pkg, javaType);
-        } else {
-            getLog().warn("Cannot generate Spring Boot AutoConfiguration as camel-component-schema.json file missing");
         }
     }
 
@@ -270,7 +270,10 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo {
             method.addParameter(configurationName, "configuration");
         }
 
-        method.addAnnotation(Bean.class).setStringValue("name", connectorScheme.toLowerCase(Locale.US) + "-connector");
+        // must be named -component because camel-spring-boot uses that to lookup components
+        String beanName = connectorScheme + "-component";
+        method.addAnnotation(Lazy.class);
+        method.addAnnotation(Bean.class).setStringValue("name", beanName);
         method.addAnnotation(ConditionalOnClass.class).setLiteralValue("value", "CamelContext.class");
         method.addAnnotation(ConditionalOnMissingBean.class).setLiteralValue("value", javaType + ".class");
 
@@ -321,6 +324,7 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo {
             sb.append("Map<String, Object> parameters = new HashMap<>();\n");
             sb.append("IntrospectionSupport.getProperties(configuration, parameters, null, false);\n");
             sb.append("IntrospectionSupport.setProperties(camelContext, camelContext.getTypeConverter(), connector, parameters);\n");
+            sb.append("connector.setComponentOptions(parameters);\n");
         }
         sb.append("\n");
         sb.append("return connector;");

http://git-wip-us.apache.org/repos/asf/camel/blob/12ddb0fc/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/ConnectorComponent.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/ConnectorComponent.java b/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/ConnectorComponent.java
index 6c4f12f..4a7dbce 100644
--- a/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/ConnectorComponent.java
+++ b/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/ConnectorComponent.java
@@ -66,4 +66,14 @@ public interface ConnectorComponent extends Component {
      */
     String getCamelConnectorJSon();
 
+    /**
+     * A set of additional component options to use for the base component when creating connector endpoints.
+     */
+    Map<String, Object> getComponentOptions();
+
+    /**
+     * A set of additional component options to use for the base component when creating connector endpoints.
+     */
+    void setComponentOptions(Map<String, Object> baseComponentOptions);
+
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/12ddb0fc/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/DefaultConnectorComponent.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/DefaultConnectorComponent.java b/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/DefaultConnectorComponent.java
index 536a224..18f6c52 100644
--- a/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/DefaultConnectorComponent.java
+++ b/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/DefaultConnectorComponent.java
@@ -16,9 +16,13 @@
  */
 package org.apache.camel.component.connector;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Modifier;
 import java.net.URISyntaxException;
+import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.camel.Component;
 import org.apache.camel.ComponentVerifier;
@@ -42,6 +46,7 @@ public abstract class DefaultConnectorComponent extends DefaultComponent impleme
 
     private final String componentName;
     private final ConnectorModel model;
+    private Map<String, Object> componentOptions;
 
     protected DefaultConnectorComponent(String componentName, String className) {
         this.componentName = componentName;
@@ -60,6 +65,31 @@ public abstract class DefaultConnectorComponent extends DefaultComponent impleme
         parameters.clear();
         
         String scheme = model.getBaseScheme();
+
+        // if we have component options then we need to create a new instance of the component
+        // which we then configure before it create the endpoint
+        if (componentOptions != null && !componentOptions.isEmpty()) {
+            String baseClassName = model.getBaseJavaType();
+            if (baseClassName != null) {
+                Class<?> type = Class.forName(baseClassName);
+                Constructor ctr = getPublicDefaultConstructor(type);
+                if (ctr != null) {
+                    // call default no-arg constructor
+                    Object base = ctr.newInstance();
+                    // configure component with extra options
+                    Map<String, Object> copy = new HashMap<>(componentOptions);
+                    IntrospectionSupport.setProperties(getCamelContext(), getCamelContext().getTypeConverter(), base, copy);
+
+                    if (base instanceof Component) {
+                        Component old = getCamelContext().removeComponent(scheme);
+                        // ensure component is started and stopped when Camel shutdown
+                        getCamelContext().addService(base, true, true);
+                        getCamelContext().addComponent(scheme, (Component) base);
+                    }
+                }
+            }
+        }
+
         String delegateUri = createEndpointUri(scheme, options);
 
         log.debug("Connector resolved: {} -> {}", uri, delegateUri);
@@ -67,6 +97,15 @@ public abstract class DefaultConnectorComponent extends DefaultComponent impleme
         return new DefaultConnectorEndpoint(uri, this, delegate, model.getInputDataType(), model.getOutputDataType());
     }
 
+    private static Constructor getPublicDefaultConstructor(Class<?> clazz) {
+        for (Constructor ctr : clazz.getConstructors()) {
+            if (Modifier.isPublic(ctr.getModifiers()) && ctr.getParameterCount() == 0) {
+                return ctr;
+            }
+        }
+        return null;
+    }
+
     @Override
     public String createEndpointUri(String scheme, Map<String, String> options) throws URISyntaxException {
         log.trace("Creating endpoint uri with scheme: {}", scheme);
@@ -99,6 +138,14 @@ public abstract class DefaultConnectorComponent extends DefaultComponent impleme
         return componentName;
     }
 
+    public Map<String, Object> getComponentOptions() {
+        return componentOptions;
+    }
+
+    public void setComponentOptions(Map<String, Object> baseComponentOptions) {
+        this.componentOptions = baseComponentOptions;
+    }
+
     @SuppressWarnings("unchecked")
     @Override
     public ComponentVerifier getVerifier() {