blob: 8d1db50f0bde4eb3dd6b528b420e7f6c129a8464 [file] [log] [blame]
package junit.util;
import java.util.*;
import java.io.*;
/**
* A custom class loader which enables the reloading
* of classes for each test run. The class loader
* can be configured with a list of package paths that
* should be excluded from loading. The loading
* of these packages is delegated to the system class
* loader. They will be shared across test runs.
* <p>
* The list of excluded package paths is specified in
* a properties file "excluded.properties" that is located in
* the same place as the TestCaseClassLoader class.
* <p>
* <b>Known limitation:</b> the TestCaseClassLoader cannot load classes
* from jar files.
*/
public class TestCaseClassLoader extends ClassLoader {
/** scanned class path */
private String[] fPathItems;
/** excluded paths */
private String[] fExcluded= { "com.sun.", "sun."};
/** name of excluded properties file */
static final String EXCLUDED_FILE= "excluded.properties";
/**
* Constructs a TestCaseLoader. It scans the class path
* and the excluded package paths
*/
public TestCaseClassLoader() {
super();
String classPath= System.getProperty("java.class.path");
String separator= System.getProperty("path.separator");
// first pass: count elements
StringTokenizer st= new StringTokenizer(classPath, separator);
int i= 0;
while (st.hasMoreTokens()) {
st.nextToken();
i++;
}
// second pass: split
fPathItems= new String[i];
st= new StringTokenizer(classPath, separator);
i= 0;
while (st.hasMoreTokens()) {
fPathItems[i++]= st.nextToken();
}
String[] excluded= readExcludedPackages();
if (excluded != null)
fExcluded= excluded;
}
public java.net.URL getResource(String name) {
return ClassLoader.getSystemResource(name);
}
public InputStream getResourceAsStream(String name) {
return ClassLoader.getSystemResourceAsStream(name);
}
protected boolean isExcluded(String name) {
// exclude the "java" and "junit" packages.
// They always need to be excluded so that they are loaded by the system class loader
if (name.startsWith("java.") ||
name.startsWith("junit.framework") ||
name.startsWith("junit.extensions") ||
name.startsWith("junit.util") ||
name.startsWith("junit.ui"))
return true;
// exclude the user defined package paths
for (int i= 0; i < fExcluded.length; i++) {
if (name.startsWith(fExcluded[i])) {
return true;
}
}
return false;
}
public synchronized Class loadClass(String name, boolean resolve)
throws ClassNotFoundException {
Class c= findLoadedClass(name);
if (c != null)
return c;
//
// Delegate the loading of excluded classes to the
// standard class loader.
//
if (isExcluded(name)) {
try {
c= findSystemClass(name);
return c;
} catch (ClassNotFoundException e) {
// keep searching
}
}
if (c == null) {
File file= locate(name);
if (file == null)
throw new ClassNotFoundException();
byte data[]= loadClassData(file);
c= defineClass(name, data, 0, data.length);
}
if (resolve)
resolveClass(c);
return c;
}
private byte[] loadClassData(File f) throws ClassNotFoundException {
try {
//System.out.println("loading: "+f.getPath());
FileInputStream stream= new FileInputStream(f);
try {
byte[] b= new byte[stream.available()];
stream.read(b);
stream.close();
return b;
}
catch (IOException e) {
throw new ClassNotFoundException();
}
}
catch (FileNotFoundException e) {
throw new ClassNotFoundException();
}
}
/**
* Locate the given file.
* @return Returns null if file couldn't be found.
*/
private File locate(String fileName) {
fileName= fileName.replace('.', '/')+".class";
File path= null;
if (fileName != null) {
for (int i= 0; i < fPathItems.length; i++) {
path= new File(fPathItems[i], fileName);
if (path.exists())
return path;
}
}
return null;
}
private String[] readExcludedPackages() {
InputStream is= getClass().getResourceAsStream(EXCLUDED_FILE);
if (is == null)
return null;
Properties p= new Properties();
try {
p.load(is);
}
catch (IOException e) {
return null;
}
Vector v= new Vector(10);
for (Enumeration e= p.propertyNames(); e.hasMoreElements(); ) {
String key= (String)e.nextElement();
if (key.startsWith("excluded.")) {
String path= p.getProperty(key);
if (path.endsWith("*"))
path= path.substring(0, path.length()-1);
if (path.length() > 0)
v.addElement(path);
}
}
String[] excluded= new String[v.size()];
for (int i= 0; i < v.size(); i++)
excluded[i]= (String)v.elementAt(i);
return excluded;
}
}