source: trunk/gcc/libjava/java/io/File.java

Last change on this file was 1392, checked in by bird, 21 years ago

This commit was generated by cvs2svn to compensate for changes in r1391,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 17.6 KB
Line 
1// File.java - File name
2
3/* Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
4
5 This file is part of libgcj.
6
7This software is copyrighted work licensed under the terms of the
8Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9details. */
10
11package java.io;
12
13import java.util.*;
14import java.net.*;
15import gnu.gcj.runtime.FileDeleter;
16
17/**
18 * @author Tom Tromey <tromey@cygnus.com>
19 * @date September 24, 1998
20 */
21
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.
25 */
26
27public class File implements Serializable, Comparable
28{
29 public boolean canRead ()
30 {
31 checkRead();
32 return _access (READ);
33 }
34
35 public boolean canWrite ()
36 {
37 checkWrite();
38 return _access (WRITE);
39 }
40
41 private native boolean performCreate() throws IOException;
42
43 /** @since 1.2 */
44 public boolean createNewFile() throws IOException
45 {
46 checkWrite();
47 return performCreate();
48 }
49
50 private native boolean performDelete ();
51 public boolean delete ()
52 {
53 SecurityManager s = System.getSecurityManager();
54 String name = path;
55 if (s != null)
56 s.checkDelete(path);
57 return performDelete ();
58 }
59
60 public boolean equals (Object obj)
61 {
62 if (! (obj instanceof File))
63 return false;
64 File other = (File) obj;
65 if (caseSensitive)
66 return (path.equals(other.path));
67 else
68 return (path.equalsIgnoreCase(other.path));
69 }
70
71 public boolean exists ()
72 {
73 checkRead();
74 return _access (EXISTS);
75 }
76
77 public File (String p)
78 {
79 path = normalizePath(p);
80 }
81
82 // Remove duplicate and redundant separator characters.
83 private String normalizePath(String p)
84 {
85 // On Windows, convert any '/' to '\'. This appears to be the same logic
86 // that Sun's Win32 Java performs.
87 if (separatorChar == '\\')
88 p = p.replace ('/', '\\');
89
90 int dupIndex = p.indexOf(dupSeparator);
91 int plen = p.length();
92
93 // Special case: permit Windows UNC path prefix.
94 if (dupSeparator.equals("\\\\") && dupIndex == 0)
95 dupIndex = p.indexOf(dupSeparator, 1);
96
97 if (dupIndex == -1)
98 {
99 // Ignore trailing separator (though on Windows "a:\", for
100 // example, is a valid and minimal path).
101 if (plen > 1 && p.charAt (plen - 1) == separatorChar)
102 {
103 if (! (separatorChar == '\\' && plen == 3 && p.charAt (1) == ':'))
104 return p.substring (0, plen - 1);
105 }
106 else
107 return p;
108 }
109
110 StringBuffer newpath = new StringBuffer(plen);
111 int last = 0;
112 while (dupIndex != -1)
113 {
114 newpath.append(p.substring(last, dupIndex));
115 // Ignore the duplicate path characters.
116 while (p.charAt(dupIndex) == separatorChar)
117 {
118 dupIndex++;
119 if (dupIndex == plen)
120 return newpath.toString();
121 }
122 newpath.append(separatorChar);
123 last = dupIndex;
124 dupIndex = p.indexOf(dupSeparator, last);
125 }
126
127 // Again, ignore possible trailing separator (except special cases
128 // like "a:\" on Windows).
129 int end;
130 if (plen > 1 && p.charAt (plen - 1) == separatorChar)
131 {
132 if (separatorChar == '\\' && plen == 3 && p.charAt (1) == ':')
133 end = plen;
134 else
135 end = plen - 1;
136 }
137 else
138 end = plen;
139 newpath.append(p.substring(last, end));
140
141 return newpath.toString();
142 }
143
144 public File (String dirPath, String name)
145 {
146 if (name == null)
147 throw new NullPointerException ();
148 if (dirPath != null && dirPath.length() > 0)
149 {
150 // Try to be smart about the number of separator characters.
151 if (dirPath.charAt(dirPath.length() - 1) == separatorChar
152 || name.length() == 0)
153 path = normalizePath(dirPath + name);
154 else
155 path = normalizePath(dirPath + separatorChar + name);
156 }
157 else
158 path = normalizePath(name);
159 }
160
161 public File (File dir, String name)
162 {
163 this (dir == null ? null : dir.path, name);
164 }
165
166 public String getAbsolutePath ()
167 {
168 if (isAbsolute ())
169 return path;
170 else if (separatorChar == '\\'
171 && path.length () > 0 && path.charAt (0) == '\\')
172 {
173 // On Windows, even if the path starts with a '\\' it is not
174 // really absolute until we prefix the drive specifier from
175 // the current working directory to it.
176 return System.getProperty ("user.dir").substring (0, 2) + path;
177 }
178 else if (separatorChar == '\\'
179 && path.length () > 1 && path.charAt (1) == ':'
180 && ((path.charAt (0) >= 'a' && path.charAt (0) <= 'z')
181 || (path.charAt (0) >= 'A' && path.charAt (0) <= 'Z')))
182 {
183 // On Windows, a process has a current working directory for
184 // each drive and a path like "G:foo\bar" would mean the
185 // absolute path "G:\wombat\foo\bar" if "\wombat" is the
186 // working directory on the G drive.
187 String drvDir = null;
188 try
189 {
190 drvDir = new File (path.substring (0, 2)).getCanonicalPath ();
191 }
192 catch (IOException e)
193 {
194 drvDir = path.substring (0, 2) + "\\";
195 }
196
197 // Note: this would return "C:\\." for the path "C:.", if "\"
198 // is the working folder on the C drive, but this is
199 // consistent with what Sun's JRE 1.4.1.01 actually returns!
200 if (path.length () > 2)
201 return drvDir + '\\' + path.substring (2, path.length ());
202 else
203 return drvDir;
204 }
205 else
206 return System.getProperty ("user.dir") + separatorChar + path;
207 }
208
209 /** @since 1.2 */
210 public File getAbsoluteFile ()
211 {
212 return new File (getAbsolutePath());
213 }
214
215 public native String getCanonicalPath () throws IOException;
216
217 /** @since 1.2 */
218 public File getCanonicalFile () throws IOException
219 {
220 return new File (getCanonicalPath());
221 }
222
223 public String getName ()
224 {
225 int nameSeqIndex = 0;
226
227 if (separatorChar == '\\' && path.length () > 1)
228 {
229 // On Windows, ignore the drive specifier or the leading '\\'
230 // of a UNC network path, if any (a.k.a. the "prefix").
231 if ((path.charAt (0) == '\\' && path.charAt (1) == '\\')
232 || (((path.charAt (0) >= 'a' && path.charAt (0) <= 'z')
233 || (path.charAt (0) >= 'A' && path.charAt (0) <= 'Z'))
234 && path.charAt (1) == ':'))
235 {
236 if (path.length () > 2)
237 nameSeqIndex = 2;
238 else
239 return "";
240 }
241 }
242
243 String nameSeq
244 = (nameSeqIndex > 0 ? path.substring (nameSeqIndex) : path);
245
246 int last = nameSeq.lastIndexOf (separatorChar);
247
248 return nameSeq.substring (last + 1);
249 }
250
251 public String getParent ()
252 {
253 String prefix = null;
254 int nameSeqIndex = 0;
255
256 // The "prefix", if present, is the leading "/" on UNIX and
257 // either the drive specifier (e.g. "C:") or the leading "\\"
258 // of a UNC network path on Windows.
259 if (separatorChar == '/' && path.charAt (0) == '/')
260 {
261 prefix = "/";
262 nameSeqIndex = 1;
263 }
264 else if (separatorChar == '\\' && path.length () > 1)
265 {
266 if ((path.charAt (0) == '\\' && path.charAt (1) == '\\')
267 || (((path.charAt (0) >= 'a' && path.charAt (0) <= 'z')
268 || (path.charAt (0) >= 'A' && path.charAt (0) <= 'Z'))
269 && path.charAt (1) == ':'))
270 {
271 prefix = path.substring (0, 2);
272 nameSeqIndex = 2;
273 }
274 }
275
276 // According to the JDK docs, the returned parent path is the
277 // portion of the name sequence before the last separator
278 // character, if found, prefixed by the prefix, otherwise null.
279 if (nameSeqIndex < path.length ())
280 {
281 String nameSeq = path.substring (nameSeqIndex, path.length ());
282 int last = nameSeq.lastIndexOf (separatorChar);
283 if (last == -1)
284 return prefix;
285 else if (last == (nameSeq.length () - 1))
286 // Note: The path would not have a trailing separator
287 // except for cases like "C:\" on Windows (see
288 // normalizePath( )), where Sun's JRE 1.4 returns null.
289 return null;
290 else if (last == 0)
291 last++;
292
293 if (prefix != null)
294 return prefix + nameSeq.substring (0, last);
295 else
296 return nameSeq.substring (0, last);
297 }
298 else
299 // Sun's JRE 1.4 returns null if the prefix is the only
300 // component of the path - so "/" gives null on UNIX and
301 // "C:", "\\", etc. return null on Windows.
302 return null;
303 }
304
305 /** @since 1.2 */
306 public File getParentFile ()
307 {
308 String parent = getParent ();
309 return (parent == null ? null : new File (parent));
310 }
311
312 public String getPath ()
313 {
314 return path;
315 }
316
317 public int hashCode ()
318 {
319 if (caseSensitive)
320 return (path.hashCode() ^ 1234321);
321 else
322 return (path.toLowerCase().hashCode() ^ 1234321);
323 }
324
325 public native boolean isAbsolute ();
326
327 public boolean isDirectory ()
328 {
329 checkRead();
330 return _stat (DIRECTORY);
331 }
332
333 public boolean isFile ()
334 {
335 checkRead();
336 return _stat (ISFILE);
337 }
338
339 /** @since 1.2 */
340 public boolean isHidden()
341 {
342 checkRead();
343 return _stat (ISHIDDEN);
344 }
345
346 public long lastModified ()
347 {
348 checkRead();
349 return attr (MODIFIED);
350 }
351
352 public long length ()
353 {
354 checkRead();
355 return attr (LENGTH);
356 }
357
358 private final native Object[] performList (FilenameFilter filter,
359 FileFilter fileFilter,
360 Class result_type);
361
362 public String[] list (FilenameFilter filter)
363 {
364 checkRead();
365 return (String[]) performList (filter, null, String.class);
366 }
367
368 public String[] list ()
369 {
370 checkRead();
371 return (String[]) performList (null, null, String.class);
372 }
373
374 /** @since 1.2 */
375 public File[] listFiles()
376 {
377 checkRead();
378 return (File[]) performList (null, null, File.class);
379 }
380
381 /** @since 1.2 */
382 public File[] listFiles(FilenameFilter filter)
383 {
384 checkRead();
385 return (File[]) performList (filter, null, File.class);
386 }
387
388 /** @since 1.2 */
389 public File[] listFiles(FileFilter filter)
390 {
391 checkRead();
392 return (File[]) performList (null, filter, File.class);
393 }
394
395 public String toString ()
396 {
397 return path;
398 }
399
400 public URL toURL () throws MalformedURLException
401 {
402 // On Win32, Sun's JDK returns URLs of the form "file:/c:/foo/bar.txt",
403 // while on UNIX, it returns URLs of the form "file:/foo/bar.txt".
404 if (separatorChar == '\\')
405 return new URL ("file:/" + getAbsolutePath ().replace ('\\', '/')
406 + (isDirectory() ? "/" : ""));
407 else
408 return new URL ("file:" + getAbsolutePath ()
409 + (isDirectory() ? "/" : ""));
410 }
411
412 private final native boolean performMkdir ();
413
414 public boolean mkdir ()
415 {
416 checkWrite();
417 return performMkdir ();
418 }
419
420 private static boolean mkdirs (File x)
421 {
422 if (x.isDirectory())
423 return true;
424 String p = x.getPath();
425 String parent = x.getParent();
426 if (parent != null)
427 {
428 x.path = parent;
429 if (! mkdirs (x))
430 return false;
431 x.path = p;
432 }
433 return x.mkdir();
434 }
435
436 public boolean mkdirs ()
437 {
438 checkWrite();
439 if (isDirectory ())
440 return false;
441 return mkdirs (new File (path));
442 }
443
444 private static synchronized String nextValue ()
445 {
446 return Long.toString(counter++, Character.MAX_RADIX);
447 }
448
449 /** @since 1.2 */
450 public static File createTempFile (String prefix, String suffix,
451 File directory)
452 throws IOException
453 {
454 // Grab the system temp directory if necessary
455 if (directory == null)
456 {
457 String dirname = tmpdir;
458 if (dirname == null)
459 throw
460 new IOException("Cannot determine system temporary directory");
461
462 directory = new File(dirname);
463 if (!directory.exists())
464 throw new IOException("System temporary directory "
465 + directory.getName() + " does not exist.");
466 if (!directory.isDirectory())
467 throw new IOException("System temporary directory "
468 + directory.getName()
469 + " is not really a directory.");
470 }
471
472 if (prefix.length () < 3)
473 throw new IllegalArgumentException ("Prefix too short: " + prefix);
474 if (suffix == null)
475 suffix = ".tmp";
476
477 // Truncation rules.
478 // `6' is the number of characters we generate.
479 if (prefix.length () + 6 + suffix.length () > maxPathLen)
480 {
481 int suf_len = 0;
482 if (suffix.charAt(0) == '.')
483 suf_len = 4;
484 suffix = suffix.substring(0, suf_len);
485 if (prefix.length () + 6 + suf_len > maxPathLen)
486 prefix = prefix.substring(0, maxPathLen - 6 - suf_len);
487 }
488
489 File f;
490
491 // How many times should we try? We choose 100.
492 for (int i = 0; i < 100; ++i)
493 {
494 // This is ugly.
495 String t = "ZZZZZZ" + nextValue ();
496 String l = prefix + t.substring(t.length() - 6) + suffix;
497 try
498 {
499 f = new File(directory, l);
500 if (f.createNewFile())
501 return f;
502 }
503 catch (IOException ignored)
504 {
505 }
506 }
507
508 throw new IOException ("cannot create temporary file");
509 }
510
511 private native boolean performSetReadOnly();
512
513 /** @since 1.2 */
514 public boolean setReadOnly()
515 {
516 checkWrite();
517 return performSetReadOnly();
518 }
519
520 private static native File[] performListRoots();
521
522 /** @since 1.2 */
523 public static File[] listRoots()
524 {
525 File[] roots = performListRoots();
526
527 SecurityManager s = System.getSecurityManager();
528 if (s != null)
529 {
530 // Only return roots to which the security manager permits read access.
531 int count = roots.length;
532 for (int i = 0; i < roots.length; i++)
533 {
534 try
535 {
536 s.checkRead(roots[i].path);
537 }
538 catch (SecurityException sx)
539 {
540 roots[i] = null;
541 count--;
542 }
543 }
544 if (count != roots.length)
545 {
546 File[] newRoots = new File[count];
547 int k = 0;
548 for (int i=0; i < roots.length; i++)
549 {
550 if (roots[i] != null)
551 newRoots[k++] = roots[i];
552 }
553 roots = newRoots;
554 }
555 }
556 return roots;
557 }
558
559 public static File createTempFile (String prefix, String suffix)
560 throws IOException
561 {
562 return createTempFile (prefix, suffix, null);
563 }
564
565 /** @since 1.2 */
566 public int compareTo(File other)
567 {
568 if (caseSensitive)
569 return path.compareTo (other.path);
570 else
571 return path.compareToIgnoreCase (other.path);
572 }
573
574 /** @since 1.2 */
575 public int compareTo(Object o)
576 {
577 File other = (File) o;
578 return compareTo (other);
579 }
580
581 private native boolean performRenameTo (File dest);
582 public boolean renameTo (File dest)
583 {
584 SecurityManager s = System.getSecurityManager();
585 String sname = getName();
586 String dname = dest.getName();
587 if (s != null)
588 {
589 s.checkWrite(sname);
590 s.checkWrite(dname);
591 }
592 return performRenameTo (dest);
593 }
594
595 private native boolean performSetLastModified(long time);
596
597 /** @since 1.2 */
598 public boolean setLastModified(long time)
599 {
600 checkWrite();
601 return performSetLastModified(time);
602 }
603
604 public static final String pathSeparator
605 = System.getProperty("path.separator");
606 public static final char pathSeparatorChar = pathSeparator.charAt(0);
607 public static final String separator = System.getProperty("file.separator");
608 public static final char separatorChar = separator.charAt(0);
609
610 static final String tmpdir = System.getProperty("java.io.tmpdir");
611 static int maxPathLen;
612 static boolean caseSensitive;
613 static String dupSeparator = separator + separator;
614
615 static
616 {
617 init_native();
618 }
619
620 // Native function called at class initialization. This should should
621 // set the maxPathLen and caseSensitive variables.
622 private static native void init_native();
623
624 // The path.
625 private String path;
626
627 // We keep a counter for use by createTempFile. We choose the first
628 // value randomly to try to avoid clashes with other VMs.
629 private static long counter = Double.doubleToLongBits (Math.random ());
630
631 private void checkWrite ()
632 {
633 SecurityManager s = System.getSecurityManager();
634 if (s != null)
635 s.checkWrite(path);
636 }
637
638 private void checkRead ()
639 {
640 SecurityManager s = System.getSecurityManager();
641 if (s != null)
642 s.checkRead(path);
643 }
644
645 /**
646 * Add this File to the set of files to be deleted upon normal
647 * termination.
648 *
649 * @since 1.2
650 */
651 // FIXME: This should use the ShutdownHook API once we implement that.
652 public void deleteOnExit ()
653 {
654 SecurityManager sm = System.getSecurityManager ();
655 if (sm != null)
656 sm.checkDelete (getName ());
657
658 FileDeleter.add (this);
659 }
660
661 private void writeObject (ObjectOutputStream oos) throws IOException
662 {
663 oos.defaultWriteObject ();
664 oos.writeChar (separatorChar);
665 }
666
667 private void readObject (ObjectInputStream ois)
668 throws ClassNotFoundException, IOException
669 {
670 ois.defaultReadObject ();
671
672 // If the file was from an OS with a different dir separator,
673 // fixup the path to use the separator on this OS.
674 char oldSeparatorChar = ois.readChar ();
675 if (oldSeparatorChar != separatorChar)
676 path = path.replace (oldSeparatorChar, separatorChar);
677 }
678
679 // QUERY arguments to access function.
680 private final static int READ = 0;
681 private final static int WRITE = 1;
682 private final static int EXISTS = 2;
683
684 // QUERY arguments to stat function.
685 private final static int DIRECTORY = 0;
686 private final static int ISFILE = 1;
687 private final static int ISHIDDEN = 2;
688
689 // QUERY arguments to attr function.
690 private final static int MODIFIED = 0;
691 private final static int LENGTH = 1;
692
693 private final native long attr (int query);
694 // On OSF1 V5.0, `stat' is a macro. It is easiest to use the name
695 // `_stat' instead. We do the same thing for `_access' just in
696 // case.
697 private final native boolean _access (int query);
698 private final native boolean _stat (int query);
699
700 private static final long serialVersionUID = 301077366599181567L;
701}
Note: See TracBrowser for help on using the repository browser.