You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2019/06/17 12:04:52 UTC

[camel] 17/20: CAMEL-13647: Allow to do autowrire by classpath. Quick and dirty prototype.

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 7c0f037ab30126ab7131e811d5cc10f114a1fa8f
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Jun 17 12:46:38 2019 +0200

    CAMEL-13647: Allow to do autowrire by classpath. Quick and dirty prototype.
---
 .../java/org/apache/camel/maven/AutowireMojo.java  | 102 ++++++++++++++++++---
 ...ypes.properties => default-mappings.properties} |   6 +-
 examples/camel-example-main-artemis/pom.xml        |   2 +
 .../src/main/resources/application.properties      |  13 ++-
 4 files changed, 102 insertions(+), 21 deletions(-)

diff --git a/catalog/camel-main-maven-plugin/src/main/java/org/apache/camel/maven/AutowireMojo.java b/catalog/camel-main-maven-plugin/src/main/java/org/apache/camel/maven/AutowireMojo.java
index 1519298..a05e5b6 100644
--- a/catalog/camel-main-maven-plugin/src/main/java/org/apache/camel/maven/AutowireMojo.java
+++ b/catalog/camel-main-maven-plugin/src/main/java/org/apache/camel/maven/AutowireMojo.java
@@ -40,7 +40,10 @@ import org.apache.camel.catalog.CamelCatalog;
 import org.apache.camel.catalog.DefaultCamelCatalog;
 import org.apache.camel.catalog.JSonSchemaHelper;
 import org.apache.camel.catalog.maven.MavenVersionManager;
+import org.apache.camel.support.PatternHelper;
 import org.apache.camel.util.IOHelper;
+import org.apache.camel.util.OrderedProperties;
+import org.apache.camel.util.StringHelper;
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.artifact.factory.ArtifactFactory;
 import org.apache.maven.artifact.repository.ArtifactRepository;
@@ -91,6 +94,27 @@ public class AutowireMojo extends AbstractExecMojo {
     @Parameter(readonly = true, defaultValue = "${project.build.directory}/classes/META-INF/services/org/apache/camel/")
     protected File outFolder;
 
+    /**
+     * To exclude autowiring specific properties with these key names.
+     * You can also configure a single entry and separate the excludes with comma
+     */
+    @Parameter(property = "camel.exclude")
+    protected String[] exclude;
+
+    /**
+     * To include autowiring specific properties or component with these key names.
+     * You can also configure a single entry and separate the includes with comma
+     */
+    @Parameter(property = "camel.include")
+    protected String[] include;
+
+    /**
+     * To setup special mappings between known types as key=value pairs.
+     * You can also configure a single entry and separate the mappings with comma
+     */
+    @Parameter(property = "camel.mappings")
+    protected String[] mappings;
+
     @Component
     private ArtifactFactory artifactFactory;
 
@@ -106,8 +130,6 @@ public class AutowireMojo extends AbstractExecMojo {
     private transient ClassLoader classLoader;
 
     // TODO: Allow to configure known types in xml config, or refer to external file
-    // TODO: Allow to configure include/exclude names on components,names
-    // TODO: Skip some known types
 
     // CHECKSTYLE:OFF
     @Override
@@ -165,12 +187,23 @@ public class AutowireMojo extends AbstractExecMojo {
                 .addClassLoader(classLoader)
                 .setScanners(new SubTypesScanner()));
 
-        // load known types
-        Properties knownTypes = loadKnownTypes();
-        getLog().debug("Loaded known-types: " + knownTypes);
+        // load default mappings
+        Properties mappingProperties = loadDefaultMappings();
+        getLog().debug("Loaded default-mappings: " + mappingProperties);
+        // add extra mappings
+        if (this.mappings != null) {
+            for (String m : this.mappings) {
+                String key = StringHelper.before(m, "=");
+                String value = StringHelper.after(m, "=");
+                if (key != null && value != null) {
+                    mappingProperties.setProperty(key, value);
+                    getLog().debug("Added mapping: " + key + "=" + value);
+                }
+            }
+        }
 
         // find the autowire via classpath scanning
-        List<String> autowires = findAutowireComponentOptionsByClasspath(catalog, components, reflections, knownTypes);
+        List<String> autowires = findAutowireComponentOptionsByClasspath(catalog, components, reflections, mappingProperties);
 
         if (!autowires.isEmpty()) {
             outFolder.mkdirs();
@@ -190,21 +223,21 @@ public class AutowireMojo extends AbstractExecMojo {
         }
     }
 
-    protected Properties loadKnownTypes() throws MojoFailureException {
-        Properties knownTypes = new Properties();
+    protected Properties loadDefaultMappings() throws MojoFailureException {
+        Properties mappings = new OrderedProperties();
         try {
-            InputStream is = AutowireMojo.class.getResourceAsStream("/known-types.properties");
+            InputStream is = AutowireMojo.class.getResourceAsStream("/default-mappings.properties");
             if (is != null) {
-                knownTypes.load(is);
+                mappings.load(is);
             }
         } catch (IOException e) {
-            throw new MojoFailureException("Cannot load known-types.properties from classpath");
+            throw new MojoFailureException("Cannot load default-mappings.properties from classpath");
         }
-        return knownTypes;
+        return mappings;
     }
 
     protected List<String> findAutowireComponentOptionsByClasspath(CamelCatalog catalog, Set<String> components,
-                                                                   Reflections reflections, Properties knownTypes) {
+                                                                   Reflections reflections, Properties mappingProperties) {
         List<String> autowires = new ArrayList<>();
 
         for (String componentName : components) {
@@ -223,13 +256,17 @@ public class AutowireMojo extends AbstractExecMojo {
                 String type = row.get("type");
                 String javaType = safeJavaType(row.get("javaType"));
                 if ("object".equals(type)) {
+                    if (!isValidPropertyName(componentName, name)) {
+                        getLog().debug("Skipping property name: " + name);
+                        continue;
+                    }
                     try {
                         Class clazz = classLoader.loadClass(javaType);
                         if (clazz.isInterface() && isComplexUserType(clazz)) {
                             Set<Class<?>> classes = reflections.getSubTypesOf(clazz);
                             // filter classes to not be interfaces or not a top level class
                             classes = classes.stream().filter(c -> !c.isInterface() && c.getEnclosingClass() == null).collect(Collectors.toSet());
-                            Class best = chooseBestKnownType(clazz, classes, knownTypes);
+                            Class best = chooseBestKnownType(clazz, classes, mappingProperties);
                             if (isValidAutowireClass(best)) {
                                 String line = "camel.component." + componentName + "." + name + "=#class:" + best.getName();
                                 getLog().debug(line);
@@ -251,7 +288,7 @@ public class AutowireMojo extends AbstractExecMojo {
     protected Class chooseBestKnownType(Class type, Set<Class<?>> candidates, Properties knownTypes) {
         String known = knownTypes.getProperty(type.getName());
         if (known != null) {
-            for (String k : known.split(",")) {
+            for (String k : known.split(";")) {
                 // special as we should skip this option
                 if ("#skip#".equals(k)) {
                     return null;
@@ -271,6 +308,41 @@ public class AutowireMojo extends AbstractExecMojo {
         return null;
     }
 
+    protected boolean isValidPropertyName(String componentName, String name) {
+        // we want to regard names as the same if they are using dash or not, and also to be case insensitive.
+        String prefix = "camel.component." + componentName + ".";
+        name = StringHelper.dashToCamelCase(name);
+
+        if (exclude != null) {
+            // works on components too
+            for (String pattern : exclude) {
+                pattern = StringHelper.dashToCamelCase(pattern);
+                if (PatternHelper.matchPattern(componentName, pattern)) {
+                    return false;
+                }
+                if (PatternHelper.matchPattern(name, pattern) || PatternHelper.matchPattern(prefix + name, pattern)) {
+                    return false;
+                }
+            }
+        }
+
+        if (include != null) {
+            for (String pattern : include) {
+                pattern = StringHelper.dashToCamelCase(pattern);
+                if (PatternHelper.matchPattern(componentName, pattern)) {
+                    return true;
+                }
+                if (PatternHelper.matchPattern(name, pattern) || PatternHelper.matchPattern(prefix + name, pattern)) {
+                    return true;
+                }
+            }
+            // we have include enabled and none matched so it should be false
+            return false;
+        }
+
+        return true;
+    }
+
     private static boolean isComplexUserType(Class type) {
         // lets consider all non java, as complex types
         return type != null && !type.isPrimitive() && !type.getName().startsWith("java.");
diff --git a/catalog/camel-main-maven-plugin/src/main/resources/known-types.properties b/catalog/camel-main-maven-plugin/src/main/resources/default-mappings.properties
similarity index 85%
rename from catalog/camel-main-maven-plugin/src/main/resources/known-types.properties
rename to catalog/camel-main-maven-plugin/src/main/resources/default-mappings.properties
index 78971fe..630a930 100644
--- a/catalog/camel-main-maven-plugin/src/main/resources/known-types.properties
+++ b/catalog/camel-main-maven-plugin/src/main/resources/default-mappings.properties
@@ -15,8 +15,8 @@
 ## limitations under the License.
 ## ---------------------------------------------------------------------------
 
-# favour these classes if there are multiple on the classpath
-javax.jms.ConnectionFactory=org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory,org.apache.activemq.ActiveMQConnectionFactory
+# favour these classes if there are multiple on the classpath (separate values with semi colon)
+javax.jms.ConnectionFactory=org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory;org.apache.activemq.ActiveMQConnectionFactory
 
-# skip these types
+# skip these mappings
 org.springframework.jms.core.JmsOperations=#skip#
diff --git a/examples/camel-example-main-artemis/pom.xml b/examples/camel-example-main-artemis/pom.xml
index cbc0485..687bfff 100644
--- a/examples/camel-example-main-artemis/pom.xml
+++ b/examples/camel-example-main-artemis/pom.xml
@@ -105,6 +105,8 @@
                 <version>${project.version}</version>
                 <configuration>
                     <logClasspath>false</logClasspath>
+                    <!-- just include only the jms component -->
+                    <include>jms</include>
                 </configuration>
                 <executions>
                     <execution>
diff --git a/examples/camel-example-main-artemis/src/main/resources/application.properties b/examples/camel-example-main-artemis/src/main/resources/application.properties
index fe60043..dd773ef 100644
--- a/examples/camel-example-main-artemis/src/main/resources/application.properties
+++ b/examples/camel-example-main-artemis/src/main/resources/application.properties
@@ -27,9 +27,16 @@ camel.main.jmx-enabled = false
 # see in pom.xml file how we use camel-main-maven-plugin to detect the Artemis JMS Client
 # and automatic generate META-INF/services/org/apache/camel/autowire.properties
 # which contains some additional autowires so we only need here to specify the URL to the broker
-camel.component.jms.connectionFactory.brokerURL=tcp://localhost:61616
-camel.component.jms.connectionFactory.user=admin
-camel.component.jms.connectionFactory.password=admin
+camel.component.jms.connection-factory.brokerURL=tcp://localhost:61616
+
+# in case you want to use Spring's CachingConnectionFactory, you can configure it as follows:
+# (then you don't need the camel-main-mavenn-plugin, as you can explicit configure it all here)
+### camel.component.jms.connectionFactory=#class:org.springframework.jms.connection.CachingConnectionFactory
+### camel.component.jms.connection-factory.session-cache-size=5
+### camel.component.jms.connection-factory.target-connection-factory=#class:org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory
+### camel.component.jms.connection-factory.target-connection-factory.user=admin
+### camel.component.jms.connection-factory.target-connection-factory.password=admin
+### camel.component.jms.connection-factory.target-connection-factory.brokerURL=tcp://localhost:61616
 
 # this is used if you enable the @BindToRegistry in MyConfiguration class to autowire
 # the Artemis JMS ConnectionFactory via Java source code