1. /*
  2. * @(#)File.java 1.122 04/05/05
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.io;
  8. import java.net.URI;
  9. import java.net.URL;
  10. import java.net.MalformedURLException;
  11. import java.net.URISyntaxException;
  12. import java.util.ArrayList;
  13. import java.util.Map;
  14. import java.util.Hashtable;
  15. import java.util.Random;
  16. import java.security.AccessController;
  17. import java.security.AccessControlException;
  18. import sun.security.action.GetPropertyAction;
  19. /**
  20. * An abstract representation of file and directory pathnames.
  21. *
  22. * <p> User interfaces and operating systems use system-dependent <em>pathname
  23. * strings</em> to name files and directories. This class presents an
  24. * abstract, system-independent view of hierarchical pathnames. An
  25. * <em>abstract pathname</em> has two components:
  26. *
  27. * <ol>
  28. * <li> An optional system-dependent <em>prefix</em> string,
  29. * such as a disk-drive specifier, <code>"/"</code> for the UNIX root
  30. * directory, or <code>"\\\\"</code> for a Microsoft Windows UNC pathname, and
  31. * <li> A sequence of zero or more string <em>names</em>.
  32. * </ol>
  33. *
  34. * Each name in an abstract pathname except for the last denotes a directory;
  35. * the last name may denote either a directory or a file. The <em>empty</em>
  36. * abstract pathname has no prefix and an empty name sequence.
  37. *
  38. * <p> The conversion of a pathname string to or from an abstract pathname is
  39. * inherently system-dependent. When an abstract pathname is converted into a
  40. * pathname string, each name is separated from the next by a single copy of
  41. * the default <em>separator character</em>. The default name-separator
  42. * character is defined by the system property <code>file.separator</code>, and
  43. * is made available in the public static fields <code>{@link
  44. * #separator}</code> and <code>{@link #separatorChar}</code> of this class.
  45. * When a pathname string is converted into an abstract pathname, the names
  46. * within it may be separated by the default name-separator character or by any
  47. * other name-separator character that is supported by the underlying system.
  48. *
  49. * <p> A pathname, whether abstract or in string form, may be either
  50. * <em>absolute</em> or <em>relative</em>. An absolute pathname is complete in
  51. * that no other information is required in order to locate the file that it
  52. * denotes. A relative pathname, in contrast, must be interpreted in terms of
  53. * information taken from some other pathname. By default the classes in the
  54. * <code>java.io</code> package always resolve relative pathnames against the
  55. * current user directory. This directory is named by the system property
  56. * <code>user.dir</code>, and is typically the directory in which the Java
  57. * virtual machine was invoked.
  58. *
  59. * <p> The prefix concept is used to handle root directories on UNIX platforms,
  60. * and drive specifiers, root directories and UNC pathnames on Microsoft Windows platforms,
  61. * as follows:
  62. *
  63. * <ul>
  64. *
  65. * <li> For UNIX platforms, the prefix of an absolute pathname is always
  66. * <code>"/"</code>. Relative pathnames have no prefix. The abstract pathname
  67. * denoting the root directory has the prefix <code>"/"</code> and an empty
  68. * name sequence.
  69. *
  70. * <li> For Microsoft Windows platforms, the prefix of a pathname that contains a drive
  71. * specifier consists of the drive letter followed by <code>":"</code> and
  72. * possibly followed by <code>"\\"</code> if the pathname is absolute. The
  73. * prefix of a UNC pathname is <code>"\\\\"</code> the hostname and the share
  74. * name are the first two names in the name sequence. A relative pathname that
  75. * does not specify a drive has no prefix.
  76. *
  77. * </ul>
  78. *
  79. * <p> Instances of the <code>File</code> class are immutable; that is, once
  80. * created, the abstract pathname represented by a <code>File</code> object
  81. * will never change.
  82. *
  83. * @version 1.122, 05/05/04
  84. * @author unascribed
  85. * @since JDK1.0
  86. */
  87. public class File
  88. implements Serializable, Comparable<File>
  89. {
  90. /**
  91. * The FileSystem object representing the platform's local file system.
  92. */
  93. static private FileSystem fs = FileSystem.getFileSystem();
  94. /**
  95. * This abstract pathname's normalized pathname string. A normalized
  96. * pathname string uses the default name-separator character and does not
  97. * contain any duplicate or redundant separators.
  98. *
  99. * @serial
  100. */
  101. private String path;
  102. /**
  103. * The length of this abstract pathname's prefix, or zero if it has no
  104. * prefix.
  105. */
  106. private transient int prefixLength;
  107. /**
  108. * Returns the length of this abstract pathname's prefix.
  109. * For use by FileSystem classes.
  110. */
  111. int getPrefixLength() {
  112. return prefixLength;
  113. }
  114. /**
  115. * The system-dependent default name-separator character. This field is
  116. * initialized to contain the first character of the value of the system
  117. * property <code>file.separator</code>. On UNIX systems the value of this
  118. * field is <code>'/'</code> on Microsoft Windows systems it is <code>'\\'</code>.
  119. *
  120. * @see java.lang.System#getProperty(java.lang.String)
  121. */
  122. public static final char separatorChar = fs.getSeparator();
  123. /**
  124. * The system-dependent default name-separator character, represented as a
  125. * string for convenience. This string contains a single character, namely
  126. * <code>{@link #separatorChar}</code>.
  127. */
  128. public static final String separator = "" + separatorChar;
  129. /**
  130. * The system-dependent path-separator character. This field is
  131. * initialized to contain the first character of the value of the system
  132. * property <code>path.separator</code>. This character is used to
  133. * separate filenames in a sequence of files given as a <em>path list</em>.
  134. * On UNIX systems, this character is <code>':'</code> on Microsoft Windows systems it
  135. * is <code>';'</code>.
  136. *
  137. * @see java.lang.System#getProperty(java.lang.String)
  138. */
  139. public static final char pathSeparatorChar = fs.getPathSeparator();
  140. /**
  141. * The system-dependent path-separator character, represented as a string
  142. * for convenience. This string contains a single character, namely
  143. * <code>{@link #pathSeparatorChar}</code>.
  144. */
  145. public static final String pathSeparator = "" + pathSeparatorChar;
  146. /* -- Constructors -- */
  147. /**
  148. * Internal constructor for already-normalized pathname strings.
  149. */
  150. private File(String pathname, int prefixLength) {
  151. this.path = pathname;
  152. this.prefixLength = prefixLength;
  153. }
  154. /**
  155. * Internal constructor for already-normalized pathname strings.
  156. * The parameter order is used to disambiguate this method from the
  157. * public(File, String) constructor.
  158. */
  159. private File(String child, File parent) {
  160. assert parent.path != null;
  161. assert (!parent.path.equals(""));
  162. this.path = fs.resolve(parent.path, child);
  163. this.prefixLength = parent.prefixLength;
  164. }
  165. /**
  166. * Creates a new <code>File</code> instance by converting the given
  167. * pathname string into an abstract pathname. If the given string is
  168. * the empty string, then the result is the empty abstract pathname.
  169. *
  170. * @param pathname A pathname string
  171. * @throws NullPointerException
  172. * If the <code>pathname</code> argument is <code>null</code>
  173. */
  174. public File(String pathname) {
  175. if (pathname == null) {
  176. throw new NullPointerException();
  177. }
  178. this.path = fs.normalize(pathname);
  179. this.prefixLength = fs.prefixLength(this.path);
  180. }
  181. /* Note: The two-argument File constructors do not interpret an empty
  182. parent abstract pathname as the current user directory. An empty parent
  183. instead causes the child to be resolved against the system-dependent
  184. directory defined by the FileSystem.getDefaultParent method. On Unix
  185. this default is "/", while on Microsoft Windows it is "\\". This is required for
  186. compatibility with the original behavior of this class. */
  187. /**
  188. * Creates a new <code>File</code> instance from a parent pathname string
  189. * and a child pathname string.
  190. *
  191. * <p> If <code>parent</code> is <code>null</code> then the new
  192. * <code>File</code> instance is created as if by invoking the
  193. * single-argument <code>File</code> constructor on the given
  194. * <code>child</code> pathname string.
  195. *
  196. * <p> Otherwise the <code>parent</code> pathname string is taken to denote
  197. * a directory, and the <code>child</code> pathname string is taken to
  198. * denote either a directory or a file. If the <code>child</code> pathname
  199. * string is absolute then it is converted into a relative pathname in a
  200. * system-dependent way. If <code>parent</code> is the empty string then
  201. * the new <code>File</code> instance is created by converting
  202. * <code>child</code> into an abstract pathname and resolving the result
  203. * against a system-dependent default directory. Otherwise each pathname
  204. * string is converted into an abstract pathname and the child abstract
  205. * pathname is resolved against the parent.
  206. *
  207. * @param parent The parent pathname string
  208. * @param child The child pathname string
  209. * @throws NullPointerException
  210. * If <code>child</code> is <code>null</code>
  211. */
  212. public File(String parent, String child) {
  213. if (child == null) {
  214. throw new NullPointerException();
  215. }
  216. if (parent != null) {
  217. if (parent.equals("")) {
  218. this.path = fs.resolve(fs.getDefaultParent(),
  219. fs.normalize(child));
  220. } else {
  221. this.path = fs.resolve(fs.normalize(parent),
  222. fs.normalize(child));
  223. }
  224. } else {
  225. this.path = fs.normalize(child);
  226. }
  227. this.prefixLength = fs.prefixLength(this.path);
  228. }
  229. /**
  230. * Creates a new <code>File</code> instance from a parent abstract
  231. * pathname and a child pathname string.
  232. *
  233. * <p> If <code>parent</code> is <code>null</code> then the new
  234. * <code>File</code> instance is created as if by invoking the
  235. * single-argument <code>File</code> constructor on the given
  236. * <code>child</code> pathname string.
  237. *
  238. * <p> Otherwise the <code>parent</code> abstract pathname is taken to
  239. * denote a directory, and the <code>child</code> pathname string is taken
  240. * to denote either a directory or a file. If the <code>child</code>
  241. * pathname string is absolute then it is converted into a relative
  242. * pathname in a system-dependent way. If <code>parent</code> is the empty
  243. * abstract pathname then the new <code>File</code> instance is created by
  244. * converting <code>child</code> into an abstract pathname and resolving
  245. * the result against a system-dependent default directory. Otherwise each
  246. * pathname string is converted into an abstract pathname and the child
  247. * abstract pathname is resolved against the parent.
  248. *
  249. * @param parent The parent abstract pathname
  250. * @param child The child pathname string
  251. * @throws NullPointerException
  252. * If <code>child</code> is <code>null</code>
  253. */
  254. public File(File parent, String child) {
  255. if (child == null) {
  256. throw new NullPointerException();
  257. }
  258. if (parent != null) {
  259. if (parent.path.equals("")) {
  260. this.path = fs.resolve(fs.getDefaultParent(),
  261. fs.normalize(child));
  262. } else {
  263. this.path = fs.resolve(parent.path,
  264. fs.normalize(child));
  265. }
  266. } else {
  267. this.path = fs.normalize(child);
  268. }
  269. this.prefixLength = fs.prefixLength(this.path);
  270. }
  271. /**
  272. * Creates a new <tt>File</tt> instance by converting the given
  273. * <tt>file:</tt> URI into an abstract pathname.
  274. *
  275. * <p> The exact form of a <tt>file:</tt> URI is system-dependent, hence
  276. * the transformation performed by this constructor is also
  277. * system-dependent.
  278. *
  279. * <p> For a given abstract pathname <i>f</i> it is guaranteed that
  280. *
  281. * <blockquote><tt>
  282. * new File(</tt><i> f</i><tt>.{@link #toURI() toURI}()).equals(</tt><i> f</i><tt>.{@link #getAbsoluteFile() getAbsoluteFile}())
  283. * </tt></blockquote>
  284. *
  285. * so long as the original abstract pathname, the URI, and the new abstract
  286. * pathname are all created in (possibly different invocations of) the same
  287. * Java virtual machine. This relationship typically does not hold,
  288. * however, when a <tt>file:</tt> URI that is created in a virtual machine
  289. * on one operating system is converted into an abstract pathname in a
  290. * virtual machine on a different operating system.
  291. *
  292. * @param uri
  293. * An absolute, hierarchical URI with a scheme equal to
  294. * <tt>"file"</tt>, a non-empty path component, and undefined
  295. * authority, query, and fragment components
  296. *
  297. * @throws NullPointerException
  298. * If <tt>uri</tt> is <tt>null</tt>
  299. *
  300. * @throws IllegalArgumentException
  301. * If the preconditions on the parameter do not hold
  302. *
  303. * @see #toURI()
  304. * @see java.net.URI
  305. * @since 1.4
  306. */
  307. public File(URI uri) {
  308. // Check our many preconditions
  309. if (!uri.isAbsolute())
  310. throw new IllegalArgumentException("URI is not absolute");
  311. if (uri.isOpaque())
  312. throw new IllegalArgumentException("URI is not hierarchical");
  313. String scheme = uri.getScheme();
  314. if ((scheme == null) || !scheme.equalsIgnoreCase("file"))
  315. throw new IllegalArgumentException("URI scheme is not \"file\"");
  316. if (uri.getAuthority() != null)
  317. throw new IllegalArgumentException("URI has an authority component");
  318. if (uri.getFragment() != null)
  319. throw new IllegalArgumentException("URI has a fragment component");
  320. if (uri.getQuery() != null)
  321. throw new IllegalArgumentException("URI has a query component");
  322. String p = uri.getPath();
  323. if (p.equals(""))
  324. throw new IllegalArgumentException("URI path component is empty");
  325. // Okay, now initialize
  326. p = fs.fromURIPath(p);
  327. if (File.separatorChar != '/')
  328. p = p.replace('/', File.separatorChar);
  329. this.path = fs.normalize(p);
  330. this.prefixLength = fs.prefixLength(this.path);
  331. }
  332. /* -- Path-component accessors -- */
  333. /**
  334. * Returns the name of the file or directory denoted by this abstract
  335. * pathname. This is just the last name in the pathname's name
  336. * sequence. If the pathname's name sequence is empty, then the empty
  337. * string is returned.
  338. *
  339. * @return The name of the file or directory denoted by this abstract
  340. * pathname, or the empty string if this pathname's name sequence
  341. * is empty
  342. */
  343. public String getName() {
  344. int index = path.lastIndexOf(separatorChar);
  345. if (index < prefixLength) return path.substring(prefixLength);
  346. return path.substring(index + 1);
  347. }
  348. /**
  349. * Returns the pathname string of this abstract pathname's parent, or
  350. * <code>null</code> if this pathname does not name a parent directory.
  351. *
  352. * <p> The <em>parent</em> of an abstract pathname consists of the
  353. * pathname's prefix, if any, and each name in the pathname's name
  354. * sequence except for the last. If the name sequence is empty then
  355. * the pathname does not name a parent directory.
  356. *
  357. * @return The pathname string of the parent directory named by this
  358. * abstract pathname, or <code>null</code> if this pathname
  359. * does not name a parent
  360. */
  361. public String getParent() {
  362. int index = path.lastIndexOf(separatorChar);
  363. if (index < prefixLength) {
  364. if ((prefixLength > 0) && (path.length() > prefixLength))
  365. return path.substring(0, prefixLength);
  366. return null;
  367. }
  368. return path.substring(0, index);
  369. }
  370. /**
  371. * Returns the abstract pathname of this abstract pathname's parent,
  372. * or <code>null</code> if this pathname does not name a parent
  373. * directory.
  374. *
  375. * <p> The <em>parent</em> of an abstract pathname consists of the
  376. * pathname's prefix, if any, and each name in the pathname's name
  377. * sequence except for the last. If the name sequence is empty then
  378. * the pathname does not name a parent directory.
  379. *
  380. * @return The abstract pathname of the parent directory named by this
  381. * abstract pathname, or <code>null</code> if this pathname
  382. * does not name a parent
  383. *
  384. * @since 1.2
  385. */
  386. public File getParentFile() {
  387. String p = this.getParent();
  388. if (p == null) return null;
  389. return new File(p, this.prefixLength);
  390. }
  391. /**
  392. * Converts this abstract pathname into a pathname string. The resulting
  393. * string uses the {@link #separator default name-separator character} to
  394. * separate the names in the name sequence.
  395. *
  396. * @return The string form of this abstract pathname
  397. */
  398. public String getPath() {
  399. return path;
  400. }
  401. /* -- Path operations -- */
  402. /**
  403. * Tests whether this abstract pathname is absolute. The definition of
  404. * absolute pathname is system dependent. On UNIX systems, a pathname is
  405. * absolute if its prefix is <code>"/"</code>. On Microsoft Windows systems, a
  406. * pathname is absolute if its prefix is a drive specifier followed by
  407. * <code>"\\"</code>, or if its prefix is <code>"\\\\"</code>.
  408. *
  409. * @return <code>true</code> if this abstract pathname is absolute,
  410. * <code>false</code> otherwise
  411. */
  412. public boolean isAbsolute() {
  413. return fs.isAbsolute(this);
  414. }
  415. /**
  416. * Returns the absolute pathname string of this abstract pathname.
  417. *
  418. * <p> If this abstract pathname is already absolute, then the pathname
  419. * string is simply returned as if by the <code>{@link #getPath}</code>
  420. * method. If this abstract pathname is the empty abstract pathname then
  421. * the pathname string of the current user directory, which is named by the
  422. * system property <code>user.dir</code>, is returned. Otherwise this
  423. * pathname is resolved in a system-dependent way. On UNIX systems, a
  424. * relative pathname is made absolute by resolving it against the current
  425. * user directory. On Microsoft Windows systems, a relative pathname is made absolute
  426. * by resolving it against the current directory of the drive named by the
  427. * pathname, if any; if not, it is resolved against the current user
  428. * directory.
  429. *
  430. * @return The absolute pathname string denoting the same file or
  431. * directory as this abstract pathname
  432. *
  433. * @throws SecurityException
  434. * If a required system property value cannot be accessed.
  435. *
  436. * @see java.io.File#isAbsolute()
  437. */
  438. public String getAbsolutePath() {
  439. return fs.resolve(this);
  440. }
  441. /**
  442. * Returns the absolute form of this abstract pathname. Equivalent to
  443. * <code>new File(this.{@link #getAbsolutePath}())</code>.
  444. *
  445. * @return The absolute abstract pathname denoting the same file or
  446. * directory as this abstract pathname
  447. *
  448. * @throws SecurityException
  449. * If a required system property value cannot be accessed.
  450. *
  451. * @since 1.2
  452. */
  453. public File getAbsoluteFile() {
  454. String absPath = getAbsolutePath();
  455. return new File(absPath, fs.prefixLength(absPath));
  456. }
  457. /**
  458. * Returns the canonical pathname string of this abstract pathname.
  459. *
  460. * <p> A canonical pathname is both absolute and unique. The precise
  461. * definition of canonical form is system-dependent. This method first
  462. * converts this pathname to absolute form if necessary, as if by invoking the
  463. * {@link #getAbsolutePath} method, and then maps it to its unique form in a
  464. * system-dependent way. This typically involves removing redundant names
  465. * such as <tt>"."</tt> and <tt>".."</tt> from the pathname, resolving
  466. * symbolic links (on UNIX platforms), and converting drive letters to a
  467. * standard case (on Microsoft Windows platforms).
  468. *
  469. * <p> Every pathname that denotes an existing file or directory has a
  470. * unique canonical form. Every pathname that denotes a nonexistent file
  471. * or directory also has a unique canonical form. The canonical form of
  472. * the pathname of a nonexistent file or directory may be different from
  473. * the canonical form of the same pathname after the file or directory is
  474. * created. Similarly, the canonical form of the pathname of an existing
  475. * file or directory may be different from the canonical form of the same
  476. * pathname after the file or directory is deleted.
  477. *
  478. * @return The canonical pathname string denoting the same file or
  479. * directory as this abstract pathname
  480. *
  481. * @throws IOException
  482. * If an I/O error occurs, which is possible because the
  483. * construction of the canonical pathname may require
  484. * filesystem queries
  485. *
  486. * @throws SecurityException
  487. * If a required system property value cannot be accessed, or
  488. * if a security manager exists and its <code>{@link
  489. * java.lang.SecurityManager#checkRead}</code> method denies
  490. * read access to the file
  491. *
  492. * @since JDK1.1
  493. */
  494. public String getCanonicalPath() throws IOException {
  495. return fs.canonicalize(fs.resolve(this));
  496. }
  497. /**
  498. * Returns the canonical form of this abstract pathname. Equivalent to
  499. * <code>new File(this.{@link #getCanonicalPath}())</code>.
  500. *
  501. * @return The canonical pathname string denoting the same file or
  502. * directory as this abstract pathname
  503. *
  504. * @throws IOException
  505. * If an I/O error occurs, which is possible because the
  506. * construction of the canonical pathname may require
  507. * filesystem queries
  508. *
  509. * @throws SecurityException
  510. * If a required system property value cannot be accessed, or
  511. * if a security manager exists and its <code>{@link
  512. * java.lang.SecurityManager#checkRead}</code> method denies
  513. * read access to the file
  514. *
  515. * @since 1.2
  516. */
  517. public File getCanonicalFile() throws IOException {
  518. String canonPath = getCanonicalPath();
  519. return new File(canonPath, fs.prefixLength(canonPath));
  520. }
  521. private static String slashify(String path, boolean isDirectory) {
  522. String p = path;
  523. if (File.separatorChar != '/')
  524. p = p.replace(File.separatorChar, '/');
  525. if (!p.startsWith("/"))
  526. p = "/" + p;
  527. if (!p.endsWith("/") && isDirectory)
  528. p = p + "/";
  529. return p;
  530. }
  531. /**
  532. * Converts this abstract pathname into a <code>file:</code> URL. The
  533. * exact form of the URL is system-dependent. If it can be determined that
  534. * the file denoted by this abstract pathname is a directory, then the
  535. * resulting URL will end with a slash.
  536. *
  537. * <p> <b>Usage note:</b> This method does not automatically escape
  538. * characters that are illegal in URLs. It is recommended that new code
  539. * convert an abstract pathname into a URL by first converting it into a
  540. * URI, via the {@link #toURI() toURI} method, and then converting the URI
  541. * into a URL via the {@link java.net.URI#toURL() URI.toURL} method.
  542. *
  543. * @return A URL object representing the equivalent file URL
  544. *
  545. * @throws MalformedURLException
  546. * If the path cannot be parsed as a URL
  547. *
  548. * @see #toURI()
  549. * @see java.net.URI
  550. * @see java.net.URI#toURL()
  551. * @see java.net.URL
  552. * @since 1.2
  553. */
  554. public URL toURL() throws MalformedURLException {
  555. return new URL("file", "", slashify(getAbsolutePath(), isDirectory()));
  556. }
  557. /**
  558. * Constructs a <tt>file:</tt> URI that represents this abstract pathname.
  559. *
  560. * <p> The exact form of the URI is system-dependent. If it can be
  561. * determined that the file denoted by this abstract pathname is a
  562. * directory, then the resulting URI will end with a slash.
  563. *
  564. * <p> For a given abstract pathname <i>f</i>, it is guaranteed that
  565. *
  566. * <blockquote><tt>
  567. * new {@link #File(java.net.URI) File}(</tt><i> f</i><tt>.toURI()).equals(</tt><i> f</i><tt>.{@link #getAbsoluteFile() getAbsoluteFile}())
  568. * </tt></blockquote>
  569. *
  570. * so long as the original abstract pathname, the URI, and the new abstract
  571. * pathname are all created in (possibly different invocations of) the same
  572. * Java virtual machine. Due to the system-dependent nature of abstract
  573. * pathnames, however, this relationship typically does not hold when a
  574. * <tt>file:</tt> URI that is created in a virtual machine on one operating
  575. * system is converted into an abstract pathname in a virtual machine on a
  576. * different operating system.
  577. *
  578. * @return An absolute, hierarchical URI with a scheme equal to
  579. * <tt>"file"</tt>, a path representing this abstract pathname,
  580. * and undefined authority, query, and fragment components
  581. *
  582. * @see #File(java.net.URI)
  583. * @see java.net.URI
  584. * @see java.net.URI#toURL()
  585. * @since 1.4
  586. */
  587. public URI toURI() {
  588. try {
  589. File f = getAbsoluteFile();
  590. String sp = slashify(f.getPath(), f.isDirectory());
  591. if (sp.startsWith("//"))
  592. sp = "//" + sp;
  593. return new URI("file", null, sp, null);
  594. } catch (URISyntaxException x) {
  595. throw new Error(x); // Can't happen
  596. }
  597. }
  598. /* -- Attribute accessors -- */
  599. /**
  600. * Tests whether the application can read the file denoted by this
  601. * abstract pathname.
  602. *
  603. * @return <code>true</code> if and only if the file specified by this
  604. * abstract pathname exists <em>and</em> can be read by the
  605. * application; <code>false</code> otherwise
  606. *
  607. * @throws SecurityException
  608. * If a security manager exists and its <code>{@link
  609. * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
  610. * method denies read access to the file
  611. */
  612. public boolean canRead() {
  613. SecurityManager security = System.getSecurityManager();
  614. if (security != null) {
  615. security.checkRead(path);
  616. }
  617. return fs.checkAccess(this, false);
  618. }
  619. /**
  620. * Tests whether the application can modify the file denoted by this
  621. * abstract pathname.
  622. *
  623. * @return <code>true</code> if and only if the file system actually
  624. * contains a file denoted by this abstract pathname <em>and</em>
  625. * the application is allowed to write to the file;
  626. * <code>false</code> otherwise.
  627. *
  628. * @throws SecurityException
  629. * If a security manager exists and its <code>{@link
  630. * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
  631. * method denies write access to the file
  632. */
  633. public boolean canWrite() {
  634. SecurityManager security = System.getSecurityManager();
  635. if (security != null) {
  636. security.checkWrite(path);
  637. }
  638. return fs.checkAccess(this, true);
  639. }
  640. /**
  641. * Tests whether the file or directory denoted by this abstract pathname
  642. * exists.
  643. *
  644. * @return <code>true</code> if and only if the file or directory denoted
  645. * by this abstract pathname exists; <code>false</code> otherwise
  646. *
  647. * @throws SecurityException
  648. * If a security manager exists and its <code>{@link
  649. * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
  650. * method denies read access to the file or directory
  651. */
  652. public boolean exists() {
  653. SecurityManager security = System.getSecurityManager();
  654. if (security != null) {
  655. security.checkRead(path);
  656. }
  657. return ((fs.getBooleanAttributes(this) & FileSystem.BA_EXISTS) != 0);
  658. }
  659. /**
  660. * Tests whether the file denoted by this abstract pathname is a
  661. * directory.
  662. *
  663. * @return <code>true</code> if and only if the file denoted by this
  664. * abstract pathname exists <em>and</em> is a directory;
  665. * <code>false</code> otherwise
  666. *
  667. * @throws SecurityException
  668. * If a security manager exists and its <code>{@link
  669. * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
  670. * method denies read access to the file
  671. */
  672. public boolean isDirectory() {
  673. SecurityManager security = System.getSecurityManager();
  674. if (security != null) {
  675. security.checkRead(path);
  676. }
  677. return ((fs.getBooleanAttributes(this) & FileSystem.BA_DIRECTORY)
  678. != 0);
  679. }
  680. /**
  681. * Tests whether the file denoted by this abstract pathname is a normal
  682. * file. A file is <em>normal</em> if it is not a directory and, in
  683. * addition, satisfies other system-dependent criteria. Any non-directory
  684. * file created by a Java application is guaranteed to be a normal file.
  685. *
  686. * @return <code>true</code> if and only if the file denoted by this
  687. * abstract pathname exists <em>and</em> is a normal file;
  688. * <code>false</code> otherwise
  689. *
  690. * @throws SecurityException
  691. * If a security manager exists and its <code>{@link
  692. * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
  693. * method denies read access to the file
  694. */
  695. public boolean isFile() {
  696. SecurityManager security = System.getSecurityManager();
  697. if (security != null) {
  698. security.checkRead(path);
  699. }
  700. return ((fs.getBooleanAttributes(this) & FileSystem.BA_REGULAR) != 0);
  701. }
  702. /**
  703. * Tests whether the file named by this abstract pathname is a hidden
  704. * file. The exact definition of <em>hidden</em> is system-dependent. On
  705. * UNIX systems, a file is considered to be hidden if its name begins with
  706. * a period character (<code>'.'</code>). On Microsoft Windows systems, a file is
  707. * considered to be hidden if it has been marked as such in the filesystem.
  708. *
  709. * @return <code>true</code> if and only if the file denoted by this
  710. * abstract pathname is hidden according to the conventions of the
  711. * underlying platform
  712. *
  713. * @throws SecurityException
  714. * If a security manager exists and its <code>{@link
  715. * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
  716. * method denies read access to the file
  717. *
  718. * @since 1.2
  719. */
  720. public boolean isHidden() {
  721. SecurityManager security = System.getSecurityManager();
  722. if (security != null) {
  723. security.checkRead(path);
  724. }
  725. return ((fs.getBooleanAttributes(this) & FileSystem.BA_HIDDEN) != 0);
  726. }
  727. /**
  728. * Returns the time that the file denoted by this abstract pathname was
  729. * last modified.
  730. *
  731. * @return A <code>long</code> value representing the time the file was
  732. * last modified, measured in milliseconds since the epoch
  733. * (00:00:00 GMT, January 1, 1970), or <code>0L</code> if the
  734. * file does not exist or if an I/O error occurs
  735. *
  736. * @throws SecurityException
  737. * If a security manager exists and its <code>{@link
  738. * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
  739. * method denies read access to the file
  740. */
  741. public long lastModified() {
  742. SecurityManager security = System.getSecurityManager();
  743. if (security != null) {
  744. security.checkRead(path);
  745. }
  746. return fs.getLastModifiedTime(this);
  747. }
  748. /**
  749. * Returns the length of the file denoted by this abstract pathname.
  750. * The return value is unspecified if this pathname denotes a directory.
  751. *
  752. * @return The length, in bytes, of the file denoted by this abstract
  753. * pathname, or <code>0L</code> if the file does not exist
  754. *
  755. * @throws SecurityException
  756. * If a security manager exists and its <code>{@link
  757. * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
  758. * method denies read access to the file
  759. */
  760. public long length() {
  761. SecurityManager security = System.getSecurityManager();
  762. if (security != null) {
  763. security.checkRead(path);
  764. }
  765. return fs.getLength(this);
  766. }
  767. /* -- File operations -- */
  768. /**
  769. * Atomically creates a new, empty file named by this abstract pathname if
  770. * and only if a file with this name does not yet exist. The check for the
  771. * existence of the file and the creation of the file if it does not exist
  772. * are a single operation that is atomic with respect to all other
  773. * filesystem activities that might affect the file.
  774. * <P>
  775. * Note: this method should <i>not</i> be used for file-locking, as
  776. * the resulting protocol cannot be made to work reliably. The
  777. * {@link java.nio.channels.FileLock FileLock}
  778. * facility should be used instead.
  779. *
  780. * @return <code>true</code> if the named file does not exist and was
  781. * successfully created; <code>false</code> if the named file
  782. * already exists
  783. *
  784. * @throws IOException
  785. * If an I/O error occurred
  786. *
  787. * @throws SecurityException
  788. * If a security manager exists and its <code>{@link
  789. * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
  790. * method denies write access to the file
  791. *
  792. * @since 1.2
  793. */
  794. public boolean createNewFile() throws IOException {
  795. SecurityManager security = System.getSecurityManager();
  796. if (security != null) security.checkWrite(path);
  797. return fs.createFileExclusively(path);
  798. }
  799. /**
  800. * Deletes the file or directory denoted by this abstract pathname. If
  801. * this pathname denotes a directory, then the directory must be empty in
  802. * order to be deleted.
  803. *
  804. * @return <code>true</code> if and only if the file or directory is
  805. * successfully deleted; <code>false</code> otherwise
  806. *
  807. * @throws SecurityException
  808. * If a security manager exists and its <code>{@link
  809. * java.lang.SecurityManager#checkDelete}</code> method denies
  810. * delete access to the file
  811. */
  812. public boolean delete() {
  813. SecurityManager security = System.getSecurityManager();
  814. if (security != null) {
  815. security.checkDelete(path);
  816. }
  817. return fs.delete(this);
  818. }
  819. /**
  820. * Requests that the file or directory denoted by this abstract
  821. * pathname be deleted when the virtual machine terminates.
  822. * Deletion will be attempted only for normal termination of the
  823. * virtual machine, as defined by the Java Language Specification.
  824. *
  825. * <p> Once deletion has been requested, it is not possible to cancel the
  826. * request. This method should therefore be used with care.
  827. *
  828. * <P>
  829. * Note: this method should <i>not</i> be used for file-locking, as
  830. * the resulting protocol cannot be made to work reliably. The
  831. * {@link java.nio.channels.FileLock FileLock}
  832. * facility should be used instead.
  833. *
  834. * @throws SecurityException
  835. * If a security manager exists and its <code>{@link
  836. * java.lang.SecurityManager#checkDelete}</code> method denies
  837. * delete access to the file
  838. *
  839. * @see #delete
  840. *
  841. * @since 1.2
  842. */
  843. public void deleteOnExit() {
  844. SecurityManager security = System.getSecurityManager();
  845. if (security != null) {
  846. security.checkDelete(path);
  847. }
  848. fs.deleteOnExit(this);
  849. }
  850. /**
  851. * Returns an array of strings naming the files and directories in the
  852. * directory denoted by this abstract pathname.
  853. *
  854. * <p> If this abstract pathname does not denote a directory, then this
  855. * method returns <code>null</code>. Otherwise an array of strings is
  856. * returned, one for each file or directory in the directory. Names
  857. * denoting the directory itself and the directory's parent directory are
  858. * not included in the result. Each string is a file name rather than a
  859. * complete path.
  860. *
  861. * <p> There is no guarantee that the name strings in the resulting array
  862. * will appear in any specific order; they are not, in particular,
  863. * guaranteed to appear in alphabetical order.
  864. *
  865. * @return An array of strings naming the files and directories in the
  866. * directory denoted by this abstract pathname. The array will be
  867. * empty if the directory is empty. Returns <code>null</code> if
  868. * this abstract pathname does not denote a directory, or if an
  869. * I/O error occurs.
  870. *
  871. * @throws SecurityException
  872. * If a security manager exists and its <code>{@link
  873. * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
  874. * method denies read access to the directory
  875. */
  876. public String[] list() {
  877. SecurityManager security = System.getSecurityManager();
  878. if (security != null) {
  879. security.checkRead(path);
  880. }
  881. return fs.list(this);
  882. }
  883. /**
  884. * Returns an array of strings naming the files and directories in the
  885. * directory denoted by this abstract pathname that satisfy the specified
  886. * filter. The behavior of this method is the same as that of the
  887. * <code>{@link #list()}</code> method, except that the strings in the
  888. * returned array must satisfy the filter. If the given
  889. * <code>filter</code> is <code>null</code> then all names are accepted.
  890. * Otherwise, a name satisfies the filter if and only if the value
  891. * <code>true</code> results when the <code>{@link
  892. * FilenameFilter#accept}</code> method of the filter is invoked on this
  893. * abstract pathname and the name of a file or directory in the directory
  894. * that it denotes.
  895. *
  896. * @param filter A filename filter
  897. *
  898. * @return An array of strings naming the files and directories in the
  899. * directory denoted by this abstract pathname that were accepted
  900. * by the given <code>filter</code>. The array will be empty if
  901. * the directory is empty or if no names were accepted by the
  902. * filter. Returns <code>null</code> if this abstract pathname
  903. * does not denote a directory, or if an I/O error occurs.
  904. *
  905. * @throws SecurityException
  906. * If a security manager exists and its <code>{@link
  907. * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
  908. * method denies read access to the directory
  909. */
  910. public String[] list(FilenameFilter filter) {
  911. String names[] = list();
  912. if ((names == null) || (filter == null)) {
  913. return names;
  914. }
  915. ArrayList v = new ArrayList();
  916. for (int i = 0 ; i < names.length ; i++) {
  917. if (filter.accept(this, names[i])) {
  918. v.add(names[i]);
  919. }
  920. }
  921. return (String[])(v.toArray(new String[0]));
  922. }
  923. /**
  924. * Returns an array of abstract pathnames denoting the files in the
  925. * directory denoted by this abstract pathname.
  926. *
  927. * <p> If this abstract pathname does not denote a directory, then this
  928. * method returns <code>null</code>. Otherwise an array of
  929. * <code>File</code> objects is returned, one for each file or directory in
  930. * the directory. Pathnames denoting the directory itself and the
  931. * directory's parent directory are not included in the result. Each
  932. * resulting abstract pathname is constructed from this abstract pathname
  933. * using the <code>{@link #File(java.io.File, java.lang.String)
  934. * File(File, String)}</code> constructor. Therefore if this pathname
  935. * is absolute then each resulting pathname is absolute; if this pathname
  936. * is relative then each resulting pathname will be relative to the same
  937. * directory.
  938. *
  939. * <p> There is no guarantee that the name strings in the resulting array
  940. * will appear in any specific order; they are not, in particular,
  941. * guaranteed to appear in alphabetical order.
  942. *
  943. * @return An array of abstract pathnames denoting the files and
  944. * directories in the directory denoted by this abstract
  945. * pathname. The array will be empty if the directory is
  946. * empty. Returns <code>null</code> if this abstract pathname
  947. * does not denote a directory, or if an I/O error occurs.
  948. *
  949. * @throws SecurityException
  950. * If a security manager exists and its <code>{@link
  951. * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
  952. * method denies read access to the directory
  953. *
  954. * @since 1.2
  955. */
  956. public File[] listFiles() {
  957. String[] ss = list();
  958. if (ss == null) return null;
  959. int n = ss.length;
  960. File[] fs = new File[n];
  961. for (int i = 0; i < n; i++) {
  962. fs[i] = new File(ss[i], this);
  963. }
  964. return fs;
  965. }
  966. /**
  967. * Returns an array of abstract pathnames denoting the files and
  968. * directories in the directory denoted by this abstract pathname that
  969. * satisfy the specified filter. The behavior of this method is the
  970. * same as that of the <code>{@link #listFiles()}</code> method, except
  971. * that the pathnames in the returned array must satisfy the filter.
  972. * If the given <code>filter</code> is <code>null</code> then all
  973. * pathnames are accepted. Otherwise, a pathname satisfies the filter
  974. * if and only if the value <code>true</code> results when the
  975. * <code>{@link FilenameFilter#accept}</code> method of the filter is
  976. * invoked on this abstract pathname and the name of a file or
  977. * directory in the directory that it denotes.
  978. *
  979. * @param filter A filename filter
  980. *
  981. * @return An array of abstract pathnames denoting the files and
  982. * directories in the directory denoted by this abstract
  983. * pathname. The array will be empty if the directory is
  984. * empty. Returns <code>null</code> if this abstract pathname
  985. * does not denote a directory, or if an I/O error occurs.
  986. *
  987. * @throws SecurityException
  988. * If a security manager exists and its <code>{@link
  989. * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
  990. * method denies read access to the directory
  991. *
  992. * @since 1.2
  993. */
  994. public File[] listFiles(FilenameFilter filter) {
  995. String ss[] = list();
  996. if (ss == null) return null;
  997. ArrayList v = new ArrayList();
  998. for (int i = 0 ; i < ss.length ; i++) {
  999. if ((filter == null) || filter.accept(this, ss[i])) {
  1000. v.add(new File(ss[i], this));
  1001. }
  1002. }
  1003. return (File[])(v.toArray(new File[0]));
  1004. }
  1005. /**
  1006. * Returns an array of abstract pathnames denoting the files and
  1007. * directories in the directory denoted by this abstract pathname that
  1008. * satisfy the specified filter. The behavior of this method is the
  1009. * same as that of the <code>{@link #listFiles()}</code> method, except
  1010. * that the pathnames in the returned array must satisfy the filter.
  1011. * If the given <code>filter</code> is <code>null</code> then all
  1012. * pathnames are accepted. Otherwise, a pathname satisfies the filter
  1013. * if and only if the value <code>true</code> results when the
  1014. * <code>{@link FileFilter#accept(java.io.File)}</code> method of
  1015. * the filter is invoked on the pathname.
  1016. *
  1017. * @param filter A file filter
  1018. *
  1019. * @return An array of abstract pathnames denoting the files and
  1020. * directories in the directory denoted by this abstract
  1021. * pathname. The array will be empty if the directory is
  1022. * empty. Returns <code>null</code> if this abstract pathname
  1023. * does not denote a directory, or if an I/O error occurs.
  1024. *
  1025. * @throws SecurityException
  1026. * If a security manager exists and its <code>{@link
  1027. * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
  1028. * method denies read access to the directory
  1029. *
  1030. * @since 1.2
  1031. */
  1032. public File[] listFiles(FileFilter filter) {
  1033. String ss[] = list();
  1034. if (ss == null) return null;
  1035. ArrayList v = new ArrayList();
  1036. for (int i = 0 ; i < ss.length ; i++) {
  1037. File f = new File(ss[i], this);
  1038. if ((filter == null) || filter.accept(f)) {
  1039. v.add(f);
  1040. }
  1041. }
  1042. return (File[])(v.toArray(new File[0]));
  1043. }
  1044. /**
  1045. * Creates the directory named by this abstract pathname.
  1046. *
  1047. * @return <code>true</code> if and only if the directory was
  1048. * created; <code>false</code> otherwise
  1049. *
  1050. * @throws SecurityException
  1051. * If a security manager exists and its <code>{@link
  1052. * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
  1053. * method does not permit the named directory to be created
  1054. */
  1055. public boolean mkdir() {
  1056. SecurityManager security = System.getSecurityManager();
  1057. if (security != null) {
  1058. security.checkWrite(path);
  1059. }
  1060. return fs.createDirectory(this);
  1061. }
  1062. /**
  1063. * Creates the directory named by this abstract pathname, including any
  1064. * necessary but nonexistent parent directories. Note that if this
  1065. * operation fails it may have succeeded in creating some of the necessary
  1066. * parent directories.
  1067. *
  1068. * @return <code>true</code> if and only if the directory was created,
  1069. * along with all necessary parent directories; <code>false</code>
  1070. * otherwise
  1071. *
  1072. * @throws SecurityException
  1073. * If a security manager exists and its <code>{@link
  1074. * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
  1075. * method does not permit verification of the existence of the
  1076. * named directory and all necessary parent directories; or if
  1077. * the <code>{@link
  1078. * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
  1079. * method does not permit the named directory and all necessary
  1080. * parent directories to be created
  1081. */
  1082. public boolean mkdirs() {
  1083. if (exists()) {
  1084. return false;
  1085. }
  1086. if (mkdir()) {
  1087. return true;
  1088. }
  1089. File canonFile = null;
  1090. try {
  1091. canonFile = getCanonicalFile();
  1092. } catch (IOException e) {
  1093. return false;
  1094. }
  1095. String parent = canonFile.getParent();
  1096. return (parent != null) &&
  1097. (new File(parent, fs.prefixLength(parent)).mkdirs() &&
  1098. canonFile.mkdir());
  1099. }
  1100. /**
  1101. * Renames the file denoted by this abstract pathname.
  1102. *
  1103. * <p> Many aspects of the behavior of this method are inherently
  1104. * platform-dependent: The rename operation might not be able to move a
  1105. * file from one filesystem to another, it might not be atomic, and it
  1106. * might not succeed if a file with the destination abstract pathname
  1107. * already exists. The return value should always be checked to make sure
  1108. * that the rename operation was successful.
  1109. *
  1110. * @param dest The new abstract pathname for the named file
  1111. *
  1112. * @return <code>true</code> if and only if the renaming succeeded;
  1113. * <code>false</code> otherwise
  1114. *
  1115. * @throws SecurityException
  1116. * If a security manager exists and its <code>{@link
  1117. * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
  1118. * method denies write access to either the old or new pathnames
  1119. *
  1120. * @throws NullPointerException
  1121. * If parameter <code>dest</code> is <code>null</code>
  1122. */
  1123. public boolean renameTo(File dest) {
  1124. SecurityManager security = System.getSecurityManager();
  1125. if (security != null) {
  1126. security.checkWrite(path);
  1127. security.checkWrite(dest.path);
  1128. }
  1129. return fs.rename(this, dest);
  1130. }
  1131. /**
  1132. * Sets the last-modified time of the file or directory named by this
  1133. * abstract pathname.
  1134. *
  1135. * <p> All platforms support file-modification times to the nearest second,
  1136. * but some provide more precision. The argument will be truncated to fit
  1137. * the supported precision. If the operation succeeds and no intervening
  1138. * operations on the file take place, then the next invocation of the
  1139. * <code>{@link #lastModified}</code> method will return the (possibly
  1140. * truncated) <code>time</code> argument that was passed to this method.
  1141. *
  1142. * @param time The new last-modified time, measured in milliseconds since
  1143. * the epoch (00:00:00 GMT, January 1, 1970)
  1144. *
  1145. * @return <code>true</code> if and only if the operation succeeded;
  1146. * <code>false</code> otherwise
  1147. *
  1148. * @throws IllegalArgumentException If the argument is negative
  1149. *
  1150. * @throws SecurityException
  1151. * If a security manager exists and its <code>{@link
  1152. * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
  1153. * method denies write access to the named file
  1154. *
  1155. * @since 1.2
  1156. */
  1157. public boolean setLastModified(long time) {
  1158. if (time < 0) throw new IllegalArgumentException("Negative time");
  1159. SecurityManager security = System.getSecurityManager();
  1160. if (security != null) {
  1161. security.checkWrite(path);
  1162. }
  1163. return fs.setLastModifiedTime(this, time);
  1164. }
  1165. /**
  1166. * Marks the file or directory named by this abstract pathname so that
  1167. * only read operations are allowed. After invoking this method the file
  1168. * or directory is guaranteed not to change until it is either deleted or
  1169. * marked to allow write access. Whether or not a read-only file or
  1170. * directory may be deleted depends upon the underlying system.
  1171. *
  1172. * @return <code>true</code> if and only if the operation succeeded;
  1173. * <code>false</code> otherwise
  1174. *
  1175. * @throws SecurityException
  1176. * If a security manager exists and its <code>{@link
  1177. * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
  1178. * method denies write access to the named file
  1179. *
  1180. * @since 1.2
  1181. */
  1182. public boolean setReadOnly() {
  1183. SecurityManager security = System.getSecurityManager();
  1184. if (security != null) {
  1185. security.checkWrite(path);
  1186. }
  1187. return fs.setReadOnly(this);
  1188. }
  1189. /* -- Filesystem interface -- */
  1190. /**
  1191. * List the available filesystem roots.
  1192. *
  1193. * <p> A particular Java platform may support zero or more
  1194. * hierarchically-organized file systems. Each file system has a
  1195. * <code>root</code> directory from which all other files in that file
  1196. * system can be reached. Windows platforms, for example, have a root
  1197. * directory for each active drive; UNIX platforms have a single root
  1198. * directory, namely <code>"/"</code>. The set of available filesystem
  1199. * roots is affected by various system-level operations such as the insertion
  1200. * or ejection of removable media and the disconnecting or unmounting of
  1201. * physical or virtual disk drives.
  1202. *
  1203. * <p> This method returns an array of <code>File</code> objects that
  1204. * denote the root directories of the available filesystem roots. It is
  1205. * guaranteed that the canonical pathname of any file physically present on
  1206. * the local machine will begin with one of the roots returned by this
  1207. * method.
  1208. *
  1209. * <p> The canonical pathname of a file that resides on some other machine
  1210. * and is accessed via a remote-filesystem protocol such as SMB or NFS may
  1211. * or may not begin with one of the roots returned by this method. If the
  1212. * pathname of a remote file is syntactically indistinguishable from the
  1213. * pathname of a local file then it will begin with one of the roots
  1214. * returned by this method. Thus, for example, <code>File</code> objects
  1215. * denoting the root directories of the mapped network drives of a Windows
  1216. * platform will be returned by this method, while <code>File</code>
  1217. * objects containing UNC pathnames will not be returned by this method.
  1218. *
  1219. * <p> Unlike most methods in this class, this method does not throw
  1220. * security exceptions. If a security manager exists and its <code>{@link
  1221. * java.lang.SecurityManager#checkRead(java.lang.String)}</code> method
  1222. * denies read access to a particular root directory, then that directory
  1223. * will not appear in the result.
  1224. *
  1225. * @return An array of <code>File</code> objects denoting the available
  1226. * filesystem roots, or <code>null</code> if the set of roots
  1227. * could not be determined. The array will be empty if there are
  1228. * no filesystem roots.
  1229. *
  1230. * @since 1.2
  1231. */
  1232. public static File[] listRoots() {
  1233. return fs.listRoots();
  1234. }
  1235. /* -- Temporary files -- */
  1236. private static final Object tmpFileLock = new Object();
  1237. private static int counter = -1; /* Protected by tmpFileLock */
  1238. private static File generateFile(String prefix, String suffix, File dir)
  1239. throws IOException
  1240. {
  1241. if (counter == -1) {
  1242. counter = new Random().nextInt() & 0xffff;
  1243. }
  1244. counter++;
  1245. return new File(dir, prefix + Integer.toString(counter) + suffix);
  1246. }
  1247. private static String tmpdir; /* Protected by tmpFileLock */
  1248. private static String getTempDir() {
  1249. if (tmpdir == null) {
  1250. GetPropertyAction a = new GetPropertyAction("java.io.tmpdir");
  1251. tmpdir = ((String) AccessController.doPrivileged(a));
  1252. tmpdir = fs.normalize(tmpdir);
  1253. }
  1254. return tmpdir;
  1255. }
  1256. private static boolean checkAndCreate(String filename, SecurityManager sm)
  1257. throws IOException
  1258. {
  1259. if (sm != null) {
  1260. try {
  1261. sm.checkWrite(filename);
  1262. } catch (AccessControlException x) {
  1263. /* Throwing the original AccessControlException could disclose
  1264. the location of the default temporary directory, so we
  1265. re-throw a more innocuous SecurityException */
  1266. throw new SecurityException("Unable to create temporary file");
  1267. }
  1268. }
  1269. return fs.createFileExclusively(filename);
  1270. }
  1271. /**
  1272. * <p> Creates a new empty file in the specified directory, using the
  1273. * given prefix and suffix strings to generate its name. If this method
  1274. * returns successfully then it is guaranteed that:
  1275. *
  1276. * <ol>
  1277. * <li> The file denoted by the returned abstract pathname did not exist
  1278. * before this method was invoked, and
  1279. * <li> Neither this method nor any of its variants will return the same
  1280. * abstract pathname again in the current invocation of the virtual
  1281. * machine.
  1282. * </ol>
  1283. *
  1284. * This method provides only part of a temporary-file facility. To arrange
  1285. * for a file created by this method to be deleted automatically, use the
  1286. * <code>{@link #deleteOnExit}</code> method.
  1287. *
  1288. * <p> The <code>prefix</code> argument must be at least three characters
  1289. * long. It is recommended that the prefix be a short, meaningful string
  1290. * such as <code>"hjb"</code> or <code>"mail"</code>. The
  1291. * <code>suffix</code> argument may be <code>null</code>, in which case the
  1292. * suffix <code>".tmp"</code> will be used.
  1293. *
  1294. * <p> To create the new file, the prefix and the suffix may first be
  1295. * adjusted to fit the limitations of the underlying platform. If the
  1296. * prefix is too long then it will be truncated, but its first three
  1297. * characters will always be preserved. If the suffix is too long then it
  1298. * too will be truncated, but if it begins with a period character
  1299. * (<code>'.'</code>) then the period and the first three characters
  1300. * following it will always be preserved. Once these adjustments have been
  1301. * made the name of the new file will be generated by concatenating the
  1302. * prefix, five or more internally-generated characters, and the suffix.
  1303. *
  1304. * <p> If the <code>directory</code> argument is <code>null</code> then the
  1305. * system-dependent default temporary-file directory will be used. The
  1306. * default temporary-file directory is specified by the system property
  1307. * <code>java.io.tmpdir</code>. On UNIX systems the default value of this
  1308. * property is typically <code>"/tmp"</code> or <code>"/var/tmp"</code> on
  1309. * Microsoft Windows systems it is typically <code>"C:\\WINNT\\TEMP"</code>. A different
  1310. * value may be given to this system property when the Java virtual machine
  1311. * is invoked, but programmatic changes to this property are not guaranteed
  1312. * to have any effect upon the temporary directory used by this method.
  1313. *
  1314. * @param prefix The prefix string to be used in generating the file's
  1315. * name; must be at least three characters long
  1316. *
  1317. * @param suffix The suffix string to be used in generating the file's
  1318. * name; may be <code>null</code>, in which case the
  1319. * suffix <code>".tmp"</code> will be used
  1320. *
  1321. * @param directory The directory in which the file is to be created, or
  1322. * <code>null</code> if the default temporary-file
  1323. * directory is to be used
  1324. *
  1325. * @return An abstract pathname denoting a newly-created empty file
  1326. *
  1327. * @throws IllegalArgumentException
  1328. * If the <code>prefix</code> argument contains fewer than three
  1329. * characters
  1330. *
  1331. * @throws IOException If a file could not be created
  1332. *
  1333. * @throws SecurityException
  1334. * If a security manager exists and its <code>{@link
  1335. * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
  1336. * method does not allow a file to be created
  1337. *
  1338. * @since 1.2
  1339. */
  1340. public static File createTempFile(String prefix, String suffix,
  1341. File directory)
  1342. throws IOException
  1343. {
  1344. if (prefix == null) throw new NullPointerException();
  1345. if (prefix.length() < 3)
  1346. throw new IllegalArgumentException("Prefix string too short");
  1347. String s = (suffix == null) ? ".tmp" : suffix;
  1348. synchronized (tmpFileLock) {
  1349. if (directory == null) {
  1350. String tmpDir = getTempDir();
  1351. directory = new File(tmpDir, fs.prefixLength(tmpDir));
  1352. }
  1353. SecurityManager sm = System.getSecurityManager();
  1354. File f;
  1355. do {
  1356. f = generateFile(prefix, s, directory);
  1357. } while (!checkAndCreate(f.getPath(), sm));
  1358. return f;
  1359. }
  1360. }
  1361. /**
  1362. * Creates an empty file in the default temporary-file directory, using
  1363. * the given prefix and suffix to generate its name. Invoking this method
  1364. * is equivalent to invoking <code>{@link #createTempFile(java.lang.String,
  1365. * java.lang.String, java.io.File)
  1366. * createTempFile(prefix, suffix, null)}</code>.
  1367. *
  1368. * @param prefix The prefix string to be used in generating the file's
  1369. * name; must be at least three characters long
  1370. *
  1371. * @param suffix The suffix string to be used in generating the file's
  1372. * name; may be <code>null</code>, in which case the
  1373. * suffix <code>".tmp"</code> will be used
  1374. *
  1375. * @return An abstract pathname denoting a newly-created empty file
  1376. *
  1377. * @throws IllegalArgumentException
  1378. * If the <code>prefix</code> argument contains fewer than three
  1379. * characters
  1380. *
  1381. * @throws IOException If a file could not be created
  1382. *
  1383. * @throws SecurityException
  1384. * If a security manager exists and its <code>{@link
  1385. * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
  1386. * method does not allow a file to be created
  1387. *
  1388. * @since 1.2
  1389. */
  1390. public static File createTempFile(String prefix, String suffix)
  1391. throws IOException
  1392. {
  1393. return createTempFile(prefix, suffix, null);
  1394. }
  1395. /* -- Basic infrastructure -- */
  1396. /**
  1397. * Compares two abstract pathnames lexicographically. The ordering
  1398. * defined by this method depends upon the underlying system. On UNIX
  1399. * systems, alphabetic case is significant in comparing pathnames; on Microsoft Windows
  1400. * systems it is not.
  1401. *
  1402. * @param pathname The abstract pathname to be compared to this abstract
  1403. * pathname
  1404. *
  1405. * @return Zero if the argument is equal to this abstract pathname, a
  1406. * value less than zero if this abstract pathname is
  1407. * lexicographically less than the argument, or a value greater
  1408. * than zero if this abstract pathname is lexicographically
  1409. * greater than the argument
  1410. *
  1411. * @since 1.2
  1412. */
  1413. public int compareTo(File pathname) {
  1414. return fs.compare(this, pathname);
  1415. }
  1416. /**
  1417. * Tests this abstract pathname for equality with the given object.
  1418. * Returns <code>true</code> if and only if the argument is not
  1419. * <code>null</code> and is an abstract pathname that denotes the same file
  1420. * or directory as this abstract pathname. Whether or not two abstract
  1421. * pathnames are equal depends upon the underlying system. On UNIX
  1422. * systems, alphabetic case is significant in comparing pathnames; on Microsoft Windows
  1423. * systems it is not.
  1424. *
  1425. * @param obj The object to be compared with this abstract pathname
  1426. *
  1427. * @return <code>true</code> if and only if the objects are the same;
  1428. * <code>false</code> otherwise
  1429. */
  1430. public boolean equals(Object obj) {
  1431. if ((obj != null) && (obj instanceof File)) {
  1432. return compareTo((File)obj) == 0;
  1433. }
  1434. return false;
  1435. }
  1436. /**
  1437. * Computes a hash code for this abstract pathname. Because equality of
  1438. * abstract pathnames is inherently system-dependent, so is the computation
  1439. * of their hash codes. On UNIX systems, the hash code of an abstract
  1440. * pathname is equal to the exclusive <em>or</em> of the hash code
  1441. * of its pathname string and the decimal value
  1442. * <code>1234321</code>. On Microsoft Windows systems, the hash
  1443. * code is equal to the exclusive <em>or</em> of the hash code of
  1444. * its pathname string converted to lower case and the decimal
  1445. * value <code>1234321</code>.
  1446. *
  1447. * @return A hash code for this abstract pathname
  1448. */
  1449. public int hashCode() {
  1450. return fs.hashCode(this);
  1451. }
  1452. /**
  1453. * Returns the pathname string of this abstract pathname. This is just the
  1454. * string returned by the <code>{@link #getPath}</code> method.
  1455. *
  1456. * @return The string form of this abstract pathname
  1457. */
  1458. public String toString() {
  1459. return getPath();
  1460. }
  1461. /**
  1462. * WriteObject is called to save this filename.
  1463. * The separator character is saved also so it can be replaced
  1464. * in case the path is reconstituted on a different host type.
  1465. */
  1466. private synchronized void writeObject(java.io.ObjectOutputStream s)
  1467. throws IOException
  1468. {
  1469. s.defaultWriteObject();
  1470. s.writeChar(this.separatorChar); // Add the separator character
  1471. }
  1472. /**
  1473. * readObject is called to restore this filename.
  1474. * The original separator character is read. If it is different
  1475. * than the separator character on this system, then the old separator
  1476. * is replaced by the local separator.
  1477. */
  1478. private synchronized void readObject(java.io.ObjectInputStream s)
  1479. throws IOException, ClassNotFoundException
  1480. {
  1481. s.defaultReadObject();
  1482. char sep = s.readChar(); // read the previous separator char
  1483. if (sep != separatorChar)
  1484. this.path = this.path.replace(sep, separatorChar);
  1485. this.path = fs.normalize(this.path);
  1486. this.prefixLength = fs.prefixLength(this.path);
  1487. }
  1488. /** use serialVersionUID from JDK 1.0.2 for interoperability */
  1489. private static final long serialVersionUID = 301077366599181567L;
  1490. }