1 /*
2 * Copyright 1994-2007 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package java.io;
27
28 import java.net.URI;
29 import java.net.URL;
30 import java.net.MalformedURLException;
31 import java.net.URISyntaxException;
32 import java.util.ArrayList;
33 import java.util.Map;
34 import java.util.Hashtable;
35 import java.util.Random;
36 import java.security.AccessController;
37 import java.security.AccessControlException;
38 import sun.security.action.GetPropertyAction;
39
40
41 /**
42 * An abstract representation of file and directory pathnames.
43 *
44 * <p> User interfaces and operating systems use system-dependent <em>pathname
45 * strings</em> to name files and directories. This class presents an
46 * abstract, system-independent view of hierarchical pathnames. An
47 * <em>abstract pathname</em> has two components:
48 *
49 * <ol>
50 * <li> An optional system-dependent <em>prefix</em> string,
51 * such as a disk-drive specifier, <code>"/"</code> for the UNIX root
52 * directory, or <code>"\\\\"</code> for a Microsoft Windows UNC pathname, and
53 * <li> A sequence of zero or more string <em>names</em>.
54 * </ol>
55 *
56 * The first name in an abstract pathname may be a directory name or, in the
57 * case of Microsoft Windows UNC pathnames, a hostname. Each subsequent name
58 * in an abstract pathname denotes a directory; the last name may denote
59 * either a directory or a file. The <em>empty</em> abstract pathname has no
60 * prefix and an empty name sequence.
61 *
62 * <p> The conversion of a pathname string to or from an abstract pathname is
63 * inherently system-dependent. When an abstract pathname is converted into a
64 * pathname string, each name is separated from the next by a single copy of
65 * the default <em>separator character</em>. The default name-separator
66 * character is defined by the system property <code>file.separator</code>, and
67 * is made available in the public static fields <code>{@link
68 * #separator}</code> and <code>{@link #separatorChar}</code> of this class.
69 * When a pathname string is converted into an abstract pathname, the names
70 * within it may be separated by the default name-separator character or by any
71 * other name-separator character that is supported by the underlying system.
72 *
73 * <p> A pathname, whether abstract or in string form, may be either
74 * <em>absolute</em> or <em>relative</em>. An absolute pathname is complete in
75 * that no other information is required in order to locate the file that it
76 * denotes. A relative pathname, in contrast, must be interpreted in terms of
77 * information taken from some other pathname. By default the classes in the
78 * <code>java.io</code> package always resolve relative pathnames against the
79 * current user directory. This directory is named by the system property
80 * <code>user.dir</code>, and is typically the directory in which the Java
81 * virtual machine was invoked.
82 *
83 * <p> The <em>parent</em> of an abstract pathname may be obtained by invoking
84 * the {@link #getParent} method of this class and consists of the pathname's
85 * prefix and each name in the pathname's name sequence except for the last.
86 * Each directory's absolute pathname is an ancestor of any <tt>File</tt>
87 * object with an absolute abstract pathname which begins with the directory's
88 * absolute pathname. For example, the directory denoted by the abstract
89 * pathname <tt>"/usr"</tt> is an ancestor of the directory denoted by the
90 * pathname <tt>"/usr/local/bin"</tt>.
91 *
92 * <p> The prefix concept is used to handle root directories on UNIX platforms,
93 * and drive specifiers, root directories and UNC pathnames on Microsoft Windows platforms,
94 * as follows:
95 *
96 * <ul>
97 *
98 * <li> For UNIX platforms, the prefix of an absolute pathname is always
99 * <code>"/"</code>. Relative pathnames have no prefix. The abstract pathname
100 * denoting the root directory has the prefix <code>"/"</code> and an empty
101 * name sequence.
102 *
103 * <li> For Microsoft Windows platforms, the prefix of a pathname that contains a drive
104 * specifier consists of the drive letter followed by <code>":"</code> and
105 * possibly followed by <code>"\\"</code> if the pathname is absolute. The
106 * prefix of a UNC pathname is <code>"\\\\"</code>; the hostname and the share
107 * name are the first two names in the name sequence. A relative pathname that
108 * does not specify a drive has no prefix.
109 *
110 * </ul>
111 *
112 * <p> Instances of this class may or may not denote an actual file-system
113 * object such as a file or a directory. If it does denote such an object
114 * then that object resides in a <i>partition</i>. A partition is an
115 * operating system-specific portion of storage for a file system. A single
116 * storage device (e.g. a physical disk-drive, flash memory, CD-ROM) may
117 * contain multiple partitions. The object, if any, will reside on the
118 * partition <a name="partName">named</a> by some ancestor of the absolute
119 * form of this pathname.
120 *
121 * <p> A file system may implement restrictions to certain operations on the
122 * actual file-system object, such as reading, writing, and executing. These
123 * restrictions are collectively known as <i>access permissions</i>. The file
124 * system may have multiple sets of access permissions on a single object.
125 * For example, one set may apply to the object's <i>owner</i>, and another
126 * may apply to all other users. The access permissions on an object may
127 * cause some methods in this class to fail.
128 *
129 * <p> Instances of the <code>File</code> class are immutable; that is, once
130 * created, the abstract pathname represented by a <code>File</code> object
131 * will never change.
132 *
133 * @author unascribed
134 * @since JDK1.0
135 */
136
137 public class File
138 implements Serializable, Comparable<File>
139 {
140
141 /**
142 * The FileSystem object representing the platform's local file system.
143 */
144 static private FileSystem fs = FileSystem.getFileSystem();
145
146 /**
147 * This abstract pathname's normalized pathname string. A normalized
148 * pathname string uses the default name-separator character and does not
149 * contain any duplicate or redundant separators.
150 *
151 * @serial
152 */
153 private String path;
154
155 /**
156 * The length of this abstract pathname's prefix, or zero if it has no
157 * prefix.
158 */
159 private transient int prefixLength;
160
161 /**
162 * Returns the length of this abstract pathname's prefix.
163 * For use by FileSystem classes.
164 */
165 int getPrefixLength() {
166 return prefixLength;
167 }
168
169 /**
170 * The system-dependent default name-separator character. This field is
171 * initialized to contain the first character of the value of the system
172 * property <code>file.separator</code>. On UNIX systems the value of this
173 * field is <code>'/'</code>; on Microsoft Windows systems it is <code>'\\'</code>.
174 *
175 * @see java.lang.System#getProperty(java.lang.String)
176 */
177 public static final char separatorChar = fs.getSeparator();
178
179 /**
180 * The system-dependent default name-separator character, represented as a
181 * string for convenience. This string contains a single character, namely
182 * <code>{@link #separatorChar}</code>.
183 */
184 public static final String separator = "" + separatorChar;
185
186 /**
187 * The system-dependent path-separator character. This field is
188 * initialized to contain the first character of the value of the system
189 * property <code>path.separator</code>. This character is used to
190 * separate filenames in a sequence of files given as a <em>path list</em>.
191 * On UNIX systems, this character is <code>':'</code>; on Microsoft Windows systems it
192 * is <code>';'</code>.
193 *
194 * @see java.lang.System#getProperty(java.lang.String)
195 */
196 public static final char pathSeparatorChar = fs.getPathSeparator();
197
198 /**
199 * The system-dependent path-separator character, represented as a string
200 * for convenience. This string contains a single character, namely
201 * <code>{@link #pathSeparatorChar}</code>.
202 */
203 public static final String pathSeparator = "" + pathSeparatorChar;
204
205
206 /* -- Constructors -- */
207
208 /**
209 * Internal constructor for already-normalized pathname strings.
210 */
211 private File(String pathname, int prefixLength) {
212 this.path = pathname;
213 this.prefixLength = prefixLength;
214 }
215
216 /**
217 * Internal constructor for already-normalized pathname strings.
218 * The parameter order is used to disambiguate this method from the
219 * public(File, String) constructor.
220 */
221 private File(String child, File parent) {
222 assert parent.path != null;
223 assert (!parent.path.equals(""));
224 this.path = fs.resolve(parent.path, child);
225 this.prefixLength = parent.prefixLength;
226 }
227
228 /**
229 * Creates a new <code>File</code> instance by converting the given
230 * pathname string into an abstract pathname. If the given string is
231 * the empty string, then the result is the empty abstract pathname.
232 *
233 * @param pathname A pathname string
234 * @throws NullPointerException
235 * If the <code>pathname</code> argument is <code>null</code>
236 */
237 public File(String pathname) {
238 if (pathname == null) {
239 throw new NullPointerException();
240 }
241 this.path = fs.normalize(pathname);
242 this.prefixLength = fs.prefixLength(this.path);
243 }
244
245 /* Note: The two-argument File constructors do not interpret an empty
246 parent abstract pathname as the current user directory. An empty parent
247 instead causes the child to be resolved against the system-dependent
248 directory defined by the FileSystem.getDefaultParent method. On Unix
249 this default is "/", while on Microsoft Windows it is "\\". This is required for
250 compatibility with the original behavior of this class. */
251
252 /**
253 * Creates a new <code>File</code> instance from a parent pathname string
254 * and a child pathname string.
255 *
256 * <p> If <code>parent</code> is <code>null</code> then the new
257 * <code>File</code> instance is created as if by invoking the
258 * single-argument <code>File</code> constructor on the given
259 * <code>child</code> pathname string.
260 *
261 * <p> Otherwise the <code>parent</code> pathname string is taken to denote
262 * a directory, and the <code>child</code> pathname string is taken to
263 * denote either a directory or a file. If the <code>child</code> pathname
264 * string is absolute then it is converted into a relative pathname in a
265 * system-dependent way. If <code>parent</code> is the empty string then
266 * the new <code>File</code> instance is created by converting
267 * <code>child</code> into an abstract pathname and resolving the result
268 * against a system-dependent default directory. Otherwise each pathname
269 * string is converted into an abstract pathname and the child abstract
270 * pathname is resolved against the parent.
271 *
272 * @param parent The parent pathname string
273 * @param child The child pathname string
274 * @throws NullPointerException
275 * If <code>child</code> is <code>null</code>
276 */
277 public File(String parent, String child) {
278 if (child == null) {
279 throw new NullPointerException();
280 }
281 if (parent != null) {
282 if (parent.equals("")) {
283 this.path = fs.resolve(fs.getDefaultParent(),
284 fs.normalize(child));
285 } else {
286 this.path = fs.resolve(fs.normalize(parent),
287 fs.normalize(child));
288 }
289 } else {
290 this.path = fs.normalize(child);
291 }
292 this.prefixLength = fs.prefixLength(this.path);
293 }
294
295 /**
296 * Creates a new <code>File</code> instance from a parent abstract
297 * pathname and a child pathname string.
298 *
299 * <p> If <code>parent</code> is <code>null</code> then the new
300 * <code>File</code> instance is created as if by invoking the
301 * single-argument <code>File</code> constructor on the given
302 * <code>child</code> pathname string.
303 *
304 * <p> Otherwise the <code>parent</code> abstract pathname is taken to
305 * denote a directory, and the <code>child</code> pathname string is taken
306 * to denote either a directory or a file. If the <code>child</code>
307 * pathname string is absolute then it is converted into a relative
308 * pathname in a system-dependent way. If <code>parent</code> is the empty
309 * abstract pathname then the new <code>File</code> instance is created by
310 * converting <code>child</code> into an abstract pathname and resolving
311 * the result against a system-dependent default directory. Otherwise each
312 * pathname string is converted into an abstract pathname and the child
313 * abstract pathname is resolved against the parent.
314 *
315 * @param parent The parent abstract pathname
316 * @param child The child pathname string
317 * @throws NullPointerException
318 * If <code>child</code> is <code>null</code>
319 */
320 public File(File parent, String child) {
321 if (child == null) {
322 throw new NullPointerException();
323 }
324 if (parent != null) {
325 if (parent.path.equals("")) {
326 this.path = fs.resolve(fs.getDefaultParent(),
327 fs.normalize(child));
328 } else {
329 this.path = fs.resolve(parent.path,
330 fs.normalize(child));
331 }
332 } else {
333 this.path = fs.normalize(child);
334 }
335 this.prefixLength = fs.prefixLength(this.path);
336 }
337
338 /**
339 * Creates a new <tt>File</tt> instance by converting the given
340 * <tt>file:</tt> URI into an abstract pathname.
341 *
342 * <p> The exact form of a <tt>file:</tt> URI is system-dependent, hence
343 * the transformation performed by this constructor is also
344 * system-dependent.
345 *
346 * <p> For a given abstract pathname <i>f</i> it is guaranteed that
347 *
348 * <blockquote><tt>
349 * new File(</tt><i> f</i><tt>.{@link #toURI() toURI}()).equals(</tt><i> f</i><tt>.{@link #getAbsoluteFile() getAbsoluteFile}())
350 * </tt></blockquote>
351 *
352 * so long as the original abstract pathname, the URI, and the new abstract
353 * pathname are all created in (possibly different invocations of) the same
354 * Java virtual machine. This relationship typically does not hold,
355 * however, when a <tt>file:</tt> URI that is created in a virtual machine
356 * on one operating system is converted into an abstract pathname in a
357 * virtual machine on a different operating system.
358 *
359 * @param uri
360 * An absolute, hierarchical URI with a scheme equal to
361 * <tt>"file"</tt>, a non-empty path component, and undefined
362 * authority, query, and fragment components
363 *
364 * @throws NullPointerException
365 * If <tt>uri</tt> is <tt>null</tt>
366 *
367 * @throws IllegalArgumentException
368 * If the preconditions on the parameter do not hold
369 *
370 * @see #toURI()
371 * @see java.net.URI
372 * @since 1.4
373 */
374 public File(URI uri) {
375
376 // Check our many preconditions
377 if (!uri.isAbsolute())
378 throw new IllegalArgumentException("URI is not absolute");
379 if (uri.isOpaque())
380 throw new IllegalArgumentException("URI is not hierarchical");
381 String scheme = uri.getScheme();
382 if ((scheme == null) || !scheme.equalsIgnoreCase("file"))
383 throw new IllegalArgumentException("URI scheme is not \"file\"");
384 if (uri.getAuthority() != null)
385 throw new IllegalArgumentException("URI has an authority component");
386 if (uri.getFragment() != null)
387 throw new IllegalArgumentException("URI has a fragment component");
388 if (uri.getQuery() != null)
389 throw new IllegalArgumentException("URI has a query component");
390 String p = uri.getPath();
391 if (p.equals(""))
392 throw new IllegalArgumentException("URI path component is empty");
393
394 // Okay, now initialize
395 p = fs.fromURIPath(p);
396 if (File.separatorChar != '/')
397 p = p.replace('/', File.separatorChar);
398 this.path = fs.normalize(p);
399 this.prefixLength = fs.prefixLength(this.path);
400 }
401
402
403 /* -- Path-component accessors -- */
404
405 /**
406 * Returns the name of the file or directory denoted by this abstract
407 * pathname. This is just the last name in the pathname's name
408 * sequence. If the pathname's name sequence is empty, then the empty
409 * string is returned.
410 *
411 * @return The name of the file or directory denoted by this abstract
412 * pathname, or the empty string if this pathname's name sequence
413 * is empty
414 */
415 public String getName() {
416 int index = path.lastIndexOf(separatorChar);
417 if (index < prefixLength) return path.substring(prefixLength);
418 return path.substring(index + 1);
419 }
420
421 /**
422 * Returns the pathname string of this abstract pathname's parent, or
423 * <code>null</code> if this pathname does not name a parent directory.
424 *
425 * <p> The <em>parent</em> of an abstract pathname consists of the
426 * pathname's prefix, if any, and each name in the pathname's name
427 * sequence except for the last. If the name sequence is empty then
428 * the pathname does not name a parent directory.
429 *
430 * @return The pathname string of the parent directory named by this
431 * abstract pathname, or <code>null</code> if this pathname
432 * does not name a parent
433 */
434 public String getParent() {
435 int index = path.lastIndexOf(separatorChar);
436 if (index < prefixLength) {
437 if ((prefixLength > 0) && (path.length() > prefixLength))
438 return path.substring(0, prefixLength);
439 return null;
440 }
441 return path.substring(0, index);
442 }
443
444 /**
445 * Returns the abstract pathname of this abstract pathname's parent,
446 * or <code>null</code> if this pathname does not name a parent
447 * directory.
448 *
449 * <p> The <em>parent</em> of an abstract pathname consists of the
450 * pathname's prefix, if any, and each name in the pathname's name
451 * sequence except for the last. If the name sequence is empty then
452 * the pathname does not name a parent directory.
453 *
454 * @return The abstract pathname of the parent directory named by this
455 * abstract pathname, or <code>null</code> if this pathname
456 * does not name a parent
457 *
458 * @since 1.2
459 */
460 public File getParentFile() {
461 String p = this.getParent();
462 if (p == null) return null;
463 return new File(p, this.prefixLength);
464 }
465
466 /**
467 * Converts this abstract pathname into a pathname string. The resulting
468 * string uses the {@link #separator default name-separator character} to
469 * separate the names in the name sequence.
470 *
471 * @return The string form of this abstract pathname
472 */
473 public String getPath() {
474 return path;
475 }
476
477
478 /* -- Path operations -- */
479
480 /**
481 * Tests whether this abstract pathname is absolute. The definition of
482 * absolute pathname is system dependent. On UNIX systems, a pathname is
483 * absolute if its prefix is <code>"/"</code>. On Microsoft Windows systems, a
484 * pathname is absolute if its prefix is a drive specifier followed by
485 * <code>"\\"</code>, or if its prefix is <code>"\\\\"</code>.
486 *
487 * @return <code>true</code> if this abstract pathname is absolute,
488 * <code>false</code> otherwise
489 */
490 public boolean isAbsolute() {
491 return fs.isAbsolute(this);
492 }
493
494 /**
495 * Returns the absolute pathname string of this abstract pathname.
496 *
497 * <p> If this abstract pathname is already absolute, then the pathname
498 * string is simply returned as if by the <code>{@link #getPath}</code>
499 * method. If this abstract pathname is the empty abstract pathname then
500 * the pathname string of the current user directory, which is named by the
501 * system property <code>user.dir</code>, is returned. Otherwise this
502 * pathname is resolved in a system-dependent way. On UNIX systems, a
503 * relative pathname is made absolute by resolving it against the current
504 * user directory. On Microsoft Windows systems, a relative pathname is made absolute
505 * by resolving it against the current directory of the drive named by the
506 * pathname, if any; if not, it is resolved against the current user
507 * directory.
508 *
509 * @return The absolute pathname string denoting the same file or
510 * directory as this abstract pathname
511 *
512 * @throws SecurityException
513 * If a required system property value cannot be accessed.
514 *
515 * @see java.io.File#isAbsolute()
516 */
517 public String getAbsolutePath() {
518 return fs.resolve(this);
519 }
520
521 /**
522 * Returns the absolute form of this abstract pathname. Equivalent to
523 * <code>new File(this.{@link #getAbsolutePath})</code>.
524 *
525 * @return The absolute abstract pathname denoting the same file or
526 * directory as this abstract pathname
527 *
528 * @throws SecurityException
529 * If a required system property value cannot be accessed.
530 *
531 * @since 1.2
532 */
533 public File getAbsoluteFile() {
534 String absPath = getAbsolutePath();
535 return new File(absPath, fs.prefixLength(absPath));
536 }
537
538 /**
539 * Returns the canonical pathname string of this abstract pathname.
540 *
541 * <p> A canonical pathname is both absolute and unique. The precise
542 * definition of canonical form is system-dependent. This method first
543 * converts this pathname to absolute form if necessary, as if by invoking the
544 * {@link #getAbsolutePath} method, and then maps it to its unique form in a
545 * system-dependent way. This typically involves removing redundant names
546 * such as <tt>"."</tt> and <tt>".."</tt> from the pathname, resolving
547 * symbolic links (on UNIX platforms), and converting drive letters to a
548 * standard case (on Microsoft Windows platforms).
549 *
550 * <p> Every pathname that denotes an existing file or directory has a
551 * unique canonical form. Every pathname that denotes a nonexistent file
552 * or directory also has a unique canonical form. The canonical form of
553 * the pathname of a nonexistent file or directory may be different from
554 * the canonical form of the same pathname after the file or directory is
555 * created. Similarly, the canonical form of the pathname of an existing
556 * file or directory may be different from the canonical form of the same
557 * pathname after the file or directory is deleted.
558 *
559 * @return The canonical pathname string denoting the same file or
560 * directory as this abstract pathname
561 *
562 * @throws IOException
563 * If an I/O error occurs, which is possible because the
564 * construction of the canonical pathname may require
565 * filesystem queries
566 *
567 * @throws SecurityException
568 * If a required system property value cannot be accessed, or
569 * if a security manager exists and its <code>{@link
570 * java.lang.SecurityManager#checkRead}</code> method denies
571 * read access to the file
572 *
573 * @since JDK1.1
574 */
575 public String getCanonicalPath() throws IOException {
576 return fs.canonicalize(fs.resolve(this));
577 }
578
579 /**
580 * Returns the canonical form of this abstract pathname. Equivalent to
581 * <code>new File(this.{@link #getCanonicalPath})</code>.
582 *
583 * @return The canonical pathname string denoting the same file or
584 * directory as this abstract pathname
585 *
586 * @throws IOException
587 * If an I/O error occurs, which is possible because the
588 * construction of the canonical pathname may require
589 * filesystem queries
590 *
591 * @throws SecurityException
592 * If a required system property value cannot be accessed, or
593 * if a security manager exists and its <code>{@link
594 * java.lang.SecurityManager#checkRead}</code> method denies
595 * read access to the file
596 *
597 * @since 1.2
598 */
599 public File getCanonicalFile() throws IOException {
600 String canonPath = getCanonicalPath();
601 return new File(canonPath, fs.prefixLength(canonPath));
602 }
603
604 private static String slashify(String path, boolean isDirectory) {
605 String p = path;
606 if (File.separatorChar != '/')
607 p = p.replace(File.separatorChar, '/');
608 if (!p.startsWith("/"))
609 p = "/" + p;
610 if (!p.endsWith("/") && isDirectory)
611 p = p + "/";
612 return p;
613 }
614
615 /**
616 * Converts this abstract pathname into a <code>file:</code> URL. The
617 * exact form of the URL is system-dependent. If it can be determined that
618 * the file denoted by this abstract pathname is a directory, then the
619 * resulting URL will end with a slash.
620 *
621 * @return A URL object representing the equivalent file URL
622 *
623 * @throws MalformedURLException
624 * If the path cannot be parsed as a URL
625 *
626 * @see #toURI()
627 * @see java.net.URI
628 * @see java.net.URI#toURL()
629 * @see java.net.URL
630 * @since 1.2
631 *
632 * @deprecated This method does not automatically escape characters that
633 * are illegal in URLs. It is recommended that new code convert an
634 * abstract pathname into a URL by first converting it into a URI, via the
635 * {@link #toURI() toURI} method, and then converting the URI into a URL
636 * via the {@link java.net.URI#toURL() URI.toURL} method.
637 */
638 @Deprecated
639 public URL toURL() throws MalformedURLException {
640 return new URL("file", "", slashify(getAbsolutePath(), isDirectory()));
641 }
642
643 /**
644 * Constructs a <tt>file:</tt> URI that represents this abstract pathname.
645 *
646 * <p> The exact form of the URI is system-dependent. If it can be
647 * determined that the file denoted by this abstract pathname is a
648 * directory, then the resulting URI will end with a slash.
649 *
650 * <p> For a given abstract pathname <i>f</i>, it is guaranteed that
651 *
652 * <blockquote><tt>
653 * new {@link #File(java.net.URI) File}(</tt><i> f</i><tt>.toURI()).equals(</tt><i> f</i><tt>.{@link #getAbsoluteFile() getAbsoluteFile}())
654 * </tt></blockquote>
655 *
656 * so long as the original abstract pathname, the URI, and the new abstract
657 * pathname are all created in (possibly different invocations of) the same
658 * Java virtual machine. Due to the system-dependent nature of abstract
659 * pathnames, however, this relationship typically does not hold when a
660 * <tt>file:</tt> URI that is created in a virtual machine on one operating
661 * system is converted into an abstract pathname in a virtual machine on a
662 * different operating system.
663 *
664 * @return An absolute, hierarchical URI with a scheme equal to
665 * <tt>"file"</tt>, a path representing this abstract pathname,
666 * and undefined authority, query, and fragment components
667 * @throws SecurityException If a required system property value cannot
668 * be accessed.
669 *
670 * @see #File(java.net.URI)
671 * @see java.net.URI
672 * @see java.net.URI#toURL()
673 * @since 1.4
674 */
675 public URI toURI() {
676 try {
677 File f = getAbsoluteFile();
678 String sp = slashify(f.getPath(), f.isDirectory());
679 if (sp.startsWith("//"))
680 sp = "//" + sp;
681 return new URI("file", null, sp, null);
682 } catch (URISyntaxException x) {
683 throw new Error(x); // Can't happen
684 }
685 }
686
687
688 /* -- Attribute accessors -- */
689
690 /**
691 * Tests whether the application can read the file denoted by this
692 * abstract pathname.
693 *
694 * @return <code>true</code> if and only if the file specified by this
695 * abstract pathname exists <em>and</em> can be read by the
696 * application; <code>false</code> otherwise
697 *
698 * @throws SecurityException
699 * If a security manager exists and its <code>{@link
700 * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
701 * method denies read access to the file
702 */
703 public boolean canRead() {
704 SecurityManager security = System.getSecurityManager();
705 if (security != null) {
706 security.checkRead(path);
707 }
708 return fs.checkAccess(this, FileSystem.ACCESS_READ);
709 }
710
711 /**
712 * Tests whether the application can modify the file denoted by this
713 * abstract pathname.
714 *
715 * @return <code>true</code> if and only if the file system actually
716 * contains a file denoted by this abstract pathname <em>and</em>
717 * the application is allowed to write to the file;
718 * <code>false</code> otherwise.
719 *
720 * @throws SecurityException
721 * If a security manager exists and its <code>{@link
722 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
723 * method denies write access to the file
724 */
725 public boolean canWrite() {
726 SecurityManager security = System.getSecurityManager();
727 if (security != null) {
728 security.checkWrite(path);
729 }
730 return fs.checkAccess(this, FileSystem.ACCESS_WRITE);
731 }
732
733 /**
734 * Tests whether the file or directory denoted by this abstract pathname
735 * exists.
736 *
737 * @return <code>true</code> if and only if the file or directory denoted
738 * by this abstract pathname exists; <code>false</code> otherwise
739 *
740 * @throws SecurityException
741 * If a security manager exists and its <code>{@link
742 * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
743 * method denies read access to the file or directory
744 */
745 public boolean exists() {
746 SecurityManager security = System.getSecurityManager();
747 if (security != null) {
748 security.checkRead(path);
749 }
750 return ((fs.getBooleanAttributes(this) & FileSystem.BA_EXISTS) != 0);
751 }
752
753 /**
754 * Tests whether the file denoted by this abstract pathname is a
755 * directory.
756 *
757 * @return <code>true</code> if and only if the file denoted by this
758 * abstract pathname exists <em>and</em> is a directory;
759 * <code>false</code> otherwise
760 *
761 * @throws SecurityException
762 * If a security manager exists and its <code>{@link
763 * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
764 * method denies read access to the file
765 */
766 public boolean isDirectory() {
767 SecurityManager security = System.getSecurityManager();
768 if (security != null) {
769 security.checkRead(path);
770 }
771 return ((fs.getBooleanAttributes(this) & FileSystem.BA_DIRECTORY)
772 != 0);
773 }
774
775 /**
776 * Tests whether the file denoted by this abstract pathname is a normal
777 * file. A file is <em>normal</em> if it is not a directory and, in
778 * addition, satisfies other system-dependent criteria. Any non-directory
779 * file created by a Java application is guaranteed to be a normal file.
780 *
781 * @return <code>true</code> if and only if the file denoted by this
782 * abstract pathname exists <em>and</em> is a normal file;
783 * <code>false</code> otherwise
784 *
785 * @throws SecurityException
786 * If a security manager exists and its <code>{@link
787 * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
788 * method denies read access to the file
789 */
790 public boolean isFile() {
791 SecurityManager security = System.getSecurityManager();
792 if (security != null) {
793 security.checkRead(path);
794 }
795 return ((fs.getBooleanAttributes(this) & FileSystem.BA_REGULAR) != 0);
796 }
797
798 /**
799 * Tests whether the file named by this abstract pathname is a hidden
800 * file. The exact definition of <em>hidden</em> is system-dependent. On
801 * UNIX systems, a file is considered to be hidden if its name begins with
802 * a period character (<code>'.'</code>). On Microsoft Windows systems, a file is
803 * considered to be hidden if it has been marked as such in the filesystem.
804 *
805 * @return <code>true</code> if and only if the file denoted by this
806 * abstract pathname is hidden according to the conventions of the
807 * underlying platform
808 *
809 * @throws SecurityException
810 * If a security manager exists and its <code>{@link
811 * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
812 * method denies read access to the file
813 *
814 * @since 1.2
815 */
816 public boolean isHidden() {
817 SecurityManager security = System.getSecurityManager();
818 if (security != null) {
819 security.checkRead(path);
820 }
821 return ((fs.getBooleanAttributes(this) & FileSystem.BA_HIDDEN) != 0);
822 }
823
824 /**
825 * Returns the time that the file denoted by this abstract pathname was
826 * last modified.
827 *
828 * @return A <code>long</code> value representing the time the file was
829 * last modified, measured in milliseconds since the epoch
830 * (00:00:00 GMT, January 1, 1970), or <code>0L</code> if the
831 * file does not exist or if an I/O error occurs
832 *
833 * @throws SecurityException
834 * If a security manager exists and its <code>{@link
835 * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
836 * method denies read access to the file
837 */
838 public long lastModified() {
839 SecurityManager security = System.getSecurityManager();
840 if (security != null) {
841 security.checkRead(path);
842 }
843 return fs.getLastModifiedTime(this);
844 }
845
846 /**
847 * Returns the length of the file denoted by this abstract pathname.
848 * The return value is unspecified if this pathname denotes a directory.
849 *
850 * @return The length, in bytes, of the file denoted by this abstract
851 * pathname, or <code>0L</code> if the file does not exist. Some
852 * operating systems may return <code>0L</code> for pathnames
853 * denoting system-dependent entities such as devices or pipes.
854 *
855 * @throws SecurityException
856 * If a security manager exists and its <code>{@link
857 * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
858 * method denies read access to the file
859 */
860 public long length() {
861 SecurityManager security = System.getSecurityManager();
862 if (security != null) {
863 security.checkRead(path);
864 }
865 return fs.getLength(this);
866 }
867
868
869 /* -- File operations -- */
870
871 /**
872 * Atomically creates a new, empty file named by this abstract pathname if
873 * and only if a file with this name does not yet exist. The check for the
874 * existence of the file and the creation of the file if it does not exist
875 * are a single operation that is atomic with respect to all other
876 * filesystem activities that might affect the file.
877 * <P>
878 * Note: this method should <i>not</i> be used for file-locking, as
879 * the resulting protocol cannot be made to work reliably. The
880 * {@link java.nio.channels.FileLock FileLock}
881 * facility should be used instead.
882 *
883 * @return <code>true</code> if the named file does not exist and was
884 * successfully created; <code>false</code> if the named file
885 * already exists
886 *
887 * @throws IOException
888 * If an I/O error occurred
889 *
890 * @throws SecurityException
891 * If a security manager exists and its <code>{@link
892 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
893 * method denies write access to the file
894 *
895 * @since 1.2
896 */
897 public boolean createNewFile() throws IOException {
898 SecurityManager security = System.getSecurityManager();
899 if (security != null) security.checkWrite(path);
900 return fs.createFileExclusively(path);
901 }
902
903 /**
904 * Deletes the file or directory denoted by this abstract pathname. If
905 * this pathname denotes a directory, then the directory must be empty in
906 * order to be deleted.
907 *
908 * @return <code>true</code> if and only if the file or directory is
909 * successfully deleted; <code>false</code> otherwise
910 *
911 * @throws SecurityException
912 * If a security manager exists and its <code>{@link
913 * java.lang.SecurityManager#checkDelete}</code> method denies
914 * delete access to the file
915 */
916 public boolean delete() {
917 SecurityManager security = System.getSecurityManager();
918 if (security != null) {
919 security.checkDelete(path);
920 }
921 return fs.delete(this);
922 }
923
924 /**
925 * Requests that the file or directory denoted by this abstract
926 * pathname be deleted when the virtual machine terminates.
927 * Files (or directories) are deleted in the reverse order that
928 * they are registered. Invoking this method to delete a file or
929 * directory that is already registered for deletion has no effect.
930 * Deletion will be attempted only for normal termination of the
931 * virtual machine, as defined by the Java Language Specification.
932 *
933 * <p> Once deletion has been requested, it is not possible to cancel the
934 * request. This method should therefore be used with care.
935 *
936 * <P>
937 * Note: this method should <i>not</i> be used for file-locking, as
938 * the resulting protocol cannot be made to work reliably. The
939 * {@link java.nio.channels.FileLock FileLock}
940 * facility should be used instead.
941 *
942 * @throws SecurityException
943 * If a security manager exists and its <code>{@link
944 * java.lang.SecurityManager#checkDelete}</code> method denies
945 * delete access to the file
946 *
947 * @see #delete
948 *
949 * @since 1.2
950 */
951 public void deleteOnExit() {
952 SecurityManager security = System.getSecurityManager();
953 if (security != null) {
954 security.checkDelete(path);
955 }
956 DeleteOnExitHook.add(path);
957 }
958
959 /**
960 * Returns an array of strings naming the files and directories in the
961 * directory denoted by this abstract pathname.
962 *
963 * <p> If this abstract pathname does not denote a directory, then this
964 * method returns {@code null}. Otherwise an array of strings is
965 * returned, one for each file or directory in the directory. Names
966 * denoting the directory itself and the directory's parent directory are
967 * not included in the result. Each string is a file name rather than a
968 * complete path.
969 *
970 * <p> There is no guarantee that the name strings in the resulting array
971 * will appear in any specific order; they are not, in particular,
972 * guaranteed to appear in alphabetical order.
973 *
974 * @return An array of strings naming the files and directories in the
975 * directory denoted by this abstract pathname. The array will be
976 * empty if the directory is empty. Returns {@code null} if
977 * this abstract pathname does not denote a directory, or if an
978 * I/O error occurs.
979 *
980 * @throws SecurityException
981 * If a security manager exists and its {@link
982 * SecurityManager#checkRead(String)} method denies read access to
983 * the directory
984 */
985 public String[] list() {
986 SecurityManager security = System.getSecurityManager();
987 if (security != null) {
988 security.checkRead(path);
989 }
990 return fs.list(this);
991 }
992
993 /**
994 * Returns an array of strings naming the files and directories in the
995 * directory denoted by this abstract pathname that satisfy the specified
996 * filter. The behavior of this method is the same as that of the
997 * {@link #list()} method, except that the strings in the returned array
998 * must satisfy the filter. If the given {@code filter} is {@code null}
999 * then all names are accepted. Otherwise, a name satisfies the filter if
1000 * and only if the value {@code true} results when the {@link
1001 * FilenameFilter#accept FilenameFilter.accept(File, String)} method
1002 * of the filter is invoked on this abstract pathname and the name of a
1003 * file or directory in the directory that it denotes.
1004 *
1005 * @param filter
1006 * A filename filter
1007 *
1008 * @return An array of strings naming the files and directories in the
1009 * directory denoted by this abstract pathname that were accepted
1010 * by the given {@code filter}. The array will be empty if the
1011 * directory is empty or if no names were accepted by the filter.
1012 * Returns {@code null} if this abstract pathname does not denote
1013 * a directory, or if an I/O error occurs.
1014 *
1015 * @throws SecurityException
1016 * If a security manager exists and its {@link
1017 * SecurityManager#checkRead(String)} method denies read access to
1018 * the directory
1019 */
1020 public String[] list(FilenameFilter filter) {
1021 String names[] = list();
1022 if ((names == null) || (filter == null)) {
1023 return names;
1024 }
1025 ArrayList v = new ArrayList();
1026 for (int i = 0 ; i < names.length ; i++) {
1027 if (filter.accept(this, names[i])) {
1028 v.add(names[i]);
1029 }
1030 }
1031 return (String[])(v.toArray(new String[v.size()]));
1032 }
1033
1034 /**
1035 * Returns an array of abstract pathnames denoting the files in the
1036 * directory denoted by this abstract pathname.
1037 *
1038 * <p> If this abstract pathname does not denote a directory, then this
1039 * method returns {@code null}. Otherwise an array of {@code File} objects
1040 * is returned, one for each file or directory in the directory. Pathnames
1041 * denoting the directory itself and the directory's parent directory are
1042 * not included in the result. Each resulting abstract pathname is
1043 * constructed from this abstract pathname using the {@link #File(File,
1044 * String) File(File, String)} constructor. Therefore if this
1045 * pathname is absolute then each resulting pathname is absolute; if this
1046 * pathname is relative then each resulting pathname will be relative to
1047 * the same directory.
1048 *
1049 * <p> There is no guarantee that the name strings in the resulting array
1050 * will appear in any specific order; they are not, in particular,
1051 * guaranteed to appear in alphabetical order.
1052 *
1053 * @return An array of abstract pathnames denoting the files and
1054 * directories in the directory denoted by this abstract pathname.
1055 * The array will be empty if the directory is empty. Returns
1056 * {@code null} if this abstract pathname does not denote a
1057 * directory, or if an I/O error occurs.
1058 *
1059 * @throws SecurityException
1060 * If a security manager exists and its {@link
1061 * SecurityManager#checkRead(String)} method denies read access to
1062 * the directory
1063 *
1064 * @since 1.2
1065 */
1066 public File[] listFiles() {
1067 String[] ss = list();
1068 if (ss == null) return null;
1069 int n = ss.length;
1070 File[] fs = new File[n];
1071 for (int i = 0; i < n; i++) {
1072 fs[i] = new File(ss[i], this);
1073 }
1074 return fs;
1075 }
1076
1077 /**
1078 * Returns an array of abstract pathnames denoting the files and
1079 * directories in the directory denoted by this abstract pathname that
1080 * satisfy the specified filter. The behavior of this method is the same
1081 * as that of the {@link #listFiles()} method, except that the pathnames in
1082 * the returned array must satisfy the filter. If the given {@code filter}
1083 * is {@code null} then all pathnames are accepted. Otherwise, a pathname
1084 * satisfies the filter if and only if the value {@code true} results when
1085 * the {@link FilenameFilter#accept
1086 * FilenameFilter.accept(File, String)} method of the filter is
1087 * invoked on this abstract pathname and the name of a file or directory in
1088 * the directory that it denotes.
1089 *
1090 * @param filter
1091 * A filename filter
1092 *
1093 * @return An array of abstract pathnames denoting the files and
1094 * directories in the directory denoted by this abstract pathname.
1095 * The array will be empty if the directory is empty. Returns
1096 * {@code null} if this abstract pathname does not denote a
1097 * directory, or if an I/O error occurs.
1098 *
1099 * @throws SecurityException
1100 * If a security manager exists and its {@link
1101 * SecurityManager#checkRead(String)} method denies read access to
1102 * the directory
1103 *
1104 * @since 1.2
1105 */
1106 public File[] listFiles(FilenameFilter filter) {
1107 String ss[] = list();
1108 if (ss == null) return null;
1109 ArrayList<File> files = new ArrayList<File>();
1110 for (String s : ss)
1111 if ((filter == null) || filter.accept(this, s))
1112 files.add(new File(s, this));
1113 return files.toArray(new File[files.size()]);
1114 }
1115
1116 /**
1117 * Returns an array of abstract pathnames denoting the files and
1118 * directories in the directory denoted by this abstract pathname that
1119 * satisfy the specified filter. The behavior of this method is the same
1120 * as that of the {@link #listFiles()} method, except that the pathnames in
1121 * the returned array must satisfy the filter. If the given {@code filter}
1122 * is {@code null} then all pathnames are accepted. Otherwise, a pathname
1123 * satisfies the filter if and only if the value {@code true} results when
1124 * the {@link FileFilter#accept FileFilter.accept(File)} method of the
1125 * filter is invoked on the pathname.
1126 *
1127 * @param filter
1128 * A file filter
1129 *
1130 * @return An array of abstract pathnames denoting the files and
1131 * directories in the directory denoted by this abstract pathname.
1132 * The array will be empty if the directory is empty. Returns
1133 * {@code null} if this abstract pathname does not denote a
1134 * directory, or if an I/O error occurs.
1135 *
1136 * @throws SecurityException
1137 * If a security manager exists and its {@link
1138 * SecurityManager#checkRead(String)} method denies read access to
1139 * the directory
1140 *
1141 * @since 1.2
1142 */
1143 public File[] listFiles(FileFilter filter) {
1144 String ss[] = list();
1145 if (ss == null) return null;
1146 ArrayList<File> files = new ArrayList<File>();
1147 for (String s : ss) {
1148 File f = new File(s, this);
1149 if ((filter == null) || filter.accept(f))
1150 files.add(f);
1151 }
1152 return files.toArray(new File[files.size()]);
1153 }
1154
1155 /**
1156 * Creates the directory named by this abstract pathname.
1157 *
1158 * @return <code>true</code> if and only if the directory was
1159 * created; <code>false</code> otherwise
1160 *
1161 * @throws SecurityException
1162 * If a security manager exists and its <code>{@link
1163 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1164 * method does not permit the named directory to be created
1165 */
1166 public boolean mkdir() {
1167 SecurityManager security = System.getSecurityManager();
1168 if (security != null) {
1169 security.checkWrite(path);
1170 }
1171 return fs.createDirectory(this);
1172 }
1173
1174 /**
1175 * Creates the directory named by this abstract pathname, including any
1176 * necessary but nonexistent parent directories. Note that if this
1177 * operation fails it may have succeeded in creating some of the necessary
1178 * parent directories.
1179 *
1180 * @return <code>true</code> if and only if the directory was created,
1181 * along with all necessary parent directories; <code>false</code>
1182 * otherwise
1183 *
1184 * @throws SecurityException
1185 * If a security manager exists and its <code>{@link
1186 * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
1187 * method does not permit verification of the existence of the
1188 * named directory and all necessary parent directories; or if
1189 * the <code>{@link
1190 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1191 * method does not permit the named directory and all necessary
1192 * parent directories to be created
1193 */
1194 public boolean mkdirs() {
1195 if (exists()) {
1196 return false;
1197 }
1198 if (mkdir()) {
1199 return true;
1200 }
1201 File canonFile = null;
1202 try {
1203 canonFile = getCanonicalFile();
1204 } catch (IOException e) {
1205 return false;
1206 }
1207
1208 File parent = canonFile.getParentFile();
1209 return (parent != null && (parent.mkdirs() || parent.exists()) &&
1210 canonFile.mkdir());
1211 }
1212
1213 /**
1214 * Renames the file denoted by this abstract pathname.
1215 *
1216 * <p> Many aspects of the behavior of this method are inherently
1217 * platform-dependent: The rename operation might not be able to move a
1218 * file from one filesystem to another, it might not be atomic, and it
1219 * might not succeed if a file with the destination abstract pathname
1220 * already exists. The return value should always be checked to make sure
1221 * that the rename operation was successful.
1222 *
1223 * @param dest The new abstract pathname for the named file
1224 *
1225 * @return <code>true</code> if and only if the renaming succeeded;
1226 * <code>false</code> otherwise
1227 *
1228 * @throws SecurityException
1229 * If a security manager exists and its <code>{@link
1230 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1231 * method denies write access to either the old or new pathnames
1232 *
1233 * @throws NullPointerException
1234 * If parameter <code>dest</code> is <code>null</code>
1235 */
1236 public boolean renameTo(File dest) {
1237 SecurityManager security = System.getSecurityManager();
1238 if (security != null) {
1239 security.checkWrite(path);
1240 security.checkWrite(dest.path);
1241 }
1242 return fs.rename(this, dest);
1243 }
1244
1245 /**
1246 * Sets the last-modified time of the file or directory named by this
1247 * abstract pathname.
1248 *
1249 * <p> All platforms support file-modification times to the nearest second,
1250 * but some provide more precision. The argument will be truncated to fit
1251 * the supported precision. If the operation succeeds and no intervening
1252 * operations on the file take place, then the next invocation of the
1253 * <code>{@link #lastModified}</code> method will return the (possibly
1254 * truncated) <code>time</code> argument that was passed to this method.
1255 *
1256 * @param time The new last-modified time, measured in milliseconds since
1257 * the epoch (00:00:00 GMT, January 1, 1970)
1258 *
1259 * @return <code>true</code> if and only if the operation succeeded;
1260 * <code>false</code> otherwise
1261 *
1262 * @throws IllegalArgumentException If the argument is negative
1263 *
1264 * @throws SecurityException
1265 * If a security manager exists and its <code>{@link
1266 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1267 * method denies write access to the named file
1268 *
1269 * @since 1.2
1270 */
1271 public boolean setLastModified(long time) {
1272 if (time < 0) throw new IllegalArgumentException("Negative time");
1273 SecurityManager security = System.getSecurityManager();
1274 if (security != null) {
1275 security.checkWrite(path);
1276 }
1277 return fs.setLastModifiedTime(this, time);
1278 }
1279
1280 /**
1281 * Marks the file or directory named by this abstract pathname so that
1282 * only read operations are allowed. After invoking this method the file
1283 * or directory is guaranteed not to change until it is either deleted or
1284 * marked to allow write access. Whether or not a read-only file or
1285 * directory may be deleted depends upon the underlying system.
1286 *
1287 * @return <code>true</code> if and only if the operation succeeded;
1288 * <code>false</code> otherwise
1289 *
1290 * @throws SecurityException
1291 * If a security manager exists and its <code>{@link
1292 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1293 * method denies write access to the named file
1294 *
1295 * @since 1.2
1296 */
1297 public boolean setReadOnly() {
1298 SecurityManager security = System.getSecurityManager();
1299 if (security != null) {
1300 security.checkWrite(path);
1301 }
1302 return fs.setReadOnly(this);
1303 }
1304
1305 /**
1306 * Sets the owner's or everybody's write permission for this abstract
1307 * pathname.
1308 *
1309 * @param writable
1310 * If <code>true</code>, sets the access permission to allow write
1311 * operations; if <code>false</code> to disallow write operations
1312 *
1313 * @param ownerOnly
1314 * If <code>true</code>, the write permission applies only to the
1315 * owner's write permission; otherwise, it applies to everybody. If
1316 * the underlying file system can not distinguish the owner's write
1317 * permission from that of others, then the permission will apply to
1318 * everybody, regardless of this value.
1319 *
1320 * @return <code>true</code> if and only if the operation succeeded. The
1321 * operation will fail if the user does not have permission to change
1322 * the access permissions of this abstract pathname.
1323 *
1324 * @throws SecurityException
1325 * If a security manager exists and its <code>{@link
1326 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1327 * method denies write access to the named file
1328 *
1329 * @since 1.6
1330 */
1331 public boolean setWritable(boolean writable, boolean ownerOnly) {
1332 SecurityManager security = System.getSecurityManager();
1333 if (security != null) {
1334 security.checkWrite(path);
1335 }
1336 return fs.setPermission(this, FileSystem.ACCESS_WRITE, writable, ownerOnly);
1337 }
1338
1339 /**
1340 * A convenience method to set the owner's write permission for this abstract
1341 * pathname.
1342 *
1343 * <p> An invocation of this method of the form <tt>file.setWritable(arg)</tt>
1344 * behaves in exactly the same way as the invocation
1345 *
1346 * <pre>
1347 * file.setWritable(arg, true) </pre>
1348 *
1349 * @param writable
1350 * If <code>true</code>, sets the access permission to allow write
1351 * operations; if <code>false</code> to disallow write operations
1352 *
1353 * @return <code>true</code> if and only if the operation succeeded. The
1354 * operation will fail if the user does not have permission to
1355 * change the access permissions of this abstract pathname.
1356 *
1357 * @throws SecurityException
1358 * If a security manager exists and its <code>{@link
1359 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1360 * method denies write access to the file
1361 *
1362 * @since 1.6
1363 */
1364 public boolean setWritable(boolean writable) {
1365 return setWritable(writable, true);
1366 }
1367
1368 /**
1369 * Sets the owner's or everybody's read permission for this abstract
1370 * pathname.
1371 *
1372 * @param readable
1373 * If <code>true</code>, sets the access permission to allow read
1374 * operations; if <code>false</code> to disallow read operations
1375 *
1376 * @param ownerOnly
1377 * If <code>true</code>, the read permission applies only to the
1378 * owner's read permission; otherwise, it applies to everybody. If
1379 * the underlying file system can not distinguish the owner's read
1380 * permission from that of others, then the permission will apply to
1381 * everybody, regardless of this value.
1382 *
1383 * @return <code>true</code> if and only if the operation succeeded. The
1384 * operation will fail if the user does not have permission to
1385 * change the access permissions of this abstract pathname. If
1386 * <code>readable</code> is <code>false</code> and the underlying
1387 * file system does not implement a read permission, then the
1388 * operation will fail.
1389 *
1390 * @throws SecurityException
1391 * If a security manager exists and its <code>{@link
1392 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1393 * method denies write access to the file
1394 *
1395 * @since 1.6
1396 */
1397 public boolean setReadable(boolean readable, boolean ownerOnly) {
1398 SecurityManager security = System.getSecurityManager();
1399 if (security != null) {
1400 security.checkWrite(path);
1401 }
1402 return fs.setPermission(this, FileSystem.ACCESS_READ, readable, ownerOnly);
1403 }
1404
1405 /**
1406 * A convenience method to set the owner's read permission for this abstract
1407 * pathname.
1408 *
1409 * <p>An invocation of this method of the form <tt>file.setReadable(arg)</tt>
1410 * behaves in exactly the same way as the invocation
1411 *
1412 * <pre>
1413 * file.setReadable(arg, true) </pre>
1414 *
1415 * @param readable
1416 * If <code>true</code>, sets the access permission to allow read
1417 * operations; if <code>false</code> to disallow read operations
1418 *
1419 * @return <code>true</code> if and only if the operation succeeded. The
1420 * operation will fail if the user does not have permission to
1421 * change the access permissions of this abstract pathname. If
1422 * <code>readable</code> is <code>false</code> and the underlying
1423 * file system does not implement a read permission, then the
1424 * operation will fail.
1425 *
1426 * @throws SecurityException
1427 * If a security manager exists and its <code>{@link
1428 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1429 * method denies write access to the file
1430 *
1431 * @since 1.6
1432 */
1433 public boolean setReadable(boolean readable) {
1434 return setReadable(readable, true);
1435 }
1436
1437 /**
1438 * Sets the owner's or everybody's execute permission for this abstract
1439 * pathname.
1440 *
1441 * @param executable
1442 * If <code>true</code>, sets the access permission to allow execute
1443 * operations; if <code>false</code> to disallow execute operations
1444 *
1445 * @param ownerOnly
1446 * If <code>true</code>, the execute permission applies only to the
1447 * owner's execute permission; otherwise, it applies to everybody.
1448 * If the underlying file system can not distinguish the owner's
1449 * execute permission from that of others, then the permission will
1450 * apply to everybody, regardless of this value.
1451 *
1452 * @return <code>true</code> if and only if the operation succeeded. The
1453 * operation will fail if the user does not have permission to
1454 * change the access permissions of this abstract pathname. If
1455 * <code>executable</code> is <code>false</code> and the underlying
1456 * file system does not implement an execute permission, then the
1457 * operation will fail.
1458 *
1459 * @throws SecurityException
1460 * If a security manager exists and its <code>{@link
1461 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1462 * method denies write access to the file
1463 *
1464 * @since 1.6
1465 */
1466 public boolean setExecutable(boolean executable, boolean ownerOnly) {
1467 SecurityManager security = System.getSecurityManager();
1468 if (security != null) {
1469 security.checkWrite(path);
1470 }
1471 return fs.setPermission(this, FileSystem.ACCESS_EXECUTE, executable, ownerOnly);
1472 }
1473
1474 /**
1475 * A convenience method to set the owner's execute permission for this abstract
1476 * pathname.
1477 *
1478 * <p>An invocation of this method of the form <tt>file.setExcutable(arg)</tt>
1479 * behaves in exactly the same way as the invocation
1480 *
1481 * <pre>
1482 * file.setExecutable(arg, true) </pre>
1483 *
1484 * @param executable
1485 * If <code>true</code>, sets the access permission to allow execute
1486 * operations; if <code>false</code> to disallow execute operations
1487 *
1488 * @return <code>true</code> if and only if the operation succeeded. The
1489 * operation will fail if the user does not have permission to
1490 * change the access permissions of this abstract pathname. If
1491 * <code>executable</code> is <code>false</code> and the underlying
1492 * file system does not implement an excute permission, then the
1493 * operation will fail.
1494 *
1495 * @throws SecurityException
1496 * If a security manager exists and its <code>{@link
1497 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1498 * method denies write access to the file
1499 *
1500 * @since 1.6
1501 */
1502 public boolean setExecutable(boolean executable) {
1503 return setExecutable(executable, true);
1504 }
1505
1506 /**
1507 * Tests whether the application can execute the file denoted by this
1508 * abstract pathname.
1509 *
1510 * @return <code>true</code> if and only if the abstract pathname exists
1511 * <em>and</em> the application is allowed to execute the file
1512 *
1513 * @throws SecurityException
1514 * If a security manager exists and its <code>{@link
1515 * java.lang.SecurityManager#checkExec(java.lang.String)}</code>
1516 * method denies execute access to the file
1517 *
1518 * @since 1.6
1519 */
1520 public boolean canExecute() {
1521 SecurityManager security = System.getSecurityManager();
1522 if (security != null) {
1523 security.checkExec(path);
1524 }
1525 return fs.checkAccess(this, FileSystem.ACCESS_EXECUTE);
1526 }
1527
1528
1529 /* -- Filesystem interface -- */
1530
1531 /**
1532 * List the available filesystem roots.
1533 *
1534 * <p> A particular Java platform may support zero or more
1535 * hierarchically-organized file systems. Each file system has a
1536 * {@code root} directory from which all other files in that file system
1537 * can be reached. Windows platforms, for example, have a root directory
1538 * for each active drive; UNIX platforms have a single root directory,
1539 * namely {@code "/"}. The set of available filesystem roots is affected
1540 * by various system-level operations such as the insertion or ejection of
1541 * removable media and the disconnecting or unmounting of physical or
1542 * virtual disk drives.
1543 *
1544 * <p> This method returns an array of {@code File} objects that denote the
1545 * root directories of the available filesystem roots. It is guaranteed
1546 * that the canonical pathname of any file physically present on the local
1547 * machine will begin with one of the roots returned by this method.
1548 *
1549 * <p> The canonical pathname of a file that resides on some other machine
1550 * and is accessed via a remote-filesystem protocol such as SMB or NFS may
1551 * or may not begin with one of the roots returned by this method. If the
1552 * pathname of a remote file is syntactically indistinguishable from the
1553 * pathname of a local file then it will begin with one of the roots
1554 * returned by this method. Thus, for example, {@code File} objects
1555 * denoting the root directories of the mapped network drives of a Windows
1556 * platform will be returned by this method, while {@code File} objects
1557 * containing UNC pathnames will not be returned by this method.
1558 *
1559 * <p> Unlike most methods in this class, this method does not throw
1560 * security exceptions. If a security manager exists and its {@link
1561 * SecurityManager#checkRead(String)} method denies read access to a
1562 * particular root directory, then that directory will not appear in the
1563 * result.
1564 *
1565 * @return An array of {@code File} objects denoting the available
1566 * filesystem roots, or {@code null} if the set of roots could not
1567 * be determined. The array will be empty if there are no
1568 * filesystem roots.
1569 *
1570 * @since 1.2
1571 */
1572 public static File[] listRoots() {
1573 return fs.listRoots();
1574 }
1575
1576
1577 /* -- Disk usage -- */
1578
1579 /**
1580 * Returns the size of the partition <a href="#partName">named</a> by this
1581 * abstract pathname.
1582 *
1583 * @return The size, in bytes, of the partition or <tt>0L</tt> if this
1584 * abstract pathname does not name a partition
1585 *
1586 * @throws SecurityException
1587 * If a security manager has been installed and it denies
1588 * {@link RuntimePermission}<tt>("getFileSystemAttributes")</tt>
1589 * or its {@link SecurityManager#checkRead(String)} method denies
1590 * read access to the file named by this abstract pathname
1591 *
1592 * @since 1.6
1593 */
1594 public long getTotalSpace() {
1595 SecurityManager sm = System.getSecurityManager();
1596 if (sm != null) {
1597 sm.checkPermission(new RuntimePermission("getFileSystemAttributes"));
1598 sm.checkRead(path);
1599 }
1600 return fs.getSpace(this, FileSystem.SPACE_TOTAL);
1601 }
1602
1603 /**
1604 * Returns the number of unallocated bytes in the partition <a
1605 * href="#partName">named</a> by this abstract path name.
1606 *
1607 * <p> The returned number of unallocated bytes is a hint, but not
1608 * a guarantee, that it is possible to use most or any of these
1609 * bytes. The number of unallocated bytes is most likely to be
1610 * accurate immediately after this call. It is likely to be made
1611 * inaccurate by any external I/O operations including those made
1612 * on the system outside of this virtual machine. This method
1613 * makes no guarantee that write operations to this file system
1614 * will succeed.
1615 *
1616 * @return The number of unallocated bytes on the partition <tt>0L</tt>
1617 * if the abstract pathname does not name a partition. This
1618 * value will be less than or equal to the total file system size
1619 * returned by {@link #getTotalSpace}.
1620 *
1621 * @throws SecurityException
1622 * If a security manager has been installed and it denies
1623 * {@link RuntimePermission}<tt>("getFileSystemAttributes")</tt>
1624 * or its {@link SecurityManager#checkRead(String)} method denies
1625 * read access to the file named by this abstract pathname
1626 *
1627 * @since 1.6
1628 */
1629 public long getFreeSpace() {
1630 SecurityManager sm = System.getSecurityManager();
1631 if (sm != null) {
1632 sm.checkPermission(new RuntimePermission("getFileSystemAttributes"));
1633 sm.checkRead(path);
1634 }
1635 return fs.getSpace(this, FileSystem.SPACE_FREE);
1636 }
1637
1638 /**
1639 * Returns the number of bytes available to this virtual machine on the
1640 * partition <a href="#partName">named</a> by this abstract pathname. When
1641 * possible, this method checks for write permissions and other operating
1642 * system restrictions and will therefore usually provide a more accurate
1643 * estimate of how much new data can actually be written than {@link
1644 * #getFreeSpace}.
1645 *
1646 * <p> The returned number of available bytes is a hint, but not a
1647 * guarantee, that it is possible to use most or any of these bytes. The
1648 * number of unallocated bytes is most likely to be accurate immediately
1649 * after this call. It is likely to be made inaccurate by any external
1650 * I/O operations including those made on the system outside of this
1651 * virtual machine. This method makes no guarantee that write operations
1652 * to this file system will succeed.
1653 *
1654 * @return The number of available bytes on the partition or <tt>0L</tt>
1655 * if the abstract pathname does not name a partition. On
1656 * systems where this information is not available, this method
1657 * will be equivalent to a call to {@link #getFreeSpace}.
1658 *
1659 * @throws SecurityException
1660 * If a security manager has been installed and it denies
1661 * {@link RuntimePermission}<tt>("getFileSystemAttributes")</tt>
1662 * or its {@link SecurityManager#checkRead(String)} method denies
1663 * read access to the file named by this abstract pathname
1664 *
1665 * @since 1.6
1666 */
1667 public long getUsableSpace() {
1668 SecurityManager sm = System.getSecurityManager();
1669 if (sm != null) {
1670 sm.checkPermission(new RuntimePermission("getFileSystemAttributes"));
1671 sm.checkRead(path);
1672 }
1673 return fs.getSpace(this, FileSystem.SPACE_USABLE);
1674 }
1675
1676
1677 /* -- Temporary files -- */
1678
1679 private static final Object tmpFileLock = new Object();
1680
1681 private static int counter = -1; /* Protected by tmpFileLock */
1682
1683 private static File generateFile(String prefix, String suffix, File dir)
1684 throws IOException
1685 {
1686 if (counter == -1) {
1687 counter = new Random().nextInt() & 0xffff;
1688 }
1689 counter++;
1690 return new File(dir, prefix + Integer.toString(counter) + suffix);
1691 }
1692
1693 private static String tmpdir; /* Protected by tmpFileLock */
1694
1695 private static String getTempDir() {
1696 if (tmpdir == null)
1697 tmpdir = fs.normalize(
1698 AccessController.doPrivileged(
1699 new GetPropertyAction("java.io.tmpdir")));
1700 return tmpdir;
1701 }
1702
1703 private static boolean checkAndCreate(String filename, SecurityManager sm)
1704 throws IOException
1705 {
1706 if (sm != null) {
1707 try {
1708 sm.checkWrite(filename);
1709 } catch (AccessControlException x) {
1710 /* Throwing the original AccessControlException could disclose
1711 the location of the default temporary directory, so we
1712 re-throw a more innocuous SecurityException */
1713 throw new SecurityException("Unable to create temporary file");
1714 }
1715 }
1716 return fs.createFileExclusively(filename);
1717 }
1718
1719 /**
1720 * <p> Creates a new empty file in the specified directory, using the
1721 * given prefix and suffix strings to generate its name. If this method
1722 * returns successfully then it is guaranteed that:
1723 *
1724 * <ol>
1725 * <li> The file denoted by the returned abstract pathname did not exist
1726 * before this method was invoked, and
1727 * <li> Neither this method nor any of its variants will return the same
1728 * abstract pathname again in the current invocation of the virtual
1729 * machine.
1730 * </ol>
1731 *
1732 * This method provides only part of a temporary-file facility. To arrange
1733 * for a file created by this method to be deleted automatically, use the
1734 * <code>{@link #deleteOnExit}</code> method.
1735 *
1736 * <p> The <code>prefix</code> argument must be at least three characters
1737 * long. It is recommended that the prefix be a short, meaningful string
1738 * such as <code>"hjb"</code> or <code>"mail"</code>. The
1739 * <code>suffix</code> argument may be <code>null</code>, in which case the
1740 * suffix <code>".tmp"</code> will be used.
1741 *
1742 * <p> To create the new file, the prefix and the suffix may first be
1743 * adjusted to fit the limitations of the underlying platform. If the
1744 * prefix is too long then it will be truncated, but its first three
1745 * characters will always be preserved. If the suffix is too long then it
1746 * too will be truncated, but if it begins with a period character
1747 * (<code>'.'</code>) then the period and the first three characters
1748 * following it will always be preserved. Once these adjustments have been
1749 * made the name of the new file will be generated by concatenating the
1750 * prefix, five or more internally-generated characters, and the suffix.
1751 *
1752 * <p> If the <code>directory</code> argument is <code>null</code> then the
1753 * system-dependent default temporary-file directory will be used. The
1754 * default temporary-file directory is specified by the system property
1755 * <code>java.io.tmpdir</code>. On UNIX systems the default value of this
1756 * property is typically <code>"/tmp"</code> or <code>"/var/tmp"</code>; on
1757 * Microsoft Windows systems it is typically <code>"C:\\WINNT\\TEMP"</code>. A different
1758 * value may be given to this system property when the Java virtual machine
1759 * is invoked, but programmatic changes to this property are not guaranteed
1760 * to have any effect upon the temporary directory used by this method.
1761 *
1762 * @param prefix The prefix string to be used in generating the file's
1763 * name; must be at least three characters long
1764 *
1765 * @param suffix The suffix string to be used in generating the file's
1766 * name; may be <code>null</code>, in which case the
1767 * suffix <code>".tmp"</code> will be used
1768 *
1769 * @param directory The directory in which the file is to be created, or
1770 * <code>null</code> if the default temporary-file
1771 * directory is to be used
1772 *
1773 * @return An abstract pathname denoting a newly-created empty file
1774 *
1775 * @throws IllegalArgumentException
1776 * If the <code>prefix</code> argument contains fewer than three
1777 * characters
1778 *
1779 * @throws IOException If a file could not be created
1780 *
1781 * @throws SecurityException
1782 * If a security manager exists and its <code>{@link
1783 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1784 * method does not allow a file to be created
1785 *
1786 * @since 1.2
1787 */
1788 public static File createTempFile(String prefix, String suffix,
1789 File directory)
1790 throws IOException
1791 {
1792 if (prefix == null) throw new NullPointerException();
1793 if (prefix.length() < 3)
1794 throw new IllegalArgumentException("Prefix string too short");
1795 String s = (suffix == null) ? ".tmp" : suffix;
1796 synchronized (tmpFileLock) {
1797 if (directory == null) {
1798 String tmpDir = getTempDir();
1799 directory = new File(tmpDir, fs.prefixLength(tmpDir));
1800 }
1801 SecurityManager sm = System.getSecurityManager();
1802 File f;
1803 do {
1804 f = generateFile(prefix, s, directory);
1805 } while (!checkAndCreate(f.getPath(), sm));
1806 return f;
1807 }
1808 }
1809
1810 /**
1811 * Creates an empty file in the default temporary-file directory, using
1812 * the given prefix and suffix to generate its name. Invoking this method
1813 * is equivalent to invoking <code>{@link #createTempFile(java.lang.String,
1814 * java.lang.String, java.io.File)
1815 * createTempFile(prefix, suffix, null)}</code>.
1816 *
1817 * @param prefix The prefix string to be used in generating the file's
1818 * name; must be at least three characters long
1819 *
1820 * @param suffix The suffix string to be used in generating the file's
1821 * name; may be <code>null</code>, in which case the
1822 * suffix <code>".tmp"</code> will be used
1823 *
1824 * @return An abstract pathname denoting a newly-created empty file
1825 *
1826 * @throws IllegalArgumentException
1827 * If the <code>prefix</code> argument contains fewer than three
1828 * characters
1829 *
1830 * @throws IOException If a file could not be created
1831 *
1832 * @throws SecurityException
1833 * If a security manager exists and its <code>{@link
1834 * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1835 * method does not allow a file to be created
1836 *
1837 * @since 1.2
1838 */
1839 public static File createTempFile(String prefix, String suffix)
1840 throws IOException
1841 {
1842 return createTempFile(prefix, suffix, null);
1843 }
1844
1845
1846 /* -- Basic infrastructure -- */
1847
1848 /**
1849 * Compares two abstract pathnames lexicographically. The ordering
1850 * defined by this method depends upon the underlying system. On UNIX
1851 * systems, alphabetic case is significant in comparing pathnames; on Microsoft Windows
1852 * systems it is not.
1853 *
1854 * @param pathname The abstract pathname to be compared to this abstract
1855 * pathname
1856 *
1857 * @return Zero if the argument is equal to this abstract pathname, a
1858 * value less than zero if this abstract pathname is
1859 * lexicographically less than the argument, or a value greater
1860 * than zero if this abstract pathname is lexicographically
1861 * greater than the argument
1862 *
1863 * @since 1.2
1864 */
1865 public int compareTo(File pathname) {
1866 return fs.compare(this, pathname);
1867 }
1868
1869 /**
1870 * Tests this abstract pathname for equality with the given object.
1871 * Returns <code>true</code> if and only if the argument is not
1872 * <code>null</code> and is an abstract pathname that denotes the same file
1873 * or directory as this abstract pathname. Whether or not two abstract
1874 * pathnames are equal depends upon the underlying system. On UNIX
1875 * systems, alphabetic case is significant in comparing pathnames; on Microsoft Windows
1876 * systems it is not.
1877 *
1878 * @param obj The object to be compared with this abstract pathname
1879 *
1880 * @return <code>true</code> if and only if the objects are the same;
1881 * <code>false</code> otherwise
1882 */
1883 public boolean equals(Object obj) {
1884 if ((obj != null) && (obj instanceof File)) {
1885 return compareTo((File)obj) == 0;
1886 }
1887 return false;
1888 }
1889
1890 /**
1891 * Computes a hash code for this abstract pathname. Because equality of
1892 * abstract pathnames is inherently system-dependent, so is the computation
1893 * of their hash codes. On UNIX systems, the hash code of an abstract
1894 * pathname is equal to the exclusive <em>or</em> of the hash code
1895 * of its pathname string and the decimal value
1896 * <code>1234321</code>. On Microsoft Windows systems, the hash
1897 * code is equal to the exclusive <em>or</em> of the hash code of
1898 * its pathname string converted to lower case and the decimal
1899 * value <code>1234321</code>. Locale is not taken into account on
1900 * lowercasing the pathname string.
1901 *
1902 * @return A hash code for this abstract pathname
1903 */
1904 public int hashCode() {
1905 return fs.hashCode(this);
1906 }
1907
1908 /**
1909 * Returns the pathname string of this abstract pathname. This is just the
1910 * string returned by the <code>{@link #getPath}</code> method.
1911 *
1912 * @return The string form of this abstract pathname
1913 */
1914 public String toString() {
1915 return getPath();
1916 }
1917
1918 /**
1919 * WriteObject is called to save this filename.
1920 * The separator character is saved also so it can be replaced
1921 * in case the path is reconstituted on a different host type.
1922 * <p>
1923 * @serialData Default fields followed by separator character.
1924 */
1925 private synchronized void writeObject(java.io.ObjectOutputStream s)
1926 throws IOException
1927 {
1928 s.defaultWriteObject();
1929 s.writeChar(this.separatorChar); // Add the separator character
1930 }
1931
1932 /**
1933 * readObject is called to restore this filename.
1934 * The original separator character is read. If it is different
1935 * than the separator character on this system, then the old separator
1936 * is replaced by the local separator.
1937 */
1938 private synchronized void readObject(java.io.ObjectInputStream s)
1939 throws IOException, ClassNotFoundException
1940 {
1941 s.defaultReadObject();
1942 char sep = s.readChar(); // read the previous separator char
1943 if (sep != separatorChar)
1944 this.path = this.path.replace(sep, separatorChar);
1945 this.path = fs.normalize(this.path);
1946 this.prefixLength = fs.prefixLength(this.path);
1947 }
1948
1949 /** use serialVersionUID from JDK 1.0.2 for interoperability */
1950 private static final long serialVersionUID = 301077366599181567L;
1951
1952 // Set up JavaIODeleteOnExitAccess in SharedSecrets
1953 // Added here as DeleteOnExitHook is package-private and SharedSecrets cannot easily access it.
1954 static {
1955 sun.misc.SharedSecrets.setJavaIODeleteOnExitAccess(
1956 new sun.misc.JavaIODeleteOnExitAccess() {
1957 public void run() {
1958 DeleteOnExitHook.hook().run();
1959 }
1960 }
1961 );
1962 }
1963
1964
1965 }