You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2013/11/05 00:53:27 UTC

svn commit: r1538807 - in /tomcat/trunk/java/org/apache/catalina: WebResourceRoot.java WebResourceSet.java webresources/AbstractResourceSet.java webresources/Cache.java webresources/CachedResource.java webresources/StandardRoot.java

Author: markt
Date: Mon Nov  4 23:53:26 2013
New Revision: 1538807

URL: http://svn.apache.org/r1538807
Log:
First pass at using the new resources implementation to provide
resources to the class loader.

Class loader resources are handled by treating JARs in WEB-INF/lib as
resource JARs (without the internal META-INF/resources/ prefix) mounted
at WEB-INF/claasses (rather than the web app root). This enables reuse
of the resource handling plumbing.

These resources are marked as class loader only so they are only used in
the methods that are explicitly defined to return class loader
resources. This prevents calls to getResource("/WEB-INF/classes")
returning from one or more of the JAR files.

Modified:
    tomcat/trunk/java/org/apache/catalina/WebResourceRoot.java
    tomcat/trunk/java/org/apache/catalina/WebResourceSet.java
    tomcat/trunk/java/org/apache/catalina/webresources/AbstractResourceSet.java
    tomcat/trunk/java/org/apache/catalina/webresources/Cache.java
    tomcat/trunk/java/org/apache/catalina/webresources/CachedResource.java
    tomcat/trunk/java/org/apache/catalina/webresources/StandardRoot.java

Modified: tomcat/trunk/java/org/apache/catalina/WebResourceRoot.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/WebResourceRoot.java?rev=1538807&r1=1538806&r2=1538807&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/WebResourceRoot.java (original)
+++ tomcat/trunk/java/org/apache/catalina/WebResourceRoot.java Mon Nov  4 23:53:26 2013
@@ -111,6 +111,22 @@ public interface WebResourceRoot extends
     WebResource[] getResources(String path);
 
     /**
+     * Obtain the object that represents the class loader resource at the given
+     * path. WEB-INF/classes is always searched prior to searching JAR files in
+     * WEB-INF/lib. The search order for JAR files will be consistent across
+     * subsequent calls to this method until the web application is reloaded. No
+     * guarantee is made as to what the search order for JAR files may be.
+     *
+     * @param path  The path of the class loader resource of interest relative
+     *              to the the root of class loader resources for this web
+     *              application.
+     *
+     * @return  The object that represents the class loader resource at the
+     *          given path
+     */
+    WebResource getClassLoaderResource(String path);
+
+    /**
      * Obtain the list of the names of all of the files and directories located
      * in the specified directory.
      *
@@ -336,6 +352,7 @@ public interface WebResourceRoot extends
     public static enum ResourceSetType {
         PRE,
         RESOURCE_JAR,
-        POST
+        POST,
+        CLASSES_JAR
     }
 }

Modified: tomcat/trunk/java/org/apache/catalina/WebResourceSet.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/WebResourceSet.java?rev=1538807&r1=1538806&r2=1538807&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/WebResourceSet.java (original)
+++ tomcat/trunk/java/org/apache/catalina/WebResourceSet.java Mon Nov  4 23:53:26 2013
@@ -90,4 +90,16 @@ public interface WebResourceSet extends 
     boolean write(String path, InputStream is, boolean overwrite);
 
     void setRoot(WebResourceRoot root);
+
+    /**
+     * Are resources provided by this resource set only intended for use by
+     * calls to {@link WebResourceRoot#getClassLoaderResource(String)}.
+     *
+     * @return @true if these resources should only be used for calls to
+     *         {@link WebResourceRoot#getClassLoaderResource(String)}, otherwise
+     *         @false
+     */
+    boolean getClassLoaderOnly();
+
+    void setClassLoaderOnly(boolean classLoaderOnly);
 }

Modified: tomcat/trunk/java/org/apache/catalina/webresources/AbstractResourceSet.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/webresources/AbstractResourceSet.java?rev=1538807&r1=1538806&r2=1538807&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/webresources/AbstractResourceSet.java (original)
+++ tomcat/trunk/java/org/apache/catalina/webresources/AbstractResourceSet.java Mon Nov  4 23:53:26 2013
@@ -30,6 +30,7 @@ public abstract class AbstractResourceSe
     private String base;
     private String internalPath;
     private String webAppMount;
+    private boolean classLoaderOnly;
 
 
     protected static final StringManager sm =
@@ -88,6 +89,15 @@ public abstract class AbstractResourceSe
         return base;
     }
 
+    @Override
+    public boolean getClassLoaderOnly() {
+        return classLoaderOnly;
+    }
+
+    @Override
+    public void setClassLoaderOnly(boolean classLoaderOnly) {
+        this.classLoaderOnly = classLoaderOnly;
+    }
 
     //-------------------------------------------------------- Lifecycle methods
     @Override

Modified: tomcat/trunk/java/org/apache/catalina/webresources/Cache.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/webresources/Cache.java?rev=1538807&r1=1538806&r2=1538807&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/webresources/Cache.java (original)
+++ tomcat/trunk/java/org/apache/catalina/webresources/Cache.java Mon Nov  4 23:53:26 2013
@@ -55,15 +55,15 @@ public class Cache {
         this.root = root;
     }
 
-    protected WebResource getResource(String path) {
+    protected WebResource getResource(String path, boolean useClassLoaderResources) {
 
         if (noCache(path)) {
-            return root.getResourceInternal(path);
+            return root.getResourceInternal(path, useClassLoaderResources);
         }
 
         CachedResource cacheEntry = resourceCache.get(path);
 
-        if (cacheEntry != null && !cacheEntry.validate()) {
+        if (cacheEntry != null && !cacheEntry.validate(useClassLoaderResources)) {
             removeCacheEntry(path, true);
             cacheEntry = null;
         }
@@ -77,7 +77,7 @@ public class Cache {
             if (cacheEntry == null) {
                 // newCacheEntry was inserted into the cache - validate it
                 cacheEntry = newCacheEntry;
-                cacheEntry.validate();
+                cacheEntry.validate(useClassLoaderResources);
                 if (newCacheEntry.getContentLength() > getMaxSizeBytes()) {
                     // Cache size has not been updated at this point
                     removeCacheEntry(path, false);
@@ -110,7 +110,7 @@ public class Cache {
             } else {
                 // Another thread added the entry to the cache
                 // Make sure it is validated
-                cacheEntry.validate();
+                cacheEntry.validate(useClassLoaderResources);
             }
         }
 
@@ -141,6 +141,8 @@ public class Cache {
 
     private boolean noCache(String path) {
         // Don't cache resources used by the class loader (it has its own cache)
+        // TODO. Review these exclusions once class loader resource handling is
+        // complete
         if (path.startsWith("/WEB-INF/classes") ||
                 path.startsWith("/WEB-INF/lib")) {
             return true;

Modified: tomcat/trunk/java/org/apache/catalina/webresources/CachedResource.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/webresources/CachedResource.java?rev=1538807&r1=1538806&r2=1538807&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/webresources/CachedResource.java (original)
+++ tomcat/trunk/java/org/apache/catalina/webresources/CachedResource.java Mon Nov  4 23:53:26 2013
@@ -53,13 +53,14 @@ public class CachedResource implements W
         this.ttl = ttl;
     }
 
-    protected boolean validate() {
+    protected boolean validate(boolean useClassLoaderResources) {
         long now = System.currentTimeMillis();
 
         if (webResource == null) {
             synchronized (this) {
                 if (webResource == null) {
-                    webResource = root.getResourceInternal(webAppPath);
+                    webResource = root.getResourceInternal(
+                            webAppPath, useClassLoaderResources);
                     getLastModified();
                     getContentLength();
                     nextCheck = ttl + now;
@@ -72,8 +73,8 @@ public class CachedResource implements W
             return true;
         }
 
-        if (!webResource.exists() &&
-                root.getResourceInternal(webAppPath).exists()) {
+        if (!webResource.exists() && root.getResourceInternal(
+                webAppPath, useClassLoaderResources).exists()) {
             return false;
         }
 

Modified: tomcat/trunk/java/org/apache/catalina/webresources/StandardRoot.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/webresources/StandardRoot.java?rev=1538807&r1=1538806&r2=1538807&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/webresources/StandardRoot.java (original)
+++ tomcat/trunk/java/org/apache/catalina/webresources/StandardRoot.java Mon Nov  4 23:53:26 2013
@@ -58,6 +58,7 @@ public class StandardRoot extends Lifecy
     private boolean allowLinking = false;
     private ArrayList<WebResourceSet> preResources = new ArrayList<>();
     private WebResourceSet main;
+    private ArrayList<WebResourceSet> classResources = new ArrayList<>();
     private ArrayList<WebResourceSet> jarResources = new ArrayList<>();
     private ArrayList<WebResourceSet> postResources = new ArrayList<>();
 
@@ -71,6 +72,7 @@ public class StandardRoot extends Lifecy
     {
         allResources.add(preResources);
         allResources.add(mainResources);
+        allResources.add(classResources);
         allResources.add(jarResources);
         allResources.add(postResources);
     }
@@ -92,15 +94,23 @@ public class StandardRoot extends Lifecy
 
     @Override
     public String[] list(String path) {
-        checkState();
+        return list(path, true);
+    }
+
+    private String[] list(String path, boolean doStateCheck) {
+        if (doStateCheck) {
+            checkState();
+        }
 
         // Set because we don't want duplicates
         HashSet<String> result = new HashSet<>();
         for (ArrayList<WebResourceSet> list : allResources) {
             for (WebResourceSet webResourceSet : list) {
-                String[] entries = webResourceSet.list(path);
-                for (String entry : entries) {
-                    result.add(entry);
+                if (!webResourceSet.getClassLoaderOnly()) {
+                    String[] entries = webResourceSet.list(path);
+                    for (String entry : entries) {
+                        result.add(entry);
+                    }
                 }
             }
         }
@@ -116,7 +126,9 @@ public class StandardRoot extends Lifecy
         HashSet<String> result = new HashSet<>();
         for (ArrayList<WebResourceSet> list : allResources) {
             for (WebResourceSet webResourceSet : list) {
-                result.addAll(webResourceSet.listWebAppPaths(path));
+                if (!webResourceSet.getClassLoaderOnly()) {
+                    result.addAll(webResourceSet.listWebAppPaths(path));
+                }
             }
         }
         if (result.size() == 0) {
@@ -159,26 +171,46 @@ public class StandardRoot extends Lifecy
 
     @Override
     public WebResource getResource(String path) {
+        return getResource(path, true, false);
+    }
+
+    private WebResource getResource(String path, boolean doStateCheck,
+            boolean useClassLoaderResources) {
+        if (doStateCheck) {
+            checkState();
+        }
+
         if (isCachingAllowed()) {
-            return cache.getResource(path);
+            return cache.getResource(path, useClassLoaderResources);
         } else {
-            return getResourceInternal(path);
+            return getResourceInternal(path, useClassLoaderResources);
         }
     }
 
-    protected WebResource getResourceInternal(String path) {
-        checkState();
 
+    @Override
+    public WebResource getClassLoaderResource(String path) {
+        if (path == null || path.length() == 0 || !path.startsWith("/")) {
+            throw new IllegalArgumentException();
+        }
+        return getResource("/WEB-INF/classes" + path, true, true);
+    }
+
+
+    protected WebResource getResourceInternal(String path,
+            boolean useClassLoaderResources) {
         WebResource result = null;
         WebResource virtual = null;
         for (ArrayList<WebResourceSet> list : allResources) {
             for (WebResourceSet webResourceSet : list) {
-                result = webResourceSet.getResource(path);
-                if (result.exists()) {
-                    return result;
-                }
-                if (virtual == null && result.isVirtual()) {
-                    virtual = result;
+                if (useClassLoaderResources || !webResourceSet.getClassLoaderOnly()) {
+                    result = webResourceSet.getResource(path);
+                    if (result.exists()) {
+                        return result;
+                    }
+                    if (virtual == null && result.isVirtual()) {
+                        virtual = result;
+                    }
                 }
             }
         }
@@ -199,9 +231,11 @@ public class StandardRoot extends Lifecy
         ArrayList<WebResource> result = new ArrayList<>();
         for (ArrayList<WebResourceSet> list : allResources) {
             for (WebResourceSet webResourceSet : list) {
-                WebResource webResource = webResourceSet.getResource(path);
-                if (webResource.exists()) {
-                    result.add(webResource);
+                if (!webResourceSet.getClassLoaderOnly()) {
+                    WebResource webResource = webResourceSet.getResource(path);
+                    if (webResource.exists()) {
+                        result.add(webResource);
+                    }
                 }
             }
         }
@@ -215,15 +249,21 @@ public class StandardRoot extends Lifecy
 
     @Override
     public WebResource[] listResources(String path) {
-        checkState();
+        return listResources(path, true);
+    }
+
+    private WebResource[] listResources(String path, boolean doStateCheck) {
+        if (doStateCheck) {
+            checkState();
+        }
 
-        String[] resources = list(path);
+        String[] resources = list(path, false);
         WebResource[] result = new WebResource[resources.length];
         for (int i = 0; i < resources.length; i++) {
             if (path.charAt(path.length() - 1) == '/') {
-                result[i] = getResource(path + resources[i]);
+                result[i] = getResource(path + resources[i], false, false);
             } else {
-                result[i] = getResource(path + '/' + resources[i]);
+                result[i] = getResource(path + '/' + resources[i], false, false);
             }
         }
         return result;
@@ -248,6 +288,9 @@ public class StandardRoot extends Lifecy
             case PRE:
                 resourceList = preResources;
                 break;
+            case CLASSES_JAR:
+                resourceList = classResources;
+                break;
             case RESOURCE_JAR:
                 resourceList = jarResources;
                 break;
@@ -283,6 +326,10 @@ public class StandardRoot extends Lifecy
                     sm.getString("standardRoot.createInvalidFile", file));
         }
 
+        if (type.equals(ResourceSetType.CLASSES_JAR)) {
+            resourceSet.setClassLoaderOnly(true);
+        }
+
         resourceList.add(resourceSet);
     }
 
@@ -386,6 +433,28 @@ public class StandardRoot extends Lifecy
         }
     }
 
+    /*
+     * Class loader resources are handled by treating JARs in WEB-INF/lib as
+     * resource JARs (without the internal META-INF/resources/ prefix) mounted
+     * at WEB-INF/claasses (rather than the web app root). This enables reuse
+     * of the resource handling plumbing.
+     *
+     * These resources are marked as class loader only so they are only used in
+     * the methods that are explicitly defined to return class loader resources.
+     * This prevents calls to getResource("/WEB-INF/classes") returning from one
+     * or more of the JAR files.
+     */
+    private void processWebInfLib() {
+        WebResource[] possibleJars = listResources("/WEB-INF/lib", false);
+
+        for (WebResource possibleJar : possibleJars) {
+            if (possibleJar.isFile() && possibleJar.getName().endsWith(".jar")) {
+                createWebResourceSet(ResourceSetType.CLASSES_JAR,
+                        "/WEB-INF/classes", possibleJar.getURL(), "/");
+            }
+        }
+    }
+
     /**
      * For unit testing
      */
@@ -463,6 +532,14 @@ public class StandardRoot extends Lifecy
             }
         }
 
+        // This has to be called after the other resources have been started
+        // else it won't find all the matching resources
+        processWebInfLib();
+        // Need to start the newly found resources
+        for (WebResourceSet classResource : classResources) {
+            classResource.start();
+        }
+
         setState(LifecycleState.STARTING);
     }
 



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