Implement support for using *.jar pattern in VirtualWebappLoader to specify all JAR...
authorkkolinko <kkolinko@13f79535-47bb-0310-9956-ffa450edef68>
Mon, 28 Jun 2010 15:59:12 +0000 (15:59 +0000)
committerkkolinko <kkolinko@13f79535-47bb-0310-9956-ffa450edef68>
Mon, 28 Jun 2010 15:59:12 +0000 (15:59 +0000)
This is inspired by Bootstrap.createClassLoader(..) and ClassLoaderFactory.createClassLoader(..).
There is a small difference with regards to ClassLoaderFactory.createClassLoader(..) implementation:
1. I removed the file.canRead() checks as I think that they are not necessary here. I am checking existence and type only.
2. Note that isFile()/isDirectory() are documented to return false if the path does not exist, so using a separate exists() call there is not necessary.

Also three other changes:
1. Added trim() to the tokens.
2. Implemented debug logging.
3. Removed "not for production" warning from the JavaDoc.

An update for the documentation (/config/loader.html) should follow later.

git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@958615 13f79535-47bb-0310-9956-ffa450edef68

java/org/apache/catalina/loader/LocalStrings.properties
java/org/apache/catalina/loader/VirtualWebappLoader.java
webapps/docs/changelog.xml

index 18c1a08..4350c71 100644 (file)
@@ -28,6 +28,12 @@ standardLoader.reloading=Reloading checks are enabled for this Context
 standardLoader.removeRepository=Removing repository {0}
 standardLoader.starting=Starting this Loader
 standardLoader.stopping=Stopping this Loader
+virtualWebappLoader.token=Processing token [{0}]
+virtualWebappLoader.token.file=Adding location: [{0}]
+virtualWebappLoader.token.glob.dir=Listing files in a directory: [{0}]
+virtualWebappLoader.token.notDirectory=Path is skipped, because it does not exist or is not a directory: [{0}]
+virtualWebappLoader.token.notExists=Path is skipped, because it does not exist: [{0}]
+virtualWebappLoader.token.notFile=Path is skipped, because it does not exist or is not a file: [{0}]
 webappClassLoader.illegalJarPath=Illegal JAR entry detected with name {0}
 webappClassLoader.jdbcRemoveFailed=JDBC driver de-registration failed for web application [{0}]
 webappClassLoader.jdbcRemoveStreamError=Exception closing input stream during JDBC driver de-registration for web application [{0}]
index bb9ea14..3f79a7b 100644 (file)
 package org.apache.catalina.loader;
 
 import java.io.File;
+import java.util.Arrays;
+import java.util.LinkedHashSet;
+import java.util.Locale;
+import java.util.Set;
 import java.util.StringTokenizer;
 
 import org.apache.catalina.LifecycleException;
 import org.apache.catalina.util.LifecycleBase;
 
 /**
- * Simple webapp classloader that allows a customized classpath to be added
+ * A WebappLoader that allows a customized classpath to be added
  * through configuration in context xml. Any additional classpath entry will be
  * added to the default webapp classpath, making easy to emulate a standard
  * webapp without the need for assembly all the webapp dependencies as jars in
@@ -32,15 +36,14 @@ import org.apache.catalina.util.LifecycleBase;
  * <pre>
  * &lt;Context docBase="\webapps\mydocbase">
  *   &lt;Loader className="org.apache.catalina.loader.VirtualWebappLoader"
- *              virtualClasspath="\dir\classes;\somedir\somejar.jar"/>
+ *              virtualClasspath="/dir/classes;/somedir/somejar.jar;/somedir/*.jar"/>
  * &lt;/Context>
  * </pre>
  *
- *
- * <strong>This is not meant to be used for production.
- * Its meant to ease development with IDE's without the
- * need for fully republishing jars in WEB-INF/lib</strong>
- *
+ * <p>The <code>*.jar</code> suffix can be used to include all JAR files in a
+ * certain directory. If a file or a directory does not exist, it will be
+ * skipped. 
+ * </p>
  *
  *
  * @author Fabrizio Giustina
@@ -48,6 +51,9 @@ import org.apache.catalina.util.LifecycleBase;
  */
 public class VirtualWebappLoader extends WebappLoader {
 
+    private static final org.apache.juli.logging.Log log=
+        org.apache.juli.logging.LogFactory.getLog( VirtualWebappLoader.class );
+
     /**
      * <code>;</code> separated list of additional path elements.
      */
@@ -108,12 +114,75 @@ public class VirtualWebappLoader extends WebappLoader {
         // just add any jar/directory set in virtual classpath to the
         // repositories list before calling start on the standard WebappLoader
         StringTokenizer tkn = new StringTokenizer(virtualClasspath, ";");
+        Set<String> set = new LinkedHashSet<String>();
         while (tkn.hasMoreTokens()) {
-            File file = new File(tkn.nextToken());
-            if (!file.exists()) {
-                continue;
+            String token = tkn.nextToken().trim();
+
+            if (log.isDebugEnabled())
+                log.debug(sm.getString("virtualWebappLoader.token", token));
+
+            if (token.endsWith("*.jar")) {
+                // glob
+                token = token.substring(0, token.length() - "*.jar".length());
+
+                File directory = new File(token);
+                if (!directory.isDirectory()) {
+                    if (log.isDebugEnabled()) {
+                        log.debug(sm.getString(
+                                "virtualWebappLoader.token.notDirectory",
+                                directory.getAbsolutePath()));
+                    }
+                    continue;
+                }
+                if (log.isDebugEnabled()) {
+                    log.debug(sm.getString(
+                            "virtualWebappLoader.token.glob.dir",
+                            directory.getAbsolutePath()));
+                }
+                String filenames[] = directory.list();
+                Arrays.sort(filenames);
+                for (int j = 0; j < filenames.length; j++) {
+                    String filename = filenames[j].toLowerCase(Locale.ENGLISH);
+                    if (!filename.endsWith(".jar"))
+                        continue;
+                    File file = new File(directory, filenames[j]);
+                    if (!file.isFile()) {
+                        if (log.isDebugEnabled()) {
+                            log.debug(sm.getString(
+                                    "virtualWebappLoader.token.notFile",
+                                    file.getAbsolutePath()));
+                        }
+                        continue;
+                    }
+                    if (log.isDebugEnabled()) {
+                        log.debug(sm.getString(
+                                "virtualWebappLoader.token.file",
+                                file.getAbsolutePath()));
+                    }
+                    set.add(file.toURI().toString());
+                }
+            } else {
+                // single file or directory
+                File file = new File(token);
+                if (!file.exists()) {
+                    if (log.isDebugEnabled()) {
+                        log.debug(sm.getString(
+                                "virtualWebappLoader.token.notExists",
+                                file.getAbsolutePath()));
+                    }
+                    continue;
+                }
+                if (log.isDebugEnabled()) {
+                    log.debug(sm.getString(
+                            "virtualWebappLoader.token.file",
+                            file.getAbsolutePath()));
+                }
+                set.add(file.toURI().toString());
             }
-            addRepository(file.toURI().toString());
+        }
+
+        for (String repository: set) {
+            addRepository(repository);
         }
 
         super.startInternal();
index b6d9021..06da9c1 100644 (file)
         request processing threads and threads started by the application.
         (markt)
       </fix>
+      <add>
+        Add support for <code>*.jar</code> pattern in VirtualWebappLoader.
+        (kkolinko)
+      </add>
     </changelog>
   </subsection>
   <subsection name="Coyote">