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 <claus.ib...@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