package jas2.loader;
import java.io.*;
import java.net.URL;
import java.util.*;
import java.util.zip.*;

public class ClassPathLoader extends ClassLoader
{
	/**
	 * A ClassLoader that loads from a ClassPath
	 * @param path The path to load from
	 * @param name The name of the class loader (just for debugging)
	 */
	public ClassPathLoader(ClassPath path, String name)
	{
		this.path = path;
		this.loaderName = name;
	}
	public ClassPath getClassPath()
	{
		return path;
	}
	public Class loadClass(String name, boolean resolve) throws ClassNotFoundException
	{
		//First look in the cache, then try findSystemClass and if all else fails scan through the user's JAS_CLASSPATH.
		Class c = (Class) m_cache.get(name);
		if (c == null) 
		{
			try
			{
                                ClassLoader parent = getClass().getClassLoader();
                                if (parent != null) c= parent.loadClass(name);
                                else                c = findSystemClass(name); 
			}
			catch (ClassNotFoundException e1)
			{
				byte[] data = loadClassData(name);
				c = defineClass(name, data, 0, data.length);
			}
			catch (NoClassDefFoundError e1)
			{
				byte[] data = loadClassData(name);
				c = defineClass(name, data, 0, data.length);
			}
			m_cache.put(name,c);
		}
		if (resolve) resolveClass(c);
		return c;
	}
	/**
	 * This cannot easily be implemented under JDK 1.1 (we would have to install our
	 * own java.net.URLStreamHandlerFactory but only one is allowed per application so 
	 * this would not be very modular). JDK 1.1 supports the jar: protocol for reading
	 * entries within JAR files, so this will be easy to implement then.
	 */
	public URL getResource(String name)
	{
		if (debug) System.err.println("Could not load resource "+name);
		return null;
	}
	public InputStream getResourceAsStream(String name)
	{
		InputStream result =  getSystemResourceAsStream(name);
		if (result != null) return result;
		
		Enumeration e = path.elements();
		while (e.hasMoreElements())
		{
			Object o = e.nextElement();
			if (o instanceof ZipFile) result = getResourceFromJar((ZipFile) o, name);
			else                      result = getResourceFromFileSystem((File) o, name); 
			if (result != null) return result;
		}
		return null;
	}
	private InputStream getResourceFromFileSystem(File dir, String name)
	{
		try
		{
			File f = new File(dir,name);
			if (f.exists()) return new FileInputStream(f);
		}
		catch (IOException x) {};
		return null;
	}
	private InputStream getResourceFromJar(ZipFile zip, String name)
	{
		try
		{
			ZipEntry entry = zip.getEntry(name);
			if (entry != null) return zip.getInputStream(entry);
		}
		catch (IOException x) {};
		return null;
	}
	public byte[] loadClassData(String theClassName) throws ClassNotFoundException	
	{
		String sep = File.separator;
		String theClassPath = theClassName.replace('.',sep.charAt(0))+".class";	//the OS-specific separator (either \ or /)
		String theJarStyleClassPath = theClassName.replace('.','/')+".class";	//the JAR-specific separator (/)

		Enumeration e = path.elements();
		while (e.hasMoreElements()) 
		{
			Object o = e.nextElement();
			byte[] data;
			if (o instanceof ZipFile) data = loadFromJar((ZipFile) o, theJarStyleClassPath);
			else                      data = loadFromFilesystem((File) o, theClassPath); 
			if (data != null)
			{
				if (debug)
				{
					String from = (o instanceof ZipFile) ? ((ZipFile) o).getName() : ((File) o).getAbsolutePath();
					System.out.println(loaderName+": loaded class "+theClassName+" from: "+from);
				}
				return data;
			}
		}
		throw new ClassNotFoundException("Class "+theClassName+" not found");
	}
	private byte[] loadFromFilesystem(File file, String theClassPath)
		throws NestedClassException
	{
		File f = new File(file,theClassPath);
		InputStream input = null;
		try 
		{
			input = new FileInputStream(f);
			int l = (int) f.length();
			return loadFromInputStream(input,l);
		}
		catch (FileNotFoundException x) 
		{
			return null;
		}
		catch (IOException x) 
		{
			throw new NestedClassException("Error reading class file: "+f.getName(),x);
		}
		finally
		{
			try
			{
				if (input != null) input.close();
			}
			catch (IOException x) {}
		}
	}
	private byte[] loadFromJar(ZipFile zipFile, String theJarStyleClassPath)
		throws ClassNotFoundException
	{
		InputStream input = null;
		try 
		{
			ZipEntry entry = zipFile.getEntry(theJarStyleClassPath);
			if (entry == null) return null;

			input = zipFile.getInputStream(entry);
			int len = (int) entry.getSize();
			return loadFromInputStream(input, len);
		} 
		catch(IOException x) 
		{
			throw new NestedClassException("Error reading zip file: "+zipFile.getName(),x);
		}
		finally
		{
			try
			{
				if (input != null) input.close();
			}
			catch (IOException x) {}		
		}
	}
	protected byte[] loadFromInputStream(InputStream input, int len) throws IOException
	{
		byte[] data = new byte[len];
		int p = 0;
		for (int n = input.read(data,p,len); n>0; n = input.read(data,p,len)) 
		{
			p += n;
			len -= n;
		}
		return data;
	}	
	private static final boolean debug = System.getProperty("debugLoader") != null; 
	private String loaderName;
	private ClassPath path;
	private Hashtable m_cache = new Hashtable();
}


 

Ads help maintain this website.