source: trunk/src/gcc/libjava/java/io/File.java@ 680

Last change on this file since 680 was 2, checked in by bird, 23 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 13.2 KB
Line 
1// File.java - File name
2
3/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation
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 <[email protected]>
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.
100 if (plen > 1 && p.charAt(plen - 1) == separatorChar)
101 return p.substring(0, plen - 1);
102 else
103 return p;
104 }
105
106 StringBuffer newpath = new StringBuffer(plen);
107 int last = 0;
108 while (dupIndex != -1)
109 {
110 newpath.append(p.substring(last, dupIndex));
111 // Ignore the duplicate path characters.
112 while (p.charAt(dupIndex) == separatorChar)
113 {
114 dupIndex++;
115 if (dupIndex == plen)
116 return newpath.toString();
117 }
118 newpath.append(separatorChar);
119 last = dupIndex;
120 dupIndex = p.indexOf(dupSeparator, last);
121 }
122
123 // Again, ignore possible trailing separator.
124 int end;
125 if (plen > 1 && p.charAt(plen - 1) == separatorChar)
126 end = plen - 1;
127 else
128 end = plen;
129 newpath.append(p.substring(last, end));
130
131 return newpath.toString();
132 }
133
134 public File (String dirPath, String name)
135 {
136 if (name == null)
137 throw new NullPointerException ();
138 if (dirPath != null && dirPath.length() > 0)
139 {
140 // Try to be smart about the number of separator characters.
141 if (dirPath.charAt(dirPath.length() - 1) == separatorChar
142 || name.length() == 0)
143 path = normalizePath(dirPath + name);
144 else
145 path = normalizePath(dirPath + separatorChar + name);
146 }
147 else
148 path = normalizePath(name);
149 }
150
151 public File (File dir, String name)
152 {
153 this (dir == null ? null : dir.path, name);
154 }
155
156 // FIXME ???
157 public String getAbsolutePath ()
158 {
159 if (isAbsolute ())
160 return path;
161 return System.getProperty("user.dir") + separatorChar + path;
162 }
163
164 /** @since 1.2 */
165 public File getAbsoluteFile ()
166 {
167 return new File (getAbsolutePath());
168 }
169
170 public native String getCanonicalPath () throws IOException;
171
172 /** @since 1.2 */
173 public File getCanonicalFile () throws IOException
174 {
175 return new File (getCanonicalPath());
176 }
177
178 public String getName ()
179 {
180 int last = path.lastIndexOf(separatorChar);
181 return path.substring(last + 1);
182 }
183
184 public String getParent ()
185 {
186 int last = path.lastIndexOf(separatorChar);
187 if (last == -1)
188 return null;
189 // FIXME: POSIX assumption.
190 if (last == 0 && path.charAt (0) == '/')
191 ++last;
192 return path.substring(0, last);
193 }
194
195 /** @since 1.2 */
196 public File getParentFile ()
197 {
198 String parent = getParent ();
199 return (parent == null ? null : new File (parent));
200 }
201
202 public String getPath ()
203 {
204 return path;
205 }
206
207 public int hashCode ()
208 {
209 if (caseSensitive)
210 return (path.hashCode() ^ 1234321);
211 else
212 return (path.toLowerCase().hashCode() ^ 1234321);
213 }
214
215 public native boolean isAbsolute ();
216
217 public boolean isDirectory ()
218 {
219 checkRead();
220 return _stat (DIRECTORY);
221 }
222
223 public boolean isFile ()
224 {
225 checkRead();
226 return _stat (ISFILE);
227 }
228
229 /** @since 1.2 */
230 public boolean isHidden()
231 {
232 checkRead();
233 return _stat (ISHIDDEN);
234 }
235
236 public long lastModified ()
237 {
238 checkRead();
239 return attr (MODIFIED);
240 }
241
242 public long length ()
243 {
244 checkRead();
245 return attr (LENGTH);
246 }
247
248 private final native Object[] performList (FilenameFilter filter,
249 FileFilter fileFilter,
250 Class result_type);
251
252 public String[] list (FilenameFilter filter)
253 {
254 checkRead();
255 return (String[]) performList (filter, null, String.class);
256 }
257
258 public String[] list ()
259 {
260 checkRead();
261 return (String[]) performList (null, null, String.class);
262 }
263
264 /** @since 1.2 */
265 public File[] listFiles()
266 {
267 checkRead();
268 return (File[]) performList (null, null, File.class);
269 }
270
271 /** @since 1.2 */
272 public File[] listFiles(FilenameFilter filter)
273 {
274 checkRead();
275 return (File[]) performList (filter, null, File.class);
276 }
277
278 /** @since 1.2 */
279 public File[] listFiles(FileFilter filter)
280 {
281 checkRead();
282 return (File[]) performList (null, filter, File.class);
283 }
284
285 public String toString ()
286 {
287 return path;
288 }
289
290 public URL toURL () throws MalformedURLException
291 {
292 return new URL ("file://" + getAbsolutePath ()
293 + (isDirectory() ? "/" : ""));
294 }
295
296 private final native boolean performMkdir ();
297
298 public boolean mkdir ()
299 {
300 checkWrite();
301 return performMkdir ();
302 }
303
304 private static boolean mkdirs (File x)
305 {
306 if (x.isDirectory())
307 return true;
308 String p = x.getPath();
309 String parent = x.getParent();
310 if (parent != null)
311 {
312 x.path = parent;
313 if (! mkdirs (x))
314 return false;
315 x.path = p;
316 }
317 return x.mkdir();
318 }
319
320 public boolean mkdirs ()
321 {
322 checkWrite();
323 if (isDirectory ())
324 return false;
325 return mkdirs (new File (path));
326 }
327
328 private static synchronized String nextValue ()
329 {
330 return Long.toString(counter++, Character.MAX_RADIX);
331 }
332
333 /** @since 1.2 */
334 public static File createTempFile (String prefix, String suffix,
335 File directory)
336 throws IOException
337 {
338 // Grab the system temp directory if necessary
339 if (directory == null)
340 {
341 String dirname = tmpdir;
342 if (dirname == null)
343 throw
344 new IOException("Cannot determine system temporary directory");
345
346 directory = new File(dirname);
347 if (!directory.exists())
348 throw new IOException("System temporary directory "
349 + directory.getName() + " does not exist.");
350 if (!directory.isDirectory())
351 throw new IOException("System temporary directory "
352 + directory.getName()
353 + " is not really a directory.");
354 }
355
356 if (prefix.length () < 3)
357 throw new IllegalArgumentException ("Prefix too short: " + prefix);
358 if (suffix == null)
359 suffix = ".tmp";
360
361 // Truncation rules.
362 // `6' is the number of characters we generate.
363 if (prefix.length () + 6 + suffix.length () > maxPathLen)
364 {
365 int suf_len = 0;
366 if (suffix.charAt(0) == '.')
367 suf_len = 4;
368 suffix = suffix.substring(0, suf_len);
369 if (prefix.length () + 6 + suf_len > maxPathLen)
370 prefix = prefix.substring(0, maxPathLen - 6 - suf_len);
371 }
372
373 File f;
374
375 // How many times should we try? We choose 100.
376 for (int i = 0; i < 100; ++i)
377 {
378 // This is ugly.
379 String t = "ZZZZZZ" + nextValue ();
380 String l = prefix + t.substring(t.length() - 6) + suffix;
381 try
382 {
383 f = new File(directory, l);
384 if (f.createNewFile())
385 return f;
386 }
387 catch (IOException ignored)
388 {
389 }
390 }
391
392 throw new IOException ("cannot create temporary file");
393 }
394
395 private native boolean performSetReadOnly();
396
397 /** @since 1.2 */
398 public boolean setReadOnly()
399 {
400 checkWrite();
401 return performSetReadOnly();
402 }
403
404 private static native File[] performListRoots();
405
406 /** @since 1.2 */
407 public static File[] listRoots()
408 {
409 File[] roots = performListRoots();
410
411 SecurityManager s = System.getSecurityManager();
412 if (s != null)
413 {
414 // Only return roots to which the security manager permits read access.
415 int count = roots.length;
416 for (int i = 0; i < roots.length; i++)
417 {
418 try
419 {
420 s.checkRead(roots[i].path);
421 }
422 catch (SecurityException sx)
423 {
424 roots[i] = null;
425 count--;
426 }
427 }
428 if (count != roots.length)
429 {
430 File[] newRoots = new File[count];
431 int k = 0;
432 for (int i=0; i < roots.length; i++)
433 {
434 if (roots[i] != null)
435 newRoots[k++] = roots[i];
436 }
437 roots = newRoots;
438 }
439 }
440 return roots;
441 }
442
443 public static File createTempFile (String prefix, String suffix)
444 throws IOException
445 {
446 return createTempFile (prefix, suffix, null);
447 }
448
449 /** @since 1.2 */
450 public int compareTo(File other)
451 {
452 if (caseSensitive)
453 return path.compareTo (other.path);
454 else
455 return path.compareToIgnoreCase (other.path);
456 }
457
458 /** @since 1.2 */
459 public int compareTo(Object o)
460 {
461 File other = (File) o;
462 return compareTo (other);
463 }
464
465 private native boolean performRenameTo (File dest);
466 public boolean renameTo (File dest)
467 {
468 SecurityManager s = System.getSecurityManager();
469 String sname = getName();
470 String dname = dest.getName();
471 if (s != null)
472 {
473 s.checkWrite(sname);
474 s.checkWrite(dname);
475 }
476 return performRenameTo (dest);
477 }
478
479 private native boolean performSetLastModified(long time);
480
481 /** @since 1.2 */
482 public boolean setLastModified(long time)
483 {
484 checkWrite();
485 return performSetLastModified(time);
486 }
487
488 public static final String pathSeparator
489 = System.getProperty("path.separator");
490 public static final char pathSeparatorChar = pathSeparator.charAt(0);
491 public static final String separator = System.getProperty("file.separator");
492 public static final char separatorChar = separator.charAt(0);
493
494 static final String tmpdir = System.getProperty("java.io.tmpdir");
495 static int maxPathLen;
496 static boolean caseSensitive;
497 static String dupSeparator = separator + separator;
498
499 static
500 {
501 init_native();
502 }
503
504 // Native function called at class initialization. This should should
505 // set the maxPathLen and caseSensitive variables.
506 private static native void init_native();
507
508 // The path.
509 private String path;
510
511 // We keep a counter for use by createTempFile. We choose the first
512 // value randomly to try to avoid clashes with other VMs.
513 private static long counter = Double.doubleToLongBits (Math.random ());
514
515 private void checkWrite ()
516 {
517 SecurityManager s = System.getSecurityManager();
518 if (s != null)
519 s.checkWrite(path);
520 }
521
522 private void checkRead ()
523 {
524 SecurityManager s = System.getSecurityManager();
525 if (s != null)
526 s.checkRead(path);
527 }
528
529 /**
530 * Add this File to the set of files to be deleted upon normal
531 * termination.
532 *
533 * @since 1.2
534 */
535 // FIXME: This should use the ShutdownHook API once we implement that.
536 public void deleteOnExit ()
537 {
538 SecurityManager sm = System.getSecurityManager ();
539 if (sm != null)
540 sm.checkDelete (getName ());
541
542 FileDeleter.add (this);
543 }
544
545 private void writeObject (ObjectOutputStream oos) throws IOException
546 {
547 oos.defaultWriteObject ();
548 oos.writeChar (separatorChar);
549 }
550
551 private void readObject (ObjectInputStream ois)
552 throws ClassNotFoundException, IOException
553 {
554 ois.defaultReadObject ();
555
556 // If the file was from an OS with a different dir separator,
557 // fixup the path to use the separator on this OS.
558 char oldSeparatorChar = ois.readChar ();
559 if (oldSeparatorChar != separatorChar)
560 path = path.replace (oldSeparatorChar, separatorChar);
561 }
562
563 // QUERY arguments to access function.
564 private final static int READ = 0;
565 private final static int WRITE = 1;
566 private final static int EXISTS = 2;
567
568 // QUERY arguments to stat function.
569 private final static int DIRECTORY = 0;
570 private final static int ISFILE = 1;
571 private final static int ISHIDDEN = 2;
572
573 // QUERY arguments to attr function.
574 private final static int MODIFIED = 0;
575 private final static int LENGTH = 1;
576
577 private final native long attr (int query);
578 // On OSF1 V5.0, `stat' is a macro. It is easiest to use the name
579 // `_stat' instead. We do the same thing for `_access' just in
580 // case.
581 private final native boolean _access (int query);
582 private final native boolean _stat (int query);
583
584 private static final long serialVersionUID = 301077366599181567L;
585}
Note: See TracBrowser for help on using the repository browser.