|
|
@@ -67,12 +67,32 @@ import java.io.*; |
|
|
|
* @author Conor MacNeill |
|
|
|
*/ |
|
|
|
public class AntClassLoader extends ClassLoader { |
|
|
|
/** |
|
|
|
* The size of buffers to be used in this classloader. |
|
|
|
*/ |
|
|
|
static private final int BUFFER_SIZE = 1024; |
|
|
|
|
|
|
|
/** |
|
|
|
* The classpath that is to be used when loading classes using this class loader. |
|
|
|
*/ |
|
|
|
private Path classpath; |
|
|
|
|
|
|
|
/** |
|
|
|
* The project to which this class loader belongs. |
|
|
|
*/ |
|
|
|
private Project project; |
|
|
|
|
|
|
|
/** |
|
|
|
* The File components of the path. Typically these will be directories or jar files. |
|
|
|
*/ |
|
|
|
private Vector components = null; |
|
|
|
|
|
|
|
/** |
|
|
|
* Create a classloader for the given project using the classpath given. |
|
|
|
* |
|
|
|
* @param project the project to ehich this classloader is to belong. |
|
|
|
* @param classpath the classpath to use to load the classes. |
|
|
|
*/ |
|
|
|
public AntClassLoader(Project project, Path classpath) { |
|
|
|
this.project = project; |
|
|
|
this.classpath = classpath; |
|
|
@@ -80,6 +100,9 @@ public class AntClassLoader extends ClassLoader { |
|
|
|
|
|
|
|
/** |
|
|
|
* Set up this classloader for the first time. |
|
|
|
* |
|
|
|
* This method will set up the components field with the components from the |
|
|
|
* given classpath. |
|
|
|
*/ |
|
|
|
private void setup() { |
|
|
|
// We iterate through the class path, resolving each element. |
|
|
@@ -95,6 +118,16 @@ public class AntClassLoader extends ClassLoader { |
|
|
|
/** |
|
|
|
* Load a class through this class loader even if that class is available on the |
|
|
|
* system classpath. |
|
|
|
* |
|
|
|
* This ensures that any classes which are loaded by the returned class will use this |
|
|
|
* classloader. |
|
|
|
* |
|
|
|
* @param classname the classname to be loaded. |
|
|
|
* |
|
|
|
* @return the required Class object |
|
|
|
* |
|
|
|
* @throws ClassNotFoundException if the requested class does not exist on |
|
|
|
* this loader's classpath. |
|
|
|
*/ |
|
|
|
public Class forceLoadClass(String classname) throws ClassNotFoundException { |
|
|
|
Class theClass = findLoadedClass(classname); |
|
|
@@ -106,6 +139,14 @@ public class AntClassLoader extends ClassLoader { |
|
|
|
return theClass; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Get a stream to read the requested resource name. |
|
|
|
* |
|
|
|
* @param name the name of the resource for which a stream is required. |
|
|
|
* |
|
|
|
* @return a stream to the required resource or null if the resource cannot be |
|
|
|
* found on the loader's classpath. |
|
|
|
*/ |
|
|
|
public InputStream getResourceAsStream(String name) { |
|
|
|
if (components == null) { |
|
|
|
// we haven't set up the list of directories and jars yet. |
|
|
@@ -124,6 +165,16 @@ public class AntClassLoader extends ClassLoader { |
|
|
|
return stream; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Get an inputstream to a given resource in the given file which may |
|
|
|
* either be a directory or a jar type file. |
|
|
|
* |
|
|
|
* @param file the file (directory or jar) in which to search for the resource. |
|
|
|
* @param resourceName the name of the resource for which a stream is required. |
|
|
|
* |
|
|
|
* @return a stream to the required resource or null if the resource cannot be |
|
|
|
* found in the given file object |
|
|
|
*/ |
|
|
|
private InputStream getResourceStream(File file, String resourceName) { |
|
|
|
try { |
|
|
|
if (file.isDirectory()) { |
|
|
@@ -133,11 +184,28 @@ public class AntClassLoader extends ClassLoader { |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
ZipFile zipFile = new ZipFile(file); |
|
|
|
ZipFile zipFile = null; |
|
|
|
try { |
|
|
|
zipFile = new ZipFile(file); |
|
|
|
|
|
|
|
ZipEntry entry = zipFile.getEntry(resourceName); |
|
|
|
if (entry != null) { |
|
|
|
return zipFile.getInputStream(entry); |
|
|
|
ZipEntry entry = zipFile.getEntry(resourceName); |
|
|
|
if (entry != null) { |
|
|
|
// we need to read the entry out of the zip file into |
|
|
|
// a baos and then |
|
|
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
|
|
|
byte[] buffer = new byte[BUFFER_SIZE]; |
|
|
|
int bytesRead; |
|
|
|
InputStream stream = zipFile.getInputStream(entry); |
|
|
|
while ((bytesRead = stream.read(buffer, 0, BUFFER_SIZE)) != -1) { |
|
|
|
baos.write(buffer, 0, bytesRead); |
|
|
|
} |
|
|
|
return new ByteArrayInputStream(baos.toByteArray()); |
|
|
|
} |
|
|
|
} |
|
|
|
finally { |
|
|
|
if (zipFile != null) { |
|
|
|
zipFile.close(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@@ -148,6 +216,22 @@ public class AntClassLoader extends ClassLoader { |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Load a class with this class loader. |
|
|
|
* |
|
|
|
* This method will load a class. |
|
|
|
* |
|
|
|
* This class attempts to load the class firstly using the parent class loader. For |
|
|
|
* JDK 1.1 compatability, this uses the findSystemClass method. |
|
|
|
* |
|
|
|
* @param classname the name of the class to be loaded. |
|
|
|
* @param resolve true if all classes upon which this class depends are to be loaded. |
|
|
|
* |
|
|
|
* @return the required Class object |
|
|
|
* |
|
|
|
* @throws ClassNotFoundException if the requested class does not exist on |
|
|
|
* the system classpath or this loader's classpath. |
|
|
|
*/ |
|
|
|
protected Class loadClass(String classname, boolean resolve) throws ClassNotFoundException { |
|
|
|
|
|
|
|
Class theClass = findLoadedClass(classname); |
|
|
@@ -167,11 +251,29 @@ public class AntClassLoader extends ClassLoader { |
|
|
|
return theClass; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Convert the class dot notation to a file system equivalent for |
|
|
|
* searching purposes. |
|
|
|
* |
|
|
|
* @param classname the class name in dot format (ie java.lang.Integer) |
|
|
|
* |
|
|
|
* @return the classname in file system format (ie java/lang/Integer.class) |
|
|
|
*/ |
|
|
|
private String getClassFilename(String classname) { |
|
|
|
return classname.replace('.', '/') + ".class"; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Read a class definition from a stream. |
|
|
|
* |
|
|
|
* @param stream the stream from which the class is to be read. |
|
|
|
* @param classname the class name of the class in the stream. |
|
|
|
* |
|
|
|
* @return the Class object read from the stream. |
|
|
|
* |
|
|
|
* @throws IOException if there is a problem reading the class from the |
|
|
|
* stream. |
|
|
|
*/ |
|
|
|
private Class getClassFromStream(InputStream stream, String classname) |
|
|
|
throws IOException { |
|
|
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
|
|
@@ -187,7 +289,16 @@ public class AntClassLoader extends ClassLoader { |
|
|
|
return defineClass(classname, classData, 0, classData.length); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Search for and load a class on the classpath of this class loader. |
|
|
|
* |
|
|
|
* @param name the classname to be loaded. |
|
|
|
* |
|
|
|
* @return the required Class object |
|
|
|
* |
|
|
|
* @throws ClassNotFoundException if the requested class does not exist on |
|
|
|
* this loader's classpath. |
|
|
|
*/ |
|
|
|
public Class findClass(String name) throws ClassNotFoundException { |
|
|
|
if (components == null) { |
|
|
|
// we haven't set up the list of directories and jars yet. |
|
|
|