package org.keel.services.misc;

import java.net.URL;
import java.net.URLClassLoader;
/**
 * This is a custom class loader that behaves similarly to URLClassLoader
 * except for the fact that unless the class being loaded is a system class,
 * then the parent classloader is not used to resolve the class.  This
 * gurantees that even if the same class (but a different version) exists
 * in the parent loader's classpath, it will not affect the child loader 
 * and the correct version of the class from the child loader's path will be
 * loaded.
 * 
 * @version	$Revision: 1.1 $	$Date: Nov 6, 2002 9:11:48 PM $
 * @author Shash Chatterjee
 * Created on Nov 6, 2002
 */
public class KeelURLClassLoader extends URLClassLoader {

	/**
	 * @see java.net.URLClassLoader#URLClassLoader(URL[])
	 */
	public KeelURLClassLoader(URL[] urls) {
		super(urls);
	}

	/**
	 * @see java.net.URLClassLoader#URLClassLoader(URL[], ClassLoader)
	 */
	public KeelURLClassLoader(URL[] urls, ClassLoader loader) {
		super(urls, loader);
	}

	/**
	 * A quick-and-dirty function to determine if the classname
	 * is a system class or not.
	 * @param name Name of the class, fully qualified with package name
	 * @return boolean True if the class is a system class, false otherwise
	 */
	protected boolean isSystemResource(String name) {
		//return true;  // Debug: Force loading all from parent class-loader
		return (name.startsWith("java.") || name.startsWith("java/"));
	}

	/**
	 * This method overrides the default behavior,  If not a system class,
	 * then the parent class-loader is never consulted.
	 * 
	 * @see java.lang.ClassLoader#loadClass(String, boolean)
	 */
	public synchronized Class loadClass(String name, boolean resolve)
		throws ClassNotFoundException {

		Class c = null;

		//Check if the class is a system class or not
		if (isSystemResource(name)) {
			// Load system classes from the parent class-loader
			if (getParent() != null) {
				c = getParent().loadClass(name);
			}
		} else {
			// Not a system class, load from local classpath

			// First, check if the class has already been loaded
			c = findLoadedClass(name);
			if (c == null) {
				// If not found, then try to find class locally
				c = findClass(name);
			}
		}

		// Link the class if specified
		if (resolve) {
			resolveClass(c);
		}
		return c;
	}

	/**
	 * This method overrides the default behavior,  If not a system resource,
	 * then the parent class-loader is never consulted.
	 *
	 * @see java.lang.ClassLoader#getResource(String)	 */
	public URL getResource(String name) {

		URL u = null;

		if (isSystemResource(name)) {
			u = getParent().getResource(name);
		} else {
			u = findResource(name);
		}

		return u;
	}

}
