package junit.runner;

import java.util.*;
import java.io.*;
import java.net.URL;
import java.util.zip.*;

/**
 * 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 Vector fPathItems;
	/** default excluded paths */
	private String[] defaultExclusions= {
		"junit.framework.", 
		"junit.extensions.", 
		"junit.runner."
	};
	/** name of excluded properties file */
	static final String EXCLUDED_FILE= "excluded.properties";
	/** excluded paths */
	private Vector fExcluded;
	 
	/**
	 * Constructs a TestCaseLoader. It scans the class path
	 * and the excluded package paths
	 */
	public TestCaseClassLoader() {
		this(System.getProperty("java.class.path"));
	}
	
	/**
	 * Constructs a TestCaseLoader. It scans the class path
	 * and the excluded package paths
	 */
	public TestCaseClassLoader(String classPath) {
		scanPath(classPath);
		readExcludedPackages();
	}

	private void scanPath(String classPath) {
		String separator= System.getProperty("path.separator");
		fPathItems= new Vector(10);
		StringTokenizer st= new StringTokenizer(classPath, separator);
		while (st.hasMoreTokens()) {
			fPathItems.addElement(st.nextToken());
		}
	}
	
	public URL getResource(String name) {
		return ClassLoader.getSystemResource(name);
	}
	
	public InputStream getResourceAsStream(String name) {
		return ClassLoader.getSystemResourceAsStream(name);
	} 
	
	public boolean isExcluded(String name) {
		for (int i= 0; i < fExcluded.size(); i++) {
			if (name.startsWith((String) fExcluded.elementAt(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) {
			byte[] data= lookupClassData(name);
			if (data == null)
				throw new ClassNotFoundException();
			c= defineClass(name, data, 0, data.length);
		}
		if (resolve) 
			resolveClass(c);
		return c;
	}
	
	private byte[] lookupClassData(String className) throws ClassNotFoundException {
		byte[] data= null;
		for (int i= 0; i < fPathItems.size(); i++) {
			String path= (String) fPathItems.elementAt(i);
			String fileName= className.replace('.', '/')+".class";
			if (isJar(path)) {
				data= loadJarData(path, fileName);
			} else {
				data= loadFileData(path, fileName);
			}
			if (data != null)
				return data;
		}
		throw new ClassNotFoundException(className);
	}
		
	boolean isJar(String pathEntry) {
		return pathEntry.endsWith(".jar") || pathEntry.endsWith(".zip");
	}

	private byte[] loadFileData(String path, String fileName) {
		File file= new File(path, fileName);
		if (file.exists()) { 
			return getClassData(file);
		}
		return null;
	}
	
	private byte[] getClassData(File f) {
		try {
			FileInputStream stream= new FileInputStream(f);
			ByteArrayOutputStream out= new ByteArrayOutputStream(1000);
			byte[] b= new byte[1000];
			int n;
			while ((n= stream.read(b)) != -1) 
				out.write(b, 0, n);
			stream.close();
			out.close();
			return out.toByteArray();

		} catch (IOException e) {
		}
		return null;
	}

	private byte[] loadJarData(String path, String fileName) {
		ZipFile zipFile= null;
		InputStream stream= null;
		File archive= new File(path);
		if (!archive.exists())
			return null;
		try {
			zipFile= new ZipFile(archive);
		} catch(IOException io) {
			return null;
		}
		ZipEntry entry= zipFile.getEntry(fileName);
		if (entry == null)
			return null;
		int size= (int) entry.getSize();
		try {
			stream= zipFile.getInputStream(entry);
			byte[] data= new byte[size];
			int pos= 0;
			while (pos < size) {
				int n= stream.read(data, pos, data.length - pos);
				pos += n;
			}
			zipFile.close();
			return data;
		} catch (IOException e) {
		} finally {
			try {
				if (stream != null)
					stream.close();
			} catch (IOException e) {
			}
		}
		return null;
	}
	
	private void readExcludedPackages() {		
		fExcluded= new Vector(10);
		for (int i= 0; i < defaultExclusions.length; i++)
			fExcluded.addElement(defaultExclusions[i]);
			
		InputStream is= getClass().getResourceAsStream(EXCLUDED_FILE);
		if (is == null) 
			return;
		Properties p= new Properties();
		try {
			p.load(is);
		}
		catch (IOException e) {
			return;
		} finally {
			try {
				is.close();
			} catch (IOException e) {
			}
		}
		for (Enumeration e= p.propertyNames(); e.hasMoreElements(); ) {
			String key= (String)e.nextElement();
			if (key.startsWith("excluded.")) {
				String path= p.getProperty(key);
				path= path.trim();
				if (path.endsWith("*"))
					path= path.substring(0, path.length()-1);
				if (path.length() > 0) 
					fExcluded.addElement(path);				
			}
		}
	}
}