1 // File.java - File name
3 /* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
15 import gnu.gcj.runtime.FileDeleter;
18 * @author Tom Tromey <tromey@cygnus.com>
19 * @date September 24, 1998
22 /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
23 * "The Java Language Specification", ISBN 0-201-63451-1
24 * Status: Complete to version 1.3.
27 public class File implements Serializable, Comparable
29 public boolean canRead ()
32 return _access (READ);
35 public boolean canWrite ()
38 return _access (WRITE);
41 private native boolean performCreate() throws IOException;
44 public boolean createNewFile() throws IOException
47 return performCreate();
50 private native boolean performDelete ();
51 public boolean delete ()
53 SecurityManager s = System.getSecurityManager();
57 return performDelete ();
60 public boolean equals (Object obj)
62 if (! (obj instanceof File))
64 File other = (File) obj;
66 return (path.equals(other.path));
68 return (path.equalsIgnoreCase(other.path));
71 public boolean exists ()
74 return _access (EXISTS);
77 public File (String p)
79 path = normalizePath(p);
82 // Remove duplicate and redundant separator characters.
83 private String normalizePath(String p)
85 int dupIndex = p.indexOf(dupSeparator);
86 int plen = p.length();
88 // Special case: permit Windows UNC path prefix.
89 if (dupSeparator.equals("\\\\") && dupIndex == 0)
90 dupIndex = p.indexOf(dupSeparator, 1);
94 // Ignore trailing separator.
95 if (plen > 1 && p.charAt(plen - 1) == separatorChar)
96 return p.substring(0, plen - 1);
101 StringBuffer newpath = new StringBuffer(plen);
103 while (dupIndex != -1)
105 newpath.append(p.substring(last, dupIndex));
106 // Ignore the duplicate path characters.
107 while (p.charAt(dupIndex) == separatorChar)
110 if (dupIndex == plen)
111 return newpath.toString();
113 newpath.append(separatorChar);
115 dupIndex = p.indexOf(dupSeparator, last);
118 // Again, ignore possible trailing separator.
120 if (plen > 1 && p.charAt(plen - 1) == separatorChar)
124 newpath.append(p.substring(last, end));
126 return newpath.toString();
129 public File (String dirPath, String name)
132 throw new NullPointerException ();
133 if (dirPath != null && dirPath.length() > 0)
135 // Try to be smart about the number of separator characters.
136 if (dirPath.charAt(dirPath.length() - 1) == separatorChar
137 || name.length() == 0)
138 path = normalizePath(dirPath + name);
140 path = normalizePath(dirPath + separatorChar + name);
143 path = normalizePath(name);
146 public File (File dir, String name)
148 this (dir == null ? null : dir.path, name);
152 public String getAbsolutePath ()
156 return System.getProperty("user.dir") + separatorChar + path;
160 public File getAbsoluteFile ()
162 return new File (getAbsolutePath());
165 public native String getCanonicalPath () throws IOException;
168 public File getCanonicalFile () throws IOException
170 return new File (getCanonicalPath());
173 public String getName ()
175 int last = path.lastIndexOf(separatorChar);
176 return path.substring(last + 1);
179 public String getParent ()
181 int last = path.lastIndexOf(separatorChar);
184 // FIXME: POSIX assumption.
185 if (last == 0 && path.charAt (0) == '/')
187 return path.substring(0, last);
191 public File getParentFile ()
193 String parent = getParent ();
194 return (parent == null ? null : new File (parent));
197 public String getPath ()
202 public int hashCode ()
205 return (path.hashCode() ^ 1234321);
207 return (path.toLowerCase().hashCode() ^ 1234321);
210 public native boolean isAbsolute ();
212 public boolean isDirectory ()
215 return _stat (DIRECTORY);
218 public boolean isFile ()
221 return _stat (ISFILE);
225 public boolean isHidden()
228 return _stat (ISHIDDEN);
231 public long lastModified ()
234 return attr (MODIFIED);
237 public long length ()
240 return attr (LENGTH);
243 private final native Object[] performList (FilenameFilter filter,
244 FileFilter fileFilter,
247 public String[] list (FilenameFilter filter)
250 return (String[]) performList (filter, null, String.class);
253 public String[] list ()
256 return (String[]) performList (null, null, String.class);
260 public File[] listFiles()
263 return (File[]) performList (null, null, File.class);
267 public File[] listFiles(FilenameFilter filter)
270 return (File[]) performList (filter, null, File.class);
274 public File[] listFiles(FileFilter filter)
277 return (File[]) performList (null, filter, File.class);
280 public String toString ()
285 public URL toURL () throws MalformedURLException
287 return new URL ("file://" + getAbsolutePath ()
288 + (isDirectory() ? "/" : ""));
291 private final native boolean performMkdir ();
293 public boolean mkdir ()
296 return performMkdir ();
299 private static boolean mkdirs (File x)
303 String p = x.getPath();
304 String parent = x.getParent();
315 public boolean mkdirs ()
320 return mkdirs (new File (path));
323 private static synchronized String nextValue ()
325 return Long.toString(counter++, Character.MAX_RADIX);
329 public static File createTempFile (String prefix, String suffix,
333 // Grab the system temp directory if necessary
334 if (directory == null)
336 String dirname = tmpdir;
339 new IOException("Cannot determine system temporary directory");
341 directory = new File(dirname);
342 if (!directory.exists())
343 throw new IOException("System temporary directory "
344 + directory.getName() + " does not exist.");
345 if (!directory.isDirectory())
346 throw new IOException("System temporary directory "
347 + directory.getName()
348 + " is not really a directory.");
351 if (prefix.length () < 3)
352 throw new IllegalArgumentException ("Prefix too short: " + prefix);
357 // `6' is the number of characters we generate.
358 if (prefix.length () + 6 + suffix.length () > maxPathLen)
361 if (suffix.charAt(0) == '.')
363 suffix = suffix.substring(0, suf_len);
364 if (prefix.length () + 6 + suf_len > maxPathLen)
365 prefix = prefix.substring(0, maxPathLen - 6 - suf_len);
370 // How many times should we try? We choose 100.
371 for (int i = 0; i < 100; ++i)
374 String t = "ZZZZZZ" + nextValue ();
375 String l = prefix + t.substring(t.length() - 6) + suffix;
378 f = new File(directory, l);
379 if (f.createNewFile())
382 catch (IOException ignored)
387 throw new IOException ("cannot create temporary file");
390 private native boolean performSetReadOnly();
393 public boolean setReadOnly()
396 return performSetReadOnly();
399 private static native File[] performListRoots();
402 public static File[] listRoots()
404 File[] roots = performListRoots();
406 SecurityManager s = System.getSecurityManager();
409 // Only return roots to which the security manager permits read access.
410 int count = roots.length;
411 for (int i = 0; i < roots.length; i++)
415 s.checkRead(roots[i].path);
417 catch (SecurityException sx)
423 if (count != roots.length)
425 File[] newRoots = new File[count];
427 for (int i=0; i < roots.length; i++)
429 if (roots[i] != null)
430 newRoots[k++] = roots[i];
438 public static File createTempFile (String prefix, String suffix)
441 return createTempFile (prefix, suffix, null);
445 public int compareTo(File other)
448 return path.compareTo (other.path);
450 return path.compareToIgnoreCase (other.path);
454 public int compareTo(Object o)
456 File other = (File) o;
457 return compareTo (other);
460 private native boolean performRenameTo (File dest);
461 public boolean renameTo (File dest)
463 SecurityManager s = System.getSecurityManager();
464 String sname = getName();
465 String dname = dest.getName();
471 return performRenameTo (dest);
474 private native boolean performSetLastModified(long time);
477 public boolean setLastModified(long time)
480 return performSetLastModified(time);
483 public static final String pathSeparator
484 = System.getProperty("path.separator");
485 public static final char pathSeparatorChar = pathSeparator.charAt(0);
486 public static final String separator = System.getProperty("file.separator");
487 public static final char separatorChar = separator.charAt(0);
489 static final String tmpdir = System.getProperty("java.io.tmpdir");
490 static int maxPathLen;
491 static boolean caseSensitive;
492 static String dupSeparator = separator + separator;
499 // Native function called at class initialization. This should should
500 // set the maxPathLen and caseSensitive variables.
501 private static native void init_native();
506 // We keep a counter for use by createTempFile. We choose the first
507 // value randomly to try to avoid clashes with other VMs.
508 private static long counter = Double.doubleToLongBits (Math.random ());
510 private void checkWrite ()
512 SecurityManager s = System.getSecurityManager();
517 private void checkRead ()
519 SecurityManager s = System.getSecurityManager();
525 * Add this File to the set of files to be deleted upon normal
530 // FIXME: This should use the ShutdownHook API once we implement that.
531 public void deleteOnExit ()
533 SecurityManager sm = System.getSecurityManager ();
535 sm.checkDelete (getName ());
537 FileDeleter.add (this);
540 private void writeObject (ObjectOutputStream oos) throws IOException
542 oos.defaultWriteObject ();
543 oos.writeChar (separatorChar);
546 private void readObject (ObjectInputStream ois)
547 throws ClassNotFoundException, IOException
549 ois.defaultReadObject ();
551 // If the file was from an OS with a different dir separator,
552 // fixup the path to use the separator on this OS.
553 char oldSeparatorChar = ois.readChar ();
554 if (oldSeparatorChar != separatorChar)
555 path = path.replace (oldSeparatorChar, separatorChar);
558 // QUERY arguments to access function.
559 private final static int READ = 0;
560 private final static int WRITE = 1;
561 private final static int EXISTS = 2;
563 // QUERY arguments to stat function.
564 private final static int DIRECTORY = 0;
565 private final static int ISFILE = 1;
566 private final static int ISHIDDEN = 2;
568 // QUERY arguments to attr function.
569 private final static int MODIFIED = 0;
570 private final static int LENGTH = 1;
572 private final native long attr (int query);
573 // On OSF1 V5.0, `stat' is a macro. It is easiest to use the name
574 // `_stat' instead. We do the same thing for `_access' just in
576 private final native boolean _access (int query);
577 private final native boolean _stat (int query);
579 private static final long serialVersionUID = 301077366599181567L;