/home/gshute/netbeans/Toolkit/src/vfs/VFSRoot.java
package vfs;

import java.io.IOException;
import java.net.URL;
import java.util.Iterator;

/**
 * A VFSRoot is the root of a virtual file system.
 * It provides access to the root directory and provides
 * an escort method for escorting visitors through the
 * file system.
 * 
 * @author gshute
 */
public class VFSRoot {

  private VFSDirectory root;

  /**
   * getResourceURL(c, nm) returns the URL for the directory
   * named nm in the classpath entry containing c.
   */
  private URL getResourceURL(Class c, String nm)
          throws IOException {
    String className = c.getSimpleName();
    URL classURL = c.getResource(className + ".class");
    if (classURL == null) {
      String message = "Resource " + className +
              ".class not found";
      throw new VFSError(message, null);
    }
    String qualifiedClassName = c.getName();
    qualifiedClassName = qualifiedClassName.replace('.', '/');
    String classURLString = classURL.toString();
    int packageNamePosition =
            classURLString.lastIndexOf(qualifiedClassName);
    String baseURLString =
            classURLString.substring(0, packageNamePosition);
    return new URL(baseURLString + nm + "/");
  }

  /**
   * getResourceURL(c) returns the URL for the package
   * that contains c.
   */
  private URL getResourceURL(Class c)
          throws IOException {
    String className = c.getSimpleName();
    URL classURL = c.getResource(className + ".class");
    if (classURL == null) {
      String message = "Resource " + className +
              ".class not found";
      throw new VFSError(message, null);
    }
    String qualifiedClassName = c.getName();
    qualifiedClassName = qualifiedClassName.replace('.', '/');
    String classURLString = classURL.toString();
    int classNamePosition =
            classURLString.lastIndexOf(className);
    String baseURLString =
            classURLString.substring(0, classNamePosition);
    return new URL(baseURLString);
  }

  /**
   * new VFSRoot(c, nm) returns a virtual file system root
   * for the directory named nm in the classpath entry
   * containing c.
   * 
   * @param c the class that determines the classpath entry
   * @param nm the name of the directory
   */
  public VFSRoot(Class c, String nm) {
    root = null;
    try {
      URL url = getResourceURL(c, nm);
      String protocol = url.getProtocol();
      if (protocol.equals("jar")) {
        root = new JarDirectory(url);
      } else if (protocol.equals("file")) {
        root = new NativeDirectory(url);
      } else {
        throw new IllegalArgumentException("Illegal protocol");
      }
    } catch (IOException ex) {
      throw new VFSError(ex);
    }
  }

  /**
   * new VFSRoot(c) returns a virtual file system root
   * for the package that contains c.
   * 
   * @param c the class that determines the package
   */
  public VFSRoot(Class c) {
    root = null;
    try {
      URL url = getResourceURL(c);
      String protocol = url.getProtocol();
      if (protocol.equals("jar")) {
        root = new JarDirectory(url);
      } else if (protocol.equals("file")) {
        root = new NativeDirectory(url);
      } else {
        throw new IllegalArgumentException("Illegal protocol");
      }
    } catch (IOException ex) {
      throw new VFSError(ex);
    }
  }

  public VFSDirectory getRootDirectory() {
    return root;
  }

  public void escort(VFSVisitor v) {
    v.start();
    Iterator<VFSDirectory> subIterator = root.getSubdirectories();
    while (subIterator.hasNext()) {
      subIterator.next().escort(v);
    }
    Iterator<VFSFile> fileIterator = root.getFiles();
    while (fileIterator.hasNext()) {
      v.visit(fileIterator.next());
    }
    v.finish();
  }

}  // public class VFSRoot