From: markt
Date: Mon, 14 Sep 2009 12:39:45 +0000 (+0000)
Subject: Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=47834
X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=2ef15b17d8d06d766e83974a2d30e2040ac1871b;p=tomcat7.0
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.
git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@814617 13f79535-47bb-0310-9956-ffa450edef68
---
diff --git a/java/org/apache/catalina/startup/LocalStrings.properties b/java/org/apache/catalina/startup/LocalStrings.properties
index cadc30ecc..6a93bd726 100644
--- a/java/org/apache/catalina/startup/LocalStrings.properties
+++ b/java/org/apache/catalina/startup/LocalStrings.properties
@@ -94,6 +94,7 @@ tldConfig.addListeners=Adding {0} listeners from TLD files
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
diff --git a/java/org/apache/catalina/startup/TldConfig.java b/java/org/apache/catalina/startup/TldConfig.java
index 33bf53d42..530bb71b3 100644
--- a/java/org/apache/catalina/startup/TldConfig.java
+++ b/java/org/apache/catalina/startup/TldConfig.java
@@ -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 @@ public final class TldConfig implements LifecycleListener {
"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 noTldJars;
@@ -564,10 +577,73 @@ public final class TldConfig implements LifecycleListener {
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
+ }
+ }
+ }
+ }
}
}
}
diff --git a/java/org/apache/jasper/compiler/TagLibraryInfoImpl.java b/java/org/apache/jasper/compiler/TagLibraryInfoImpl.java
index b3b7e92b5..63725b324 100644
--- a/java/org/apache/jasper/compiler/TagLibraryInfoImpl.java
+++ b/java/org/apache/jasper/compiler/TagLibraryInfoImpl.java
@@ -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 @@ class TagLibraryInfoImpl extends TagLibraryInfo implements TagConstants {
// 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);
}
-
}
/**
diff --git a/java/org/apache/jasper/compiler/TldLocationsCache.java b/java/org/apache/jasper/compiler/TldLocationsCache.java
index dc8134076..40a57fe0b 100644
--- a/java/org/apache/jasper/compiler/TldLocationsCache.java
+++ b/java/org/apache/jasper/compiler/TldLocationsCache.java
@@ -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 @@ public class TldLocationsCache {
"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 noTldJars;
@@ -478,10 +491,67 @@ public class TldLocationsCache {
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
+ }
+ }
+ }
+ }
}
}
}
diff --git a/webapps/docs/config/systemprops.xml b/webapps/docs/config/systemprops.xml
index 8d60ed9dd..b024f3978 100644
--- a/webapps/docs/config/systemprops.xml
+++ b/webapps/docs/config/systemprops.xml
@@ -103,6 +103,23 @@
be used.
+
+ 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 false will
+ be used.
+
+
+
+ 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 false will be used.
+
+
If true, any tag buffer that expands beyond
org.apache.jasper.Constants.DEFAULT_TAG_BUFFER_SIZE will be