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.