This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch route-collector in repository https://gitbox.apache.org/repos/asf/camel.git
commit f727b5ce91c110eadd05968982dbfeca01a5b1ac Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Thu Oct 17 13:43:24 2019 +0200 CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has --- .../spring/boot/CamelConfigurationProperties.java | 67 +++++------ .../apache/camel/spring/boot/RoutesCollector.java | 69 +----------- .../camel/main/DefaultConfigurationProperties.java | 124 +++++++++++++++++++++ .../org/apache/camel/main/MainRoutesCollector.java | 113 +++++++++++++++++++ .../camel-main-configuration-metadata.json | 12 ++ 5 files changed, 278 insertions(+), 107 deletions(-) diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelConfigurationProperties.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelConfigurationProperties.java index 9f33bac..3018a8d 100644 --- a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelConfigurationProperties.java +++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelConfigurationProperties.java @@ -48,32 +48,6 @@ public class CamelConfigurationProperties extends DefaultConfigurationProperties private boolean warnOnEarlyShutdown = true; /** - * Used for inclusive filtering component scanning of RouteBuilder classes with @Component annotation. - * The exclusive filtering takes precedence over inclusive filtering. - * The pattern is using Ant-path style pattern. - * - * Multiple patterns can be specified separated by comma. - * For example to include all classes starting with Foo use: **/Foo* - * To include all routes form a specific package use: com/mycompany/foo/* - * To include all routes form a specific package and its sub-packages use double wildcards: com/mycompany/foo/** - * And to include all routes from two specific packages use: com/mycompany/foo/*,com/mycompany/stuff/* - */ - private String javaRoutesIncludePattern; - - /** - * Used for exclusive filtering component scanning of RouteBuilder classes with @Component annotation. - * The exclusive filtering takes precedence over inclusive filtering. - * The pattern is using Ant-path style pattern. - * Multiple patterns can be specified separated by comma. - * - * For example to exclude all classes starting with Bar use: **/Bar* - * To exclude all routes form a specific package use: com/mycompany/bar/* - * To exclude all routes form a specific package and its sub-packages use double wildcards: com/mycompany/bar/** - * And to exclude all routes from two specific packages use: com/mycompany/bar/*,com/mycompany/stuff/* - */ - private String javaRoutesExcludePattern; - - /** * Directory to scan for adding additional XML routes. * You can turn this off by setting the value to false. * @@ -457,6 +431,31 @@ public class CamelConfigurationProperties extends DefaultConfigurationProperties */ private LoggingLevel beanIntrospectionLoggingLevel; + /** + * Used for inclusive filtering component scanning of RouteBuilder classes with @Component annotation. + * The exclusive filtering takes precedence over inclusive filtering. + * The pattern is using Ant-path style pattern. + * + * Multiple patterns can be specified separated by comma. + * For example to include all classes starting with Foo use: **/Foo* + * To include all routes form a specific package use: com/mycompany/foo/* + * To include all routes form a specific package and its sub-packages use double wildcards: com/mycompany/foo/** + * And to include all routes from two specific packages use: com/mycompany/foo/*,com/mycompany/stuff/* + */ + private String javaRoutesIncludePattern; + + /** + * Used for exclusive filtering component scanning of RouteBuilder classes with @Component annotation. + * The exclusive filtering takes precedence over inclusive filtering. + * The pattern is using Ant-path style pattern. + * Multiple patterns can be specified separated by comma. + * + * For example to exclude all classes starting with Bar use: **/Bar* + * To exclude all routes form a specific package use: com/mycompany/bar/* + * To exclude all routes form a specific package and its sub-packages use double wildcards: com/mycompany/bar/** + * And to exclude all routes from two specific packages use: com/mycompany/bar/*,com/mycompany/stuff/* + */ + private String javaRoutesExcludePattern; // Getters & setters // ----------------- @@ -485,22 +484,6 @@ public class CamelConfigurationProperties extends DefaultConfigurationProperties this.warnOnEarlyShutdown = warnOnEarlyShutdown; } - public String getJavaRoutesIncludePattern() { - return javaRoutesIncludePattern; - } - - public void setJavaRoutesIncludePattern(String javaRoutesIncludePattern) { - this.javaRoutesIncludePattern = javaRoutesIncludePattern; - } - - public String getJavaRoutesExcludePattern() { - return javaRoutesExcludePattern; - } - - public void setJavaRoutesExcludePattern(String javaRoutesExcludePattern) { - this.javaRoutesExcludePattern = javaRoutesExcludePattern; - } - public String getXmlRoutes() { return xmlRoutes; } diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/RoutesCollector.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/RoutesCollector.java index cb02311..1858219 100644 --- a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/RoutesCollector.java +++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/RoutesCollector.java @@ -17,7 +17,6 @@ package org.apache.camel.spring.boot; import java.io.FileNotFoundException; -import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; @@ -30,6 +29,7 @@ import org.apache.camel.CamelContext; import org.apache.camel.RoutesBuilder; import org.apache.camel.StartupListener; import org.apache.camel.main.MainDurationEventNotifier; +import org.apache.camel.main.MainRoutesCollector; import org.apache.camel.model.Model; import org.apache.camel.model.ModelHelper; import org.apache.camel.model.RoutesDefinition; @@ -40,7 +40,6 @@ import org.apache.camel.spi.EventNotifier; import org.apache.camel.support.EventNotifierSupport; import org.apache.camel.support.OrderedComparator; import org.apache.camel.support.service.ServiceHelper; -import org.apache.camel.util.ObjectHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContext; @@ -49,7 +48,6 @@ import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.core.Ordered; import org.springframework.core.io.Resource; -import org.springframework.util.AntPathMatcher; /** * Collects routes and rests from the various sources (like Spring application context beans registry or opinionated @@ -89,68 +87,8 @@ public class RoutesCollector implements ApplicationListener<ContextRefreshedEven && camelContext.getStatus().isStopped()) { LOG.debug("Post-processing CamelContext bean: {}", camelContext.getName()); - final AntPathMatcher matcher = new AntPathMatcher(); - final List<RoutesBuilder> routes = new ArrayList<>(); - for (RoutesBuilder routesBuilder : applicationContext.getBeansOfType(RoutesBuilder.class, configurationProperties.isIncludeNonSingletons(), true).values()) { - // filter out abstract classes - boolean abs = Modifier.isAbstract(routesBuilder.getClass().getModifiers()); - if (!abs) { - String name = routesBuilder.getClass().getName(); - // make name as path so we can use ant path matcher - name = name.replace('.', '/'); - - String exclude = configurationProperties.getJavaRoutesExcludePattern(); - String include = configurationProperties.getJavaRoutesIncludePattern(); - - boolean match = !"false".equals(include); - // exclude take precedence over include - if (match && ObjectHelper.isNotEmpty(exclude)) { - // there may be multiple separated by comma - String[] parts = exclude.split(","); - for (String part : parts) { - // must negate when excluding, and hence ! - match = !matcher.match(part, name); - LOG.trace("Java RoutesBuilder: {} exclude filter: {} -> {}", name, part, match); - if (!match) { - break; - } - } - } - // special support for testing with @ExcludeRoutes annotation with camel-test-spring - exclude = System.getProperty("CamelTestSpringExcludeRoutes"); - // exclude take precedence over include - if (match && ObjectHelper.isNotEmpty(exclude)) { - // this property is a comma separated list of FQN class names, so we need to make - // name as path so we can use ant patch matcher - exclude = exclude.replace('.', '/'); - // there may be multiple separated by comma - String[] parts = exclude.split(","); - for (String part : parts) { - // must negate when excluding, and hence ! - match = !matcher.match(part, name); - LOG.trace("Java RoutesBuilder: {} exclude filter: {} -> {}", name, part, match); - if (!match) { - break; - } - } - } - if (match && ObjectHelper.isNotEmpty(include)) { - // there may be multiple separated by comma - String[] parts = include.split(","); - for (String part : parts) { - match = matcher.match(part, name); - LOG.trace("Java RoutesBuilder: {} include filter: {} -> {}", name, part, match); - if (match) { - break; - } - } - } - LOG.debug("Java RoutesBuilder: {} accepted by include/exclude filter: {}", name, match); - if (match) { - routes.add(routesBuilder); - } - } - } + MainRoutesCollector collector = new MainRoutesCollector(); + final List<RoutesBuilder> routes = collector.collectRoutes(camelContext, configurationProperties); // sort routes according to ordered routes.sort(OrderedComparator.get()); @@ -300,6 +238,7 @@ public class RoutesCollector implements ApplicationListener<ContextRefreshedEven // Helpers + private void loadXmlRoutes(ApplicationContext applicationContext, CamelContext camelContext, String directory) throws Exception { String[] parts = directory.split(","); for (String part : parts) { diff --git a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java index 3e92f77..fdd1c66 100644 --- a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java +++ b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java @@ -71,6 +71,31 @@ public abstract class DefaultConfigurationProperties<T> { private String routeFilterExcludePattern; private boolean beanIntrospectionExtendedStatistics; private LoggingLevel beanIntrospectionLoggingLevel; + /** + * Used for inclusive filtering component scanning of RouteBuilder classes with @Component annotation. + * The exclusive filtering takes precedence over inclusive filtering. + * The pattern is using Ant-path style pattern. + * + * Multiple patterns can be specified separated by comma. + * For example to include all classes starting with Foo use: **/Foo* + * To include all routes form a specific package use: com/mycompany/foo/* + * To include all routes form a specific package and its sub-packages use double wildcards: com/mycompany/foo/** + * And to include all routes from two specific packages use: com/mycompany/foo/*,com/mycompany/stuff/* + */ + private String javaRoutesIncludePattern; + + /** + * Used for exclusive filtering component scanning of RouteBuilder classes with @Component annotation. + * The exclusive filtering takes precedence over inclusive filtering. + * The pattern is using Ant-path style pattern. + * Multiple patterns can be specified separated by comma. + * + * For example to exclude all classes starting with Bar use: **/Bar* + * To exclude all routes form a specific package use: com/mycompany/bar/* + * To exclude all routes form a specific package and its sub-packages use double wildcards: com/mycompany/bar/** + * And to exclude all routes from two specific packages use: com/mycompany/bar/*,com/mycompany/stuff/* + */ + private String javaRoutesExcludePattern; // getter and setters // -------------------------------------------------------------- @@ -704,6 +729,44 @@ public abstract class DefaultConfigurationProperties<T> { this.beanIntrospectionLoggingLevel = beanIntrospectionLoggingLevel; } + public String getJavaRoutesIncludePattern() { + return javaRoutesIncludePattern; + } + + /** + * Used for inclusive filtering component scanning of RouteBuilder classes with @Component annotation. + * The exclusive filtering takes precedence over inclusive filtering. + * The pattern is using Ant-path style pattern. + * + * Multiple patterns can be specified separated by comma. + * For example to include all classes starting with Foo use: **/Foo* + * To include all routes form a specific package use: com/mycompany/foo/* + * To include all routes form a specific package and its sub-packages use double wildcards: com/mycompany/foo/** + * And to include all routes from two specific packages use: com/mycompany/foo/*,com/mycompany/stuff/* + */ + public void setJavaRoutesIncludePattern(String javaRoutesIncludePattern) { + this.javaRoutesIncludePattern = javaRoutesIncludePattern; + } + + public String getJavaRoutesExcludePattern() { + return javaRoutesExcludePattern; + } + + /** + * Used for exclusive filtering component scanning of RouteBuilder classes with @Component annotation. + * The exclusive filtering takes precedence over inclusive filtering. + * The pattern is using Ant-path style pattern. + * Multiple patterns can be specified separated by comma. + * + * For example to exclude all classes starting with Bar use: **/Bar* + * To exclude all routes form a specific package use: com/mycompany/bar/* + * To exclude all routes form a specific package and its sub-packages use double wildcards: com/mycompany/bar/** + * And to exclude all routes from two specific packages use: com/mycompany/bar/*,com/mycompany/stuff/* + */ + public void setJavaRoutesExcludePattern(String javaRoutesExcludePattern) { + this.javaRoutesExcludePattern = javaRoutesExcludePattern; + } + // fluent builders // -------------------------------------------------------------- @@ -1168,4 +1231,65 @@ public abstract class DefaultConfigurationProperties<T> { return (T) this; } + /** + * Tracing pattern to match which node EIPs to trace. + * For example to match all To EIP nodes, use to*. + * The pattern matches by node and route id's + * Multiple patterns can be separated by comma. + */ + public DefaultConfigurationProperties withTracingPattern(String tracingPattern) { + this.tracingPattern = tracingPattern; + return this; + } + + /** + * Sets the pattern used for determine which custom MDC keys to propagate during message routing when + * the routing engine continues routing asynchronously for the given message. Setting this pattern to * will + * propagate all custom keys. Or setting the pattern to foo*,bar* will propagate any keys starting with + * either foo or bar. + * Notice that a set of standard Camel MDC keys are always propagated which starts with camel. as key name. + * + * The match rules are applied in this order (case insensitive): + * + * 1. exact match, returns true + * 2. wildcard match (pattern ends with a * and the name starts with the pattern), returns true + * 3. regular expression match, returns true + * 4. otherwise returns false + */ + public DefaultConfigurationProperties withMdcLoggingKeysPattern(String mdcLoggingKeysPattern) { + this.mdcLoggingKeysPattern = mdcLoggingKeysPattern; + return this; + } + + /** + * Used for inclusive filtering component scanning of RouteBuilder classes with @Component annotation. + * The exclusive filtering takes precedence over inclusive filtering. + * The pattern is using Ant-path style pattern. + * + * Multiple patterns can be specified separated by comma. + * For example to include all classes starting with Foo use: **/Foo* + * To include all routes form a specific package use: com/mycompany/foo/* + * To include all routes form a specific package and its sub-packages use double wildcards: com/mycompany/foo/** + * And to include all routes from two specific packages use: com/mycompany/foo/*,com/mycompany/stuff/* + */ + public DefaultConfigurationProperties withJavaRoutesIncludePattern(String javaRoutesIncludePattern) { + this.javaRoutesIncludePattern = javaRoutesIncludePattern; + return this; + } + + /** + * Used for exclusive filtering component scanning of RouteBuilder classes with @Component annotation. + * The exclusive filtering takes precedence over inclusive filtering. + * The pattern is using Ant-path style pattern. + * Multiple patterns can be specified separated by comma. + * + * For example to exclude all classes starting with Bar use: **/Bar* + * To exclude all routes form a specific package use: com/mycompany/bar/* + * To exclude all routes form a specific package and its sub-packages use double wildcards: com/mycompany/bar/** + * And to exclude all routes from two specific packages use: com/mycompany/bar/*,com/mycompany/stuff/* + */ + public DefaultConfigurationProperties withJavaRoutesExcludePattern(String javaRoutesExcludePattern) { + this.javaRoutesExcludePattern = javaRoutesExcludePattern; + return this; + } } diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainRoutesCollector.java b/core/camel-main/src/main/java/org/apache/camel/main/MainRoutesCollector.java new file mode 100644 index 0000000..fe5c2da --- /dev/null +++ b/core/camel-main/src/main/java/org/apache/camel/main/MainRoutesCollector.java @@ -0,0 +1,113 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.main; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.apache.camel.CamelContext; +import org.apache.camel.RoutesBuilder; +import org.apache.camel.util.AntPathMatcher; +import org.apache.camel.util.ObjectHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Collects routes and rests from the various sources (like registry or opinionated + * classpath locations) and injects these into the Camel context. + */ +public class MainRoutesCollector { + + // TODO: Add load routes from xml and rest + // TODO: Base class and extended for spring-boot etc + + private static final Logger LOG = LoggerFactory.getLogger(MainRoutesCollector.class); + + public List<RoutesBuilder> collectRoutes(CamelContext camelContext, DefaultConfigurationProperties configurationProperties) { + final List<RoutesBuilder> routes = new ArrayList<>(); + + final AntPathMatcher matcher = new AntPathMatcher(); + Set<RoutesBuilder> builders = camelContext.getRegistry().findByType(RoutesBuilder.class); + for (RoutesBuilder routesBuilder : builders) { + // filter out abstract classes + boolean abs = Modifier.isAbstract(routesBuilder.getClass().getModifiers()); + if (!abs) { + String name = routesBuilder.getClass().getName(); + // make name as path so we can use ant path matcher + name = name.replace('.', '/'); + + String exclude = configurationProperties.getJavaRoutesExcludePattern(); + String include = configurationProperties.getJavaRoutesIncludePattern(); + + boolean match = !"false".equals(include); + // exclude take precedence over include + if (match && ObjectHelper.isNotEmpty(exclude)) { + // there may be multiple separated by comma + String[] parts = exclude.split(","); + for (String part : parts) { + // must negate when excluding, and hence ! + match = !matcher.match(part, name); + LOG.trace("Java RoutesBuilder: {} exclude filter: {} -> {}", name, part, match); + if (!match) { + break; + } + } + } + // special support for testing with @ExcludeRoutes annotation with camel-test-spring + exclude = System.getProperty("CamelTestSpringExcludeRoutes"); + // exclude take precedence over include + if (match && ObjectHelper.isNotEmpty(exclude)) { + // this property is a comma separated list of FQN class names, so we need to make + // name as path so we can use ant patch matcher + exclude = exclude.replace('.', '/'); + // there may be multiple separated by comma + String[] parts = exclude.split(","); + for (String part : parts) { + // must negate when excluding, and hence ! + match = !matcher.match(part, name); + LOG.trace("Java RoutesBuilder: {} exclude filter: {} -> {}", name, part, match); + if (!match) { + break; + } + } + } + if (match && ObjectHelper.isNotEmpty(include)) { + // there may be multiple separated by comma + String[] parts = include.split(","); + for (String part : parts) { + match = matcher.match(part, name); + LOG.trace("Java RoutesBuilder: {} include filter: {} -> {}", name, part, match); + if (match) { + break; + } + } + } + LOG.debug("Java RoutesBuilder: {} accepted by include/exclude filter: {}", name, match); + if (match) { + routes.add(routesBuilder); + } + } + + + } + + return routes; + } + +} diff --git a/core/camel-main/src/main/resources/META-INF/camel-main-configuration-metadata.json b/core/camel-main/src/main/resources/META-INF/camel-main-configuration-metadata.json index 8548426..d0f9a75 100644 --- a/core/camel-main/src/main/resources/META-INF/camel-main-configuration-metadata.json +++ b/core/camel-main/src/main/resources/META-INF/camel-main-configuration-metadata.json @@ -147,6 +147,18 @@ "defaultValue":"true" }, { + "name":"camel.main.java-routes-exclude-pattern", + "type":"java.lang.String", + "sourceType":"org.apache.camel.main.DefaultConfigurationProperties", + "description":"Used for exclusive filtering component scanning of RouteBuilder classes with Component annotation. The exclusive filtering takes precedence over inclusive filtering. The pattern is using Ant-path style pattern. Multiple patterns can be specified separated by comma. For example to exclude all classes starting with Bar use: **\/Bar* To exclude all routes form a specific package use: com\/mycompany\/bar\/* To exclude all routes form a specific package and i [...] + }, + { + "name":"camel.main.java-routes-include-pattern", + "type":"java.lang.String", + "sourceType":"org.apache.camel.main.DefaultConfigurationProperties", + "description":"Used for inclusive filtering component scanning of RouteBuilder classes with Component annotation. The exclusive filtering takes precedence over inclusive filtering. The pattern is using Ant-path style pattern. Multiple patterns can be specified separated by comma. For example to include all classes starting with Foo use: **\/Foo To include all routes form a specific package use: com\/mycompany\/foo\/* To include all routes form a specific package and its su [...] + }, + { "name":"camel.main.jmx-create-connector", "type":"boolean", "sourceType":"org.apache.camel.main.DefaultConfigurationProperties",