CAMEL-11196: Camel connectors - Allow to configure in one place and let it 
figure out component vs endpoint level


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

Branch: refs/heads/master
Commit: 3dd29006c3aa1c9612dc25461b64a4845e31138d
Parents: 000e09a
Author: lburgazzoli <lburgazz...@gmail.com>
Authored: Wed May 10 18:20:48 2017 +0200
Committer: lburgazzoli <lburgazz...@gmail.com>
Committed: Mon May 15 17:06:47 2017 +0200

----------------------------------------------------------------------
 .../apache/camel/util/IntrospectionSupport.java |   5 +
 connectors/camel-connector-maven-plugin/pom.xml |   7 +
 .../SpringBootAutoConfigurationMojo.java        | 236 ++++++++++++++-----
 .../maven/connector/model/ComponentModel.java   |  11 +-
 .../connector/model/ComponentOptionModel.java   | 128 +---------
 .../connector/model/EndpointOptionModel.java    | 215 +++++++++++++++++
 .../maven/connector/model/OptionModel.java      | 146 ++++++++++++
 .../src/main/docs/connector-component.adoc      |  56 ++++-
 .../component/connector/ConnectorComponent.java |  39 ++-
 .../component/connector/ConnectorModel.java     |  76 ++++++
 .../connector/DefaultConnectorComponent.java    | 199 ++++++++++------
 .../PetStoreConnectorAutoConfiguration.java     |  41 +++-
 .../PetStoreConnectorConfiguration.java         |  33 +--
 .../PetStoreConnectorConfigurationCommon.java   |  61 +++++
 connectors/examples/pom.xml                     |   2 +
 ...UpsertContactConnectorAutoConfiguration.java |  41 +++-
 ...orceUpsertContactConnectorConfiguration.java |  73 +-----
 ...sertContactConnectorConfigurationCommon.java | 113 +++++++++
 .../examples/twitter-mention-connector/pom.xml  |   2 +
 ...witterMentionConnectorAutoConfiguration.java |  41 +++-
 .../TwitterMentionConnectorConfiguration.java   |  62 +----
 ...tterMentionConnectorConfigurationCommon.java |  78 ++++++
 .../examples/twitter-search-connector/pom.xml   | 188 +++++++++++++++
 .../org/foo/search/TwitterSearchComponent.java  |  30 +++
 ...TwitterSearchConnectorAutoConfiguration.java |  93 ++++++++
 .../TwitterSearchConnectorConfiguration.java    |  38 +++
 ...itterSearchConnectorConfigurationCommon.java | 116 +++++++++
 .../org/apache/camel/component/twitter-search   |  18 ++
 .../main/resources/META-INF/spring.factories    |  19 ++
 .../main/resources/camel-connector-schema.json  |  30 +++
 .../src/main/resources/camel-connector.json     |  25 ++
 .../springbot/TwitterSearchConnectorTest.java   |  65 +++++
 .../src/test/resources/application.properties   |   7 +
 .../src/test/resources/logback.xml              |  36 +++
 .../examples/twitter-search-example/README.md   |  18 ++
 .../examples/twitter-search-example/pom.xml     | 112 +++++++++
 .../java/org/foo/TwitterSearchApplication.java  |  32 +++
 .../main/java/org/foo/TwitterSearchRoute.java   |  29 +++
 .../src/main/resources/META-INF/LICENSE.txt     | 203 ++++++++++++++++
 .../src/main/resources/META-INF/NOTICE.txt      |  11 +
 .../src/main/resources/application.properties   |  29 +++
 41 files changed, 2345 insertions(+), 419 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java 
b/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
index 185ef3b..21384cc 100755
--- a/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
+++ b/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
@@ -635,6 +635,11 @@ public final class IntrospectionSupport {
         return false;
     }
 
+    public static boolean setProperty(CamelContext context, Object target, 
String name, Object value) throws Exception {
+        // allow build pattern as a setter as well
+        return setProperty(context, context != null ? 
context.getTypeConverter() : null, target, name, value, null, true);
+    }
+
     public static boolean setProperty(CamelContext context, TypeConverter 
typeConverter, Object target, String name, Object value) throws Exception {
         // allow build pattern as a setter as well
         return setProperty(context, typeConverter, target, name, value, null, 
true);

http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/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 2e8bb3b..cbb2c84 100644
--- a/connectors/camel-connector-maven-plugin/pom.xml
+++ b/connectors/camel-connector-maven-plugin/pom.xml
@@ -85,6 +85,13 @@
       <version>${spring-boot-version}</version>
     </dependency>
 
+    <!-- guava for some word wrap helper -->
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+      <version>${google-guava-version}</version>
+    </dependency>
+
     <!-- logging -->
     <dependency>
       <groupId>org.slf4j</groupId>

http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/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 997878a..c8ca459 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
@@ -21,13 +21,18 @@ import java.io.FileInputStream;
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import javax.annotation.Generated;
+import javax.annotation.PostConstruct;
 
 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.model.EndpointOptionModel;
+import org.apache.camel.maven.connector.model.OptionModel;
 import org.apache.camel.maven.connector.util.JSonSchemaHelper;
 import org.apache.commons.io.FileUtils;
 import org.apache.maven.plugin.AbstractMojo;
@@ -44,10 +49,13 @@ 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.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.annotation.Autowired;
 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.ConfigurationProperties;
 import 
org.springframework.boot.context.properties.DeprecatedConfigurationProperty;
 import 
org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.context.annotation.Bean;
@@ -89,7 +97,8 @@ public class SpringBootAutoConfigurationMojo extends 
AbstractMojo {
 
         String javaType = null;
         String connectorScheme = null;
-        List<String> componentOptions = null;
+        List<String> componentOptions = Collections.emptyList();
+        List<String> endpointOptions = Collections.emptyList();
 
         File file = new File(classesDirectory, "camel-connector.json");
         if (file.exists()) {
@@ -99,6 +108,7 @@ public class SpringBootAutoConfigurationMojo extends 
AbstractMojo {
             javaType = (String) dto.get("javaType");
             connectorScheme = (String) dto.get("scheme");
             componentOptions = (List) dto.get("componentOptions");
+            endpointOptions = (List) dto.get("endpointOptions");
         }
 
         // find the component dependency and get its .json file
@@ -119,7 +129,7 @@ public class SpringBootAutoConfigurationMojo extends 
AbstractMojo {
             if (hasOptions) {
                 getLog().info("Generating Spring Boot AutoConfiguration for 
Connector: " + model.getScheme());
 
-                createConnectorConfigurationSource(pkg, model, javaType, 
connectorScheme, componentOptions);
+                createConnectorConfigurationSource(pkg, model, javaType, 
connectorScheme, componentOptions, endpointOptions);
                 createConnectorAutoConfigurationSource(pkg, hasOptions, 
javaType, connectorScheme);
                 createConnectorSpringFactorySource(pkg, javaType);
             }
@@ -165,23 +175,29 @@ public class SpringBootAutoConfigurationMojo extends 
AbstractMojo {
         }
     }
 
+
+
     private void createConnectorConfigurationSource(String packageName, 
ComponentModel model, String javaType,
-                                                    String connectorScheme, 
List<String> componentOptions) throws MojoFailureException {
-        final JavaClassSource javaClass = 
Roaster.create(JavaClassSource.class);
+                                                     String connectorScheme, 
List<String> componentOptions, List<String> endpointOptions) throws 
MojoFailureException {
 
-        int pos = javaType.lastIndexOf(".");
-        String name = javaType.substring(pos + 1);
-        name = name.replace("Component", "ConnectorConfiguration");
-        javaClass.setPackage(packageName).setName(name);
+        final int pos = javaType.lastIndexOf(".");
+        final String commonName = javaType.substring(pos + 
1).replace("Component", "ConnectorConfigurationCommon");
+        final String configName = javaType.substring(pos + 
1).replace("Component", "ConnectorConfiguration");
 
-        String doc = "Generated by camel-connector-maven-plugin - do not edit 
this file!";
+        // Common base class
+        JavaClassSource commonClass = Roaster.create(JavaClassSource.class);
+        commonClass.setPackage(packageName);
+        commonClass.setName(commonName);
+
+        String doc = "Generated by camel-package-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);
+        commonClass.getJavaDoc().setFullText(doc);
+        commonClass.addAnnotation(Generated.class).setStringValue("value", 
SpringBootAutoConfigurationMojo.class.getName());
 
         // compute the configuration prefix to use with spring boot 
configuration
         String prefix = "";
@@ -194,53 +210,53 @@ public class SpringBootAutoConfigurationMojo extends 
AbstractMojo {
         }
         prefix += connectorScheme.toLowerCase(Locale.US);
 
-        
javaClass.addAnnotation("org.springframework.boot.context.properties.ConfigurationProperties").setStringValue("prefix",
 prefix);
-
-        for (ComponentOptionModel option : model.getComponentOptions()) {
+        for (OptionModel option : model.getComponentOptions()) {
+            boolean isComponentOption= componentOptions != null && 
componentOptions.stream().anyMatch(o -> o.equals(option.getName()));
+            boolean isEndpointOption = endpointOptions != null && 
endpointOptions.stream().anyMatch(o -> o.equals(option.getName()));
 
-            // only include the options that has been explicit configured in 
the camel-connector.json file
-            boolean accepted = false;
-            if (componentOptions != null) {
-                accepted = componentOptions.stream().anyMatch(o -> 
o.equals(option.getName()));
+            // only include the options that has been explicit configured in 
the
+            // componentOptions section of camel-connector.json file and 
exclude
+            // those configured on endpointOptions in the same file
+            if (isComponentOption && !isEndpointOption) {
+                addProperty(commonClass, model, option);
             }
+        }
 
-            if (accepted) {
-                String type = option.getJavaType();
-                PropertySource<JavaClassSource> prop = 
javaClass.addProperty(type, option.getName());
-
-                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());
-                    }
-                }
+        for (OptionModel option : model.getEndpointOptions()) {
+            if (endpointOptions != null && endpointOptions.stream().anyMatch(o 
-> o.equals(option.getName()))) {
+                addProperty(commonClass, model, option);
             }
         }
 
+        sortImports(commonClass);
+        writeSourceIfChanged(commonClass, packageName.replaceAll("\\.", "\\/") 
+ "/" + commonName + ".java");
 
-        sortImports(javaClass);
+        // Config class
+        JavaClassSource configClass = Roaster.create(JavaClassSource.class);
+        configClass.setPackage(packageName);
+        configClass.setName(configName);
+        configClass.extendSuperType(commonClass);
+        configClass.addAnnotation(Generated.class).setStringValue("value", 
SpringBootAutoConfigurationMojo.class.getName());
+        
configClass.addAnnotation(ConfigurationProperties.class).setStringValue("prefix",
 prefix);
+        configClass.addImport(Map.class);
+        configClass.addImport(HashMap.class);
+        configClass.removeImport(commonClass);
 
-        String fileName = packageName.replaceAll("\\.", "\\/") + "/" + name + 
".java";
-        writeSourceIfChanged(javaClass, fileName);
+        configClass.addField("Map<String, " + commonName + "> configurations = 
new HashMap<>()")
+            .setPrivate()
+            .getJavaDoc().setFullText("Define additional configuration 
definitions");
+
+        MethodSource<JavaClassSource> method;
+
+        method = configClass.addMethod();
+        method.setName("getConfigurations");
+        method.setReturnType("Map<String, " + commonName + ">");
+        method.setPublic();
+        method.setBody("return configurations;");
+
+
+        sortImports(configClass);
+        writeSourceIfChanged(configClass, packageName.replaceAll("\\.", "\\/") 
+ "/" + configName + ".java");
     }
 
     private void createConnectorAutoConfigurationSource(String packageName, 
boolean hasOptions,
@@ -251,12 +267,15 @@ public class SpringBootAutoConfigurationMojo extends 
AbstractMojo {
         int pos = javaType.lastIndexOf(".");
         String name = javaType.substring(pos + 1);
         name = name.replace("Component", "ConnectorAutoConfiguration");
+        final String configNameCommon = javaType.substring(pos + 
1).replace("Component", "ConnectorConfigurationCommon");
+        final String configName = javaType.substring(pos + 
1).replace("Component", "ConnectorConfiguration");
 
         javaClass.setPackage(packageName).setName(name);
 
         String doc = "Generated by camel-connector-maven-plugin - do not edit 
this file!";
         javaClass.getJavaDoc().setFullText(doc);
 
+        javaClass.addAnnotation(Generated.class).setStringValue("value", 
SpringBootAutoConfigurationMojo.class.getName());
         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");
@@ -272,32 +291,44 @@ public class SpringBootAutoConfigurationMojo extends 
AbstractMojo {
         }
 
         javaClass.addImport(javaType);
+        javaClass.addImport(BeanCreationException.class);
         javaClass.addImport("org.apache.camel.CamelContext");
 
+        javaClass.addField()
+            .setName("camelContext")
+            .setType("org.apache.camel.CamelContext")
+            .setPrivate()
+            .addAnnotation(Autowired.class);
+        javaClass.addField()
+            .setName("configuration")
+            .setType(configName)
+            .setPrivate()
+            .addAnnotation(Autowired.class);
+
         // add method for auto configure
         String shortJavaType = getShortJavaType(javaType);
-        String body = createComponentBody(shortJavaType, hasOptions);
-        String methodName = "configure" + shortJavaType;
+        // must be named -component because camel-spring-boot uses that to 
lookup components
+        String beanName = connectorScheme + "-component";
 
-        MethodSource<JavaClassSource> method = javaClass.addMethod()
-            .setName(methodName)
+        MethodSource<JavaClassSource> configureMethod = javaClass.addMethod()
+            .setName("configure" + shortJavaType)
             .setPublic()
-            .setBody(body)
+            .setBody(createComponentBody(shortJavaType, hasOptions))
             .setReturnType(shortJavaType)
             .addThrows(Exception.class);
 
-        method.addParameter("CamelContext", "camelContext");
+        configureMethod.addAnnotation(Lazy.class);
+        configureMethod.addAnnotation(Bean.class).setStringValue("name", 
beanName);
+        
configureMethod.addAnnotation(ConditionalOnClass.class).setLiteralValue("value",
 "CamelContext.class");
+        
configureMethod.addAnnotation(ConditionalOnMissingBean.class).setStringValue("name",
 beanName);
 
-        if (hasOptions) {
-            method.addParameter(configurationName, "configuration");
-        }
+        MethodSource<JavaClassSource> postProcessMethod = javaClass.addMethod()
+            .setName("postConstruct" + shortJavaType)
+            .setPublic()
+            .setBody(createPostConstructBody(shortJavaType, configNameCommon));
 
-        // 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");
+
+        postProcessMethod.addAnnotation(PostConstruct.class);
 
         sortImports(javaClass);
 
@@ -353,6 +384,31 @@ public class SpringBootAutoConfigurationMojo extends 
AbstractMojo {
         return sb.toString();
     }
 
+    private static String createPostConstructBody(String shortJavaType, String 
commonConfigurationName) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("if (camelContext != null) {\n");
+        sb.append("Map<String, Object> parameters = new HashMap<>();\n");
+        sb.append("\n");
+        sb.append("for (Map.Entry<String, " + commonConfigurationName + "> 
entry : configuration.getConfigurations().entrySet()) {\n");
+        sb.append("parameters.clear();\n");
+        sb.append("\n");
+        sb.append(shortJavaType).append(" connector = new 
").append(shortJavaType).append("();\n");
+        sb.append("connector.setCamelContext(camelContext);\n");
+        sb.append("\n");
+        sb.append("try {\n");
+        sb.append("IntrospectionSupport.getProperties(entry.getValue(), 
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("camelContext.addComponent(entry.getKey(), connector);\n");
+        sb.append("} catch (Exception e) {\n");
+        sb.append("throw new BeanCreationException(entry.getKey(), 
e.getMessage(), e);\n");
+        sb.append("}\n");
+        sb.append("}\n");
+        sb.append("}\n");
+        return sb.toString();
+    }
+
     private static void sortImports(JavaClassSource javaClass) {
         // sort imports
         List<Import> imports = javaClass.getImports();
@@ -439,7 +495,59 @@ public class SpringBootAutoConfigurationMojo extends 
AbstractMojo {
             component.addComponentOption(option);
         }
 
+        rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
+        for (Map<String, String> row : rows) {
+            EndpointOptionModel option = new EndpointOptionModel();
+            option.setName(getSafeValue("name", row));
+            option.setDisplayName(getSafeValue("displayName", row));
+            option.setKind(getSafeValue("kind", row));
+            option.setGroup(getSafeValue("group", row));
+            option.setRequired(getSafeValue("required", row));
+            option.setType(getSafeValue("type", row));
+            option.setJavaType(getSafeValue("javaType", row));
+            option.setEnums(getSafeValue("enum", row));
+            option.setPrefix(getSafeValue("prefix", row));
+            option.setMultiValue(getSafeValue("multiValue", row));
+            option.setDeprecated(getSafeValue("deprecated", row));
+            option.setDefaultValue(getSafeValue("defaultValue", row));
+            option.setDescription(getSafeValue("description", row));
+            option.setEnumValues(getSafeValue("enum", row));
+            component.addEndpointOption(option);
+        }
+
         return component;
     }
 
+
+    private void addProperty(JavaClassSource clazz, ComponentModel model, 
OptionModel option) {
+        String type = option.getJavaType();
+        PropertySource<JavaClassSource> prop = clazz.addProperty(type, 
option.getName());
+
+        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());
+                clazz.addImport(model.getJavaType());
+            }
+        }
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/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 2cacb78..0d61b14 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
@@ -37,7 +37,8 @@ public class ComponentModel {
     private String groupId;
     private String artifactId;
     private String version;
-    private final List<ComponentOptionModel> componentOptions = new 
ArrayList<ComponentOptionModel>();
+    private final List<ComponentOptionModel> componentOptions = new 
ArrayList<>();
+    private final List<EndpointOptionModel> endpointOptions = new 
ArrayList<>();
 
     public String getKind() {
         return kind;
@@ -175,6 +176,14 @@ public class ComponentModel {
         componentOptions.add(option);
     }
 
+    public List<EndpointOptionModel> getEndpointOptions() {
+        return endpointOptions;
+    }
+
+    public void addEndpointOption(EndpointOptionModel option) {
+        endpointOptions.add(option);
+    }
+
     public String getShortJavaType() {
         if (javaType.startsWith("java.util.Map")) {
             return "Map";

http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/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
index 96b5598..a97cf53 100644
--- 
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
@@ -16,131 +16,5 @@
  */
 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;
-        }
-    }
-
+public class ComponentOptionModel extends OptionModel {
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/EndpointOptionModel.java
----------------------------------------------------------------------
diff --git 
a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/EndpointOptionModel.java
 
b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/EndpointOptionModel.java
new file mode 100644
index 0000000..07d536a
--- /dev/null
+++ 
b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/EndpointOptionModel.java
@@ -0,0 +1,215 @@
+/**
+ * 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.model;
+
+import com.google.common.base.CaseFormat;
+
+public class EndpointOptionModel extends OptionModel {
+    private String prefix;
+    private String multiValue;
+    private String enumValues;
+
+    // special for documentation rendering
+    private boolean newGroup;
+
+
+    public String getPrefix() {
+        return prefix;
+    }
+
+    public void setPrefix(String prefix) {
+        this.prefix = prefix;
+    }
+
+    public String getMultiValue() {
+        return multiValue;
+    }
+
+    public void setMultiValue(String multiValue) {
+        this.multiValue = multiValue;
+    }
+
+    public String getEnumValues() {
+        return enumValues;
+    }
+
+    public void setEnumValues(String enumValues) {
+        this.enumValues = enumValues;
+    }
+
+    public boolean isNewGroup() {
+        return newGroup;
+    }
+
+    public void setNewGroup(boolean newGroup) {
+        this.newGroup = newGroup;
+    }
+
+    @Override
+    public String getShortJavaType() {
+        // TODO: use watermark in the others
+        return getShortJavaType(40);
+    }
+
+    public String getShortJavaType(int watermark) {
+        String group = getGroup();
+        String type = getType();
+        String javaType = getJavaType();
+
+        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";
+        }
+
+        String text = javaType;
+
+        int pos = text.lastIndexOf(".");
+        if (pos != -1) {
+            text = text.substring(pos + 1);
+        }
+
+        // if its some kind of java object then lets wrap it as its long
+        if ("object".equals(type)) {
+            text = wrapCamelCaseWords(text, watermark, " ");
+        }
+        return text;
+    }
+
+    public String getShortGroup() {
+        String group = getGroup();
+
+        if (group.endsWith(" (advanced)")) {
+            return group.substring(0, group.length() - 11);
+        }
+        return group;
+    }
+
+    public String getShortDefaultValue(int watermark) {
+        String defaultValue = getDefaultValue();
+
+        if (defaultValue.isEmpty()) {
+            return "";
+        }
+        String text = defaultValue;
+        if (text.endsWith("<T>")) {
+            text = text.substring(0, text.length() - 3);
+        } else if (text.endsWith("<T>>")) {
+            text = text.substring(0, text.length() - 4);
+        }
+
+        // TODO: dirty hack for AUTO_ACKNOWLEDGE which we should wrap
+        if ("AUTO_ACKNOWLEDGE".equals(text)) {
+            return "AUTO_ ACKNOWLEDGE";
+        }
+
+        return text;
+    }
+
+    public String getShortName(int watermark) {
+        String text = wrapCamelCaseWords(getName(), watermark, " ");
+        // ensure the option name starts with lower-case
+        return Character.toLowerCase(text.charAt(0)) + text.substring(1);
+    }
+
+    /**
+     * To wrap long camel cased texts by words.
+     *
+     * @param option  the option which is camel cased.
+     * @param watermark a watermark to denote the size to cut after
+     * @param newLine the new line to use when breaking into a new line
+     */
+    private String wrapCamelCaseWords(String option, int watermark, String 
newLine) {
+        String text = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, 
option);
+        text = text.replace('-', ' ');
+        text = wrapWords(text, "\n", watermark, false);
+        text = text.replace(' ', '-');
+        text = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, text);
+
+        // upper case first char on each line
+        String[] lines = text.split("\n");
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < lines.length; i++) {
+            String line = lines[i];
+            line = Character.toUpperCase(line.charAt(0)) + line.substring(1);
+            sb.append(line);
+            if (i < lines.length - 1) {
+                sb.append(newLine);
+            }
+        }
+        return sb.toString();
+    }
+
+    /**
+     * To wrap a big line by words.
+     *
+     * @param line the big line
+     * @param newLine the new line to use when breaking into a new line
+     * @param watermark a watermark to denote the size to cut after
+     * @param wrapLongWords whether to wrap long words
+     */
+    private String wrapWords(String line, String newLine, int watermark, 
boolean wrapLongWords) {
+        if (line == null) {
+            return null;
+        } else {
+            if (newLine == null) {
+                newLine = System.lineSeparator();
+            }
+
+            if (watermark < 1) {
+                watermark = 1;
+            }
+
+            int inputLineLength = line.length();
+            int offset = 0;
+            StringBuilder sb = new StringBuilder(inputLineLength + 32);
+
+            while (inputLineLength - offset > watermark) {
+                if (line.charAt(offset) == 32) {
+                    ++offset;
+                } else {
+                    int spaceToWrapAt = line.lastIndexOf(32, watermark + 
offset);
+                    if (spaceToWrapAt >= offset) {
+                        sb.append(line.substring(offset, spaceToWrapAt));
+                        sb.append(newLine);
+                        offset = spaceToWrapAt + 1;
+                    } else if (wrapLongWords) {
+                        sb.append(line.substring(offset, watermark + offset));
+                        sb.append(newLine);
+                        offset += watermark;
+                    } else {
+                        spaceToWrapAt = line.indexOf(32, watermark + offset);
+                        if (spaceToWrapAt >= 0) {
+                            sb.append(line.substring(offset, spaceToWrapAt));
+                            sb.append(newLine);
+                            offset = spaceToWrapAt + 1;
+                        } else {
+                            sb.append(line.substring(offset));
+                            offset = inputLineLength;
+                        }
+                    }
+                }
+            }
+
+            sb.append(line.substring(offset));
+            return sb.toString();
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/OptionModel.java
----------------------------------------------------------------------
diff --git 
a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/OptionModel.java
 
b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/OptionModel.java
new file mode 100644
index 0000000..64d8002
--- /dev/null
+++ 
b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/OptionModel.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
+ *
+ *      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.model;
+
+public class OptionModel {
+
+    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/3dd29006/connectors/camel-connector/src/main/docs/connector-component.adoc
----------------------------------------------------------------------
diff --git a/connectors/camel-connector/src/main/docs/connector-component.adoc 
b/connectors/camel-connector/src/main/docs/connector-component.adoc
index f3f1e67..a5ea535 100644
--- a/connectors/camel-connector/src/main/docs/connector-component.adoc
+++ b/connectors/camel-connector/src/main/docs/connector-component.adoc
@@ -42,6 +42,7 @@ You can also copy the existing examples from the `connectors` 
directory where th
 - `foo-connector` - A connector that is based on the Timer component from 
`camel-core`.
 - `bar-connector` - A connector that is based on the 3rd party 
`beverage-component`.
 - `wine-connector` - Another connector that is based on the 3rd party 
`beverage-component`.
+- 'twitter-search' - A connector based on twitter to search for keywords.
 
 You can find an example using these connectors in the `foo-bar-wine-example` 
in the `connectors` directory.
 
@@ -111,14 +112,18 @@ And these following Maven plugins:
 
 ### Spring Boot compliant
 
-A Camel connector works great with Spring Boot. If a connector has been 
configured to allow configuration
-  on the component level which is done in the `camel-connector.json` file, 
such as
+A Camel connector works great with Spring Boot. If a connector has been 
configured to allow configuration on the component and/por endpoint level which 
is done in the `camel-connector.json` file, such as
 
-      "componentOptions" : [ "loginUrl", "clientId", "clientSecret", 
"refreshToken" ],
+      "componentOptions" : [ "consumerKey", "consumerSecret", "accessToken", 
"accessTokenSecret" ],
+      "endpointOptions" : [ "keywords" ],
 
 Then the `camel-connector-maven-plugin` will be able to generate Spring Boot 
auto configuration for these options.
 This allows users to essily configure these options if using Spring Boot with 
the connector.
 
+NOTE: There's no disctinction between component/endpoint options on 
spring-boot auto configuration side so all the options are flattered to a 
single namespace thus they appear as connector options and then the conenctor 
figures out where they should be applied.
+
+TIP: The options configured through spring-boot auto configuration classes can 
be overridden by standard endpoint options.
+
 To enable Spring Boot generation you need to enable this in the 
`camel-connector-maven-plugin` by adding
 an `<execution>` with the `prepare-spring-boot-auto-configuration` goal:
 
@@ -157,6 +162,50 @@ You will also need to add the 
`spring-boot-configuration-processor` in the Maven
     </dependency>
 ------------
 
+An example on how to configure a component in spring boot can be taken from 
the twitter-search connector:
+
+[source]
+------------
+    camel.connector.twitter-search.consumer-key = ...
+    camel.connector.twitter-search.consumer-secret = ...
+    camel.connector.twitter-search.access-token = ...
+    camel.connector.twitter-search.access-token-secret = ...
+    camel.connector.twitter-search.keywords = apache-camel
+------------
+
+You may need to instantiate multiple instance of the connector i.e. to use 
different logins and this is now possible through the 'configurations' 
parameters:
+
+[source]
+------------
+    camel.connector.twitter-search.configurations.tw-search1.consumer-key = ...
+    camel.connector.twitter-search.configurations.tw-search1.consumer-secret = 
...
+    camel.connector.twitter-search.configurations.tw-search1.access-token = ...
+    
camel.connector.twitter-search.configurations.tw-search1.access-token-secret = 
...
+    camel.connector.twitter-search.configurations.tw-search1.keywords = 
apache-camel
+
+    camel.connector.twitter-search.configurations.tw-search2.consumer-key = ...
+    camel.connector.twitter-search.configurations.tw-search2.consumer-secret = 
...
+    camel.connector.twitter-search.configurations.tw-search2.access-token = ...
+    
camel.connector.twitter-search.configurations.tw-search2.access-token-secret = 
...
+    camel.connector.twitter-search.configurations.tw-search2.keywords = 
apache-karaf
+------------
+
+This would create two instances of the twitter-search connector each one 
configured with its own list o options.
+You can no use the nre connector as standard components like:
+
+[source,java]
+------------
+    @Component
+    public class MyRouteBuilder implements RouteBuilder{
+        public void configure() throws Exception {
+            from("tw-search1")
+                .log("On account 1 I got:  ${body}")
+            from("tw-search2")
+                .log("On account 2 I got: ${body}")
+        }
+    }
+------------
+
 
 ### Input and Output Data Type
 
@@ -192,4 +241,3 @@ The options the connector can provide is a limited set of 
all the existing optio
 its based upon. Each option can then also be pre-configured with a 
default-value.
 
 To understand this schema file, its easier to study those existing connectors 
from the `connectors` directory.
-

http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/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 901ed0b..b25ff70 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
@@ -68,20 +68,42 @@ public interface ConnectorComponent extends Component {
     String getCamelConnectorJSon();
 
     /**
-     * A set of additional component options to use for the base component 
when creating connector endpoints.
+     * A set of additional component/endpoint options to use for the base 
component when creating connector endpoints.
+     *
+     * @deprecated use {@link #getOptions()} instead
+     */
+    @Deprecated
+    default Map<String, Object> getComponentOptions() {
+        return getOptions();
+    }
+
+    /**
+     * A set of additional component/endpoint options to use for the base 
component when creating connector endpoints.
+     */
+    Map<String, Object> getOptions();
+
+    /**
+     * A set of additional component/endpoint options to use for the base 
component when creating connector endpoints.
+     *
+     * @deprecated use {@link #setOptions(Map)} instead
      */
-    Map<String, Object> getComponentOptions();
+    default void setComponentOptions(Map<String, Object> options) {
+        setOptions(options);
+    }
 
     /**
-     * A set of additional component options to use for the base component 
when creating connector endpoints.
+     * A set of additional component/endpoint options to use for the base 
component when creating connector endpoints.
      */
-    void setComponentOptions(Map<String, Object> baseComponentOptions);
+    void setOptions(Map<String, Object> options);
 
     /**
      * To perform custom processing before the producer is sending the message.
      */
     void setBeforeProducer(Processor processor);
 
+    /**
+     * Gets the processor used to perform custom processing before the 
producer is sending the message.
+     */
     Processor getBeforeProducer();
 
     /**
@@ -89,6 +111,9 @@ public interface ConnectorComponent extends Component {
      */
     void setAfterProducer(Processor processor);
 
+    /**
+     * Gets the processor used to perform custom processing after the producer 
has sent the message and received any reply (if InOut).
+     */
     Processor getAfterProducer();
 
     /**
@@ -96,6 +121,9 @@ public interface ConnectorComponent extends Component {
      */
     void setBeforeConsumer(Processor processor);
 
+    /**
+     * Gets the processor used to perform custom processing when the consumer 
has just received a new incoming message.
+     */
     Processor getBeforeConsumer();
 
     /**
@@ -103,5 +131,8 @@ public interface ConnectorComponent extends Component {
      */
     void setAfterConsumer(Processor processor);
 
+    /**
+     * Gets the processor used to perform custom processing when the consumer 
is about to send back a reply message to the caller (if InOut).
+     */
     Processor getAfterConsumer();
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/ConnectorModel.java
----------------------------------------------------------------------
diff --git 
a/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/ConnectorModel.java
 
b/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/ConnectorModel.java
index 2165d41..8d409f7 100644
--- 
a/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/ConnectorModel.java
+++ 
b/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/ConnectorModel.java
@@ -61,6 +61,8 @@ final class ConnectorModel {
     private DataType outputDataType;
     private Map<String, String> defaultComponentOptions;
     private Map<String, String> defaultEndpointOptions;
+    private List<String> endpointOptions;
+    private List<String> componentOptions;
 
     ConnectorModel(String componentName, String className) {
         this.componentName = componentName;
@@ -132,6 +134,22 @@ final class ConnectorModel {
         return defaultEndpointOptions;
     }
 
+    public List<String> getEndpointOptions() {
+        if (endpointOptions == null) {
+            endpointOptions = 
Collections.unmodifiableList(extractEndpointOptions(lines.get()));
+        }
+
+        return endpointOptions;
+    }
+
+    public List<String> getComponentOptions() {
+        if (endpointOptions == null) {
+            endpointOptions = 
Collections.unmodifiableList(extractComponentOptions(lines.get()));
+        }
+
+        return endpointOptions;
+    }
+
     public DataType getInputDataType() {
         if (inputDataType == null) {
             String line = extractInputDataType(lines.get());
@@ -334,4 +352,62 @@ final class ConnectorModel {
 
         return answer;
     }
+
+    private List<String> extractComponentOptions(List<String> lines) {
+        List<String> answer = new ArrayList<>();
+
+        // extract the default options
+        for (String line : lines) {
+            line = line.trim();
+            if (line.startsWith("\"componentOptions\"")) {
+                int start = line.indexOf('[');
+                if (start == -1) {
+                    throw new IllegalStateException("Malformed 
camel-connector.json");
+                }
+
+                int end = line.indexOf(']', start);
+                if (end == -1) {
+                    throw new IllegalStateException("Malformed 
camel-connector.json");
+                }
+
+                line = line.substring(start + 1, end).trim();
+                for (String option : line.split(",")) {
+                    
answer.add(StringHelper.removeLeadingAndEndingQuotes(option));
+                }
+
+                break;
+            }
+        }
+
+        return answer;
+    }
+
+    private List<String> extractEndpointOptions(List<String> lines) {
+        List<String> answer = new ArrayList<>();
+
+        // extract the default options
+        for (String line : lines) {
+            line = line.trim();
+            if (line.startsWith("\"endpointOptions\"")) {
+                int start = line.indexOf('[');
+                if (start == -1) {
+                    throw new IllegalStateException("Malformed 
camel-connector.json");
+                }
+
+                int end = line.indexOf(']', start);
+                if (end == -1) {
+                    throw new IllegalStateException("Malformed 
camel-connector.json");
+                }
+
+                line = line.substring(start + 1, end).trim();
+                for (String option : line.split(",")) {
+                    
answer.add(StringHelper.removeLeadingAndEndingQuotes(option));
+                }
+
+                break;
+            }
+        }
+
+        return answer;
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/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 192ebf1..50d1407 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
@@ -20,13 +20,18 @@ import java.lang.reflect.Constructor;
 import java.lang.reflect.Modifier;
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
 
+import org.apache.camel.CamelContext;
 import org.apache.camel.Component;
 import org.apache.camel.ComponentVerifier;
 import org.apache.camel.Endpoint;
+import org.apache.camel.NoTypeConversionAvailableException;
 import org.apache.camel.Processor;
 import org.apache.camel.VerifiableComponent;
 import org.apache.camel.catalog.CamelCatalog;
@@ -35,6 +40,7 @@ import org.apache.camel.impl.DefaultComponent;
 import org.apache.camel.impl.verifier.ResultBuilder;
 import org.apache.camel.impl.verifier.ResultErrorBuilder;
 import org.apache.camel.util.IntrospectionSupport;
+import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.URISupport;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -48,20 +54,35 @@ public abstract class DefaultConnectorComponent extends 
DefaultComponent impleme
     private final Logger log = LoggerFactory.getLogger(getClass());
     private final CamelCatalog catalog = new DefaultCamelCatalog(false);
 
+    private final String baseScheme;
     private final String componentName;
+    private final String componentScheme;
     private final ConnectorModel model;
-    private Map<String, Object> componentOptions;
+    private Map<String, Object> options;
     private Processor beforeProducer;
     private Processor afterProducer;
     private Processor beforeConsumer;
     private Processor afterConsumer;
 
     protected DefaultConnectorComponent(String componentName, String 
className) {
-        this.componentName = componentName;
         this.model = new ConnectorModel(componentName, className);
+        this.baseScheme = this.model.getBaseScheme();
+        this.componentName = componentName;
+        this.componentScheme = componentName + "-component";
 
         // add to catalog
         this.catalog.addComponent(componentName, className);
+
+        // It may be a custom component so we need to register this in the 
camel catalog also
+        if (!catalog.findComponentNames().contains(baseScheme)) {
+            catalog.addComponent(baseScheme,  model.getBaseJavaType());
+        }
+
+        // Add an alias for the base component so there's no clash between 
connectors
+        // if they set options targeting the component.
+        if (!catalog.findComponentNames().contains(componentScheme)) {
+            this.catalog.addComponent(componentScheme, 
this.model.getBaseJavaType(), catalog.componentJSonSchema(baseScheme));
+        }
     }
 
     @Override
@@ -78,16 +99,10 @@ public abstract class DefaultConnectorComponent extends 
DefaultComponent impleme
         // grab the regular query parameters
         Map<String, String> options = buildEndpointOptions(remaining, 
parameters);
 
-        String scheme = model.getBaseScheme();
-
-        // now create the endpoint instance which either happens with a new
-        // base component which has been pre-configured for this connector
-        // or we fallback and use the default component in the camel context
-        createNewBaseComponent(scheme);
-
         // create the uri of the base component
-        String delegateUri = createEndpointUri(scheme, options);
+        String delegateUri = createEndpointUri(componentScheme, options);
         Endpoint delegate = getCamelContext().getEndpoint(delegateUri);
+
         if (log.isInfoEnabled()) {
             // the uris can have sensitive information so sanitize
             log.info("Connector resolved: {} -> {}", sanitizeUri(uri), 
sanitizeUri(delegateUri));
@@ -119,7 +134,10 @@ public abstract class DefaultConnectorComponent extends 
DefaultComponent impleme
     @Override
     public void addConnectorOption(Map<String, String> options, String name, 
String value) {
         log.trace("Adding option: {}={}", name, value);
-        options.put(name, value);
+        Object val = options.put(name, value);
+        if (val != null) {
+            log.debug("Options {} overridden, old value was {}", name, val);
+        }
     }
 
     @Override
@@ -142,48 +160,60 @@ public abstract class DefaultConnectorComponent extends 
DefaultComponent impleme
         return componentName;
     }
 
-    public Map<String, Object> getComponentOptions() {
-        return componentOptions;
+    @Override
+    public Map<String, Object> getOptions() {
+        return options;
     }
 
-    public void setComponentOptions(Map<String, Object> baseComponentOptions) {
-        this.componentOptions = baseComponentOptions;
+    @Override
+    public void setOptions(Map<String, Object> baseComponentOptions) {
+        // Copy the map so if the given map is externally modified the 
connector
+        // is not impacted.
+        this.options = Collections.unmodifiableMap(new 
HashMap<>(baseComponentOptions));
     }
 
     @SuppressWarnings("unchecked")
     @Override
     public ComponentVerifier getVerifier() {
-        final String scheme = model.getBaseScheme();
-        // only get or create component but do NOT start it as component
-        final Component component = getCamelContext().getComponent(scheme, 
true, false);
+        try {
+            // Create the component but no need to add it to the camel context
+            // nor to start it.
+            final Component component = createNewBaseComponent();
+
+            if (component instanceof VerifiableComponent) {
+                return (scope, map) -> {
+                    Map<String, Object> options;
+
+                    try {
+                        // A little nasty hack required as verifier uses 
Map<String, Object>
+                        // to be compatible with all the methods in 
CamelContext whereas
+                        // catalog deals with Map<String, String>
+                        options = (Map) buildEndpointOptions(null, map);
+                    } catch (URISyntaxException | 
NoTypeConversionAvailableException e) {
+                        // If a failure is detected while reading the catalog, 
wrap it
+                        // and stop the validation step.
+                        return 
ResultBuilder.withStatusAndScope(ComponentVerifier.Result.Status.OK, scope)
+                            .error(ResultErrorBuilder.withException(e).build())
+                            .build();
+                    }
 
-        if (component instanceof VerifiableComponent) {
-            return (scope, map) -> {
-                Map<String, Object> options;
-
-                try {
-                    // A little nasty hack required as verifier uses 
Map<String, Object>
-                    // to be compatible with all the methods in CamelContext 
whereas
-                    // catalog deals with Map<String, String>
-                    options = (Map) buildEndpointOptions(null, map);
-                } catch (URISyntaxException e) {
-                    // If a failure is detected while reading the catalog, 
wrap it
-                    // and stop the validation step.
-                    return 
ResultBuilder.withStatusAndScope(ComponentVerifier.Result.Status.OK, scope)
-                        .error(ResultErrorBuilder.withException(e).build())
+                    return ((VerifiableComponent) 
component).getVerifier().verify(scope, options);
+                };
+            } else {
+                return (scope, map) -> {
+                    return 
ResultBuilder.withStatusAndScope(ComponentVerifier.Result.Status.UNSUPPORTED, 
scope)
+                        .error(
+                            
ResultErrorBuilder.withCode(ComponentVerifier.VerificationError.StandardCode.UNSUPPORTED)
+                                .detail("camel_connector_name", 
getConnectorName())
+                                .detail("camel_component_name", 
getComponentName())
+                                .build())
                         .build();
-                }
-
-                return 
((VerifiableComponent)component).getVerifier().verify(scope, options);
-            };
-        } else {
+                };
+            }
+        } catch (Exception e) {
             return (scope, map) -> {
-                return 
ResultBuilder.withStatusAndScope(ComponentVerifier.Result.Status.UNSUPPORTED, 
scope)
-                    .error(
-                        
ResultErrorBuilder.withCode(ComponentVerifier.VerificationError.StandardCode.UNSUPPORTED)
-                            .detail("camel_connector_name", getConnectorName())
-                            .detail("camel_component_name", getComponentName())
-                            .build())
+                return 
ResultBuilder.withStatusAndScope(ComponentVerifier.Result.Status.OK, scope)
+                    .error(ResultErrorBuilder.withException(e).build())
                     .build();
             };
         }
@@ -194,7 +224,6 @@ public abstract class DefaultConnectorComponent extends 
DefaultComponent impleme
     @Override
     protected void doStart() throws Exception {
         // lets enforce that every connector must have an input and output 
data type
-
         if (model.getInputDataType() == null) {
             throw new IllegalArgumentException("Camel connector must have 
inputDataType defined in camel-connector.json file");
         }
@@ -208,11 +237,13 @@ public abstract class DefaultConnectorComponent extends 
DefaultComponent impleme
             throw new IllegalArgumentException("Camel connector must have 
baseJavaType defined in camel-connector.json file");
         }
 
-        // it may be a custom component so we need to register this in the 
camel catalog also
-        String scheme = model.getBaseScheme();
-        if (!catalog.findComponentNames().contains(scheme)) {
-            String javaType = model.getBaseJavaType();
-            catalog.addComponent(scheme, javaType);
+        Component component = createNewBaseComponent();
+        if (component != null) {
+            getCamelContext().removeComponent(this.componentScheme);
+
+            // ensure component is started and stopped when Camel shutdown
+            getCamelContext().addService(component, true, true);
+            getCamelContext().addComponent(this.componentScheme, component);
         }
 
         log.debug("Starting connector: {}", componentName);
@@ -269,8 +300,16 @@ public abstract class DefaultConnectorComponent extends 
DefaultComponent impleme
     // Helpers
     // ***************************************
 
-    private Component createNewBaseComponent(String scheme) throws Exception {
-        String baseClassName = model.getBaseJavaType();
+    /**
+     * Create the endpoint instance which either happens with a new base 
component
+     * which has been pre-configured for this connector or we fallback and use
+     * the default component in the camel context
+     */
+    private Component createNewBaseComponent() throws Exception {
+        final String baseClassName = model.getBaseJavaType();
+        final CamelContext context = getCamelContext();
+
+        Component base = null;
 
         if (baseClassName != null) {
             // create a new instance of this base component
@@ -278,45 +317,46 @@ public abstract class DefaultConnectorComponent extends 
DefaultComponent impleme
             Constructor ctr = getPublicDefaultConstructor(type);
             if (ctr != null) {
                 // call default no-arg constructor
-                Object base = ctr.newInstance();
+                base = (Component)ctr.newInstance();
+                base.setCamelContext(context);
 
                 // the connector may have default values for the component 
level also
-                // and if so we need to prepare these values and set on this 
component before we can start
+                // and if so we need to prepare these values and set on this 
component
+                // before we can start
                 Map<String, String> defaultOptions = 
model.getDefaultComponentOptions();
 
                 if (!defaultOptions.isEmpty()) {
-                    Map<String, Object> copy = new LinkedHashMap<>();
                     for (Map.Entry<String, String> entry : 
defaultOptions.entrySet()) {
                         String key = entry.getKey();
                         String value = entry.getValue();
                         if (value != null) {
                             // also support {{ }} placeholders so resolve 
those first
                             value = 
getCamelContext().resolvePropertyPlaceholders(value);
+
                             log.debug("Using component option: {}={}", key, 
value);
-                            copy.put(key, value);
+                            IntrospectionSupport.setProperty(context, base, 
key, value);
                         }
                     }
-                    IntrospectionSupport.setProperties(getCamelContext(), 
getCamelContext().getTypeConverter(), base, copy);
                 }
 
                 // configure component with extra options
-                if (componentOptions != null && !componentOptions.isEmpty()) {
-                    Map<String, Object> copy = new 
LinkedHashMap<>(componentOptions);
-                    IntrospectionSupport.setProperties(getCamelContext(), 
getCamelContext().getTypeConverter(), base, copy);
-                }
-
-                if (base instanceof Component) {
-                    getCamelContext().removeComponent(scheme);
-                    // ensure component is started and stopped when Camel 
shutdown
-                    getCamelContext().addService(base, true, true);
-                    getCamelContext().addComponent(scheme, (Component) base);
-
-                    return (Component) base;
+                if (options != null && !options.isEmpty()) {
+                    // Get the list of options from the connector catalog that
+                    // are configured to target the endpoint
+                    List<String> endpointOptions = model.getEndpointOptions();
+
+                    for (Map.Entry<String, Object> entry : options.entrySet()) 
{
+                        // Only set options that are not targeting the endpoint
+                        if (!endpointOptions.contains(entry.getKey())) {
+                            log.debug("Using component option: {}={}", 
entry.getKey(), entry.getValue());
+                            IntrospectionSupport.setProperty(context, base, 
entry.getKey(), entry.getValue());
+                        }
+                    }
                 }
             }
         }
 
-        return null;
+        return base;
     }
 
     /**
@@ -366,8 +406,7 @@ public abstract class DefaultConnectorComponent extends 
DefaultComponent impleme
         }
     }
 
-    private Map<String, String> buildEndpointOptions(String remaining, 
Map<String, Object> parameters) throws URISyntaxException {
-        String scheme = model.getBaseScheme();
+    private Map<String, String> buildEndpointOptions(String remaining, 
Map<String, Object> parameters) throws URISyntaxException, 
NoTypeConversionAvailableException {
         Map<String, String> defaultOptions = model.getDefaultEndpointOptions();
 
         // gather all options to use when building the delegate uri
@@ -382,6 +421,22 @@ public abstract class DefaultConnectorComponent extends 
DefaultComponent impleme
             });
         }
 
+        // Extract options from options that are supposed to be set at the 
endpoint
+        // level, those options can be overridden and extended using by the 
query
+        // parameters.
+        List<String> endpointOptions = model.getEndpointOptions();
+        if (ObjectHelper.isNotEmpty(endpointOptions) && 
ObjectHelper.isNotEmpty(this.options)) {
+            for (String endpointOption : endpointOptions) {
+                Object value = this.options.get(endpointOption);
+                if (value != null) {
+                    addConnectorOption(
+                        options,
+                        endpointOption,
+                        
getCamelContext().getTypeConverter().mandatoryConvertTo(String.class, value));
+                }
+            }
+        }
+
         // options from query parameters
         for (Map.Entry<String, Object> entry : parameters.entrySet()) {
             String key = entry.getKey();
@@ -396,7 +451,7 @@ public abstract class DefaultConnectorComponent extends 
DefaultComponent impleme
 
         // add extra options from remaining (context-path)
         if (remaining != null) {
-            String targetUri = scheme + ":" + remaining;
+            String targetUri = componentScheme + ":" + remaining;
             Map<String, String> extra = catalog.endpointProperties(targetUri);
             if (extra != null && !extra.isEmpty()) {
                 extra.forEach((key, value) -> {

http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorAutoConfiguration.java
----------------------------------------------------------------------
diff --git 
a/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorAutoConfiguration.java
 
b/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorAutoConfiguration.java
index b2739c5..85e27b0 100644
--- 
a/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorAutoConfiguration.java
+++ 
b/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorAutoConfiguration.java
@@ -18,9 +18,13 @@ package org.foo.connector.springboot;
 
 import java.util.HashMap;
 import java.util.Map;
+import javax.annotation.Generated;
+import javax.annotation.PostConstruct;
 import org.apache.camel.CamelContext;
 import org.apache.camel.util.IntrospectionSupport;
 import org.foo.connector.PetStoreComponent;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.autoconfigure.AutoConfigureAfter;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@@ -33,19 +37,23 @@ import org.springframework.context.annotation.Lazy;
 /**
  * Generated by camel-connector-maven-plugin - do not edit this file!
  */
+@Generated("org.apache.camel.maven.connector.SpringBootAutoConfigurationMojo")
 @Configuration
 @ConditionalOnBean(type = 
"org.apache.camel.spring.boot.CamelAutoConfiguration")
 @AutoConfigureAfter(name = 
"org.apache.camel.spring.boot.CamelAutoConfiguration")
 @EnableConfigurationProperties(PetStoreConnectorConfiguration.class)
 public class PetStoreConnectorAutoConfiguration {
 
+    @Autowired
+    private CamelContext camelContext;
+    @Autowired
+    private PetStoreConnectorConfiguration configuration;
+
     @Lazy
     @Bean(name = "petstore-component")
     @ConditionalOnClass(CamelContext.class)
-    @ConditionalOnMissingBean(org.foo.connector.PetStoreComponent.class)
-    public PetStoreComponent configurePetStoreComponent(
-            CamelContext camelContext,
-            PetStoreConnectorConfiguration configuration) throws Exception {
+    @ConditionalOnMissingBean(name = "petstore-component")
+    public PetStoreComponent configurePetStoreComponent() throws Exception {
         PetStoreComponent connector = new PetStoreComponent();
         connector.setCamelContext(camelContext);
         Map<String, Object> parameters = new HashMap<>();
@@ -56,4 +64,29 @@ public class PetStoreConnectorAutoConfiguration {
         connector.setComponentOptions(parameters);
         return connector;
     }
+
+    @PostConstruct
+    public void postConstructPetStoreComponent() {
+        if (camelContext != null) {
+            Map<String, Object> parameters = new HashMap<>();
+            for (Map.Entry<String, PetStoreConnectorConfigurationCommon> entry 
: configuration
+                    .getConfigurations().entrySet()) {
+                parameters.clear();
+                PetStoreComponent connector = new PetStoreComponent();
+                connector.setCamelContext(camelContext);
+                try {
+                    IntrospectionSupport.getProperties(entry.getValue(),
+                            parameters, null, false);
+                    IntrospectionSupport.setProperties(camelContext,
+                            camelContext.getTypeConverter(), connector,
+                            parameters);
+                    connector.setComponentOptions(parameters);
+                    camelContext.addComponent(entry.getKey(), connector);
+                } catch (Exception e) {
+                    throw new BeanCreationException(entry.getKey(),
+                            e.getMessage(), e);
+                }
+            }
+        }
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorConfiguration.java
----------------------------------------------------------------------
diff --git 
a/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorConfiguration.java
 
b/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorConfiguration.java
index 0ae5ef3..fa19e29 100644
--- 
a/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorConfiguration.java
+++ 
b/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorConfiguration.java
@@ -16,34 +16,23 @@
  */
 package org.foo.connector.springboot;
 
-import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.Generated;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 
-/**
- * An awesome REST endpoint backed by Swagger specifications.
- * 
- * Generated by camel-connector-maven-plugin - do not edit this file!
- */
+@Generated("org.apache.camel.maven.connector.SpringBootAutoConfigurationMojo")
 @ConfigurationProperties(prefix = "camel.connector.petstore")
-public class PetStoreConnectorConfiguration {
+public class PetStoreConnectorConfiguration
+        extends
+            PetStoreConnectorConfigurationCommon {
 
     /**
-     * Path to the Swagger specification file. The scheme host base path are
-     * taken from this specification but these can be overriden with properties
-     * on the component or endpoint level. If not given the component tries to
-     * load swagger.json resource. Note that the host defined on the component
-     * and endpoint of this Component should contain the scheme hostname and
-     * optionally the port in the URI syntax (i.e.
-     * https://api.example.com:8080). Can be overriden in endpoint
-     * configuration.
+     * Define additional configuration definitions
      */
-    private URI specificationUri;
-
-    public URI getSpecificationUri() {
-        return specificationUri;
-    }
+    private Map<String, PetStoreConnectorConfigurationCommon> configurations = 
new HashMap<>();
 
-    public void setSpecificationUri(URI specificationUri) {
-        this.specificationUri = specificationUri;
+    public Map<String, PetStoreConnectorConfigurationCommon> 
getConfigurations() {
+        return configurations;
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorConfigurationCommon.java
----------------------------------------------------------------------
diff --git 
a/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorConfigurationCommon.java
 
b/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorConfigurationCommon.java
new file mode 100644
index 0000000..8af2c18
--- /dev/null
+++ 
b/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorConfigurationCommon.java
@@ -0,0 +1,61 @@
+/**
+ * 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.foo.connector.springboot;
+
+import java.net.URI;
+import javax.annotation.Generated;
+
+/**
+ * An awesome REST endpoint backed by Swagger specifications.
+ * 
+ * Generated by camel-package-maven-plugin - do not edit this file!
+ */
+@Generated("org.apache.camel.maven.connector.SpringBootAutoConfigurationMojo")
+public class PetStoreConnectorConfigurationCommon {
+
+    /**
+     * Path to the Swagger specification file. The scheme host base path are
+     * taken from this specification but these can be overriden with properties
+     * on the component or endpoint level. If not given the component tries to
+     * load swagger.json resource. Note that the host defined on the component
+     * and endpoint of this Component should contain the scheme hostname and
+     * optionally the port in the URI syntax (i.e.
+     * https://api.example.com:8080). Can be overriden in endpoint
+     * configuration.
+     */
+    private URI specificationUri;
+    /**
+     * ID of the operation from the Swagger specification.
+     */
+    private String operationId;
+
+    public URI getSpecificationUri() {
+        return specificationUri;
+    }
+
+    public void setSpecificationUri(URI specificationUri) {
+        this.specificationUri = specificationUri;
+    }
+
+    public String getOperationId() {
+        return operationId;
+    }
+
+    public void setOperationId(String operationId) {
+        this.operationId = operationId;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/connectors/examples/pom.xml
----------------------------------------------------------------------
diff --git a/connectors/examples/pom.xml b/connectors/examples/pom.xml
index 65bc229..8a4b10a 100644
--- a/connectors/examples/pom.xml
+++ b/connectors/examples/pom.xml
@@ -40,6 +40,8 @@
     <module>wine-connector</module>
     <module>foo-bar-wine-example</module>
     <module>twitter-mention-connector</module>
+    <module>twitter-search-connector</module>
+    <module>twitter-search-example</module>
     <module>twitter-salesforce-example</module>
     <module>salesforce-upsert-contact-connector</module>
     <module>petstore-connector</module>

http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/connectors/examples/salesforce-upsert-contact-connector/src/main/java/org/foo/salesforce/contact/springboot/SalesforceUpsertContactConnectorAutoConfiguration.java
----------------------------------------------------------------------
diff --git 
a/connectors/examples/salesforce-upsert-contact-connector/src/main/java/org/foo/salesforce/contact/springboot/SalesforceUpsertContactConnectorAutoConfiguration.java
 
b/connectors/examples/salesforce-upsert-contact-connector/src/main/java/org/foo/salesforce/contact/springboot/SalesforceUpsertContactConnectorAutoConfiguration.java
index c9045ed..89c4dee 100644
--- 
a/connectors/examples/salesforce-upsert-contact-connector/src/main/java/org/foo/salesforce/contact/springboot/SalesforceUpsertContactConnectorAutoConfiguration.java
+++ 
b/connectors/examples/salesforce-upsert-contact-connector/src/main/java/org/foo/salesforce/contact/springboot/SalesforceUpsertContactConnectorAutoConfiguration.java
@@ -18,9 +18,13 @@ package org.foo.salesforce.contact.springboot;
 
 import java.util.HashMap;
 import java.util.Map;
+import javax.annotation.Generated;
+import javax.annotation.PostConstruct;
 import org.apache.camel.CamelContext;
 import org.apache.camel.util.IntrospectionSupport;
 import org.foo.salesforce.contact.SalesforceUpsertContactComponent;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.autoconfigure.AutoConfigureAfter;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@@ -33,19 +37,23 @@ import org.springframework.context.annotation.Lazy;
 /**
  * Generated by camel-connector-maven-plugin - do not edit this file!
  */
+@Generated("org.apache.camel.maven.connector.SpringBootAutoConfigurationMojo")
 @Configuration
 @ConditionalOnBean(type = 
"org.apache.camel.spring.boot.CamelAutoConfiguration")
 @AutoConfigureAfter(name = 
"org.apache.camel.spring.boot.CamelAutoConfiguration")
 
@EnableConfigurationProperties(SalesforceUpsertContactConnectorConfiguration.class)
 public class SalesforceUpsertContactConnectorAutoConfiguration {
 
+    @Autowired
+    private CamelContext camelContext;
+    @Autowired
+    private SalesforceUpsertContactConnectorConfiguration configuration;
+
     @Lazy
     @Bean(name = "salesforce-upsert-contact-component")
     @ConditionalOnClass(CamelContext.class)
-    
@ConditionalOnMissingBean(org.foo.salesforce.contact.SalesforceUpsertContactComponent.class)
-    public SalesforceUpsertContactComponent 
configureSalesforceUpsertContactComponent(
-            CamelContext camelContext,
-            SalesforceUpsertContactConnectorConfiguration configuration)
+    @ConditionalOnMissingBean(name = "salesforce-upsert-contact-component")
+    public SalesforceUpsertContactComponent 
configureSalesforceUpsertContactComponent()
             throws Exception {
         SalesforceUpsertContactComponent connector = new 
SalesforceUpsertContactComponent();
         connector.setCamelContext(camelContext);
@@ -57,4 +65,29 @@ public class 
SalesforceUpsertContactConnectorAutoConfiguration {
         connector.setComponentOptions(parameters);
         return connector;
     }
+
+    @PostConstruct
+    public void postConstructSalesforceUpsertContactComponent() {
+        if (camelContext != null) {
+            Map<String, Object> parameters = new HashMap<>();
+            for (Map.Entry<String, 
SalesforceUpsertContactConnectorConfigurationCommon> entry : configuration
+                    .getConfigurations().entrySet()) {
+                parameters.clear();
+                SalesforceUpsertContactComponent connector = new 
SalesforceUpsertContactComponent();
+                connector.setCamelContext(camelContext);
+                try {
+                    IntrospectionSupport.getProperties(entry.getValue(),
+                            parameters, null, false);
+                    IntrospectionSupport.setProperties(camelContext,
+                            camelContext.getTypeConverter(), connector,
+                            parameters);
+                    connector.setComponentOptions(parameters);
+                    camelContext.addComponent(entry.getKey(), connector);
+                } catch (Exception e) {
+                    throw new BeanCreationException(entry.getKey(),
+                            e.getMessage(), e);
+                }
+            }
+        }
+    }
 }
\ No newline at end of file

Reply via email to