FileDocCategorySizeDatePackage
Resource.javaAPI DocExample5655Fri Feb 21 13:11:42 GMT 2003None

Resource.java

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

/**
 * A class to locate resources, retrieve their contents, and determine their
 * last modified time.  To find the resource the class searches the CLASSPATH
 * first, then Resource.class.getResource("/" + name).  If the Resource finds
 * a "file:" URL then the file path will be treated as a file.  Otherwise the
 * path is treated as a URL and has limited last modified info.
 */
public class Resource implements Serializable {

  private String name;
  private File file;
  private URL url;

  public Resource(String name) throws IOException {
    this.name = name;
    SecurityException exception = null;

    try {
      // Search using the CLASSPATH.  If found, "file" is set and the call
      // returns true.  A SecurityException may bubble up.
      if (tryClasspath(name)) {
        return;
      }
    }
    catch (SecurityException e) {
      exception = e;  // save for later
    }

    try {
      // Search using the class loader getResource().  If found as a file,
      // "file" is set, if found as a URL then "url" is set.
      if (tryLoader(name)) {
        return;
      }
    }
    catch (SecurityException e) {
      exception = e;  // save for later
    }

    // If we get here we failed, report the exception
    String msg = "";
    if (exception != null) {
      msg = ": " + exception;
    }

    throw new IOException("Resource '" + name + "' could not be found in " +
      "the CLASSPATH (" + System.getProperty("java.class.path") +
      "), nor could it be located by the classloader responsible for the " +
      "web application (WEB-INF/classes)" + msg);
  }

  /**
   * Returns the resource name, as passed to the constructor.
   */
  public String getName() {
    return name;
  }

  /**
   * Returns an input stream to read the resource contents.
   */
  public InputStream getInputStream() throws IOException {
    if (file != null) {
      return new BufferedInputStream(new FileInputStream(file));
    }
    else if (url != null) {
      return new BufferedInputStream(url.openStream());
    }
    return null;
  }

  /**
   * Returns when the resource was last modified.  If the resource was found
   * using a URL, this method will only work if the URL connection supports
   * last modified information.  If there's no support, Long.MAX_VALUE is
   * returned.  Perhaps this should return -1 but we return MAX_VALUE on
   * the assumption that if you can't determine the time, assume it's 
   * maximally new.
   */
  public long lastModified() {
    if (file != null) {
      return file.lastModified();
    }
    else if (url != null) {
      try {
        return url.openConnection().getLastModified();  // hail mary
      }
      catch (IOException e) { return Long.MAX_VALUE; }
    }
    return 0;  // can't happen
  }

  /**
   * Returns the directory containing the resource, or null if the resource
   * isn't directly available on the filesystem.  This value can be used to
   * locate the config file on disk or write files in the same directory.
   */
  public String getDirectory() {
    if (file != null) {
      return file.getParent();
    }
    else if (url != null) {
      return null;
    }
    return null;
  }

  // Returns true if found
  private boolean tryClasspath(String filename) {
    String classpath = System.getProperty("java.class.path");
    String[] paths = split(classpath, File.pathSeparator);
    file = searchDirectories(paths, filename);
    return (file != null);
  }

  private static File searchDirectories(String[] paths, String filename) {
    SecurityException exception = null;
    for (int i = 0; i < paths.length; i++) {
      try {
        File file = new File(paths[i], filename);
        if (file.exists() && !file.isDirectory()) {
          return file;
        }
      }
      catch (SecurityException e) {
        // Security exceptions can usually be ignored, but if all attempts
        // to find the file fail, then report the (last) security exception.
        exception = e;
      }
    }
    // Couldn't find any match
    if (exception != null) {
      throw exception;
    }
    else {
      return null;
    }
  }

  // Splits a String into pieces according to a delimiter.
  // Uses JDK 1.1 classes for backward compatibility.
  // JDK 1.4 actually has a split() method now.
  private static String[] split(String str, String delim) {
    // Use a Vector to hold the splittee strings
    Vector v = new Vector();

    // Use a StringTokenizer to do the splitting
    StringTokenizer tokenizer = new StringTokenizer(str, delim);
    while (tokenizer.hasMoreTokens()) {
      v.addElement(tokenizer.nextToken());
    }

    String[] ret = new String[v.size()];
    v.copyInto(ret);
    return ret;
  }

  // Returns true if found
  private boolean tryLoader(String name) {
    name = "/" + name;
    URL res = Resource.class.getResource(name);
    if (res == null) {
      return false;
    }

    // Try converting from a URL to a File
    File resFile = urlToFile(res);
    if (resFile != null) {
      file = resFile;
    }
    else {
      url = res;
    }
    return true;
  }

  private static File urlToFile(URL res) {
    String externalForm = res.toExternalForm();
    if (externalForm.startsWith("file:")) {
      return new File(externalForm.substring(5));
    }
    return null;
  }

  public String toString() {
    return "[Resource: File: " + file + " URL: " + url + "]";
  }
}