From a6799306b032ba31b42af535044d2a1df96dc26a Mon Sep 17 00:00:00 2001 From: rjung Date: Thu, 22 Apr 2010 13:08:01 +0000 Subject: [PATCH] Add property "searchExternalFirst" to WebappLoader: 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 --- .../apache/catalina/loader/WebappClassLoader.java | 108 +++++++++++++++------ java/org/apache/catalina/loader/WebappLoader.java | 24 +++++ .../apache/catalina/loader/mbeans-descriptors.xml | 8 ++ webapps/docs/config/loader.xml | 6 ++ 4 files changed, 116 insertions(+), 30 deletions(-) diff --git a/java/org/apache/catalina/loader/WebappClassLoader.java b/java/org/apache/catalina/loader/WebappClassLoader.java index 2aee5422d..29197271c 100644 --- a/java/org/apache/catalina/loader/WebappClassLoader.java +++ b/java/org/apache/catalina/loader/WebappClassLoader.java @@ -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 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 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 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 otherResourcePaths = super.findResources(name); @@ -3178,4 +3227,3 @@ public class WebappClassLoader } - diff --git a/java/org/apache/catalina/loader/WebappLoader.java b/java/org/apache/catalina/loader/WebappLoader.java index bda7a70b9..aaaaea155 100644 --- a/java/org/apache/catalina/loader/WebappLoader.java +++ b/java/org/apache/catalina/loader/WebappLoader.java @@ -196,6 +196,12 @@ public class WebappLoader extends LifecycleBase private ArrayList 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()); diff --git a/java/org/apache/catalina/loader/mbeans-descriptors.xml b/java/org/apache/catalina/loader/mbeans-descriptors.xml index 606c9643f..2474f1f2f 100644 --- a/java/org/apache/catalina/loader/mbeans-descriptors.xml +++ b/java/org/apache/catalina/loader/mbeans-descriptors.xml @@ -38,6 +38,10 @@ description="The reloadable flag for this Loader" type="boolean"/> + + @@ -133,6 +137,10 @@ description="The antiJARLocking flag for this Loader" type="boolean"/> + + diff --git a/webapps/docs/config/loader.xml b/webapps/docs/config/loader.xml index 27fd0a3e0..19af2d3a3 100644 --- a/webapps/docs/config/loader.xml +++ b/webapps/docs/config/loader.xml @@ -130,6 +130,12 @@ org.apache.catalina.loader.WebappClassLoader.

+ +

Set to true if you want repositories outside + of WEB-INF/classes and WEB-INF/lib to + be searched first. Default value is false.

+
+ -- 2.11.0