| // File.java - File name |
| |
| /* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation |
| |
| This file is part of libgcj. |
| |
| This software is copyrighted work licensed under the terms of the |
| Libgcj License. Please consult the file "LIBGCJ_LICENSE" for |
| details. */ |
| |
| package java.io; |
| |
| import java.util.*; |
| import java.net.*; |
| import gnu.gcj.runtime.FileDeleter; |
| |
| /** |
| * @author Tom Tromey <tromey@cygnus.com> |
| * @date September 24, 1998 |
| */ |
| |
| /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 |
| * "The Java Language Specification", ISBN 0-201-63451-1 |
| * Status: Complete to version 1.3. |
| */ |
| |
| public class File implements Serializable, Comparable |
| { |
| public boolean canRead () |
| { |
| checkRead(); |
| return access (READ); |
| } |
| |
| public boolean canWrite () |
| { |
| checkWrite(); |
| return access (WRITE); |
| } |
| |
| private native boolean performCreate() throws IOException; |
| |
| /** @since 1.2 */ |
| public boolean createNewFile() throws IOException |
| { |
| checkWrite(); |
| return performCreate(); |
| } |
| |
| private native boolean performDelete (); |
| public boolean delete () |
| { |
| SecurityManager s = System.getSecurityManager(); |
| String name = path; |
| if (s != null) |
| s.checkDelete(path); |
| return performDelete (); |
| } |
| |
| public boolean equals (Object obj) |
| { |
| if (! (obj instanceof File)) |
| return false; |
| File other = (File) obj; |
| if (caseSensitive) |
| return (path.equals(other.path)); |
| else |
| return (path.equalsIgnoreCase(other.path)); |
| } |
| |
| public boolean exists () |
| { |
| checkRead(); |
| return access (EXISTS); |
| } |
| |
| public File (String p) |
| { |
| if (p == null) |
| throw new NullPointerException (); |
| path = p; |
| } |
| |
| public File (String dirPath, String name) |
| { |
| if (name == null) |
| throw new NullPointerException (); |
| if (dirPath != null && dirPath.length() > 0) |
| { |
| // Try to be smart about the number of separator characters. |
| if (dirPath.charAt(dirPath.length() - 1) == separatorChar) |
| path = dirPath + name; |
| else |
| path = dirPath + separatorChar + name; |
| } |
| else |
| path = name; |
| } |
| |
| public File (File dir, String name) |
| { |
| this (dir == null ? null : dir.path, name); |
| } |
| |
| // FIXME ??? |
| public String getAbsolutePath () |
| { |
| if (isAbsolute ()) |
| return path; |
| return System.getProperty("user.dir") + separatorChar + path; |
| } |
| |
| /** @since 1.2 */ |
| public File getAbsoluteFile () throws IOException |
| { |
| return new File (getAbsolutePath()); |
| } |
| |
| public native String getCanonicalPath () throws IOException; |
| |
| /** @since 1.2 */ |
| public File getCanonicalFile () throws IOException |
| { |
| return new File (getCanonicalPath()); |
| } |
| |
| public String getName () |
| { |
| int last = path.lastIndexOf(separatorChar); |
| return path.substring(last + 1); |
| } |
| |
| public String getParent () |
| { |
| int last = path.lastIndexOf(separatorChar); |
| if (last == -1) |
| return null; |
| return path.substring(0, last); |
| } |
| |
| /** @since 1.2 */ |
| public File getParentFile () |
| { |
| String parent = getParent (); |
| return (parent == null ? null : new File (parent)); |
| } |
| |
| public String getPath () |
| { |
| return path; |
| } |
| |
| public int hashCode () |
| { |
| if (caseSensitive) |
| return (path.hashCode() ^ 1234321); |
| else |
| return (path.toLowerCase().hashCode() ^ 1234321); |
| } |
| |
| public native boolean isAbsolute (); |
| |
| public boolean isDirectory () |
| { |
| checkRead(); |
| return stat (DIRECTORY); |
| } |
| |
| public boolean isFile () |
| { |
| checkRead(); |
| return stat (ISFILE); |
| } |
| |
| /** @since 1.2 */ |
| public boolean isHidden() |
| { |
| checkRead(); |
| return stat (ISHIDDEN); |
| } |
| |
| public long lastModified () |
| { |
| checkRead(); |
| return attr (MODIFIED); |
| } |
| |
| public long length () |
| { |
| checkRead(); |
| return attr (LENGTH); |
| } |
| |
| private final native Object[] performList (FilenameFilter filter, |
| FileFilter fileFilter, |
| Class result_type); |
| |
| public String[] list (FilenameFilter filter) |
| { |
| checkRead(); |
| return (String[]) performList (filter, null, String.class); |
| } |
| |
| public String[] list () |
| { |
| checkRead(); |
| return (String[]) performList (null, null, String.class); |
| } |
| |
| /** @since 1.2 */ |
| public File[] listFiles() |
| { |
| checkRead(); |
| return (File[]) performList (null, null, File.class); |
| } |
| |
| /** @since 1.2 */ |
| public File[] listFiles(FilenameFilter filter) |
| { |
| checkRead(); |
| return (File[]) performList (filter, null, File.class); |
| } |
| |
| /** @since 1.2 */ |
| public File[] listFiles(FileFilter filter) |
| { |
| checkRead(); |
| return (File[]) performList (null, filter, File.class); |
| } |
| |
| public String toString () |
| { |
| return path; |
| } |
| |
| public URL toURL () throws MalformedURLException |
| { |
| return new URL ("file:" + path + (isDirectory() ? "/" : "")); |
| } |
| |
| private final native boolean performMkdir (); |
| |
| public boolean mkdir () |
| { |
| checkWrite(); |
| return performMkdir (); |
| } |
| |
| private static boolean mkdirs (File x) |
| { |
| if (x.isDirectory()) |
| return true; |
| String p = x.getPath(); |
| String parent = x.getParent(); |
| if (parent != null) |
| { |
| x.path = parent; |
| if (! mkdirs (x)) |
| return false; |
| x.path = p; |
| } |
| return x.mkdir(); |
| } |
| |
| public boolean mkdirs () |
| { |
| checkWrite(); |
| if (isDirectory ()) |
| return false; |
| return mkdirs (new File (path)); |
| } |
| |
| private static synchronized String nextValue () |
| { |
| return Long.toString(counter++, Character.MAX_RADIX); |
| } |
| |
| /** @since 1.2 */ |
| public static File createTempFile (String prefix, String suffix, |
| File directory) |
| throws IOException |
| { |
| // Grab the system temp directory if necessary |
| if (directory == null) |
| { |
| String dirname = tmpdir; |
| if (dirname == null) |
| throw |
| new IOException("Cannot determine system temporary directory"); |
| |
| directory = new File(dirname); |
| if (!directory.exists()) |
| throw new IOException("System temporary directory " |
| + directory.getName() + " does not exist."); |
| if (!directory.isDirectory()) |
| throw new IOException("System temporary directory " |
| + directory.getName() |
| + " is not really a directory."); |
| } |
| |
| if (prefix.length () < 3) |
| throw new IllegalArgumentException ("Prefix too short: " + prefix); |
| if (suffix == null) |
| suffix = ".tmp"; |
| |
| // Truncation rules. |
| // `6' is the number of characters we generate. |
| if (prefix.length () + 6 + suffix.length () > maxPathLen) |
| { |
| int suf_len = 0; |
| if (suffix.charAt(0) == '.') |
| suf_len = 4; |
| suffix = suffix.substring(0, suf_len); |
| if (prefix.length () + 6 + suf_len > maxPathLen) |
| prefix = prefix.substring(0, maxPathLen - 6 - suf_len); |
| } |
| |
| File f; |
| |
| // How many times should we try? We choose 100. |
| for (int i = 0; i < 100; ++i) |
| { |
| // This is ugly. |
| String t = "ZZZZZZ" + nextValue (); |
| String l = prefix + t.substring(t.length() - 6) + suffix; |
| try |
| { |
| f = new File(directory, l); |
| if (f.createNewFile()) |
| return f; |
| } |
| catch (IOException ignored) |
| { |
| } |
| } |
| |
| throw new IOException ("cannot create temporary file"); |
| } |
| |
| private native boolean performSetReadOnly(); |
| |
| /** @since 1.2 */ |
| public boolean setReadOnly() |
| { |
| checkWrite(); |
| return performSetReadOnly(); |
| } |
| |
| private static native File[] performListRoots(); |
| |
| /** @since 1.2 */ |
| public static File[] listRoots() |
| { |
| File[] roots = performListRoots(); |
| |
| SecurityManager s = System.getSecurityManager(); |
| if (s != null) |
| { |
| // Only return roots to which the security manager permits read access. |
| int count = roots.length; |
| for (int i = 0; i < roots.length; i++) |
| { |
| try |
| { |
| s.checkRead(roots[i].path); |
| } |
| catch (SecurityException sx) |
| { |
| roots[i] = null; |
| count--; |
| } |
| } |
| if (count != roots.length) |
| { |
| File[] newRoots = new File[count]; |
| int k = 0; |
| for (int i=0; i < roots.length; i++) |
| { |
| if (roots[i] != null) |
| newRoots[k++] = roots[i]; |
| } |
| roots = newRoots; |
| } |
| } |
| return roots; |
| } |
| |
| public static File createTempFile (String prefix, String suffix) |
| throws IOException |
| { |
| return createTempFile (prefix, suffix, null); |
| } |
| |
| /** @since 1.2 */ |
| public int compareTo(File other) |
| { |
| if (caseSensitive) |
| return path.compareTo (other.path); |
| else |
| return path.compareToIgnoreCase (other.path); |
| } |
| |
| /** @since 1.2 */ |
| public int compareTo(Object o) |
| { |
| File other = (File) o; |
| return compareTo (other); |
| } |
| |
| private native boolean performRenameTo (File dest); |
| public boolean renameTo (File dest) |
| { |
| SecurityManager s = System.getSecurityManager(); |
| String sname = getName(); |
| String dname = dest.getName(); |
| if (s != null) |
| { |
| s.checkWrite(sname); |
| s.checkWrite(dname); |
| } |
| return performRenameTo (dest); |
| } |
| |
| private native boolean performSetLastModified(long time); |
| |
| /** @since 1.2 */ |
| public boolean setLastModified(long time) |
| { |
| checkWrite(); |
| return performSetLastModified(time); |
| } |
| |
| public static final String pathSeparator |
| = System.getProperty("path.separator"); |
| public static final char pathSeparatorChar = pathSeparator.charAt(0); |
| public static final String separator = System.getProperty("file.separator"); |
| public static final char separatorChar = separator.charAt(0); |
| |
| static final String tmpdir = System.getProperty("java.io.tmpdir"); |
| static int maxPathLen; |
| static boolean caseSensitive; |
| |
| static |
| { |
| init_native(); |
| } |
| |
| // Native function called at class initialization. This should should |
| // set the maxPathLen and caseSensitive variables. |
| private static native void init_native(); |
| |
| // The path. |
| private String path; |
| |
| // We keep a counter for use by createTempFile. We choose the first |
| // value randomly to try to avoid clashes with other VMs. |
| private static long counter = Double.doubleToLongBits (Math.random ()); |
| |
| private void checkWrite () |
| { |
| SecurityManager s = System.getSecurityManager(); |
| if (s != null) |
| s.checkWrite(path); |
| } |
| |
| private void checkRead () |
| { |
| SecurityManager s = System.getSecurityManager(); |
| if (s != null) |
| s.checkRead(path); |
| } |
| |
| /** |
| * Add this File to the set of files to be deleted upon normal |
| * termination. |
| * |
| * @since 1.2 |
| */ |
| // FIXME: This should use the ShutdownHook API once we implement that. |
| public void deleteOnExit () |
| { |
| SecurityManager sm = System.getSecurityManager (); |
| if (sm != null) |
| sm.checkDelete (getName ()); |
| |
| FileDeleter.add (this); |
| } |
| |
| private void writeObject (ObjectOutputStream oos) throws IOException |
| { |
| oos.defaultWriteObject (); |
| oos.writeChar (separatorChar); |
| } |
| |
| private void readObject (ObjectInputStream ois) |
| throws ClassNotFoundException, IOException |
| { |
| ois.defaultReadObject (); |
| |
| // If the file was from an OS with a different dir separator, |
| // fixup the path to use the separator on this OS. |
| char oldSeparatorChar = ois.readChar (); |
| if (oldSeparatorChar != separatorChar) |
| path = path.replace (oldSeparatorChar, separatorChar); |
| } |
| |
| // QUERY arguments to access function. |
| private final static int READ = 0; |
| private final static int WRITE = 1; |
| private final static int EXISTS = 2; |
| |
| // QUERY arguments to stat function. |
| private final static int DIRECTORY = 0; |
| private final static int ISFILE = 1; |
| private final static int ISHIDDEN = 2; |
| |
| // QUERY arguments to attr function. |
| private final static int MODIFIED = 0; |
| private final static int LENGTH = 1; |
| |
| private final native long attr (int query); |
| private final native boolean access (int query); |
| private final native boolean stat (int query); |
| |
| private static final long serialVersionUID = 301077366599181567L; |
| } |