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: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to