You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by lu...@apache.org on 2003/03/26 21:40:37 UTC
cvs commit: jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/startup TldConfig.java
luehe 2003/03/26 12:40:37
Modified: catalina/src/share/org/apache/catalina/startup
TldConfig.java
Log:
Fixed Bugzilla 15875 ("Support global sharing of tag libraries")
Revision Changes Path
1.3 +186 -66 jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/startup/TldConfig.java
Index: TldConfig.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/startup/TldConfig.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- TldConfig.java 16 Feb 2003 19:40:21 -0000 1.2
+++ TldConfig.java 26 Mar 2003 20:40:37 -0000 1.3
@@ -69,6 +69,8 @@
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
+import java.net.URLConnection;
+import java.net.URLClassLoader;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.ArrayList;
@@ -106,6 +108,9 @@
private static org.apache.commons.logging.Log log=
org.apache.commons.logging.LogFactory.getLog( TldConfig.class );
+ private static final String FILE_URL_PREFIX = "file:";
+ private static final int FILE_URL_PREFIX_LEN = FILE_URL_PREFIX.length();
+
// ----------------------------------------------------- Instance Variables
/**
@@ -199,32 +204,23 @@
}
}
- // Acquire this list of TLD resource paths to be processed
+ /*
+ * Acquire the list of TLD resource paths, possibly embedded in JAR
+ * files, to be processed
+ */
Set resourcePaths = tldScanResourcePaths();
+ Set globalJarPaths = getGlobalJarPaths();
- if( tldCache!= null && tldCache.exists()) {
- // Find last modified
- Iterator paths = resourcePaths.iterator();
- long lastModified=0;
- while (paths.hasNext()) {
- String path = (String) paths.next();
- URL url = context.getServletContext().getResource(path);
- if( url==null ) {
- log.info( "Null url "+ path );
- break;
- }
- long lastM=url.openConnection().getLastModified();
- if( lastM > lastModified ) lastModified=lastM;
- if( log.isDebugEnabled() )
- log.debug( "Last modified " + path + " " + lastM);
- }
-
- if( lastModified < tldCache.lastModified()) {
+ // Check to see if we can use cached listeners
+ if (tldCache != null && tldCache.exists()) {
+ long lastModified = getLastModified(resourcePaths, globalJarPaths);
+ if (lastModified < tldCache.lastModified()) {
processCache(tldCache);
return;
}
}
- // Scan each accumulated resource paths for TLDs to be processed
+
+ // Scan each accumulated resource path for TLDs to be processed
Iterator paths = resourcePaths.iterator();
while (paths.hasNext()) {
String path = (String) paths.next();
@@ -234,7 +230,12 @@
tldScanTld(path);
}
}
- String list[]=getTldListeners();
+ paths = globalJarPaths.iterator();
+ while (paths.hasNext()) {
+ tldScanJar((JarURLConnection) paths.next());
+ }
+
+ String list[] = getTldListeners();
if( tldCache!= null ) {
log.info( "Saving tld cache: " + tldCache + " " + list.length);
@@ -263,6 +264,48 @@
// -------------------------------------------------------- Private Methods
+ /*
+ * Returns the last modification date of the given sets of resources.
+ *
+ * @param resourcePaths
+ * @param globalJarPaths
+ *
+ * @return Last modification date
+ */
+ private long getLastModified(Set resourcePaths, Set globalJarPaths)
+ throws Exception {
+
+ long lastModified = 0;
+
+ Iterator paths = resourcePaths.iterator();
+ while (paths.hasNext()) {
+ String path = (String) paths.next();
+ URL url = context.getServletContext().getResource(path);
+ if (url == null) {
+ log.info( "Null url "+ path );
+ break;
+ }
+ long lastM = url.openConnection().getLastModified();
+ if (lastM > lastModified) lastModified = lastM;
+ if (log.isDebugEnabled()) {
+ log.debug( "Last modified " + path + " " + lastM);
+ }
+ }
+
+ paths = globalJarPaths.iterator();
+ while (paths.hasNext()) {
+ JarURLConnection conn = (JarURLConnection) paths.next();
+ long lastM = conn.getLastModified();
+ if (lastM > lastModified) lastModified = lastM;
+ if (log.isDebugEnabled()) {
+ log.debug("Last modified " + conn.getJarFileURL().toString()
+ + " " + lastM);
+ }
+ }
+
+ return lastModified;
+ }
+
private void processCache(File tldCache ) throws IOException {
// read the cache and return;
try {
@@ -394,21 +437,33 @@
log.debug(" Scanning JAR at resource path '" + resourcePath + "'");
}
+ URL url = context.getServletContext().getResource(resourcePath);
+ if (url == null) {
+ throw new IllegalArgumentException
+ (sm.getString("contextConfig.tldResourcePath",
+ resourcePath));
+ }
+ url = new URL("jar:" + url.toString() + "!/");
+ tldScanJar((JarURLConnection) url.openConnection());
+ }
+
+ /*
+ * Scans all TLD entries in the given JAR for application listeners.
+ *
+ * @param conn URLConnection to the JAR file whose TLD entries are
+ * scanned for application listeners
+ */
+ private void tldScanJar(JarURLConnection conn) throws Exception {
+
JarFile jarFile = null;
String name = null;
InputStream inputStream = null;
- try {
- URL url = context.getServletContext().getResource(resourcePath);
- if (url == null) {
- throw new IllegalArgumentException
- (sm.getString("contextConfig.tldResourcePath",
- resourcePath));
- }
- url = new URL("jar:" + url.toString() + "!/");
- JarURLConnection conn =
- (JarURLConnection) url.openConnection();
- conn.setUseCaches(false);
- jarFile = conn.getJarFile();
+
+ String jarPath = conn.getJarFileURL().toString();
+
+ try {
+ conn.setUseCaches(false);
+ jarFile = conn.getJarFile();
Enumeration entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = (JarEntry) entries.nextElement();
@@ -434,10 +489,13 @@
// XXX Why do we wrap it ? The signature is 'throws Exception'
if (name == null) {
log.error(sm.getString("contextConfig.tldJarException",
- resourcePath, context.getPath()), e);
+ jarPath, context.getPath()),
+ e);
} else {
log.error(sm.getString("contextConfig.tldEntryException",
- name, resourcePath, context.getPath()), e);
+ name, jarPath,
+ context.getPath()),
+ e);
}
} finally {
if (inputStream != null) {
@@ -461,7 +519,6 @@
}
-
/**
* Scan the TLD contents in the specified input stream, and register
* any application event listeners found there. <b>NOTE</b> - It is
@@ -487,7 +544,6 @@
}
-
/**
* Scan the TLD contents at the specified resource path, and register
* any application event listeners found there.
@@ -531,7 +587,6 @@
}
-
/**
* Accumulate and return a Set of resource paths to be analyzed for
* tag library descriptors. Each element of the returned set will be
@@ -568,38 +623,66 @@
resourcePaths.add(resourcePath);
}
- // Scan TLDs in the /WEB-INF subdirectory of the web application
+ DirContext resources = context.getResources();
+ if (resources != null) {
+ tldScanResourcePathsWebInf(resources, resourcePaths);
+ tldScanResourcePathsWebInfLibJars(resources, resourcePaths);
+ }
+
+ // Return the completed set
+ return (resourcePaths);
+
+ }
+
+ /*
+ * Scans TLDs in the /WEB-INF subdirectory of the web application.
+ *
+ * @param resources The web application's resources
+ * @param resourcePaths The set of resource paths to add to
+ */
+ private void tldScanResourcePathsWebInf(DirContext resources,
+ Set resourcePaths)
+ throws IOException {
+
if (log.isTraceEnabled()) {
log.trace(" Scanning TLDs in /WEB-INF subdirectory");
}
- DirContext resources = context.getResources();
- if( resources!=null ) {
- try {
- NamingEnumeration items = resources.list("/WEB-INF");
- while (items.hasMoreElements()) {
- NameClassPair item = (NameClassPair) items.nextElement();
- String resourcePath = "/WEB-INF/" + item.getName();
- // FIXME - JSP 2.0 is not explicit about whether we should
- // scan subdirectories of /WEB-INF for TLDs also
- if (!resourcePath.endsWith(".tld")) {
- continue;
- }
- if (log.isTraceEnabled()) {
- log.trace(" Adding path '" + resourcePath + "'");
- }
- resourcePaths.add(resourcePath);
- }
- } catch (NamingException e) {
- ; // Silent catch: it's valid that no /WEB-INF directory exists
- }
- } else {
- log.info("No resource " + context + " " + context.getClass());
- }
- // Scan JARs in the /WEB-INF/lib subdirectory of the web application
+ try {
+ NamingEnumeration items = resources.list("/WEB-INF");
+ while (items.hasMoreElements()) {
+ NameClassPair item = (NameClassPair) items.nextElement();
+ String resourcePath = "/WEB-INF/" + item.getName();
+ // FIXME - JSP 2.0 is not explicit about whether we should
+ // scan subdirectories of /WEB-INF for TLDs also
+ if (!resourcePath.endsWith(".tld")) {
+ continue;
+ }
+ if (log.isTraceEnabled()) {
+ log.trace(" Adding path '" + resourcePath + "'");
+ }
+ resourcePaths.add(resourcePath);
+ }
+ } catch (NamingException e) {
+ ; // Silent catch: it's valid that no /WEB-INF directory exists
+ }
+ }
+
+ /*
+ * Adds any JARs in the /WEB-INF/lib subdirectory of the web application
+ * to the given set of resource paths.
+ *
+ * @param resources The web application's resources
+ * @param resourcePaths The set of resource paths to add to
+ */
+ private void tldScanResourcePathsWebInfLibJars(DirContext resources,
+ Set resourcePaths)
+ throws IOException {
+
if (log.isTraceEnabled()) {
log.trace(" Scanning JARs in /WEB-INF/lib subdirectory");
}
+
try {
NamingEnumeration items = resources.list("/WEB-INF/lib");
while (items.hasMoreElements()) {
@@ -616,10 +699,47 @@
} catch (NamingException e) {
; // Silent catch: it's valid that no /WEB-INF/lib directory exists
}
+ }
- // Return the completed set
- return (resourcePaths);
+ /*
+ * Returns the paths to all JAR files accessible to all parent
+ * classloaders of the web application class loader.
+ *
+ * This is a Tomcat-specific extension to the TLD search order defined in
+ * the JSP spec, which will allow tag libraries packaged as JAR
+ * files to be shared by web applications by simply dropping them in a
+ * location that all web applications have access to (e.g.,
+ * <CATALINA_HOME>/common/lib).
+ *
+ * @return Set of paths to all JAR files accessible to all parent class
+ * loaders of the web application class loader
+ */
+ private Set getGlobalJarPaths() throws IOException {
- }
+ Set globalJarPaths = new HashSet();
+
+ 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++) {
+ URLConnection conn = urls[i].openConnection();
+ if (conn instanceof JarURLConnection) {
+ globalJarPaths.add((JarURLConnection) conn);
+ } else {
+ String urlStr = urls[i].toString();
+ if (urlStr.startsWith("file:")
+ && urlStr.endsWith(".jar")) {
+ URL jarURL = new URL("jar:" + urlStr + "!/");
+ globalJarPaths.add((JarURLConnection)
+ jarURL.openConnection());
+ }
+ }
+ }
+ }
+ loader = loader.getParent();
+ }
+ return globalJarPaths;
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-dev-help@jakarta.apache.org