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(".apk") ||
                       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);
            }
        }
    }
}
