Move JAR scanning into a new JAR used by both Catalina and Jasper
authormarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Thu, 24 Dec 2009 11:14:46 +0000 (11:14 +0000)
committermarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Thu, 24 Dec 2009 11:14:46 +0000 (11:14 +0000)
git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@893731 13f79535-47bb-0310-9956-ffa450edef68

build.xml
java/org/apache/catalina/core/StandardContext.java
java/org/apache/catalina/startup/DefaultJarScanner.java [deleted file]
java/org/apache/jasper/compiler/InternalJarScanner.java [deleted file]
java/org/apache/jasper/compiler/JarScannerFactory.java
java/org/apache/tomcat/util/scan/DefaultJarScanner.java [new file with mode: 0644]
java/org/apache/tomcat/util/scan/package.html [new file with mode: 0644]
res/maven/mvn-pub.xml
res/maven/tomcat-catalina.pom
res/maven/tomcat-jasper.pom
res/maven/tomcat-util.pom [new file with mode: 0644]

index 53e587c..fb80562 100644 (file)
--- a/build.xml
+++ b/build.xml
@@ -84,6 +84,7 @@
   <property name="catalina-ant.jar" value="${tomcat.build}/lib/catalina-ant.jar"/>
   <property name="tomcat-coyote.jar" value="${tomcat.build}/lib/tomcat-coyote.jar"/>
   <property name="tomcat-api.jar" value="${tomcat.build}/lib/tomcat-api.jar"/>
+  <property name="tomcat-util.jar" value="${tomcat.build}/lib/tomcat-util.jar"/>
 
   <property name="jasper.jar" value="${tomcat.build}/lib/jasper.jar"/>
   <property name="jasper-el.jar" value="${tomcat.build}/lib/jasper-el.jar"/>
   <patternset id="files.tomcat-api">
     <include name="org/apache/tomcat/*.class" />
   </patternset>
-       
+
+  <patternset id="files.tomcat-util">
+    <include name="org/apache/tomcat/util/scan/*.class" />
+  </patternset>
+
   <patternset id="files.catalina">
     <include name="org/apache/catalina/**" />
     <include name="org/apache/naming/**" />
     <include name="org/apache/tomcat/jni/**" />
     <include name="org/apache/jk/**" />
     <include name="org/apache/tomcat/util/**" />
+    <!-- Exclude the files shared between Catalina & Jasper -->
+    <exclude name="org/apache/tomcat/util/scan/**" />
   </patternset>
 
   <patternset id="files.jasper">
       filesDir="${tomcat.classes}"
       filesId="files.tomcat-api" />
 
+    <!-- Tomcat API JAR File -->
+    <jarIt jarfile="${tomcat-util.jar}"
+      filesDir="${tomcat.classes}"
+      filesId="files.tomcat-util" />
+
     <!-- Protocol handlers - Coyote -->
     <jarIt jarfile="${tomcat-coyote.jar}"
       filesDir="${tomcat.classes}"
index 67d0916..01309f5 100644 (file)
@@ -88,7 +88,6 @@ import org.apache.catalina.deploy.SecurityConstraint;
 import org.apache.catalina.loader.WebappLoader;
 import org.apache.catalina.session.StandardManager;
 import org.apache.catalina.startup.ContextConfig;
-import org.apache.catalina.startup.DefaultJarScanner;
 import org.apache.catalina.startup.TldConfig;
 import org.apache.catalina.util.CharsetMapper;
 import org.apache.catalina.util.ExtensionValidator;
@@ -105,6 +104,7 @@ import org.apache.naming.resources.WARDirContext;
 import org.apache.tomcat.InstanceManager;
 import org.apache.tomcat.JarScanner;
 import org.apache.tomcat.util.modeler.Registry;
+import org.apache.tomcat.util.scan.DefaultJarScanner;
 
 /**
  * Standard implementation of the <b>Context</b> interface.  Each
diff --git a/java/org/apache/catalina/startup/DefaultJarScanner.java b/java/org/apache/catalina/startup/DefaultJarScanner.java
deleted file mode 100644 (file)
index 331eee5..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- *  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
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  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.catalina.startup;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.JarURLConnection;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.net.URLConnection;
-import java.util.Iterator;
-import java.util.Set;
-
-import javax.servlet.ServletContext;
-
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.JarScanner;
-import org.apache.tomcat.JarScannerCallback;
-import org.apache.tomcat.util.res.StringManager;
-
-/**
- * The default {@link JarScanner} implementation scans the WEB-INF/lib directory
- * followed by the provided classloader and then works up the classloader
- * hierarchy. This implementation is sufficient to meet the requirements of the
- * Servlet 3.0 specification as well as to provide a number of Tomcat specific
- * extensions. The extensions are:
- * <ul>
- *   <li>Scanning the classloader hierarchy (enabled by default)</li>
- *   <li>Testing all files to see if they are JARs (disabled by default)</li>
- *   <li>Testing all directories to see if they are exploded JARs
- *       (disabled by default)</li>
- * </ul>
- * All of the extensions may be controlled via configuration.
- * 
- * Keep in sync with org.apache.jasper.compiler.InternalJarScanner
- */
-public class DefaultJarScanner implements JarScanner {
-
-    private static final String JAR_EXT = ".jar";
-    private static final String WEB_INF_LIB = "/WEB-INF/lib/";
-
-    private static final Log log = LogFactory.getLog(DefaultJarScanner.class);
-
-    /**
-     * The string resources for this package.
-     */
-    private static final StringManager sm =
-        StringManager.getManager(Constants.Package);
-
-
-    /**
-     * Controls the classpath scanning extension.
-     */
-    private boolean scanClassPath = true;
-    public boolean isScanClassPath() {
-        return scanClassPath;
-    }
-    public void setScanClassPath(boolean scanClassPath) {
-        this.scanClassPath = scanClassPath;
-    }
-
-    /**
-     * Controls the testing all files to see of they are JAR files extension.
-     */
-    private boolean scanAllFiles = false;
-    public boolean isScanAllFiles() {
-        return scanAllFiles;
-    }
-    public void setScanAllFiles(boolean scanAllFiles) {
-        this.scanAllFiles = scanAllFiles;
-    }
-
-    /**
-     * Controls the testing all directories to see of they are exploded JAR
-     * files extension.
-     */
-    private boolean scanAllDirectories = false;
-    public boolean isScanAllDirectories() {
-        return scanAllDirectories;
-    }
-    public void setScanAllDirectories(boolean scanAllDirectories) {
-        this.scanAllDirectories = scanAllDirectories;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void scan(ServletContext context, ClassLoader classloader,
-            JarScannerCallback callback, Set<String> jarsToSkip) {
-
-        if (log.isTraceEnabled()) {
-            log.trace(sm.getString("jarScan.webinflibStart"));
-        }
-
-        // Scan WEB-INF/lib
-        Set<String> dirList = context.getResourcePaths(WEB_INF_LIB);
-        if (dirList != null) {
-            Iterator<String> it = dirList.iterator();
-            while (it.hasNext()) {
-                String path = it.next();
-                if (path.endsWith(JAR_EXT) &&
-                        !jarsToSkip.contains(
-                                path.substring(path.lastIndexOf('/')))) {
-                    // Need to scan this JAR
-                    URL url = null;
-                    try {
-                        url = context.getResource(path);
-                        process(callback, url);
-                    } catch (IOException e) {
-                        log.warn(sm.getString("jarScan.webinflibFail", url), e);
-                    }
-                }
-            }
-        }
-        
-        // Scan the classpath
-        if (scanClassPath) {
-            if (log.isTraceEnabled()) {
-                log.trace(sm.getString("jarScan.classloaderStart"));
-            }
-
-            ClassLoader loader = 
-                Thread.currentThread().getContextClassLoader();
-            
-            while (loader != null) {
-                if (loader instanceof URLClassLoader) {
-                    URL[] urls = ((URLClassLoader) loader).getURLs();
-                    for (int i=0; i<urls.length; i++) {
-                        // Extract the jarName if there is one to be found
-                        String jarName = getJarName(urls[i]);
-                        
-                        // Skip JARs with known not to be interesting and JARs
-                        // in WEB-INF/lib we have already scanned
-                        if (!(jarsToSkip.contains(jarName) ||
-                                urls[i].toString().contains(
-                                        WEB_INF_LIB + jarName))) {
-                            try {
-                                process(callback, urls[i]);
-                            } catch (IOException ioe) {
-                                log.warn(sm.getString(
-                                        "jarScan.classloaderFail",urls[i]), ioe);
-                            }
-                        }
-                    }
-                }
-                loader = loader.getParent();
-            }
-
-        }
-    }
-
-    /*
-     * Scan a URL for JARs with the optional extensions to look at all files
-     * and all directories.
-     */
-    private void process(JarScannerCallback callback, URL url)
-            throws IOException {
-
-        if (log.isTraceEnabled()) {
-            log.trace(sm.getString("jarScan.jarUrlStart", url));
-        }
-
-        URLConnection conn = url.openConnection();
-        if (conn instanceof JarURLConnection) {
-            callback.scan((JarURLConnection) conn);
-        } else {
-            String urlStr = url.toString();
-            if (urlStr.startsWith("file:") || urlStr.startsWith("jndi:")) {
-                if (urlStr.endsWith(JAR_EXT)) {
-                    URL jarURL = new URL("jar:" + urlStr + "!/");
-                    callback.scan((JarURLConnection) jarURL.openConnection());
-                } else {
-                    File f;
-                    try {
-                        f = new File(url.toURI());
-                        if (f.isFile() && scanAllFiles) {
-                            // Treat this file as a JAR
-                            URL jarURL = new URL("jar:" + urlStr + "!/");
-                            callback.scan((JarURLConnection) jarURL.openConnection());
-                        } else if (f.isDirectory() && scanAllDirectories) {
-                            File metainf = new File(f.getAbsoluteFile() +
-                                    File.separator + "META-INF");
-                            if (metainf.isDirectory()) {
-                                callback.scan(f);
-                            }
-                        }
-                    } catch (URISyntaxException e) {
-                        // Wrap the exception and re-throw
-                        IOException ioe = new IOException();
-                        ioe.initCause(e);
-                        throw ioe;
-                    }
-                }
-            }
-        }
-        
-    }
-
-    /*
-     * Extract the JAR name, if present, from a URL
-     */
-    private String getJarName(URL url) {
-        
-        String name = null;
-        
-        String path = url.getPath();
-        int end = path.indexOf(JAR_EXT);
-        if (end != -1) {
-            int start = path.lastIndexOf('/', end);
-            name = path.substring(start + 1, end + 4);
-        }
-        
-        return name;
-    }
-
-}
diff --git a/java/org/apache/jasper/compiler/InternalJarScanner.java b/java/org/apache/jasper/compiler/InternalJarScanner.java
deleted file mode 100644 (file)
index 20feea6..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- *  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
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  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.jasper.compiler;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.JarURLConnection;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.net.URLConnection;
-import java.util.Iterator;
-import java.util.Set;
-
-import javax.servlet.ServletContext;
-
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.JarScanner;
-import org.apache.tomcat.JarScannerCallback;
-
-/**
- * The default {@link JarScanner} implementation scans the WEB-INF/lib directory
- * followed by the provided classloader and then works up the classloader
- * hierarchy. This implementation is sufficient to meet the requirements of the
- * Servlet 3.0 specification as well as to provide a number of Tomcat specific
- * extensions. The extensions are:
- * <ul>
- *   <li>Scanning the classloader hierarchy (enabled by default)</li>
- *   <li>Testing all files to see if they are JARs (disabled by default)</li>
- *   <li>Testing all directories to see if they are exploded JARs
- *       (disabled by default)</li>
- * </ul>
- * All of the extensions may be controlled via configuration.
- * 
- * Keep in sync with org.apache.catalina.startup.DefaultJarScanner
- */
-public class InternalJarScanner implements JarScanner {
-
-    private static final String JAR_EXT = ".jar";
-    private static final String WEB_INF_LIB = "/WEB-INF/lib/";
-
-    private static final Log log = LogFactory.getLog(InternalJarScanner.class);
-
-    /**
-     * Controls the classpath scanning extension.
-     */
-    private boolean scanClassPath = true;
-    public boolean isScanClassPath() {
-        return scanClassPath;
-    }
-    public void setScanClassPath(boolean scanClassPath) {
-        this.scanClassPath = scanClassPath;
-    }
-
-    /**
-     * Controls the testing all files to see of they are JAR files extension.
-     */
-    private boolean scanAllFiles = false;
-    public boolean isScanAllFiles() {
-        return scanAllFiles;
-    }
-    public void setScanAllFiles(boolean scanAllFiles) {
-        this.scanAllFiles = scanAllFiles;
-    }
-
-    /**
-     * Controls the testing all directories to see of they are exploded JAR
-     * files extension.
-     */
-    private boolean scanAllDirectories = false;
-    public boolean isScanAllDirectories() {
-        return scanAllDirectories;
-    }
-    public void setScanAllDirectories(boolean scanAllDirectories) {
-        this.scanAllDirectories = scanAllDirectories;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void scan(ServletContext context, ClassLoader classloader,
-            JarScannerCallback callback, Set<String> jarsToSkip) {
-
-        if (log.isTraceEnabled()) {
-            log.trace(Localizer.getMessage("jsp.jarScan.webinflibStart"));
-        }
-
-        // Scan WEB-INF/lib
-        Set<String> dirList = context.getResourcePaths(WEB_INF_LIB);
-        if (dirList != null) {
-            Iterator<String> it = dirList.iterator();
-            while (it.hasNext()) {
-                String path = it.next();
-                if (path.endsWith(JAR_EXT) &&
-                        !jarsToSkip.contains(
-                                path.substring(path.lastIndexOf('/')))) {
-                    // Need to scan this JAR
-                    URL url = null;
-                    try {
-                        url = context.getResource(path);
-                        process(callback, url);
-                    } catch (IOException e) {
-                        if (url == null) {
-                            log.warn(Localizer.getMessage(
-                                    "jsp.jarScan.webinflibFail",
-                                    path), e);
-                        } else {
-                            log.warn(Localizer.getMessage(
-                                    "jsp.jarScan.webinflibFail",
-                                    url.toString()), e);
-                        }
-                    }
-                }
-            }
-        }
-        
-        // Scan the classpath
-        if (scanClassPath) {
-            if (log.isTraceEnabled()) {
-                log.trace(Localizer.getMessage("jsp.jarScan.classloaderStart"));
-            }
-
-            ClassLoader loader = 
-                Thread.currentThread().getContextClassLoader();
-            
-            while (loader != null) {
-                if (loader instanceof URLClassLoader) {
-                    URL[] urls = ((URLClassLoader) loader).getURLs();
-                    for (int i=0; i<urls.length; i++) {
-                        // Extract the jarName if there is one to be found
-                        String jarName = getJarName(urls[i]);
-                        
-                        // Skip JARs with known not to be interesting and JARs
-                        // in WEB-INF/lib we have already scanned
-                        if (!(jarsToSkip.contains(jarName) ||
-                                urls[i].toString().contains(
-                                        WEB_INF_LIB + jarName))) {
-                            try {
-                                process(callback, urls[i]);
-                            } catch (IOException ioe) {
-                                log.warn(Localizer.getMessage(
-                                        "jsp.jarScan.classloaderFail",
-                                        urls[i].toString()), ioe);
-                            }
-                        }
-                    }
-                }
-                loader = loader.getParent();
-            }
-
-        }
-    }
-
-    /*
-     * Scan a URL for JARs with the optional extensions to look at all files
-     * and all directories.
-     */
-    private void process(JarScannerCallback callback, URL url)
-            throws IOException {
-
-        if (log.isTraceEnabled()) {
-            log.trace(Localizer.getMessage("jsp.jarScan.jarUrlStart",
-                    url.toString()));
-        }
-
-        URLConnection conn = url.openConnection();
-        if (conn instanceof JarURLConnection) {
-            callback.scan((JarURLConnection) conn);
-        } else {
-            String urlStr = url.toString();
-            if (urlStr.startsWith("file:") || urlStr.startsWith("jndi:")) {
-                if (urlStr.endsWith(JAR_EXT)) {
-                    URL jarURL = new URL("jar:" + urlStr + "!/");
-                    callback.scan((JarURLConnection) jarURL.openConnection());
-                } else {
-                    File f;
-                    try {
-                        f = new File(url.toURI());
-                        if (f.isFile() && scanAllFiles) {
-                            // Treat this file as a JAR
-                            URL jarURL = new URL("jar:" + urlStr + "!/");
-                            callback.scan((JarURLConnection) jarURL.openConnection());
-                        } else if (f.isDirectory() && scanAllDirectories) {
-                            File metainf = new File(f.getAbsoluteFile() +
-                                    File.separator + "META-INF");
-                            if (metainf.isDirectory()) {
-                                callback.scan(f);
-                            }
-                        }
-                    } catch (URISyntaxException e) {
-                        // Wrap the exception and re-throw
-                        IOException ioe = new IOException();
-                        ioe.initCause(e);
-                        throw ioe;
-                    }
-                }
-            }
-        }
-        
-    }
-
-    /*
-     * Extract the JAR name, if present, from a URL
-     */
-    private String getJarName(URL url) {
-        
-        String name = null;
-        
-        String path = url.getPath();
-        int end = path.indexOf(JAR_EXT);
-        if (end != -1) {
-            int start = path.lastIndexOf('/', end);
-            name = path.substring(start + 1, end + 4);
-        }
-        
-        return name;
-    }
-
-}
index 8c8def4..d8a3234 100644 (file)
@@ -23,6 +23,7 @@ package org.apache.jasper.compiler;
 import javax.servlet.ServletContext;
 
 import org.apache.tomcat.JarScanner;
+import org.apache.tomcat.util.scan.DefaultJarScanner;
 
 /**
  * Provide a mechanism for Jasper to obtain a reference to the JarScanner
@@ -43,7 +44,7 @@ public class JarScannerFactory {
                (JarScanner) ctxt.getAttribute(JarScanner.class.getName());
         if (jarScanner == null) {
             ctxt.log(Localizer.getMessage("jsp.warning.noJarScanner"));
-            jarScanner = new InternalJarScanner();
+            jarScanner = new DefaultJarScanner();
         }
         return jarScanner;
     }
diff --git a/java/org/apache/tomcat/util/scan/DefaultJarScanner.java b/java/org/apache/tomcat/util/scan/DefaultJarScanner.java
new file mode 100644 (file)
index 0000000..8780fe8
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ *  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
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  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.tomcat.util.scan;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.JarURLConnection;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.net.URLConnection;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.servlet.ServletContext;
+
+import org.apache.catalina.startup.Constants;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.JarScanner;
+import org.apache.tomcat.JarScannerCallback;
+import org.apache.tomcat.util.res.StringManager;
+
+/**
+ * The default {@link JarScanner} implementation scans the WEB-INF/lib directory
+ * followed by the provided classloader and then works up the classloader
+ * hierarchy. This implementation is sufficient to meet the requirements of the
+ * Servlet 3.0 specification as well as to provide a number of Tomcat specific
+ * extensions. The extensions are:
+ * <ul>
+ *   <li>Scanning the classloader hierarchy (enabled by default)</li>
+ *   <li>Testing all files to see if they are JARs (disabled by default)</li>
+ *   <li>Testing all directories to see if they are exploded JARs
+ *       (disabled by default)</li>
+ * </ul>
+ * All of the extensions may be controlled via configuration.
+ */
+public class DefaultJarScanner implements JarScanner {
+
+    private static final String JAR_EXT = ".jar";
+    private static final String WEB_INF_LIB = "/WEB-INF/lib/";
+
+    private static final Log log = LogFactory.getLog(DefaultJarScanner.class);
+
+    /**
+     * The string resources for this package.
+     */
+    private static final StringManager sm =
+        StringManager.getManager(Constants.Package);
+
+
+    /**
+     * Controls the classpath scanning extension.
+     */
+    private boolean scanClassPath = true;
+    public boolean isScanClassPath() {
+        return scanClassPath;
+    }
+    public void setScanClassPath(boolean scanClassPath) {
+        this.scanClassPath = scanClassPath;
+    }
+
+    /**
+     * Controls the testing all files to see of they are JAR files extension.
+     */
+    private boolean scanAllFiles = false;
+    public boolean isScanAllFiles() {
+        return scanAllFiles;
+    }
+    public void setScanAllFiles(boolean scanAllFiles) {
+        this.scanAllFiles = scanAllFiles;
+    }
+
+    /**
+     * Controls the testing all directories to see of they are exploded JAR
+     * files extension.
+     */
+    private boolean scanAllDirectories = false;
+    public boolean isScanAllDirectories() {
+        return scanAllDirectories;
+    }
+    public void setScanAllDirectories(boolean scanAllDirectories) {
+        this.scanAllDirectories = scanAllDirectories;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void scan(ServletContext context, ClassLoader classloader,
+            JarScannerCallback callback, Set<String> jarsToSkip) {
+
+        if (log.isTraceEnabled()) {
+            log.trace(sm.getString("jarScan.webinflibStart"));
+        }
+
+        // Scan WEB-INF/lib
+        Set<String> dirList = context.getResourcePaths(WEB_INF_LIB);
+        if (dirList != null) {
+            Iterator<String> it = dirList.iterator();
+            while (it.hasNext()) {
+                String path = it.next();
+                if (path.endsWith(JAR_EXT) &&
+                        !jarsToSkip.contains(
+                                path.substring(path.lastIndexOf('/')))) {
+                    // Need to scan this JAR
+                    URL url = null;
+                    try {
+                        url = context.getResource(path);
+                        process(callback, url);
+                    } catch (IOException e) {
+                        log.warn(sm.getString("jarScan.webinflibFail", url), e);
+                    }
+                }
+            }
+        }
+        
+        // Scan the classpath
+        if (scanClassPath) {
+            if (log.isTraceEnabled()) {
+                log.trace(sm.getString("jarScan.classloaderStart"));
+            }
+
+            ClassLoader loader = 
+                Thread.currentThread().getContextClassLoader();
+            
+            while (loader != null) {
+                if (loader instanceof URLClassLoader) {
+                    URL[] urls = ((URLClassLoader) loader).getURLs();
+                    for (int i=0; i<urls.length; i++) {
+                        // Extract the jarName if there is one to be found
+                        String jarName = getJarName(urls[i]);
+                        
+                        // Skip JARs with known not to be interesting and JARs
+                        // in WEB-INF/lib we have already scanned
+                        if (!(jarsToSkip.contains(jarName) ||
+                                urls[i].toString().contains(
+                                        WEB_INF_LIB + jarName))) {
+                            try {
+                                process(callback, urls[i]);
+                            } catch (IOException ioe) {
+                                log.warn(sm.getString(
+                                        "jarScan.classloaderFail",urls[i]), ioe);
+                            }
+                        }
+                    }
+                }
+                loader = loader.getParent();
+            }
+
+        }
+    }
+
+    /*
+     * Scan a URL for JARs with the optional extensions to look at all files
+     * and all directories.
+     */
+    private void process(JarScannerCallback callback, URL url)
+            throws IOException {
+
+        if (log.isTraceEnabled()) {
+            log.trace(sm.getString("jarScan.jarUrlStart", url));
+        }
+
+        URLConnection conn = url.openConnection();
+        if (conn instanceof JarURLConnection) {
+            callback.scan((JarURLConnection) conn);
+        } else {
+            String urlStr = url.toString();
+            if (urlStr.startsWith("file:") || urlStr.startsWith("jndi:")) {
+                if (urlStr.endsWith(JAR_EXT)) {
+                    URL jarURL = new URL("jar:" + urlStr + "!/");
+                    callback.scan((JarURLConnection) jarURL.openConnection());
+                } else {
+                    File f;
+                    try {
+                        f = new File(url.toURI());
+                        if (f.isFile() && scanAllFiles) {
+                            // Treat this file as a JAR
+                            URL jarURL = new URL("jar:" + urlStr + "!/");
+                            callback.scan((JarURLConnection) jarURL.openConnection());
+                        } else if (f.isDirectory() && scanAllDirectories) {
+                            File metainf = new File(f.getAbsoluteFile() +
+                                    File.separator + "META-INF");
+                            if (metainf.isDirectory()) {
+                                callback.scan(f);
+                            }
+                        }
+                    } catch (URISyntaxException e) {
+                        // Wrap the exception and re-throw
+                        IOException ioe = new IOException();
+                        ioe.initCause(e);
+                        throw ioe;
+                    }
+                }
+            }
+        }
+        
+    }
+
+    /*
+     * Extract the JAR name, if present, from a URL
+     */
+    private String getJarName(URL url) {
+        
+        String name = null;
+        
+        String path = url.getPath();
+        int end = path.indexOf(JAR_EXT);
+        if (end != -1) {
+            int start = path.lastIndexOf('/', end);
+            name = path.substring(start + 1, end + 4);
+        }
+        
+        return name;
+    }
+
+}
diff --git a/java/org/apache/tomcat/util/scan/package.html b/java/org/apache/tomcat/util/scan/package.html
new file mode 100644 (file)
index 0000000..bf69b24
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+$Id$
+-->
+</head>
+<body bgcolor="white">
+<p>
+This package contains the common classes used to perform configuration scanning
+for Catalina and Jasper.
+</p>
+</body>
+</html>
index 16144e7..cad825d 100644 (file)
     <doMavenDeploy artifactId="tomcat-jsp-api" jarFileName="jsp-api.jar"/>
     <doMavenDeploy artifactId="tomcat-servlet-api" jarFileName="servlet-api.jar"/>
     <doMavenDeploy artifactId="tomcat-api"/>
+    <doMavenDeploy artifactId="tomcat-util"/>
     <doMavenDeploy artifactId="tomcat-coyote"/>
     <doMavenDeploy artifactId="tomcat-dbcp"/>
     <doMavenDeploy artifactId="tomcat-i18n-es"/>
index aec7447..563a39c 100644 (file)
       <version>@MAVEN.DEPLOY.VERSION@</version>
       <scope>compile</scope>
     </dependency>
+    <dependency>
+      <groupId>org.apache.tomcat</groupId>
+      <artifactId>tomcat-util</artifactId>
+      <version>@MAVEN.DEPLOY.VERSION@</version>
+      <scope>compile</scope>
+    </dependency>
   </dependencies>
 </project>
index 09e4e42..6238c90 100644 (file)
       <version>@MAVEN.DEPLOY.VERSION@</version>
       <scope>compile</scope>
     </dependency>
+    <dependency>
+      <groupId>org.apache.tomcat</groupId>
+      <artifactId>tomcat-util</artifactId>
+      <version>@MAVEN.DEPLOY.VERSION@</version>
+      <scope>compile</scope>
+    </dependency>
   </dependencies>
 </project>
diff --git a/res/maven/tomcat-util.pom b/res/maven/tomcat-util.pom
new file mode 100644 (file)
index 0000000..67e486f
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  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.
+-->
+<project>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.tomcat</groupId>
+  <artifactId>tomcat-util</artifactId>
+  <version>@MAVEN.DEPLOY.VERSION@</version>
+  <description>Common code shared by Catalina and Jasper</description>
+</project>