Author: markt
Date: Mon Sep 14 12:39:45 2009
New Revision: 814617

URL: http://svn.apache.org/viewvc?rev=814617&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=47834
As well as the JAR as directory feature requested, this adds looking at all 
files to see if they are JARs rather than using the presence of a .jar 
extension. These features are optional for the Servlet spec but required for 
RFC66 in an OSGI environment.
Both options are configurable with system properties and default to off.

Modified:
    tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties
    tomcat/trunk/java/org/apache/catalina/startup/TldConfig.java
    tomcat/trunk/java/org/apache/jasper/compiler/TagLibraryInfoImpl.java
    tomcat/trunk/java/org/apache/jasper/compiler/TldLocationsCache.java
    tomcat/trunk/webapps/docs/config/systemprops.xml

Modified: tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties?rev=814617&r1=814616&r2=814617&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties 
(original)
+++ tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties Mon 
Sep 14 12:39:45 2009
@@ -94,6 +94,7 @@
 tldConfig.cce=Lifecycle event data object {0} is not a Context
 tldConfig.classloaderFail=Failed to process ''{0}'' for TLDs.
 tldConfig.classloaderStart=Scanning for TLDs in classloader hierarchy
+tldConfig.dirScan=Scanning for TLD files in directory ''{0}''
 tldConfig.execute=Error processing TLD files for context path {0}
 tldConfig.jarUrlStart=Scanning for TLD files in URL ''{0}''
 tldConfig.webinflibStart=Scanning WEB-INF/lib for JARs containing 
META-INF/**/*.TLD

Modified: tomcat/trunk/java/org/apache/catalina/startup/TldConfig.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/TldConfig.java?rev=814617&r1=814616&r2=814617&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/TldConfig.java (original)
+++ tomcat/trunk/java/org/apache/catalina/startup/TldConfig.java Mon Sep 14 
12:39:45 2009
@@ -19,9 +19,12 @@
 package org.apache.catalina.startup;
 
 
+import java.io.File;
+import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.JarURLConnection;
+import java.net.URISyntaxException;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.net.URLConnection;
@@ -69,6 +72,16 @@
                 "org.apache.jasper.compiler.TldLocationsCache.SCAN_CLASSPATH",
                 "true")).booleanValue();
 
+    private static final boolean SCAN_ALL_FILES = Boolean.valueOf(
+            System.getProperty(
+                "org.apache.jasper.compiler.TldLocationsCache.SCAN_ALL_FILES",
+                "false")).booleanValue();
+
+    private static final boolean SCAN_ALL_DIRS = Boolean.valueOf(
+            System.getProperty(
+                "org.apache.jasper.compiler.TldLocationsCache.SCAN_ALL_DIRS",
+                "false")).booleanValue();
+
     // Names of JARs that are known not to contain any TLDs
     private static HashSet<String> noTldJars;
 
@@ -564,10 +577,73 @@
             tldScanJar((JarURLConnection) conn);
         } else {
             String urlStr = url.toString();
-            if (urlStr.startsWith("file:")
-                    && urlStr.endsWith(JAR_EXT)) {
-                URL jarURL = new URL("jar:" + urlStr + "!/");
-                tldScanJar((JarURLConnection) jarURL.openConnection());
+            if (urlStr.startsWith("file:")) {
+                if (urlStr.endsWith(JAR_EXT)) {
+                    URL jarURL = new URL("jar:" + urlStr + "!/");
+                    tldScanJar((JarURLConnection) jarURL.openConnection());
+                } else {
+                    File f;
+                    try {
+                        f = new File(url.toURI());
+                        if (f.isFile() && SCAN_ALL_FILES) {
+                            // Treat this file as a JAR
+                            URL jarURL = new URL("jar:" + urlStr + "!/");
+                            tldScanJar((JarURLConnection) 
jarURL.openConnection());
+                        } else if (f.isDirectory() && SCAN_ALL_DIRS) {
+                            File metainf = new File(f.getAbsoluteFile() +
+                                    File.separator + "META-INF");
+                            if (metainf.isDirectory()) {
+                                tldScanDir(metainf);
+                            }
+                        }
+                    } catch (URISyntaxException e) {
+                        // Wrap the exception and re-throw
+                        IOException ioe = new IOException();
+                        ioe.initCause(e);
+                        throw ioe;
+                    }
+                }
+            }
+        }
+    }
+
+    /*
+     * Scans the directory identified by startPath, along with its
+     * sub-directories, for TLDs.
+     *
+     * Keep in sync with o.a.j.comiler.TldLocationsCache
+     */
+    private void tldScanDir(File start) {
+
+        if (log.isTraceEnabled()) {
+            log.trace(sm.getString("tldConfig.dirScan", 
start.getAbsolutePath()));
+        }
+
+        File[] fileList = start.listFiles();
+        if (fileList != null) {
+            for (int i = 0; i < fileList.length; i++) {
+                // Scan recursively
+                if (fileList[i].isDirectory()) {
+                    tldScanDir(fileList[i]);
+                } else if (fileList[i].getAbsolutePath().endsWith(TLD_EXT)) {
+                    InputStream stream = null;
+                    try {
+                        stream = new FileInputStream(fileList[i]);
+                        tldScanStream(stream);
+                    } catch (IOException ioe) {
+                        log.warn(sm.getString("tldConfig.dirFail",
+                                fileList[i].getAbsolutePath()),
+                                ioe);
+                    } finally {
+                        if (stream != null) {
+                            try {
+                                stream.close();
+                            } catch (Throwable t) {
+                                // do nothing
+                            }
+                        }
+                    }
+                }
             }
         }
     }

Modified: tomcat/trunk/java/org/apache/jasper/compiler/TagLibraryInfoImpl.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/TagLibraryInfoImpl.java?rev=814617&r1=814616&r2=814617&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/jasper/compiler/TagLibraryInfoImpl.java 
(original)
+++ tomcat/trunk/java/org/apache/jasper/compiler/TagLibraryInfoImpl.java Mon 
Sep 14 12:39:45 2009
@@ -17,6 +17,7 @@
 
 package org.apache.jasper.compiler;
 
+import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.InputStream;
@@ -111,20 +112,24 @@
     // the following is a workaround until these problems are resolved.
     private InputStream getResourceAsStream(String uri)
             throws FileNotFoundException {
-        try {
-            // see if file exists on the filesystem first
-            String real = ctxt.getRealPath(uri);
-            if (real == null) {
+        // Is uri absolute?
+        if (uri.startsWith("file:")) {
+            return new FileInputStream(new File(uri.substring(5)));
+        } else {
+            try {
+                // see if file exists on the filesystem
+                String real = ctxt.getRealPath(uri);
+                if (real == null) {
+                    return ctxt.getResourceAsStream(uri);
+                } else {
+                    return new FileInputStream(real);
+                }
+            } catch (FileNotFoundException ex) {
+                // if file not found on filesystem, get the resource through
+                // the context
                 return ctxt.getResourceAsStream(uri);
-            } else {
-                return new FileInputStream(real);
             }
-        } catch (FileNotFoundException ex) {
-            // if file not found on filesystem, get the resource through
-            // the context
-            return ctxt.getResourceAsStream(uri);
         }
-
     }
 
     /**

Modified: tomcat/trunk/java/org/apache/jasper/compiler/TldLocationsCache.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/TldLocationsCache.java?rev=814617&r1=814616&r2=814617&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/jasper/compiler/TldLocationsCache.java 
(original)
+++ tomcat/trunk/java/org/apache/jasper/compiler/TldLocationsCache.java Mon Sep 
14 12:39:45 2009
@@ -17,10 +17,13 @@
 
 package org.apache.jasper.compiler;
 
+import java.io.File;
+import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.JarURLConnection;
 import java.net.MalformedURLException;
+import java.net.URISyntaxException;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.net.URLConnection;
@@ -101,6 +104,16 @@
                 "org.apache.jasper.compiler.TldLocationsCache.SCAN_CLASSPATH",
                 "true")).booleanValue();
 
+    private static final boolean SCAN_ALL_FILES = Boolean.valueOf(
+            System.getProperty(
+                "org.apache.jasper.compiler.TldLocationsCache.SCAN_ALL_FILES",
+                "false")).booleanValue();
+
+    private static final boolean SCAN_ALL_DIRS = Boolean.valueOf(
+            System.getProperty(
+                "org.apache.jasper.compiler.TldLocationsCache.SCAN_ALL_DIRS",
+                "false")).booleanValue();
+
     // Names of JARs that are known not to contain any TLDs
     private static HashSet<String> noTldJars;
 
@@ -478,10 +491,67 @@
             tldScanJar((JarURLConnection) conn);
         } else {
             String urlStr = url.toString();
-            if (urlStr.startsWith(FILE_PROTOCOL)
-                    && urlStr.endsWith(JAR_EXT)) {
-                URL jarURL = new URL("jar:" + urlStr + "!/");
-                tldScanJar((JarURLConnection) jarURL.openConnection());
+            if (urlStr.startsWith("file:")) {
+                if (urlStr.endsWith(JAR_EXT)) {
+                    URL jarURL = new URL("jar:" + urlStr + "!/");
+                    tldScanJar((JarURLConnection) jarURL.openConnection());
+                } else {
+                    File f;
+                    try {
+                        f = new File(url.toURI());
+                        if (f.isFile() && SCAN_ALL_FILES) {
+                            // Treat this file as a JAR
+                            URL jarURL = new URL("jar:" + urlStr + "!/");
+                            tldScanJar((JarURLConnection) 
jarURL.openConnection());
+                            tldScanJar((JarURLConnection) 
jarURL.openConnection());
+                        } else if (f.isDirectory() && SCAN_ALL_DIRS) {
+                            File metainf = new File(f.getAbsoluteFile() +
+                                    File.separator + "META-INF");
+                            if (metainf.isDirectory()) {
+                                tldScanDir(metainf);
+                            }
+                        }
+                    } catch (URISyntaxException e) {
+                        // Wrap the exception and re-throw
+                        IOException ioe = new IOException();
+                        ioe.initCause(e);
+                        throw ioe;
+                    }
+                }
+            }
+        }
+    }
+
+    /*
+     * Scans the directory identified by startPath, along with its
+     * sub-directories, for TLDs.
+     *
+     * Keep in sync with o.a.c.startup.TldConfig
+     */
+    private void tldScanDir(File start) throws IOException {
+
+        File[] fileList = start.listFiles();
+        if (fileList != null) {
+            for (int i = 0; i < fileList.length; i++) {
+                // Scan recursively
+                if (fileList[i].isDirectory()) {
+                    tldScanDir(fileList[i]);
+                } else if (fileList[i].getAbsolutePath().endsWith(TLD_EXT)) {
+                    InputStream stream = null;
+                    try {
+                        stream = new FileInputStream(fileList[i]);
+                        tldScanStream(
+                                fileList[i].toURI().toString(), null, stream);
+                    } finally {
+                        if (stream != null) {
+                            try {
+                                stream.close();
+                            } catch (Throwable t) {
+                                // do nothing
+                            }
+                        }
+                    }
+                }
             }
         }
     }

Modified: tomcat/trunk/webapps/docs/config/systemprops.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/systemprops.xml?rev=814617&r1=814616&r2=814617&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/systemprops.xml (original)
+++ tomcat/trunk/webapps/docs/config/systemprops.xml Mon Sep 14 12:39:45 2009
@@ -103,6 +103,23 @@
       be used.</p>
     </property>
 
+    <property name="org.apache.jasper.compiler. 
TldLocationsCache.SCAN_ALL_FILES">
+      <p>When scanning the class path for TLDs, should Jasper scan all files
+      as if they are JAR files even if they do not have a .jar file extension?
+      This is intended for use in embedded environments where custom
+      classloaders allow for archives on the classpath with non-standard file
+      extensions. If not specified, the default value of <code>false</code> 
will
+      be used.</p>
+    </property>
+
+    <property name="org.apache.jasper.compiler. 
TldLocationsCache.SCAN_ALL_DIRS">
+      <p>When scanning the class path for TLDs, should Jasper scan all
+      directories as if they are unpacked JAR files? This is intended for use 
in
+      embedded environments where custom classloaders allow for directories
+      representing unpacked WAR files on the classpath. If not specified, the
+      default value of <code>false</code> will be used.</p>
+    </property>
+
     <property name="org.apache.jasper.runtime. BodyContentImpl.LIMIT_BUFFER">
       <p>If <code>true</code>, any tag buffer that expands beyond
       <code>org.apache.jasper.Constants.DEFAULT_TAG_BUFFER_SIZE</code> will be



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to