You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@geronimo.apache.org by Donald Woods <dr...@yahoo.com> on 2007/03/29 15:58:16 UTC
Re: svn commit: r518426 - in /geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel:
classloader/ config/
David, the below change to IOUtil.java -
- return Collections.singleton(match.toURL());
+ return Collections.singleton(match.toURI().normalize().toURL());
looks like it is causing the G3016 reported failure, that the server
will no longer start on Windows when there is a white space in the
GERONIMO_HOME path.
Was there some reason we need to normalize the URI before its converted
to a URL?
-Donald
djencks@apache.org wrote:
> Author: djencks
> Date: Wed Mar 14 18:22:56 2007
> New Revision: 518426
>
> URL: http://svn.apache.org/viewvc?view=rev&rev=518426
> Log:
> GERONIMO-2693 eliminate most duplicate entries from getResources. This should also produce only normailized urls. This should make jetty start quickly
>
> Modified:
> geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/classloader/JarFileClassLoader.java
> geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/classloader/UnionEnumeration.java
> geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/classloader/UrlResourceFinder.java
> geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/config/IOUtil.java
> geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/config/MultiParentClassLoader.java
>
> Modified: geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/classloader/JarFileClassLoader.java
> URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/classloader/JarFileClassLoader.java?view=diff&rev=518426&r1=518425&r2=518426
> ==============================================================================
> --- geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/classloader/JarFileClassLoader.java (original)
> +++ geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/classloader/JarFileClassLoader.java Wed Mar 14 18:22:56 2007
> @@ -184,6 +184,7 @@
> /**
> * {@inheritDoc}
> */
> +/*
> public Enumeration findResources(final String resourceName) throws IOException {
> // todo this is not right
> // first get the resources from the parent classloaders
> @@ -199,6 +200,15 @@
> // join the two together
> Enumeration resources = new UnionEnumeration(parentResources, myResources);
> return resources;
> + }
> +*/
> +
> + protected Enumeration<URL> internalfindResources(final String name) throws IOException {
> + return AccessController.doPrivileged(new PrivilegedAction<Enumeration<URL>>() {
> + public Enumeration<URL> run() {
> + return resourceFinder.findResources(name);
> + }
> + }, acc);
> }
>
> /**
>
> Modified: geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/classloader/UnionEnumeration.java
> URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/classloader/UnionEnumeration.java?view=diff&rev=518426&r1=518425&r2=518426
> ==============================================================================
> --- geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/classloader/UnionEnumeration.java (original)
> +++ geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/classloader/UnionEnumeration.java Wed Mar 14 18:22:56 2007
> @@ -24,14 +24,14 @@
> /**
> * @version $Rev$ $Date$
> */
> -public final class UnionEnumeration implements Enumeration {
> - private final LinkedList enumerations = new LinkedList();
> +public final class UnionEnumeration<T> implements Enumeration<T> {
> + private final LinkedList<Enumeration<T>> enumerations = new LinkedList<Enumeration<T>>();
>
> - public UnionEnumeration(List enumerations) {
> + public UnionEnumeration(List<Enumeration<T>> enumerations) {
> this.enumerations.addAll(enumerations);
> }
>
> - public UnionEnumeration(Enumeration first, Enumeration second) {
> + public UnionEnumeration(Enumeration<T> first, Enumeration<T> second) {
> if (first == null) throw new NullPointerException("first is null");
> if (second == null) throw new NullPointerException("second is null");
>
> @@ -41,7 +41,7 @@
>
> public boolean hasMoreElements() {
> while (!enumerations.isEmpty()) {
> - Enumeration enumeration = (Enumeration) enumerations.getFirst();
> + Enumeration enumeration = enumerations.getFirst();
> if (enumeration.hasMoreElements()) {
> return true;
> }
> @@ -50,9 +50,9 @@
> return false;
> }
>
> - public Object nextElement() {
> + public T nextElement() {
> while (!enumerations.isEmpty()) {
> - Enumeration enumeration = (Enumeration) enumerations.getFirst();
> + Enumeration<T> enumeration = enumerations.getFirst();
> if (enumeration.hasMoreElements()) {
> return enumeration.nextElement();
> }
>
> Modified: geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/classloader/UrlResourceFinder.java
> URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/classloader/UrlResourceFinder.java?view=diff&rev=518426&r1=518425&r2=518426
> ==============================================================================
> --- geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/classloader/UrlResourceFinder.java (original)
> +++ geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/classloader/UrlResourceFinder.java Wed Mar 14 18:22:56 2007
> @@ -25,7 +25,6 @@
> import java.util.Arrays;
> import java.util.Collections;
> import java.util.Enumeration;
> -import java.util.Iterator;
> import java.util.LinkedHashMap;
> import java.util.LinkedHashSet;
> import java.util.LinkedList;
> @@ -41,9 +40,9 @@
> public class UrlResourceFinder implements ResourceFinder {
> private final Object lock = new Object();
>
> - private final LinkedHashSet urls = new LinkedHashSet();
> - private final LinkedHashMap classPath = new LinkedHashMap();
> - private final LinkedHashSet watchedFiles = new LinkedHashSet();
> + private final LinkedHashSet<URL> urls = new LinkedHashSet<URL>();
> + private final LinkedHashMap<URL,ResourceLocation> classPath = new LinkedHashMap<URL,ResourceLocation>();
> + private final LinkedHashSet<File> watchedFiles = new LinkedHashSet<File>();
>
> private boolean destroyed = false;
>
> @@ -61,8 +60,7 @@
> }
> destroyed = true;
> urls.clear();
> - for (Iterator iterator = classPath.values().iterator(); iterator.hasNext();) {
> - ResourceLocation resourceLocation = (ResourceLocation) iterator.next();
> + for (ResourceLocation resourceLocation : classPath.values()) {
> resourceLocation.close();
> }
> classPath.clear();
> @@ -74,9 +72,8 @@
> if (destroyed) {
> return null;
> }
> - for (Iterator iterator = getClassPath().entrySet().iterator(); iterator.hasNext();) {
> - Map.Entry entry = (Map.Entry) iterator.next();
> - ResourceLocation resourceLocation = (ResourceLocation) entry.getValue();
> + for (Map.Entry<URL, ResourceLocation> entry : getClassPath().entrySet()) {
> + ResourceLocation resourceLocation = entry.getValue();
> ResourceHandle resourceHandle = resourceLocation.getResourceHandle(resourceName);
> if (resourceHandle != null && !resourceHandle.isDirectory()) {
> return resourceHandle;
> @@ -91,9 +88,8 @@
> if (destroyed) {
> return null;
> }
> - for (Iterator iterator = getClassPath().entrySet().iterator(); iterator.hasNext();) {
> - Map.Entry entry = (Map.Entry) iterator.next();
> - ResourceLocation resourceLocation = (ResourceLocation) entry.getValue();
> + for (Map.Entry<URL, ResourceLocation> entry : getClassPath().entrySet()) {
> + ResourceLocation resourceLocation = entry.getValue();
> ResourceHandle resourceHandle = resourceLocation.getResourceHandle(resourceName);
> if (resourceHandle != null) {
> return resourceHandle.getUrl();
> @@ -105,7 +101,7 @@
>
> public Enumeration findResources(String resourceName) {
> synchronized (lock) {
> - return new ResourceEnumeration(new ArrayList(getClassPath().values()), resourceName);
> + return new ResourceEnumeration(new ArrayList<ResourceLocation>(getClassPath().values()), resourceName);
> }
> }
>
> @@ -115,7 +111,7 @@
>
> public URL[] getUrls() {
> synchronized (lock) {
> - return (URL[]) urls.toArray(new URL[urls.size()]);
> + return urls.toArray(new URL[urls.size()]);
> }
> }
>
> @@ -131,7 +127,7 @@
> * Adds a list of urls to the end of this class loader.
> * @param urls the URLs to add
> */
> - protected void addUrls(List urls) {
> + protected void addUrls(List<URL> urls) {
> synchronized (lock) {
> if (destroyed) {
> throw new IllegalStateException("UrlResourceFinder has been destroyed");
> @@ -144,11 +140,10 @@
> }
> }
>
> - private LinkedHashMap getClassPath() {
> + private LinkedHashMap<URL, ResourceLocation> getClassPath() {
> assert Thread.holdsLock(lock): "This method can only be called while holding the lock";
>
> - for (Iterator iterator = watchedFiles.iterator(); iterator.hasNext();) {
> - File file = (File) iterator.next();
> + for (File file : watchedFiles) {
> if (file.canRead()) {
> rebuildClassPath();
> break;
> @@ -167,21 +162,21 @@
> assert Thread.holdsLock(lock): "This method can only be called while holding the lock";
>
> // copy all of the existing locations into a temp map and clear the class path
> - Map existingJarFiles = new LinkedHashMap(classPath);
> + Map<URL,ResourceLocation> existingJarFiles = new LinkedHashMap<URL,ResourceLocation>(classPath);
> classPath.clear();
>
> - LinkedList locationStack = new LinkedList(urls);
> + LinkedList<URL> locationStack = new LinkedList<URL>(urls);
> try {
> while (!locationStack.isEmpty()) {
> - URL url = (URL) locationStack.removeFirst();
> + URL url = locationStack.removeFirst();
>
> - // Skip any duplicate urls in the claspath
> + // Skip any duplicate urls in the classpath
> if (classPath.containsKey(url)) {
> continue;
> }
>
> // Check is this URL has already been opened
> - ResourceLocation resourceLocation = (ResourceLocation) existingJarFiles.remove(url);
> + ResourceLocation resourceLocation = existingJarFiles.remove(url);
>
> // If not opened, cache the url and wrap it with a resource location
> if (resourceLocation == null) {
> @@ -208,7 +203,7 @@
> classPath.put(resourceLocation.getCodeSource(), resourceLocation);
>
> // push the manifest classpath on the stack (make sure to maintain the order)
> - List manifestClassPath = getManifestClassPath(resourceLocation);
> + List<URL> manifestClassPath = getManifestClassPath(resourceLocation);
> locationStack.addAll(0, manifestClassPath);
> }
> } catch (Error e) {
> @@ -216,8 +211,7 @@
> throw e;
> }
>
> - for (Iterator iterator = existingJarFiles.values().iterator(); iterator.hasNext();) {
> - ResourceLocation resourceLocation = (ResourceLocation) iterator.next();
> + for (ResourceLocation resourceLocation : existingJarFiles.values()) {
> resourceLocation.close();
> }
> }
> @@ -246,7 +240,7 @@
> throw new IOException("File is not readable: " + cacheFile.getAbsolutePath());
> }
>
> - ResourceLocation resourceLocation = null;
> + ResourceLocation resourceLocation;
> if (cacheFile.isDirectory()) {
> // DirectoryResourceLocation will only return "file" URLs within this directory
> // do not user the DirectoryResourceLocation for non file based urls
> @@ -257,7 +251,7 @@
> return resourceLocation;
> }
>
> - private List getManifestClassPath(ResourceLocation resourceLocation) {
> + private List<URL> getManifestClassPath(ResourceLocation resourceLocation) {
> try {
> // get the manifest, if possible
> Manifest manifest = resourceLocation.getManifest();
> @@ -275,7 +269,7 @@
> // build the urls...
> // the class-path attribute is space delimited
> URL codeSource = resourceLocation.getCodeSource();
> - LinkedList classPathUrls = new LinkedList();
> + LinkedList<URL> classPathUrls = new LinkedList<URL>();
> for (StringTokenizer tokenizer = new StringTokenizer(manifestClassPath, " "); tokenizer.hasMoreTokens();) {
> String entry = tokenizer.nextToken();
> try {
>
> Modified: geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/config/IOUtil.java
> URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/config/IOUtil.java?view=diff&rev=518426&r1=518425&r2=518426
> ==============================================================================
> --- geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/config/IOUtil.java (original)
> +++ geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/config/IOUtil.java Wed Mar 14 18:22:56 2007
> @@ -189,7 +189,7 @@
> if (!SelectorUtils.hasWildcards(pattern)) {
> File match = new File(root, pattern);
> if (match.exists() && match.canRead()) {
> - return Collections.singleton(match.toURL());
> + return Collections.singleton(match.toURI().normalize().toURL());
> } else {
> return Collections.EMPTY_SET;
> }
> @@ -201,7 +201,7 @@
> String fileName = (String) entry.getKey();
> if (SelectorUtils.matchPath(pattern, fileName)) {
> File file = (File) entry.getValue();
> - matches.add(file.toURL());
> + matches.add(file.toURI().normalize().toURL());
> }
> }
> return matches;
>
> Modified: geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/config/MultiParentClassLoader.java
> URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/config/MultiParentClassLoader.java?view=diff&rev=518426&r1=518425&r2=518426
> ==============================================================================
> --- geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/config/MultiParentClassLoader.java (original)
> +++ geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/config/MultiParentClassLoader.java Wed Mar 14 18:22:56 2007
> @@ -29,10 +29,13 @@
> import java.util.Collection;
> import java.util.Collections;
> import java.util.Enumeration;
> +import java.util.HashSet;
> import java.util.List;
> import java.util.Map;
> +import java.util.Set;
>
> import org.apache.commons.logging.LogFactory;
> +import org.apache.geronimo.kernel.classloader.UnionEnumeration;
> import org.apache.geronimo.kernel.repository.Artifact;
> import org.apache.geronimo.kernel.util.ClassLoaderRegistry;
>
> @@ -145,7 +148,7 @@
> if (source instanceof MultiParentClassLoader) {
> return new MultiParentClassLoader((MultiParentClassLoader) source);
> } else if (source instanceof URLClassLoader) {
> - return new URLClassLoader(((URLClassLoader)source).getURLs(), source.getParent());
> + return new URLClassLoader(((URLClassLoader) source).getURLs(), source.getParent());
> } else {
> return new URLClassLoader(new URL[0], source);
> }
> @@ -175,7 +178,7 @@
> */
> public MultiParentClassLoader(Artifact id, URL[] urls, ClassLoader[] parents, URLStreamHandlerFactory factory) {
> super(urls, null, factory);
> - this.id = id;
> + this.id = id;
> this.parents = copyParents(parents);
> inverseClassLoading = false;
> hiddenClasses = new String[0];
> @@ -205,7 +208,7 @@
> throw new NullPointerException("parent[" + i + "] is null");
> }
> if (parent instanceof MultiParentClassLoader) {
> - parent = ((MultiParentClassLoader)parent).copy();
> + parent = ((MultiParentClassLoader) parent).copy();
> }
> newParentsArray[i] = parent;
> }
> @@ -243,23 +246,23 @@
> if (cachedClass != null) {
> return resolveClass(cachedClass, resolve);
> }
> -
> +
> // This is a reasonable hack. We can add some classes to the list below.
> // Since we know these classes are in the system class loader let's not waste our
> // time going through the hierarchy.
> //
> // The order is based on profiling the server. It may not be optimal for all
> // workloads.
> -
> - if ( name.startsWith("java.") ||
> - name.equals("boolean") ||
> - name.equals("int") ||
> - name.equals("double") ||
> - name.equals("long")) {
> +
> + if (name.startsWith("java.") ||
> + name.equals("boolean") ||
> + name.equals("int") ||
> + name.equals("double") ||
> + name.equals("long")) {
> Class clazz = ClassLoader.getSystemClassLoader().loadClass(name);
> return resolveClass(clazz, resolve);
> }
> -
> +
> //
> // if we are using inverse class loading, check local urls first
> //
> @@ -275,8 +278,7 @@
> // Check parent class loaders
> //
> if (!isHiddenClass(name)) {
> - for (int i = 0; i < parents.length; i++) {
> - ClassLoader parent = parents[i];
> + for (ClassLoader parent : parents) {
> try {
> Class clazz = parent.loadClass(name);
> return resolveClass(clazz, resolve);
> @@ -304,8 +306,8 @@
> }
>
> private boolean isNonOverridableClass(String name) {
> - for (int i = 0; i < nonOverridableClasses.length; i++) {
> - if (name.startsWith(nonOverridableClasses[i])) {
> + for (String nonOverridableClass : nonOverridableClasses) {
> + if (name.startsWith(nonOverridableClass)) {
> return true;
> }
> }
> @@ -313,8 +315,8 @@
> }
>
> private boolean isHiddenClass(String name) {
> - for (int i = 0; i < hiddenClasses.length; i++) {
> - if (name.startsWith(hiddenClasses[i])) {
> + for (String hiddenClass : hiddenClasses) {
> + if (name.startsWith(hiddenClass)) {
> return true;
> }
> }
> @@ -347,8 +349,7 @@
> // Check parent class loaders
> //
> if (!isHiddenResource(name)) {
> - for (int i = 0; i < parents.length; i++) {
> - ClassLoader parent = parents[i];
> + for (ClassLoader parent : parents) {
> URL url = parent.getResource(name);
> if (url != null) {
> return url;
> @@ -370,44 +371,94 @@
> return null;
> }
>
> - public Enumeration findResources(String name) throws IOException {
> + public Enumeration<URL> findResources(String name) throws IOException {
> if (isDestroyed()) {
> return Collections.enumeration(Collections.EMPTY_SET);
> }
>
> - List resources = new ArrayList();
> + Set<ClassLoader> knownClassloaders = new HashSet<ClassLoader>();
> + List<Enumeration<URL>> enumerations = new ArrayList<Enumeration<URL>>();
>
> - //
> - // if we are using inverse class loading, add the resources from local urls first
> - //
> - if (inverseClassLoading && !isDestroyed()) {
> - List myResources = Collections.list(super.findResources(name));
> - resources.addAll(myResources);
> - }
> + recursiveFind(knownClassloaders, enumerations, name);
>
> - //
> - // Add parent resources
> - //
> - for (int i = 0; i < parents.length; i++) {
> - ClassLoader parent = parents[i];
> - List parentResources = Collections.list(parent.getResources(name));
> - resources.addAll(parentResources);
> + return new UnionEnumeration<URL>(enumerations);
> + /*
> + List<URL> resources = new ArrayList<URL>();
> + Set<URL> found = new HashSet<URL>();
> +
> + //
> + // if we are using inverse class loading, add the resources from local urls first
> + //
> + if (inverseClassLoading && !isDestroyed()) {
> + for (Enumeration myResources = super.findResources(name); myResources.hasMoreElements();) {
> + URL url = (URL) myResources.nextElement();
> + if (!found.contains(url)) {
> + found.add(url);
> + resources.add(url);
> + }
> + }
> + }
> +
> + //
> + // Add parent resources
> + //
> + for (ClassLoader parent : parents) {
> + for (Enumeration parentResources = parent.getResources(name); parentResources.hasMoreElements();) {
> + URL url = (URL) parentResources.nextElement();
> + if (!found.contains(url)) {
> + found.add(url);
> + resources.add(url);
> + }
> + }
> + }
> +
> + //
> + // if we are not using inverse class loading, add the resources from local urls now
> + //
> + if (!inverseClassLoading && !isDestroyed()) {
> + for (Enumeration myResources = super.findResources(name); myResources.hasMoreElements();) {
> + URL url = (URL) myResources.nextElement();
> + if (!found.contains(url)) {
> + found.add(url);
> + resources.add(url);
> + }
> + }
> + }
> +
> + return Collections.enumeration(resources);
> + */
> + }
> +
> + protected void recursiveFind(Set<ClassLoader> knownClassloaders, List<Enumeration<URL>> enumerations, String name) throws IOException {
> + if (isDestroyed() || knownClassloaders.contains(this)) {
> + return;
> + }
> + knownClassloaders.add(this);
> + if (inverseClassLoading) {
> + enumerations.add(internalfindResources(name));
> }
> -
> - //
> - // if we are not using inverse class loading, add the resources from local urls now
> - //
> - if (!inverseClassLoading && !isDestroyed()) {
> - List myResources = Collections.list(super.findResources(name));
> - resources.addAll(myResources);
> + for (ClassLoader parent : parents) {
> + if (parent instanceof MultiParentClassLoader) {
> + ((MultiParentClassLoader) parent).recursiveFind(knownClassloaders, enumerations, name);
> + } else {
> + if (!knownClassloaders.contains(parent)) {
> + enumerations.add(parent.getResources(name));
> + knownClassloaders.add(parent);
> + }
> + }
> + }
> + if (!inverseClassLoading) {
> + enumerations.add(internalfindResources(name));
> }
> + }
>
> - return Collections.enumeration(resources);
> + protected Enumeration<URL> internalfindResources(String name) throws IOException {
> + return super.findResources(name);
> }
>
> private boolean isNonOverridableResource(String name) {
> - for (int i = 0; i < nonOverridableResources.length; i++) {
> - if (name.startsWith(nonOverridableResources[i])) {
> + for (String nonOverridableResource : nonOverridableResources) {
> + if (name.startsWith(nonOverridableResource)) {
> return true;
> }
> }
> @@ -415,8 +466,8 @@
> }
>
> private boolean isHiddenResource(String name) {
> - for (int i = 0; i < hiddenResources.length; i++) {
> - if (name.startsWith(hiddenResources[i])) {
> + for (String hiddenResource : hiddenResources) {
> + if (name.startsWith(hiddenResource)) {
> return true;
> }
> }
> @@ -432,7 +483,7 @@
> }
>
> public void destroy() {
> - synchronized(this) {
> + synchronized (this) {
> if (destroyed) return;
> destroyed = true;
> }
> @@ -447,7 +498,7 @@
> // it has introspected. If we don't flush the cache, we may run out of
> // Permanent Generation space.
> Introspector.flushCaches();
> -
> +
> ClassLoaderRegistry.remove(this);
> }
>
> @@ -475,8 +526,10 @@
> }
> }
> }
> - protected void finalize(){
> +
> + protected void finalize() throws Throwable {
> ClassLoaderRegistry.remove(this);
> + super.finalize();
> }
>
> }
>
>
>
>
Re: svn commit: r518426 - in /geronimo/server/trunk/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel: classloader/ config/
Posted by David Jencks <da...@yahoo.com>.
On Mar 29, 2007, at 6:58 AM, Donald Woods wrote:
> David, the below change to IOUtil.java -
> - return Collections.singleton(match.toURL());
> + return Collections.singleton(match.toURI().normalize().toURL
> ());
> looks like it is causing the G3016 reported failure, that the
> server will no longer start on Windows when there is a white space
> in the GERONIMO_HOME path.
>
> Was there some reason we need to normalize the URI before its
> converted to a URL?
The problem I was trying to solve is that if you have manifest
classpatch entries in a war in an ear (that refer to stuff outside
the war, in the ear), and you try webClassLoader.getResources("/META-
INF") you get a lot of copies of urls from those mcp jars , except
most of them aren't normailzed..... <pathToEar>/myWebApp.war/../
lib/foo/foo.jar!/META-INF but some of them are.
This confuses a bunch of other apps that expect that if there are
duplicate URLS, they have the same path.
This is the main complaint in GERONIMO-2693
Can you figure out something that works for both problems at once?
thanks
david jencks
>
> -Donald
>
>
> djencks@apache.org wrote:
>> Author: djencks
>> Date: Wed Mar 14 18:22:56 2007
>> New Revision: 518426
>> URL: http://svn.apache.org/viewvc?view=rev&rev=518426
>> Log:
>> GERONIMO-2693 eliminate most duplicate entries from getResources.
>> This should also produce only normailized urls. This should make
>> jetty start quickly
>> Modified:
>> geronimo/server/trunk/modules/geronimo-kernel/src/main/java/
>> org/apache/geronimo/kernel/classloader/JarFileClassLoader.java
>> geronimo/server/trunk/modules/geronimo-kernel/src/main/java/
>> org/apache/geronimo/kernel/classloader/UnionEnumeration.java
>> geronimo/server/trunk/modules/geronimo-kernel/src/main/java/
>> org/apache/geronimo/kernel/classloader/UrlResourceFinder.java
>> geronimo/server/trunk/modules/geronimo-kernel/src/main/java/
>> org/apache/geronimo/kernel/config/IOUtil.java
>> geronimo/server/trunk/modules/geronimo-kernel/src/main/java/
>> org/apache/geronimo/kernel/config/MultiParentClassLoader.java
>> Modified: geronimo/server/trunk/modules/geronimo-kernel/src/main/
>> java/org/apache/geronimo/kernel/classloader/JarFileClassLoader.java
>> URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/
>> geronimo-kernel/src/main/java/org/apache/geronimo/kernel/
>> classloader/JarFileClassLoader.java?
>> view=diff&rev=518426&r1=518425&r2=518426
>> =====================================================================
>> =========
>> --- geronimo/server/trunk/modules/geronimo-kernel/src/main/java/
>> org/apache/geronimo/kernel/classloader/JarFileClassLoader.java
>> (original)
>> +++ geronimo/server/trunk/modules/geronimo-kernel/src/main/java/
>> org/apache/geronimo/kernel/classloader/JarFileClassLoader.java Wed
>> Mar 14 18:22:56 2007
>> @@ -184,6 +184,7 @@
>> /**
>> * {@inheritDoc}
>> */
>> +/*
>> public Enumeration findResources(final String resourceName)
>> throws IOException {
>> // todo this is not right
>> // first get the resources from the parent classloaders
>> @@ -199,6 +200,15 @@
>> // join the two together
>> Enumeration resources = new UnionEnumeration
>> (parentResources, myResources);
>> return resources;
>> + }
>> +*/
>> +
>> + protected Enumeration<URL> internalfindResources(final String
>> name) throws IOException {
>> + return AccessController.doPrivileged(new
>> PrivilegedAction<Enumeration<URL>>() {
>> + public Enumeration<URL> run() {
>> + return resourceFinder.findResources(name);
>> + }
>> + }, acc);
>> }
>> /**
>> Modified: geronimo/server/trunk/modules/geronimo-kernel/src/main/
>> java/org/apache/geronimo/kernel/classloader/UnionEnumeration.java
>> URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/
>> geronimo-kernel/src/main/java/org/apache/geronimo/kernel/
>> classloader/UnionEnumeration.java?
>> view=diff&rev=518426&r1=518425&r2=518426
>> =====================================================================
>> =========
>> --- geronimo/server/trunk/modules/geronimo-kernel/src/main/java/
>> org/apache/geronimo/kernel/classloader/UnionEnumeration.java
>> (original)
>> +++ geronimo/server/trunk/modules/geronimo-kernel/src/main/java/
>> org/apache/geronimo/kernel/classloader/UnionEnumeration.java Wed
>> Mar 14 18:22:56 2007
>> @@ -24,14 +24,14 @@
>> /**
>> * @version $Rev$ $Date$
>> */
>> -public final class UnionEnumeration implements Enumeration {
>> - private final LinkedList enumerations = new LinkedList();
>> +public final class UnionEnumeration<T> implements Enumeration<T> {
>> + private final LinkedList<Enumeration<T>> enumerations = new
>> LinkedList<Enumeration<T>>();
>> - public UnionEnumeration(List enumerations) {
>> + public UnionEnumeration(List<Enumeration<T>> enumerations) {
>> this.enumerations.addAll(enumerations);
>> }
>> - public UnionEnumeration(Enumeration first, Enumeration
>> second) {
>> + public UnionEnumeration(Enumeration<T> first, Enumeration<T>
>> second) {
>> if (first == null) throw new NullPointerException("first
>> is null");
>> if (second == null) throw new NullPointerException
>> ("second is null");
>> @@ -41,7 +41,7 @@
>> public boolean hasMoreElements() {
>> while (!enumerations.isEmpty()) {
>> - Enumeration enumeration = (Enumeration)
>> enumerations.getFirst();
>> + Enumeration enumeration = enumerations.getFirst();
>> if (enumeration.hasMoreElements()) {
>> return true;
>> }
>> @@ -50,9 +50,9 @@
>> return false;
>> }
>> - public Object nextElement() {
>> + public T nextElement() {
>> while (!enumerations.isEmpty()) {
>> - Enumeration enumeration = (Enumeration)
>> enumerations.getFirst();
>> + Enumeration<T> enumeration = enumerations.getFirst();
>> if (enumeration.hasMoreElements()) {
>> return enumeration.nextElement();
>> }
>> Modified: geronimo/server/trunk/modules/geronimo-kernel/src/main/
>> java/org/apache/geronimo/kernel/classloader/UrlResourceFinder.java
>> URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/
>> geronimo-kernel/src/main/java/org/apache/geronimo/kernel/
>> classloader/UrlResourceFinder.java?
>> view=diff&rev=518426&r1=518425&r2=518426
>> =====================================================================
>> =========
>> --- geronimo/server/trunk/modules/geronimo-kernel/src/main/java/
>> org/apache/geronimo/kernel/classloader/UrlResourceFinder.java
>> (original)
>> +++ geronimo/server/trunk/modules/geronimo-kernel/src/main/java/
>> org/apache/geronimo/kernel/classloader/UrlResourceFinder.java Wed
>> Mar 14 18:22:56 2007
>> @@ -25,7 +25,6 @@
>> import java.util.Arrays;
>> import java.util.Collections;
>> import java.util.Enumeration;
>> -import java.util.Iterator;
>> import java.util.LinkedHashMap;
>> import java.util.LinkedHashSet;
>> import java.util.LinkedList;
>> @@ -41,9 +40,9 @@
>> public class UrlResourceFinder implements ResourceFinder {
>> private final Object lock = new Object();
>> - private final LinkedHashSet urls = new LinkedHashSet();
>> - private final LinkedHashMap classPath = new LinkedHashMap();
>> - private final LinkedHashSet watchedFiles = new LinkedHashSet();
>> + private final LinkedHashSet<URL> urls = new LinkedHashSet<URL>
>> ();
>> + private final LinkedHashMap<URL,ResourceLocation> classPath =
>> new LinkedHashMap<URL,ResourceLocation>();
>> + private final LinkedHashSet<File> watchedFiles = new
>> LinkedHashSet<File>();
>> private boolean destroyed = false;
>> @@ -61,8 +60,7 @@
>> }
>> destroyed = true;
>> urls.clear();
>> - for (Iterator iterator = classPath.values().iterator
>> (); iterator.hasNext();) {
>> - ResourceLocation resourceLocation =
>> (ResourceLocation) iterator.next();
>> + for (ResourceLocation resourceLocation :
>> classPath.values()) {
>> resourceLocation.close();
>> }
>> classPath.clear();
>> @@ -74,9 +72,8 @@
>> if (destroyed) {
>> return null;
>> }
>> - for (Iterator iterator = getClassPath().entrySet
>> ().iterator(); iterator.hasNext();) {
>> - Map.Entry entry = (Map.Entry) iterator.next();
>> - ResourceLocation resourceLocation =
>> (ResourceLocation) entry.getValue();
>> + for (Map.Entry<URL, ResourceLocation> entry :
>> getClassPath().entrySet()) {
>> + ResourceLocation resourceLocation = entry.getValue
>> ();
>> ResourceHandle resourceHandle =
>> resourceLocation.getResourceHandle(resourceName);
>> if (resourceHandle != null && !
>> resourceHandle.isDirectory()) {
>> return resourceHandle;
>> @@ -91,9 +88,8 @@
>> if (destroyed) {
>> return null;
>> }
>> - for (Iterator iterator = getClassPath().entrySet
>> ().iterator(); iterator.hasNext();) {
>> - Map.Entry entry = (Map.Entry) iterator.next();
>> - ResourceLocation resourceLocation =
>> (ResourceLocation) entry.getValue();
>> + for (Map.Entry<URL, ResourceLocation> entry :
>> getClassPath().entrySet()) {
>> + ResourceLocation resourceLocation = entry.getValue
>> ();
>> ResourceHandle resourceHandle =
>> resourceLocation.getResourceHandle(resourceName);
>> if (resourceHandle != null) {
>> return resourceHandle.getUrl();
>> @@ -105,7 +101,7 @@
>> public Enumeration findResources(String resourceName) {
>> synchronized (lock) {
>> - return new ResourceEnumeration(new ArrayList
>> (getClassPath().values()), resourceName);
>> + return new ResourceEnumeration(new
>> ArrayList<ResourceLocation>(getClassPath().values()), resourceName);
>> }
>> }
>> @@ -115,7 +111,7 @@
>> public URL[] getUrls() {
>> synchronized (lock) {
>> - return (URL[]) urls.toArray(new URL[urls.size()]);
>> + return urls.toArray(new URL[urls.size()]);
>> }
>> }
>> @@ -131,7 +127,7 @@
>> * Adds a list of urls to the end of this class loader.
>> * @param urls the URLs to add
>> */
>> - protected void addUrls(List urls) {
>> + protected void addUrls(List<URL> urls) {
>> synchronized (lock) {
>> if (destroyed) {
>> throw new IllegalStateException
>> ("UrlResourceFinder has been destroyed");
>> @@ -144,11 +140,10 @@
>> }
>> }
>> - private LinkedHashMap getClassPath() {
>> + private LinkedHashMap<URL, ResourceLocation> getClassPath() {
>> assert Thread.holdsLock(lock): "This method can only be
>> called while holding the lock";
>> - for (Iterator iterator = watchedFiles.iterator();
>> iterator.hasNext();) {
>> - File file = (File) iterator.next();
>> + for (File file : watchedFiles) {
>> if (file.canRead()) {
>> rebuildClassPath();
>> break;
>> @@ -167,21 +162,21 @@
>> assert Thread.holdsLock(lock): "This method can only be
>> called while holding the lock";
>> // copy all of the existing locations into a temp map
>> and clear the class path
>> - Map existingJarFiles = new LinkedHashMap(classPath);
>> + Map<URL,ResourceLocation> existingJarFiles = new
>> LinkedHashMap<URL,ResourceLocation>(classPath);
>> classPath.clear();
>> - LinkedList locationStack = new LinkedList(urls);
>> + LinkedList<URL> locationStack = new LinkedList<URL>(urls);
>> try {
>> while (!locationStack.isEmpty()) {
>> - URL url = (URL) locationStack.removeFirst();
>> + URL url = locationStack.removeFirst();
>> - // Skip any duplicate urls in the claspath
>> + // Skip any duplicate urls in the classpath
>> if (classPath.containsKey(url)) {
>> continue;
>> }
>> // Check is this URL has already been opened
>> - ResourceLocation resourceLocation =
>> (ResourceLocation) existingJarFiles.remove(url);
>> + ResourceLocation resourceLocation =
>> existingJarFiles.remove(url);
>> // If not opened, cache the url and wrap it with
>> a resource location
>> if (resourceLocation == null) {
>> @@ -208,7 +203,7 @@
>> classPath.put(resourceLocation.getCodeSource(),
>> resourceLocation);
>> // push the manifest classpath on the stack
>> (make sure to maintain the order)
>> - List manifestClassPath = getManifestClassPath
>> (resourceLocation);
>> + List<URL> manifestClassPath = getManifestClassPath
>> (resourceLocation);
>> locationStack.addAll(0, manifestClassPath);
>> }
>> } catch (Error e) {
>> @@ -216,8 +211,7 @@
>> throw e;
>> }
>> - for (Iterator iterator = existingJarFiles.values
>> ().iterator(); iterator.hasNext();) {
>> - ResourceLocation resourceLocation =
>> (ResourceLocation) iterator.next();
>> + for (ResourceLocation resourceLocation :
>> existingJarFiles.values()) {
>> resourceLocation.close();
>> }
>> }
>> @@ -246,7 +240,7 @@
>> throw new IOException("File is not readable: " +
>> cacheFile.getAbsolutePath());
>> }
>> - ResourceLocation resourceLocation = null;
>> + ResourceLocation resourceLocation;
>> if (cacheFile.isDirectory()) {
>> // DirectoryResourceLocation will only return "file"
>> URLs within this directory
>> // do not user the DirectoryResourceLocation for non
>> file based urls
>> @@ -257,7 +251,7 @@
>> return resourceLocation;
>> }
>> - private List getManifestClassPath(ResourceLocation
>> resourceLocation) {
>> + private List<URL> getManifestClassPath(ResourceLocation
>> resourceLocation) {
>> try {
>> // get the manifest, if possible
>> Manifest manifest = resourceLocation.getManifest();
>> @@ -275,7 +269,7 @@
>> // build the urls...
>> // the class-path attribute is space delimited
>> URL codeSource = resourceLocation.getCodeSource();
>> - LinkedList classPathUrls = new LinkedList();
>> + LinkedList<URL> classPathUrls = new LinkedList<URL>();
>> for (StringTokenizer tokenizer = new StringTokenizer
>> (manifestClassPath, " "); tokenizer.hasMoreTokens();) {
>> String entry = tokenizer.nextToken();
>> try {
>> Modified: geronimo/server/trunk/modules/geronimo-kernel/src/main/
>> java/org/apache/geronimo/kernel/config/IOUtil.java
>> URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/
>> geronimo-kernel/src/main/java/org/apache/geronimo/kernel/config/
>> IOUtil.java?view=diff&rev=518426&r1=518425&r2=518426
>> =====================================================================
>> =========
>> --- geronimo/server/trunk/modules/geronimo-kernel/src/main/java/
>> org/apache/geronimo/kernel/config/IOUtil.java (original)
>> +++ geronimo/server/trunk/modules/geronimo-kernel/src/main/java/
>> org/apache/geronimo/kernel/config/IOUtil.java Wed Mar 14 18:22:56
>> 2007
>> @@ -189,7 +189,7 @@
>> if (!SelectorUtils.hasWildcards(pattern)) {
>> File match = new File(root, pattern);
>> if (match.exists() && match.canRead()) {
>> - return Collections.singleton(match.toURL());
>> + return Collections.singleton(match.toURI
>> ().normalize().toURL());
>> } else {
>> return Collections.EMPTY_SET;
>> }
>> @@ -201,7 +201,7 @@
>> String fileName = (String) entry.getKey();
>> if (SelectorUtils.matchPath(pattern,
>> fileName)) {
>> File file = (File) entry.getValue();
>> - matches.add(file.toURL());
>> + matches.add(file.toURI().normalize().toURL
>> ());
>> }
>> }
>> return matches;
>> Modified: geronimo/server/trunk/modules/geronimo-kernel/src/main/
>> java/org/apache/geronimo/kernel/config/MultiParentClassLoader.java
>> URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/
>> geronimo-kernel/src/main/java/org/apache/geronimo/kernel/config/
>> MultiParentClassLoader.java?view=diff&rev=518426&r1=518425&r2=518426
>> =====================================================================
>> =========
>> --- geronimo/server/trunk/modules/geronimo-kernel/src/main/java/
>> org/apache/geronimo/kernel/config/MultiParentClassLoader.java
>> (original)
>> +++ geronimo/server/trunk/modules/geronimo-kernel/src/main/java/
>> org/apache/geronimo/kernel/config/MultiParentClassLoader.java Wed
>> Mar 14 18:22:56 2007
>> @@ -29,10 +29,13 @@
>> import java.util.Collection;
>> import java.util.Collections;
>> import java.util.Enumeration;
>> +import java.util.HashSet;
>> import java.util.List;
>> import java.util.Map;
>> +import java.util.Set;
>> import org.apache.commons.logging.LogFactory;
>> +import org.apache.geronimo.kernel.classloader.UnionEnumeration;
>> import org.apache.geronimo.kernel.repository.Artifact;
>> import org.apache.geronimo.kernel.util.ClassLoaderRegistry;
>> @@ -145,7 +148,7 @@
>> if (source instanceof MultiParentClassLoader) {
>> return new MultiParentClassLoader
>> ((MultiParentClassLoader) source);
>> } else if (source instanceof URLClassLoader) {
>> - return new URLClassLoader(((URLClassLoader)
>> source).getURLs(), source.getParent());
>> + return new URLClassLoader(((URLClassLoader)
>> source).getURLs(), source.getParent());
>> } else {
>> return new URLClassLoader(new URL[0], source);
>> }
>> @@ -175,7 +178,7 @@
>> */
>> public MultiParentClassLoader(Artifact id, URL[] urls,
>> ClassLoader[] parents, URLStreamHandlerFactory factory) {
>> super(urls, null, factory);
>> - this.id = id; + this.id = id;
>> this.parents = copyParents(parents);
>> inverseClassLoading = false;
>> hiddenClasses = new String[0];
>> @@ -205,7 +208,7 @@
>> throw new NullPointerException("parent[" + i + "]
>> is null");
>> }
>> if (parent instanceof MultiParentClassLoader) {
>> - parent = ((MultiParentClassLoader)parent).copy();
>> + parent = ((MultiParentClassLoader) parent).copy();
>> }
>> newParentsArray[i] = parent;
>> }
>> @@ -243,23 +246,23 @@
>> if (cachedClass != null) {
>> return resolveClass(cachedClass, resolve);
>> }
>> - +
>> // This is a reasonable hack. We can add some classes to
>> the list below.
>> // Since we know these classes are in the system class
>> loader let's not waste our
>> // time going through the hierarchy.
>> //
>> // The order is based on profiling the server. It may
>> not be optimal for all
>> // workloads.
>> - - if ( name.startsWith("java.") ||
>> - name.equals("boolean") ||
>> - name.equals("int") ||
>> - name.equals("double") ||
>> - name.equals("long")) {
>> +
>> + if (name.startsWith("java.") ||
>> + name.equals("boolean") ||
>> + name.equals("int") ||
>> + name.equals("double") ||
>> + name.equals("long")) {
>> Class clazz = ClassLoader.getSystemClassLoader
>> ().loadClass(name);
>> return resolveClass(clazz, resolve);
>> }
>> - +
>> //
>> // if we are using inverse class loading, check local
>> urls first
>> //
>> @@ -275,8 +278,7 @@
>> // Check parent class loaders
>> //
>> if (!isHiddenClass(name)) {
>> - for (int i = 0; i < parents.length; i++) {
>> - ClassLoader parent = parents[i];
>> + for (ClassLoader parent : parents) {
>> try {
>> Class clazz = parent.loadClass(name);
>> return resolveClass(clazz, resolve);
>> @@ -304,8 +306,8 @@
>> }
>> private boolean isNonOverridableClass(String name) {
>> - for (int i = 0; i < nonOverridableClasses.length; i++) {
>> - if (name.startsWith(nonOverridableClasses[i])) {
>> + for (String nonOverridableClass : nonOverridableClasses) {
>> + if (name.startsWith(nonOverridableClass)) {
>> return true;
>> }
>> }
>> @@ -313,8 +315,8 @@
>> }
>> private boolean isHiddenClass(String name) {
>> - for (int i = 0; i < hiddenClasses.length; i++) {
>> - if (name.startsWith(hiddenClasses[i])) {
>> + for (String hiddenClass : hiddenClasses) {
>> + if (name.startsWith(hiddenClass)) {
>> return true;
>> }
>> }
>> @@ -347,8 +349,7 @@
>> // Check parent class loaders
>> //
>> if (!isHiddenResource(name)) {
>> - for (int i = 0; i < parents.length; i++) {
>> - ClassLoader parent = parents[i];
>> + for (ClassLoader parent : parents) {
>> URL url = parent.getResource(name);
>> if (url != null) {
>> return url;
>> @@ -370,44 +371,94 @@
>> return null;
>> }
>> - public Enumeration findResources(String name) throws
>> IOException {
>> + public Enumeration<URL> findResources(String name) throws
>> IOException {
>> if (isDestroyed()) {
>> return Collections.enumeration(Collections.EMPTY_SET);
>> }
>> - List resources = new ArrayList();
>> + Set<ClassLoader> knownClassloaders = new
>> HashSet<ClassLoader>();
>> + List<Enumeration<URL>> enumerations = new
>> ArrayList<Enumeration<URL>>();
>> - //
>> - // if we are using inverse class loading, add the
>> resources from local urls first
>> - //
>> - if (inverseClassLoading && !isDestroyed()) {
>> - List myResources = Collections.list
>> (super.findResources(name));
>> - resources.addAll(myResources);
>> - }
>> + recursiveFind(knownClassloaders, enumerations, name);
>> - //
>> - // Add parent resources
>> - //
>> - for (int i = 0; i < parents.length; i++) {
>> - ClassLoader parent = parents[i];
>> - List parentResources = Collections.list
>> (parent.getResources(name));
>> - resources.addAll(parentResources);
>> + return new UnionEnumeration<URL>(enumerations);
>> + /*
>> + List<URL> resources = new ArrayList<URL>();
>> + Set<URL> found = new HashSet<URL>();
>> +
>> + //
>> + // if we are using inverse class loading, add the
>> resources from local urls first
>> + //
>> + if (inverseClassLoading && !isDestroyed()) {
>> + for (Enumeration myResources =
>> super.findResources(name); myResources.hasMoreElements();) {
>> + URL url = (URL) myResources.nextElement();
>> + if (!found.contains(url)) {
>> + found.add(url);
>> + resources.add(url);
>> + }
>> + }
>> + }
>> +
>> + //
>> + // Add parent resources
>> + //
>> + for (ClassLoader parent : parents) {
>> + for (Enumeration parentResources =
>> parent.getResources(name); parentResources.hasMoreElements();) {
>> + URL url = (URL) parentResources.nextElement();
>> + if (!found.contains(url)) {
>> + found.add(url);
>> + resources.add(url);
>> + }
>> + }
>> + }
>> +
>> + //
>> + // if we are not using inverse class loading, add
>> the resources from local urls now
>> + //
>> + if (!inverseClassLoading && !isDestroyed()) {
>> + for (Enumeration myResources =
>> super.findResources(name); myResources.hasMoreElements();) {
>> + URL url = (URL) myResources.nextElement();
>> + if (!found.contains(url)) {
>> + found.add(url);
>> + resources.add(url);
>> + }
>> + }
>> + }
>> +
>> + return Collections.enumeration(resources);
>> + */
>> + }
>> +
>> + protected void recursiveFind(Set<ClassLoader>
>> knownClassloaders, List<Enumeration<URL>> enumerations, String
>> name) throws IOException {
>> + if (isDestroyed() || knownClassloaders.contains(this)) {
>> + return;
>> + }
>> + knownClassloaders.add(this);
>> + if (inverseClassLoading) {
>> + enumerations.add(internalfindResources(name));
>> }
>> -
>> - //
>> - // if we are not using inverse class loading, add the
>> resources from local urls now
>> - //
>> - if (!inverseClassLoading && !isDestroyed()) {
>> - List myResources = Collections.list
>> (super.findResources(name));
>> - resources.addAll(myResources);
>> + for (ClassLoader parent : parents) {
>> + if (parent instanceof MultiParentClassLoader) {
>> + ((MultiParentClassLoader) parent).recursiveFind
>> (knownClassloaders, enumerations, name);
>> + } else {
>> + if (!knownClassloaders.contains(parent)) {
>> + enumerations.add(parent.getResources(name));
>> + knownClassloaders.add(parent);
>> + }
>> + }
>> + }
>> + if (!inverseClassLoading) {
>> + enumerations.add(internalfindResources(name));
>> }
>> + }
>> - return Collections.enumeration(resources);
>> + protected Enumeration<URL> internalfindResources(String name)
>> throws IOException {
>> + return super.findResources(name);
>> }
>> private boolean isNonOverridableResource(String name) {
>> - for (int i = 0; i < nonOverridableResources.length; i++) {
>> - if (name.startsWith(nonOverridableResources[i])) {
>> + for (String nonOverridableResource :
>> nonOverridableResources) {
>> + if (name.startsWith(nonOverridableResource)) {
>> return true;
>> }
>> }
>> @@ -415,8 +466,8 @@
>> }
>> private boolean isHiddenResource(String name) {
>> - for (int i = 0; i < hiddenResources.length; i++) {
>> - if (name.startsWith(hiddenResources[i])) {
>> + for (String hiddenResource : hiddenResources) {
>> + if (name.startsWith(hiddenResource)) {
>> return true;
>> }
>> }
>> @@ -432,7 +483,7 @@
>> }
>> public void destroy() {
>> - synchronized(this) {
>> + synchronized (this) {
>> if (destroyed) return;
>> destroyed = true;
>> }
>> @@ -447,7 +498,7 @@
>> // it has introspected. If we don't flush the cache, we
>> may run out of
>> // Permanent Generation space.
>> Introspector.flushCaches();
>> - +
>> ClassLoaderRegistry.remove(this);
>> }
>> @@ -475,8 +526,10 @@
>> }
>> }
>> }
>> - protected void finalize(){
>> +
>> + protected void finalize() throws Throwable {
>> ClassLoaderRegistry.remove(this);
>> + super.finalize();
>> }
>> }