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