import java.util.Hashtable;
import java.net.*;
import java.io.*;
public class URLClassLoader extends ClassLoader {
Hashtable cache;
URL u;
public URLClassLoader(URL u) {
this.u = u;
cache = new Hashtable();
}
public synchronized Class loadClass(String name, boolean resolve)
throws ClassNotFoundException {
// first look for the class in the cache
Class c = (Class) cache.get(name);
// If it's not in the cache, then look
// in the system classes
if (c == null) {
try {
c = findSystemClass(name);
}
catch (ClassNotFoundException e) {
}
}
// if the class still hasn't been found,
// load it from the network
if (c == null) {
byte b[] = loadClassData(name);
c = defineClass(b, 0, b.length);
cache.put(name, c);
}
if (resolve) {
resolveClass(c);
}
return c;
} // end loadClass
private byte[] loadClassData(String name)
throws ClassNotFoundException {
byte[] b;
InputStream theClass = null;
int bfr = 128;
try {
URL classURL = new URL(u, name + ".class");
URLConnection uc = classURL.openConnection();
uc.setAllowUserInteraction(false);
// I don't know why, but uc.getInputStream absolutely
// has to come before uc.getContentLength or you'll
// get a nasty NullPointerException
try {
theClass = uc.getInputStream();
}
catch (NullPointerException e) {
System.err.println(e);
throw new ClassNotFoundException(name + " input stream problem");
}
int cl = uc.getContentLength();
// A lot of web servers don't send content-lengths
// for .class files
if (cl == -1 ) {
b = new byte[bfr * 16];
}
else {
b = new byte[cl];
}
int bytesread = 0;
int offset = 0;
while (bytesread >= 0) {
bytesread = theClass.read(b, offset, bfr);
if (bytesread == -1) break;
offset += bytesread;
if (cl == -1 && offset == b.length) { // grow the array
byte temp[] = new byte[offset * 2];
System.arraycopy(b, 0, temp, 0, offset);
b = temp;
}
else if (offset > b.length) {
throw new ClassNotFoundException(name
+ " error reading data into the array");
}
}
if (offset < b.length) { // shrink the array
byte temp[] = new byte[offset];
System.arraycopy(b, 0, temp, 0, offset);
b = temp;
}
// Make sure all the bytes were received
if (cl != -1 && offset != cl) {
throw new ClassNotFoundException("Only " + offset +
" bytes received for " + name +
"\n Expected " + cl + " bytes");
}
} // end try
catch (Exception e) {
throw new ClassNotFoundException(name + " " + e);
}
finally {
try {
if (theClass != null) theClass.close();
}
catch (IOException e) {
}
}
return b;
} // end loadClassData
} // end URLClassLoader
|