001    /* Copyright 2000, 2001, Compaq Computer Corporation */
002    
003    package javafe.genericfile;
004    
005    import javafe.Tool;
006    import java.io.File;
007    import java.io.FileInputStream;
008    import java.io.IOException;
009    import java.io.InputStream;
010    
011    /**
012     * A NormalGenericFile represents a normal file ({@link java.io.File})
013     * as a GenericFile.
014     */
015    
016    public class NormalGenericFile extends File implements GenericFile {
017      private static final long serialVersionUID = 4996822143630105487L;
018      
019      /**
020       * Create a NormalGenericFile to represent an existing {@link
021       * File}.
022       */
023      //@ requires underlyingFile != null;
024      
025      public NormalGenericFile(File underlyingFile) {
026        super(underlyingFile.getPath());
027      }
028      
029      /**
030       * Create a NormalGenericFile from a filename.
031       */
032      //@ requires name != null;
033      public NormalGenericFile(String name) {
034        super(name);
035      }
036      
037      /**
038       * @return a name that uniquely identifies us to the user.
039       *
040       * Warning: the result may not be a conventional filename or use
041       * the system separators.
042       */
043      public String getHumanName() {
044        String result = null;
045        if (Tool.options.testMode)
046          result = this.toString().replace('/', '|').replace('\\', '|');
047        else
048          result = this.toString();
049        return result;
050      }
051      
052      /**
053       * @return a String that canonically represents the identity of
054       * our underlying file.
055       *
056       * This function must be defined such that if two GenericFiles
057       * return non-null canonical ID's then the IDs are the same
058       * (modulo .equals) => the GenericFiles represent the same
059       * underlying file.  Ideally, under normal circumstances, the =>
060       * is actually a <=>.
061       *
062       * This function should only return null in exceptional cases,
063       * such as when an I/O error in the underlying storage media
064       * prevents construction of a canonical ID.
065       *
066       * Convention: Canonical IDs start with <X> where X is the
067       * fully-qualified name of the class that mediates I/O to the
068       * underlying file.  E.g., java.io.File for a normal disk file.
069       */
070      public String getCanonicalID() {
071        try {
072          return "<java.io.File>" + this.getCanonicalPath();
073        } catch (IOException e) {
074          return null;
075        }
076      }
077      
078      /**
079       * @return our local name, the name that distinguishes us within
080       * the directory that contains us.
081       *
082       * E.g., "/a/b/c" has local name "c", "/e/r/" has local name "r", and
083       * "/" has local name "".  (assuming "/" is the separator char)
084       */
085      public String getLocalName() { return getName(); }
086      
087      /**
088       * Open the file we represent as an {@link InputStream}.
089       *
090       * @exception IOException May be thrown for many reasons,
091       * including no such file and read permission denied.
092       */
093      public InputStream getInputStream() throws IOException {
094        return new FileInputStream(this);
095      }
096      
097      /**
098       * @return a GenericFile that describes the file in the same
099       * "directory" as us that has the local name <code>n</code>.  No
100       * attempt is made to verify whether or not that file exists.  In
101       * cases where the notion of "containing directory" makes no sense
102       * (e.g., streams or root directories), null is returned.
103       */
104      public GenericFile getSibling(String n) { 
105        String dir = super.getParent();
106        if (dir==null)
107          return null;
108        
109        return new NormalGenericFile(dir + separator + n);
110      }
111    }