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 2020/01/03 08:14:27 UTC

[camel] 02/02: CAMEL-14350: camel-main - Add support for file prefix in loading XML routes.

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 <cl...@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:&#42;&#42;/&#42;camel&#42;.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:&#42;&#42;/&#42;camel&#42;.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:&#42;&#42;/&#42;camel&#42;.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);