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 0b9c0c00339938c6f4f55c1da1db6923afdff106 Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Fri Jan 3 09:14:00 2020 +0100 CAMEL-14350: camel-main - Add support for file prefix in loading XML routes. --- .../camel/spi/PackageScanResourceResolver.java | 14 +++++- .../engine/DefaultPackageScanResourceResolver.java | 50 ++++++++++++++++++---- .../camel/main/DefaultConfigurationProperties.java | 4 ++ .../org/apache/camel/main/xml/MainXmlTest.java | 21 +++++++++ 4 files changed, 79 insertions(+), 10 deletions(-) diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/PackageScanResourceResolver.java b/core/camel-api/src/main/java/org/apache/camel/spi/PackageScanResourceResolver.java index e3c11db..9052255 100644 --- a/core/camel-api/src/main/java/org/apache/camel/spi/PackageScanResourceResolver.java +++ b/core/camel-api/src/main/java/org/apache/camel/spi/PackageScanResourceResolver.java @@ -58,10 +58,20 @@ public interface PackageScanResourceResolver extends StaticService { /** * Finds the resources from the given location. * - * @param locations the location (support ANT style patterns, eg routes/camel-*.xml) + * The location can be prefixed with either file: or classpath: to look in either file system or classpath. + * By default classpath is assumed if no prefix is specified. + * + * Wildcards is supported using a ANT pattern style paths, such as classpath:**/*camel*.xml + * + * Notice when using wildcards, then there is additional overhead as the classpath is scanned, where + * as if you specific the exact name for each XML file is faster as no classpath scanning is needed. + * + * <b>Important:</b> Make sure to close the returned input streams after use. + * + * @param location the location (support ANT style patterns, eg routes/camel-*.xml) * @return the found resources, or an empty set if no resources found * @throws Exception can be thrown during scanning for resources. */ - Set<InputStream> findResources(String locations) throws Exception; + Set<InputStream> findResources(String location) throws Exception; } diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultPackageScanResourceResolver.java b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultPackageScanResourceResolver.java index 27b3ea2..61b28b9 100644 --- a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultPackageScanResourceResolver.java +++ b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultPackageScanResourceResolver.java @@ -49,26 +49,60 @@ public class DefaultPackageScanResourceResolver extends BasePackageScanResolver private static final AntPathMatcher PATH_MATCHER = AntPathMatcher.INSTANCE; - public Set<InputStream> findResources(String locations) throws Exception { + public Set<InputStream> findResources(String location) throws Exception { Set<InputStream> answer = new LinkedHashSet<>(); // if its a pattern then we need to scan its root path and find // all matching resources using the sub pattern - if (PATH_MATCHER.isPattern(locations)) { - String root = PATH_MATCHER.determineRootDir(locations); - String subPattern = locations.substring(root.length()); - // scan from root path and find all resources - find(root, answer, subPattern); + if (PATH_MATCHER.isPattern(location)) { + String root = PATH_MATCHER.determineRootDir(location); + String subPattern = location.substring(root.length()); + + String scheme = ResourceHelper.getScheme(location); + if ("file:".equals(scheme)) { + // file based scanning + root = root.substring(scheme.length()); + findInFileSystem(root, answer, subPattern); + } else { + if ("classpath:".equals(scheme)) { + root = root.substring(scheme.length()); + } + // assume classpath based scan from root path and find all resources + findInClasspath(root, answer, subPattern); + } } else { // its a single resource so load it directly - InputStream is = ResourceHelper.resolveMandatoryResourceAsInputStream(getCamelContext(), locations); + InputStream is = ResourceHelper.resolveMandatoryResourceAsInputStream(getCamelContext(), location); answer.add(is); } return answer; } - protected void find(String packageName, Set<InputStream> resources, String subPattern) { + protected void findInFileSystem(String root, Set<InputStream> resources, String subPattern) { + File dir = new File(root); + if (dir.exists() && dir.isDirectory()) { + File[] files = dir.listFiles(); + if (files != null) { + for (File file : files) { + if (file.isFile()) { + boolean match = PATH_MATCHER.match(subPattern, file.getName()); + log.debug("Found resource: {} matching pattern: {} -> {}", file.getName(), subPattern, match); + if (match) { + try { + // the input stream will be closed later + resources.add(new FileInputStream(file)); + } catch (FileNotFoundException e) { + // ignore + } + } + } + } + } + } + } + + protected void findInClasspath(String packageName, Set<InputStream> resources, String subPattern) { packageName = packageName.replace('.', '/'); // If the URL is a jar, the URLClassloader.getResources() seems to require a trailing slash. // The trailing slash is harmless for other URLs 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 7d2c955..63b11b3 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 @@ -1437,6 +1437,8 @@ public abstract class DefaultConfigurationProperties<T> { * You can turn this off by setting the value to false. * * Files can be loaded from either classpath or file by prefixing with classpath: or file: + * By default classpath is assumed if no prefix is specified. + * * Wildcards is supported using a ANT pattern style paths, such as classpath:**/*camel*.xml * * Notice when using wildcards, then there is additional overhead as the classpath is scanned, where @@ -1455,6 +1457,8 @@ public abstract class DefaultConfigurationProperties<T> { * You can turn this off by setting the value to false. * * Files can be loaded from either classpath or file by prefixing with classpath: or file: + * By default classpath is assumed if no prefix is specified. + * * Wildcards is supported using a ANT pattern style paths, such as classpath:**/*camel*.xml * * Notice when using wildcards, then there is additional overhead as the classpath is scanned, where diff --git a/core/camel-main/src/test/java/org/apache/camel/main/xml/MainXmlTest.java b/core/camel-main/src/test/java/org/apache/camel/main/xml/MainXmlTest.java index 7b2ce3d..7d03132 100644 --- a/core/camel-main/src/test/java/org/apache/camel/main/xml/MainXmlTest.java +++ b/core/camel-main/src/test/java/org/apache/camel/main/xml/MainXmlTest.java @@ -37,11 +37,32 @@ public class MainXmlTest extends Assert { } @Test + public void testMainRoutesCollectorScanClasspathPrefix() throws Exception { + // will load XML from target/classes when testing + doTestMain("classpath:org/apache/camel/main/xml/camel-*.xml"); + } + + @Test public void testMainRoutesCollectorScanInJar() throws Exception { // will load XML from camel-core test JAR when testing doTestMain("org/apache/camel/model/scan-*.xml"); } + @Test + public void testMainRoutesCollectorScanInDir() throws Exception { + doTestMain("file:src/test/resources/org/apache/camel/main/xml/camel-*.xml"); + } + + @Test + public void testMainRoutesCollectorFile() throws Exception { + doTestMain("file:src/test/resources/org/apache/camel/main/xml/camel-dummy.xml,file:src/test/resources/org/apache/camel/main/xml/camel-scan.xml,"); + } + + @Test + public void testMainRoutesCollectorScanInJarAndDir() throws Exception { + doTestMain("classpath:org/apache/camel/main/xml/*dummy.xml,file:src/test/resources/org/apache/camel/main/xml/*scan.xml"); + } + protected void doTestMain(String xmlRoutes) throws Exception { Main main = new Main(); main.configure().withXmlRoutes(xmlRoutes);