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