Add property "searchExternalFirst" to WebappLoader:
authorrjung <rjung@13f79535-47bb-0310-9956-ffa450edef68>
Thu, 22 Apr 2010 13:08:01 +0000 (13:08 +0000)
committerrjung <rjung@13f79535-47bb-0310-9956-ffa450edef68>
Thu, 22 Apr 2010 13:08:01 +0000 (13:08 +0000)
if set the external repositories will be searched before
the WEB-INF ones. Default (false) is unchanged behaviour.
Expose the new property via JMX and document it..

git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@936823 13f79535-47bb-0310-9956-ffa450edef68

java/org/apache/catalina/loader/WebappClassLoader.java
java/org/apache/catalina/loader/WebappLoader.java
java/org/apache/catalina/loader/mbeans-descriptors.xml
webapps/docs/config/loader.xml

index 2aee542..2919727 100644 (file)
@@ -410,6 +410,11 @@ public class WebappClassLoader
     protected boolean hasExternalRepositories = false;
 
     /**
+     * Search external repositories first
+     */
+    protected boolean searchExternalFirst = false;
+
+    /**
      * need conversion for properties files
      */
     protected boolean needConvert = false;
@@ -535,7 +540,21 @@ public class WebappClassLoader
         this.antiJARLocking = antiJARLocking;
     }
 
-    
+    /**
+     * @return Returns the searchExternalFirst.
+     */
+    public boolean getSearchExternalFirst() {
+        return searchExternalFirst;
+    }
+
+    /**
+     * @param searchExternalFirst Whether external repositories should be searched first
+     */
+    public void setSearchExternalFirst(boolean searchExternalFirst) {
+        this.searchExternalFirst = searchExternalFirst;
+    }
+
+
     /**
      * If there is a Java SecurityManager create a read FilePermission
      * or JndiPermission for the file directory path.
@@ -1065,22 +1084,37 @@ public class WebappClassLoader
         try {
             if (log.isTraceEnabled())
                 log.trace("      findClassInternal(" + name + ")");
-            try {
-                clazz = findClassInternal(name);
-            } catch(ClassNotFoundException cnfe) {
-                if (!hasExternalRepositories) {
-                    throw cnfe;
+            if (hasExternalRepositories && searchExternalFirst) {
+                try {
+                    clazz = super.findClass(name);
+                } catch(AccessControlException ace) {
+                    log.warn("WebappClassLoader.findClassInternal(" + name
+                            + ") security exception: " + ace.getMessage(), ace);
+                    throw new ClassNotFoundException(name, ace);
+                } catch (RuntimeException e) {
+                    if (log.isTraceEnabled())
+                        log.trace("      -->RuntimeException Rethrown", e);
+                    throw e;
                 }
-            } catch(AccessControlException ace) {
-                log.warn("WebappClassLoader.findClassInternal(" + name
-                        + ") security exception: " + ace.getMessage(), ace);
-                throw new ClassNotFoundException(name, ace);
-            } catch (RuntimeException e) {
-                if (log.isTraceEnabled())
-                    log.trace("      -->RuntimeException Rethrown", e);
-                throw e;
-            }
-            if ((clazz == null) && hasExternalRepositories) {
+            }
+            if ((clazz == null)) {
+                try {
+                    clazz = findClassInternal(name);
+                } catch(ClassNotFoundException cnfe) {
+                    if (!hasExternalRepositories || searchExternalFirst) {
+                        throw cnfe;
+                    }
+                } catch(AccessControlException ace) {
+                    log.warn("WebappClassLoader.findClassInternal(" + name
+                            + ") security exception: " + ace.getMessage(), ace);
+                    throw new ClassNotFoundException(name, ace);
+                } catch (RuntimeException e) {
+                    if (log.isTraceEnabled())
+                        log.trace("      -->RuntimeException Rethrown", e);
+                    throw e;
+                }
+            }
+            if ((clazz == null) && hasExternalRepositories && !searchExternalFirst) {
                 try {
                     clazz = super.findClass(name);
                 } catch(AccessControlException ace) {
@@ -1138,21 +1172,26 @@ public class WebappClassLoader
 
         URL url = null;
 
-        ResourceEntry entry = resourceEntries.get(name);
-        if (entry == null) {
-            if (securityManager != null) {
-                PrivilegedAction<ResourceEntry> dp =
-                    new PrivilegedFindResourceByName(name, name);
-                entry = AccessController.doPrivileged(dp);
-            } else {
-                entry = findResourceInternal(name, name);
+        if (hasExternalRepositories && searchExternalFirst)
+            url = super.findResource(name);
+
+        if (url == null) {
+            ResourceEntry entry = resourceEntries.get(name);
+            if (entry == null) {
+                if (securityManager != null) {
+                    PrivilegedAction<ResourceEntry> dp =
+                        new PrivilegedFindResourceByName(name, name);
+                    entry = AccessController.doPrivileged(dp);
+                } else {
+                    entry = findResourceInternal(name, name);
+                }
+            }
+            if (entry != null) {
+                url = entry.source;
             }
-        }
-        if (entry != null) {
-            url = entry.source;
         }
 
-        if ((url == null) && hasExternalRepositories)
+        if ((url == null) && hasExternalRepositories && !searchExternalFirst)
             url = super.findResource(name);
 
         if (log.isDebugEnabled()) {
@@ -1188,6 +1227,16 @@ public class WebappClassLoader
 
         int i;
 
+        // Adding the results of a call to the superclass
+        if (hasExternalRepositories && searchExternalFirst) {
+
+            Enumeration<URL> otherResourcePaths = super.findResources(name);
+
+            while (otherResourcePaths.hasMoreElements()) {
+                result.addElement(otherResourcePaths.nextElement());
+            }
+
+        }
         // Looking at the repositories
         for (i = 0; i < repositoriesLength; i++) {
             try {
@@ -1223,7 +1272,7 @@ public class WebappClassLoader
         }
 
         // Adding the results of a call to the superclass
-        if (hasExternalRepositories) {
+        if (hasExternalRepositories && !searchExternalFirst) {
 
             Enumeration<URL> otherResourcePaths = super.findResources(name);
 
@@ -3178,4 +3227,3 @@ public class WebappClassLoader
 
 
 }
-
index bda7a70..aaaaea1 100644 (file)
@@ -196,6 +196,12 @@ public class WebappLoader extends LifecycleBase
     private ArrayList<String> loaderRepositories = null;
 
 
+    /**
+     * Whether we should search the external repositories first
+     */
+    private boolean searchExternalFirst = false;
+
+
     // ------------------------------------------------------------- Properties
 
 
@@ -331,6 +337,23 @@ public class WebappLoader extends LifecycleBase
 
     }
 
+    /**
+     * @return Returns searchExternalFirst.
+     */
+    public boolean getSearchExternalFirst() {
+        return searchExternalFirst;
+    }
+
+    /**
+     * @param searchExternalFirst Whether external repositories should be searched first
+     */
+    public void setSearchExternalFirst(boolean searchExternalFirst) {
+        this.searchExternalFirst = searchExternalFirst;
+        if (classLoader != null) {
+            classLoader.setSearchExternalFirst(searchExternalFirst);
+        }
+    }
+
 
     // --------------------------------------------------------- Public Methods
 
@@ -589,6 +612,7 @@ public class WebappLoader extends LifecycleBase
             classLoader = createClassLoader();
             classLoader.setResources(container.getResources());
             classLoader.setDelegate(this.delegate);
+            classLoader.setSearchExternalFirst(searchExternalFirst);
             if (container instanceof StandardContext) {
                 classLoader.setAntiJARLocking(
                         ((StandardContext) container).getAntiJARLocking());
index 606c964..2474f1f 100644 (file)
           description="The reloadable flag for this Loader"
                  type="boolean"/>
 
+    <attribute   name="searchExternalFirst"
+          description="The searchExternalFirst flag for this Loader"
+                 type="boolean"/>
+
     <attribute   name="repositories"
           description="Extra repositories managed by this loader"
                  type="[Ljava.lang.String;"/>
           description="The antiJARLocking flag for this Loader"
                  type="boolean"/>
 
+    <attribute   name="searchExternalFirst"
+          description="The searchExternalFirst flag for this Loader"
+                 type="boolean"/>
+
     <attribute   name="uRLs"
           description="The URLs of this loader"
                  type="[Ljava.net.URL;"/>
index 27fd0a3..19af2d3 100644 (file)
         <code>org.apache.catalina.loader.WebappClassLoader</code>.</p>
       </attribute>
 
+      <attribute name="searchExternalFirst" required="false">
+        <p>Set to <code>true</code> if you want repositories outside
+        of <code>WEB-INF/classes</code> and <code>WEB-INF/lib</code> to
+        be searched first. Default value is <code>false</code>.</p>
+      </attribute>
+
     </attributes>
 
   </subsection>