blob: 64a38f36acb9c587ff6a8f65c1a58d3516e711d4 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.tomcat.util.loader;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
import java.util.Vector;
/**
* Class loader associated with a repository ( common, shared, server, etc ).
*
* This class loader will never load any class by itself ( since it has no repository ),
* it will just delegate to modules.
*
* Refactored as a separate class to make the code cleaner.
* Based on catalina loader.
*
* @author Costin Manolache
* @author Remy Maucherat
* @author Craig R. McClanahan
*/
public class RepositoryClassLoader
extends URLClassLoader
{
private static final boolean DEBUG=false; //LoaderProperties.getProperty("loader.debug.ModuleClassLoader") != null;
private static final boolean DEBUGNF=false;//LoaderProperties.getProperty("loader.debug.ModuleClassLoaderNF") != null;
// ----------------------------------------------------------- Constructors
public RepositoryClassLoader(URL repositories[], ClassLoader parent, Repository lg) {
super(repositories, parent);
this.repository=lg;
}
public RepositoryClassLoader(URL repositories[], Repository lg) {
super(repositories);
this.repository=lg;
}
// ----------------------------------------------------- Instance Variables
private Repository repository;
// ---------------------------------------------------- ClassLoader Methods
/**
* Find the specified class in our local repositories, if possible. If
* not found, throw <code>ClassNotFoundException</code>.
*
* @param name Name of the class to be loaded
*
* @exception ClassNotFoundException if the class was not found
*/
public Class findClass(String name) throws ClassNotFoundException {
Class clazz = null;
Enumeration modulesE=repository.getModules();
while( modulesE.hasMoreElements() ) {
try {
Module m=(Module)modulesE.nextElement();
return ((ModuleClassLoader)m.getClassLoader()).findClass2(name, false);
} catch( ClassNotFoundException ex ) {
// ignore
}
}
throw new ClassNotFoundException( name );
}
/** Same as findClass, but also checks if the class has been previously
* loaded.
*
* In most implementations, findClass() doesn't check with findLoadedClass().
* In order to implement repository, we need to ask each loader in the group
* to load only from it's local resources - however this will lead to errors
* ( duplicated definition ) if findClass() is used.
*
* @param name
* @return
* @throws ClassNotFoundException
*/
public Class findLocalClass(String name) throws ClassNotFoundException
{
Enumeration modulesE=repository.getModules();
while( modulesE.hasMoreElements() ) {
try {
Module m=(Module)modulesE.nextElement();
return ((ModuleClassLoader)m.getClassLoader()).findLocalClass(name);
} catch( ClassNotFoundException ex ) {
// ignore
}
}
throw new ClassNotFoundException( name );
}
/**
* Find the specified resource in our local repository, and return a
* <code>URL</code> refering to it, or <code>null</code> if this resource
* cannot be found.
*
* @param name Name of the resource to be found
*/
public URL findResource(final String name) {
URL url = null;
Enumeration modulesE=repository.getModules();
while( modulesE.hasMoreElements() ) {
Module m=(Module)modulesE.nextElement();
url=((ModuleClassLoader)m.getClassLoader()).findResource2(name, false);
if( url!= null ) {
return url;
}
}
if (url==null && DEBUG) {
if (DEBUGNF) log("findResource() NOTFOUND " + name );
}
return null;
}
/**
* Return an enumeration of <code>URLs</code> representing all of the
* resources with the given name. If no resources with this name are
* found, return an empty enumeration.
*
* @param name Name of the resources to be found
*
* @exception IOException if an input/output error occurs
*/
public Enumeration findResources(String name) throws IOException {
Vector result=new Vector();
Enumeration modulesE=repository.getModules();
while( modulesE.hasMoreElements() ) {
Module m=(Module)modulesE.nextElement();
Enumeration myRes=((ModuleClassLoader)m.getClassLoader()).findResources2(name,false);
if( myRes!=null ) {
while( myRes.hasMoreElements() ) {
result.addElement(myRes.nextElement());
}
}
}
return result.elements();
}
// Next methods implement the search alghoritm - parent, repo, delegation, etc
/** getResource() - modified to implement the search alghoritm
*
*/
public URL getResource(String name) {
URL url = null;
Enumeration modulesE=repository.getModules();
while( modulesE.hasMoreElements() ) {
Module m=(Module)modulesE.nextElement();
url=((ModuleClassLoader)m.getClassLoader()).getResource2(name, null, false);
if( url!= null ) {
return url;
}
}
if (url==null && DEBUG) {
if (DEBUGNF) log("findResource() NOTFOUND " + name );
}
return null;
}
/**
* Load the class with the specified name, searching using the following
* algorithm until it finds and returns the class. If the class cannot
* be found, returns <code>ClassNotFoundException</code>.
* <ul>
* <li>Call <code>findLoadedClass(String)</code> to check if the
* class has already been loaded. If it has, the same
* <code>Class</code> object is returned.</li>
* <li>If the <code>delegate</code> property is set to <code>true</code>,
* call the <code>loadClass()</code> method of the parent class
* loader, if any.</li>
* <li>Call <code>findClass()</code> to find this class in our locally
* defined repositories.</li>
* <li>Call the <code>loadClass()</code> method of our parent
* class loader, if any.</li>
* </ul>
* If the class was found using the above steps, and the
* <code>resolve</code> flag is <code>true</code>, this method will then
* call <code>resolveClass(Class)</code> on the resulting Class object.
*
* @param name Name of the class to be loaded
* @param resolve If <code>true</code> then resolve the class
*
* @exception ClassNotFoundException if the class was not found
*/
public Class loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
Class clazz = null;
Enumeration modulesE=repository.getModules();
while( modulesE.hasMoreElements() ) {
try {
Module m=(Module)modulesE.nextElement();
return ((ModuleClassLoader)m.getClassLoader()).loadClass2(name, resolve, false);
} catch( ClassNotFoundException ex ) {
// ignore
}
}
throw new ClassNotFoundException( name );
}
// ------------------ Local methods ------------------------
private void log(String s ) {
System.err.println("RepositoryClassLoader: " + s);
}
private void log(String s, Throwable t ) {
System.err.println("RepositoryClassLoader: " + s);
t.printStackTrace();
}
}