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