package ij.io;
import ij.IJ;
import java.io.*;
import java.net.*;

/** ImageJ uses this class loader to load plugins and resources from the
 * plugins directory and immediate subdirectories. This class loader will
 * also load classes and resources from JAR files.
 *
 * <p> The class loader searches for classes and resources in the following order:
 * <ol>
 *  <li> Plugins directory</li>
 *  <li> Subdirectories of the Plugins directory</li>
 *  <li> JAR and ZIP files in the plugins directory and subdirectories</li>
 * </ol>
 * <p> The class loader does not recurse into subdirectories beyond the first level.
*/
public class PluginClassLoader extends URLClassLoader {
    protected String path;

    /**
     * Creates a new PluginClassLoader that searches in the directory path
     * passed as a parameter. The constructor automatically finds all JAR and ZIP
     * files in the path and first level of subdirectories. The JAR and ZIP files
     * are stored in a Vector for future searches.
     * @param path the path to the plugins directory.
     */
    public PluginClassLoader(String path) {
        super(new URL[0], IJ.class.getClassLoader());
        init(path);
    }
    
    /** This version of the constructor is used when ImageJ is launched using Java WebStart. */
    public PluginClassLoader(String path, boolean callSuper) {
        super(new URL[0], Thread.currentThread().getContextClassLoader());
        init(path);
    }

    void init(String path) {
        this.path = path;

        //find all JAR files on the path and subdirectories
        File f = new File(path);
        try {
            // Add plugin directory to search path
            addURL(f.toURI().toURL());
        } catch (MalformedURLException e) {
            ij.IJ.log("PluginClassLoader: "+e);
        }
        String[] list = f.list();
        if (list==null)
            return;
        for (int i=0; i<list.length; i++) {
            if (list[i].equals(".rsrc"))
                continue;
            File f2=new File(path, list[i]);
            if (f2.isDirectory())
                addDirectory(f2);
            else 
                addJar(f2);
        }
        addDirectory(f, "jars"); // add ImageJ/jars; requested by Wilhelm Burger
    }

    private void addDirectory(File f) {
        //if (IJ.debugMode) IJ.log("PluginClassLoader.addDirectory: "+f);
        try {
            // Add first level subdirectories to search path
            addURL(f.toURI().toURL());
        } catch (MalformedURLException e) {
            ij.IJ.log("PluginClassLoader: "+e);
        }
        String[] innerlist = f.list();
        if (innerlist==null)
            return;
        for (int j=0; j<innerlist.length; j++) {
            File g = new File(f,innerlist[j]);
            if (g.isFile())
                addJar(g);
        }
    }

    private void addJar(File f) {
        if (f.getName().endsWith(".jar") || f.getName().endsWith(".zip")) {
            //if (IJ.debugMode) IJ.log("PluginClassLoader.addJar: "+f);
            try {
                addURL(f.toURI().toURL());
            } catch (MalformedURLException e) {
                ij.IJ.log("PluginClassLoader: "+e);
            }
        }
    }

    private void addDirectory(File f, String name) {
        f = f.getParentFile();
        if (f==null)
            return;
        f = new File(f, name);
        if (f==null)
            return;
        if (f.isDirectory())
            addDirectory(f);
    }

}