PageRenderTime 63ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/enhanced/java/branches/omd/classlib/modules/luni/src/main/java/java/io/File.java

https://bitbucket.org/varialus/harmony
Java | 1492 lines | 1406 code | 26 blank | 60 comment | 8 complexity | 61ce9ea481a4c545b9825e496e46fcfb MD5 | raw file
Possible License(s): Apache-2.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package java.io;
  18. import java.net.URI;
  19. import java.net.URISyntaxException;
  20. import java.net.URL;
  21. import java.security.AccessController;
  22. import java.security.SecureRandom;
  23. import java.util.ArrayList;
  24. import java.util.List;
  25. import org.apache.harmony.luni.internal.io.FileCanonPathCache;
  26. import org.apache.harmony.luni.util.DeleteOnExit;
  27. import org.apache.harmony.luni.internal.nls.Messages;
  28. import org.apache.harmony.luni.util.PriviAction;
  29. import org.apache.harmony.luni.util.Util;
  30. /**
  31. * An "abstract" representation of a file system entity identified by a
  32. * pathname. The pathname may be absolute (relative to the root directory
  33. * of the file system) or relative to the current directory in which the program
  34. * is running.
  35. * <p>
  36. * This class provides methods for querying/changing information about the file
  37. * as well as directory listing capabilities if the file represents a directory.
  38. * <p>
  39. * When manipulating file paths, the static fields of this class may be used to
  40. * determine the platform specific separators.
  41. *
  42. * @see java.io.Serializable
  43. * @see java.lang.Comparable
  44. */
  45. public class File implements Serializable, Comparable<File> {
  46. private static final long serialVersionUID = 301077366599181567L;
  47. private static final String EMPTY_STRING = ""; //$NON-NLS-1$
  48. private String path;
  49. transient byte[] properPath;
  50. /**
  51. * The system dependent file separator character.
  52. */
  53. public static final char separatorChar;
  54. /**
  55. * The system dependent file separator string. The initial value of this
  56. * field is the system property "file.separator".
  57. */
  58. public static final String separator;
  59. /**
  60. * The system dependent path separator character.
  61. */
  62. public static final char pathSeparatorChar;
  63. /**
  64. * The system dependent path separator string. The initial value of this
  65. * field is the system property "path.separator".
  66. */
  67. public static final String pathSeparator;
  68. /* Temp file counter */
  69. private static int counter = 0;
  70. /* identify for differnt VM processes */
  71. private static int counterBase = 0;
  72. private static class TempFileLocker {};
  73. private static TempFileLocker tempFileLocker = new TempFileLocker();
  74. private static boolean caseSensitive;
  75. private static native void oneTimeInitialization();
  76. static {
  77. oneTimeInitialization();
  78. // The default protection domain grants access to these properties
  79. separatorChar = System.getProperty("file.separator", "\\").charAt(0); //$NON-NLS-1$ //$NON-NLS-2$
  80. pathSeparatorChar = System.getProperty("path.separator", ";").charAt(0); //$NON-NLS-1$//$NON-NLS-2$
  81. separator = new String(new char[] { separatorChar }, 0, 1);
  82. pathSeparator = new String(new char[] { pathSeparatorChar }, 0, 1);
  83. caseSensitive = isCaseSensitiveImpl();
  84. }
  85. /**
  86. * Constructs a new file using the specified directory and name.
  87. *
  88. * @param dir
  89. * the directory where the file is stored.
  90. * @param name
  91. * the file's name.
  92. * @throws NullPointerException
  93. * if {@code name} is {@code null}.
  94. */
  95. public File(File dir, String name) {
  96. if (name == null) {
  97. throw new NullPointerException();
  98. }
  99. if (dir == null) {
  100. this.path = fixSlashes(name);
  101. } else {
  102. this.path = calculatePath(dir.getPath(), name);
  103. }
  104. }
  105. /**
  106. * Constructs a new file using the specified path.
  107. *
  108. * @param path
  109. * the path to be used for the file.
  110. */
  111. public File(String path) {
  112. // path == null check & NullPointerException thrown by fixSlashes
  113. this.path = fixSlashes(path);
  114. }
  115. /**
  116. * Constructs a new File using the specified directory path and file name,
  117. * placing a path separator between the two.
  118. *
  119. * @param dirPath
  120. * the path to the directory where the file is stored.
  121. * @param name
  122. * the file's name.
  123. * @throws NullPointerException
  124. * if {@code name} is {@code null}.
  125. */
  126. public File(String dirPath, String name) {
  127. if (name == null) {
  128. throw new NullPointerException();
  129. }
  130. if (dirPath == null) {
  131. this.path = fixSlashes(name);
  132. } else {
  133. this.path = calculatePath(dirPath, name);
  134. }
  135. }
  136. /**
  137. * Constructs a new File using the path of the specified URI. {@code uri}
  138. * needs to be an absolute and hierarchical Unified Resource Identifier with
  139. * file scheme and non-empty path component, but with undefined authority,
  140. * query or fragment components.
  141. *
  142. * @param uri
  143. * the Unified Resource Identifier that is used to construct this
  144. * file.
  145. * @throws IllegalArgumentException
  146. * if {@code uri} does not comply with the conditions above.
  147. * @see #toURI
  148. * @see java.net.URI
  149. */
  150. public File(URI uri) {
  151. // check pre-conditions
  152. checkURI(uri);
  153. this.path = fixSlashes(uri.getPath());
  154. }
  155. private String calculatePath(String dirPath, String name) {
  156. dirPath = fixSlashes(dirPath);
  157. if (!name.equals(EMPTY_STRING) || dirPath.equals(EMPTY_STRING)) {
  158. // Remove all the proceeding separator chars from name
  159. name = fixSlashes(name);
  160. int separatorIndex = 0;
  161. while ((separatorIndex < name.length())
  162. && (name.charAt(separatorIndex) == separatorChar)) {
  163. separatorIndex++;
  164. }
  165. if (separatorIndex > 0) {
  166. name = name.substring(separatorIndex, name.length());
  167. }
  168. // Ensure there is a separator char between dirPath and name
  169. if (dirPath.length() > 0
  170. && (dirPath.charAt(dirPath.length() - 1) == separatorChar)) {
  171. return dirPath + name;
  172. }
  173. return dirPath + separatorChar + name;
  174. }
  175. return dirPath;
  176. }
  177. @SuppressWarnings("nls")
  178. private void checkURI(URI uri) {
  179. if (!uri.isAbsolute()) {
  180. throw new IllegalArgumentException(Messages.getString("luni.AD", uri));
  181. } else if (!uri.getRawSchemeSpecificPart().startsWith("/")) {
  182. throw new IllegalArgumentException(Messages.getString("luni.AE", uri));
  183. }
  184. String temp = uri.getScheme();
  185. if (temp == null || !temp.equals("file")) {
  186. throw new IllegalArgumentException(Messages.getString("luni.AF", uri));
  187. }
  188. temp = uri.getRawPath();
  189. if (temp == null || temp.length() == 0) {
  190. throw new IllegalArgumentException(Messages.getString("luni.B0", uri));
  191. }
  192. if (uri.getRawAuthority() != null) {
  193. throw new IllegalArgumentException(Messages.getString("luni.B1",
  194. new String[] { "authority", uri.toString() }));
  195. }
  196. if (uri.getRawQuery() != null) {
  197. throw new IllegalArgumentException(Messages.getString("luni.B1",
  198. new String[] { "query", uri.toString() }));
  199. }
  200. if (uri.getRawFragment() != null) {
  201. throw new IllegalArgumentException(Messages.getString("luni.B1",
  202. new String[] { "fragment", uri.toString() }));
  203. }
  204. }
  205. private static native byte[][] rootsImpl();
  206. private static native boolean isCaseSensitiveImpl();
  207. /**
  208. * Lists the file system roots. The Java platform may support zero or more
  209. * file systems, each with its own platform-dependent root. Further, the
  210. * canonical pathname of any file on the system will always begin with one
  211. * of the returned file system roots.
  212. *
  213. * @return the array of file system roots.
  214. */
  215. public static File[] listRoots() {
  216. byte[][] rootsList = rootsImpl();
  217. if (rootsList == null) {
  218. return new File[0];
  219. }
  220. File result[] = new File[rootsList.length];
  221. for (int i = 0; i < rootsList.length; i++) {
  222. result[i] = new File(Util.toString(rootsList[i]));
  223. }
  224. return result;
  225. }
  226. /**
  227. * The purpose of this method is to take a path and fix the slashes up. This
  228. * includes changing them all to the current platforms fileSeparator and
  229. * removing duplicates.
  230. */
  231. private String fixSlashes(String origPath) {
  232. int uncIndex = 1;
  233. int length = origPath.length(), newLength = 0;
  234. if (separatorChar == '/') {
  235. uncIndex = 0;
  236. } else if (length > 2 && origPath.charAt(1) == ':') {
  237. uncIndex = 2;
  238. }
  239. boolean foundSlash = false;
  240. char newPath[] = origPath.toCharArray();
  241. for (int i = 0; i < length; i++) {
  242. char pathChar = newPath[i];
  243. if ((separatorChar == '\\' && pathChar == '\\')
  244. || pathChar == '/') {
  245. /* UNC Name requires 2 leading slashes */
  246. if ((foundSlash && i == uncIndex) || !foundSlash) {
  247. newPath[newLength++] = separatorChar;
  248. foundSlash = true;
  249. }
  250. } else {
  251. // check for leading slashes before a drive
  252. if (pathChar == ':'
  253. && uncIndex > 0
  254. && (newLength == 2 || (newLength == 3 && newPath[1] == separatorChar))
  255. && newPath[0] == separatorChar) {
  256. newPath[0] = newPath[newLength - 1];
  257. newLength = 1;
  258. // allow trailing slash after drive letter
  259. uncIndex = 2;
  260. }
  261. newPath[newLength++] = pathChar;
  262. foundSlash = false;
  263. }
  264. }
  265. // remove trailing slash
  266. if (foundSlash
  267. && (newLength > (uncIndex + 1) || (newLength == 2 && newPath[0] != separatorChar))) {
  268. newLength--;
  269. }
  270. return new String(newPath, 0, newLength);
  271. }
  272. /**
  273. * Indicates whether the current context is allowed to read from this file.
  274. *
  275. * @return {@code true} if this file can be read, {@code false} otherwise.
  276. * @throws SecurityException
  277. * if a {@code SecurityManager} is installed and it denies the
  278. * read request.
  279. */
  280. public boolean canRead() {
  281. if (path.length() == 0) {
  282. return false;
  283. }
  284. SecurityManager security = System.getSecurityManager();
  285. if (security != null) {
  286. security.checkRead(path);
  287. }
  288. byte[] pp = properPath(true);
  289. return existsImpl(pp) && !isWriteOnlyImpl(pp);
  290. }
  291. /**
  292. * Indicates whether the current context is allowed to write to this file.
  293. *
  294. * @return {@code true} if this file can be written, {@code false}
  295. * otherwise.
  296. * @throws SecurityException
  297. * if a {@code SecurityManager} is installed and it denies the
  298. * write request.
  299. */
  300. public boolean canWrite() {
  301. SecurityManager security = System.getSecurityManager();
  302. if (security != null) {
  303. security.checkWrite(path);
  304. }
  305. // Cannot use exists() since that does an unwanted read-check.
  306. boolean exists = false;
  307. if (path.length() > 0) {
  308. exists = existsImpl(properPath(true));
  309. }
  310. return exists && !isReadOnlyImpl(properPath(true));
  311. }
  312. /**
  313. * Returns the relative sort ordering of the paths for this file and the
  314. * file {@code another}. The ordering is platform dependent.
  315. *
  316. * @param another
  317. * a file to compare this file to
  318. * @return an int determined by comparing the two paths. Possible values are
  319. * described in the Comparable interface.
  320. * @see Comparable
  321. */
  322. public int compareTo(File another) {
  323. if (caseSensitive) {
  324. return this.getPath().compareTo(another.getPath());
  325. }
  326. return this.getPath().compareToIgnoreCase(another.getPath());
  327. }
  328. /**
  329. * Deletes this file. Directories must be empty before they will be deleted.
  330. *
  331. * @return {@code true} if this file was deleted, {@code false} otherwise.
  332. * @throws SecurityException
  333. * if a {@code SecurityManager} is installed and it denies the
  334. * request.
  335. * @see java.lang.SecurityManager#checkDelete
  336. */
  337. public boolean delete() {
  338. SecurityManager security = System.getSecurityManager();
  339. if (security != null) {
  340. security.checkDelete(path);
  341. }
  342. byte[] propPath = properPath(true);
  343. if ((path.length() != 0) && isDirectoryImpl(propPath)) {
  344. return deleteDirImpl(propPath);
  345. }
  346. return deleteFileImpl(propPath);
  347. }
  348. private native boolean deleteDirImpl(byte[] filePath);
  349. private native boolean deleteFileImpl(byte[] filePath);
  350. /**
  351. * Schedules this file to be automatically deleted once the virtual machine
  352. * terminates. This will only happen when the virtual machine terminates
  353. * normally as described by the Java Language Specification section 12.9.
  354. *
  355. * @throws SecurityException
  356. * if a {@code SecurityManager} is installed and it denies the
  357. * request.
  358. */
  359. public void deleteOnExit() {
  360. SecurityManager security = System.getSecurityManager();
  361. if (security != null) {
  362. security.checkDelete(path);
  363. }
  364. DeleteOnExit.addFile(Util.toUTF8String(properPath(true)));
  365. }
  366. /**
  367. * Compares {@code obj} to this file and returns {@code true} if they
  368. * represent the <em>same</em> object using a path specific comparison.
  369. *
  370. * @param obj
  371. * the object to compare this file with.
  372. * @return {@code true} if {@code obj} is the same as this object,
  373. * {@code false} otherwise.
  374. */
  375. @Override
  376. public boolean equals(Object obj) {
  377. if (!(obj instanceof File)) {
  378. return false;
  379. }
  380. if (!caseSensitive) {
  381. return path.equalsIgnoreCase(((File) obj).getPath());
  382. }
  383. return path.equals(((File) obj).getPath());
  384. }
  385. /**
  386. * Returns a boolean indicating whether this file can be found on the
  387. * underlying file system.
  388. *
  389. * @return {@code true} if this file exists, {@code false} otherwise.
  390. * @throws SecurityException
  391. * if a {@code SecurityManager} is installed and it denies read
  392. * access to this file.
  393. * @see #getPath
  394. * @see java.lang.SecurityManager#checkRead(FileDescriptor)
  395. */
  396. public boolean exists() {
  397. if (path.length() == 0) {
  398. return false;
  399. }
  400. SecurityManager security = System.getSecurityManager();
  401. if (security != null) {
  402. security.checkRead(path);
  403. }
  404. return existsImpl(properPath(true));
  405. }
  406. private native boolean existsImpl(byte[] filePath);
  407. /**
  408. * Returns the absolute path of this file.
  409. *
  410. * @return the absolute file path.
  411. * @see java.lang.SecurityManager#checkPropertyAccess
  412. */
  413. public String getAbsolutePath() {
  414. byte[] absolute = properPath(false);
  415. return Util.toUTF8String(absolute);
  416. }
  417. /**
  418. * Returns a new file constructed using the absolute path of this file.
  419. *
  420. * @return a new file from this file's absolute path.
  421. * @see java.lang.SecurityManager#checkPropertyAccess
  422. */
  423. public File getAbsoluteFile() {
  424. return new File(this.getAbsolutePath());
  425. }
  426. /**
  427. * Returns the absolute path of this file with all references resolved. An
  428. * <em>absolute</em> path is one that begins at the root of the file
  429. * system. The canonical path is one in which all references have been
  430. * resolved. For the cases of '..' and '.', where the file system supports
  431. * parent and working directory respectively, these are removed and replaced
  432. * with a direct directory reference. If the file does not exist,
  433. * getCanonicalPath() may not resolve any references and simply returns an
  434. * absolute path name or throws an IOException.
  435. *
  436. * @return the canonical path of this file.
  437. * @throws IOException
  438. * if an I/O error occurs.
  439. * @see java.lang.SecurityManager#checkPropertyAccess
  440. */
  441. public String getCanonicalPath() throws IOException {
  442. byte[] result = properPath(false);
  443. String absPath = Util.toUTF8String(result);
  444. String canonPath = FileCanonPathCache.get(absPath);
  445. if (canonPath != null) {
  446. return canonPath;
  447. }
  448. if(separatorChar == '/') {
  449. // resolve the full path first
  450. result = resolveLink(result, result.length, false);
  451. // resolve the parent directories
  452. result = resolve(result);
  453. }
  454. int numSeparators = 1;
  455. for (int i = 0; i < result.length; i++) {
  456. if (result[i] == separatorChar) {
  457. numSeparators++;
  458. }
  459. }
  460. int sepLocations[] = new int[numSeparators];
  461. int rootLoc = 0;
  462. if (separatorChar != '/') {
  463. if (result[0] == '\\') {
  464. rootLoc = (result.length > 1 && result[1] == '\\') ? 1 : 0;
  465. } else {
  466. rootLoc = 2; // skip drive i.e. c:
  467. }
  468. }
  469. byte newResult[] = new byte[result.length + 1];
  470. int newLength = 0, lastSlash = 0, foundDots = 0;
  471. sepLocations[lastSlash] = rootLoc;
  472. for (int i = 0; i <= result.length; i++) {
  473. if (i < rootLoc) {
  474. newResult[newLength++] = result[i];
  475. } else {
  476. if (i == result.length || result[i] == separatorChar) {
  477. if (i == result.length && foundDots == 0) {
  478. break;
  479. }
  480. if (foundDots == 1) {
  481. /* Don't write anything, just reset and continue */
  482. foundDots = 0;
  483. continue;
  484. }
  485. if (foundDots > 1) {
  486. /* Go back N levels */
  487. lastSlash = lastSlash > (foundDots - 1) ? lastSlash
  488. - (foundDots - 1) : 0;
  489. newLength = sepLocations[lastSlash] + 1;
  490. foundDots = 0;
  491. continue;
  492. }
  493. sepLocations[++lastSlash] = newLength;
  494. newResult[newLength++] = (byte) separatorChar;
  495. continue;
  496. }
  497. if (result[i] == '.') {
  498. foundDots++;
  499. continue;
  500. }
  501. /* Found some dots within text, write them out */
  502. if (foundDots > 0) {
  503. for (int j = 0; j < foundDots; j++) {
  504. newResult[newLength++] = (byte) '.';
  505. }
  506. }
  507. newResult[newLength++] = result[i];
  508. foundDots = 0;
  509. }
  510. }
  511. // remove trailing slash
  512. if (newLength > (rootLoc + 1)
  513. && newResult[newLength - 1] == separatorChar) {
  514. newLength--;
  515. }
  516. newResult[newLength] = 0;
  517. newResult = getCanonImpl(newResult);
  518. newLength = newResult.length;
  519. canonPath = Util.toUTF8String(newResult, 0, newLength);
  520. FileCanonPathCache.put(absPath, canonPath);
  521. return canonPath;
  522. }
  523. /*
  524. * Resolve symbolic links in the parent directories.
  525. */
  526. private byte[] resolve(byte[] newResult) throws IOException {
  527. int last = 1, nextSize, linkSize;
  528. byte[] linkPath = newResult, bytes;
  529. boolean done, inPlace;
  530. for (int i = 1; i <= newResult.length; i++) {
  531. if (i == newResult.length || newResult[i] == separatorChar) {
  532. done = i >= newResult.length - 1;
  533. // if there is only one segment, do nothing
  534. if (done && linkPath.length == 1) {
  535. return newResult;
  536. }
  537. inPlace = false;
  538. if (linkPath == newResult) {
  539. bytes = newResult;
  540. // if there are no symbolic links, terminate the C string
  541. // instead of copying
  542. if (!done) {
  543. inPlace = true;
  544. newResult[i] = '\0';
  545. }
  546. } else {
  547. nextSize = i - last + 1;
  548. linkSize = linkPath.length;
  549. if (linkPath[linkSize - 1] == separatorChar) {
  550. linkSize--;
  551. }
  552. bytes = new byte[linkSize + nextSize];
  553. System.arraycopy(linkPath, 0, bytes, 0, linkSize);
  554. System.arraycopy(newResult, last - 1, bytes, linkSize,
  555. nextSize);
  556. // the full path has already been resolved
  557. }
  558. if (done) {
  559. return bytes;
  560. }
  561. linkPath = resolveLink(bytes, inPlace ? i : bytes.length, true);
  562. if (inPlace) {
  563. newResult[i] = '/';
  564. }
  565. last = i + 1;
  566. }
  567. }
  568. throw new InternalError();
  569. }
  570. /*
  571. * Resolve a symbolic link. While the path resolves to an existing path,
  572. * keep resolving. If an absolute link is found, resolve the parent
  573. * directories if resolveAbsolute is true.
  574. */
  575. private byte[] resolveLink(byte[] pathBytes, int length,
  576. boolean resolveAbsolute) throws IOException {
  577. boolean restart = false;
  578. byte[] linkBytes, temp;
  579. do {
  580. linkBytes = getLinkImpl(pathBytes);
  581. if (linkBytes == pathBytes) {
  582. break;
  583. }
  584. if (linkBytes[0] == separatorChar) {
  585. // link to an absolute path, if resolving absolute paths,
  586. // resolve the parent dirs again
  587. restart = resolveAbsolute;
  588. pathBytes = linkBytes;
  589. } else {
  590. int last = length - 1;
  591. while (pathBytes[last] != separatorChar) {
  592. last--;
  593. }
  594. last++;
  595. temp = new byte[last + linkBytes.length];
  596. System.arraycopy(pathBytes, 0, temp, 0, last);
  597. System.arraycopy(linkBytes, 0, temp, last, linkBytes.length);
  598. pathBytes = temp;
  599. }
  600. length = pathBytes.length;
  601. } while (existsImpl(pathBytes));
  602. // resolve the parent directories
  603. if (restart) {
  604. return resolve(pathBytes);
  605. }
  606. return pathBytes;
  607. }
  608. /**
  609. * Returns a new file created using the canonical path of this file.
  610. * Equivalent to {@code new File(this.getCanonicalPath())}.
  611. *
  612. * @return the new file constructed from this file's canonical path.
  613. * @throws IOException
  614. * if an I/O error occurs.
  615. * @see java.lang.SecurityManager#checkPropertyAccess
  616. */
  617. public File getCanonicalFile() throws IOException {
  618. return new File(getCanonicalPath());
  619. }
  620. private native byte[] getCanonImpl(byte[] filePath);
  621. /**
  622. * Returns the name of the file or directory represented by this file.
  623. *
  624. * @return this file's name or an empty string if there is no name part in
  625. * the file's path.
  626. */
  627. public String getName() {
  628. int separatorIndex = path.lastIndexOf(separator);
  629. return (separatorIndex < 0) ? path : path.substring(separatorIndex + 1,
  630. path.length());
  631. }
  632. /**
  633. * Returns the pathname of the parent of this file. This is the path up to
  634. * but not including the last name. {@code null} is returned if there is no
  635. * parent.
  636. *
  637. * @return this file's parent pathname or {@code null}.
  638. */
  639. public String getParent() {
  640. int length = path.length(), firstInPath = 0;
  641. if (separatorChar == '\\' && length > 2 && path.charAt(1) == ':') {
  642. firstInPath = 2;
  643. }
  644. int index = path.lastIndexOf(separatorChar);
  645. if (index == -1 && firstInPath > 0) {
  646. index = 2;
  647. }
  648. if (index == -1 || path.charAt(length - 1) == separatorChar) {
  649. return null;
  650. }
  651. if (path.indexOf(separatorChar) == index
  652. && path.charAt(firstInPath) == separatorChar) {
  653. return path.substring(0, index + 1);
  654. }
  655. return path.substring(0, index);
  656. }
  657. /**
  658. * Returns a new file made from the pathname of the parent of this file.
  659. * This is the path up to but not including the last name. {@code null} is
  660. * returned when there is no parent.
  661. *
  662. * @return a new file representing this file's parent or {@code null}.
  663. */
  664. public File getParentFile() {
  665. String tempParent = getParent();
  666. if (tempParent == null) {
  667. return null;
  668. }
  669. return new File(tempParent);
  670. }
  671. /**
  672. * Returns the path of this file.
  673. *
  674. * @return this file's path.
  675. */
  676. public String getPath() {
  677. return path;
  678. }
  679. /**
  680. * Returns an integer hash code for the receiver. Any two objects for which
  681. * {@code equals} returns {@code true} must return the same hash code.
  682. *
  683. * @return this files's hash value.
  684. * @see #equals
  685. */
  686. @Override
  687. public int hashCode() {
  688. if (caseSensitive) {
  689. return path.hashCode() ^ 1234321;
  690. }
  691. return path.toLowerCase().hashCode() ^ 1234321;
  692. }
  693. /**
  694. * Indicates if this file's pathname is absolute. Whether a pathname is
  695. * absolute is platform specific. On UNIX, absolute paths must start with
  696. * the character '/'; on Windows it is absolute if either it starts with
  697. * '\\' (to represent a file server), or a letter followed by a colon.
  698. *
  699. * @return {@code true} if this file's pathname is absolute, {@code false}
  700. * otherwise.
  701. * @see #getPath
  702. */
  703. public boolean isAbsolute() {
  704. if (File.separatorChar == '\\') {
  705. // for windows
  706. if (path.length() > 1 && path.charAt(0) == File.separatorChar
  707. && path.charAt(1) == File.separatorChar) {
  708. return true;
  709. }
  710. if (path.length() > 2) {
  711. if (Character.isLetter(path.charAt(0)) && path.charAt(1) == ':'
  712. && (path.charAt(2) == '/' || path.charAt(2) == '\\')) {
  713. return true;
  714. }
  715. }
  716. return false;
  717. }
  718. // for Linux
  719. return (path.length() > 0 && path.charAt(0) == File.separatorChar);
  720. }
  721. /**
  722. * Indicates if this file represents a <em>directory</em> on the
  723. * underlying file system.
  724. *
  725. * @return {@code true} if this file is a directory, {@code false}
  726. * otherwise.
  727. * @throws SecurityException
  728. * if a {@code SecurityManager} is installed and it denies read
  729. * access to this file.
  730. */
  731. public boolean isDirectory() {
  732. if (path.length() == 0) {
  733. return false;
  734. }
  735. SecurityManager security = System.getSecurityManager();
  736. if (security != null) {
  737. security.checkRead(path);
  738. }
  739. return isDirectoryImpl(properPath(true));
  740. }
  741. private native boolean isDirectoryImpl(byte[] filePath);
  742. /**
  743. * Indicates if this file represents a <em>file</em> on the underlying
  744. * file system.
  745. *
  746. * @return {@code true} if this file is a file, {@code false} otherwise.
  747. * @throws SecurityException
  748. * if a {@code SecurityManager} is installed and it denies read
  749. * access to this file.
  750. */
  751. public boolean isFile() {
  752. if (path.length() == 0) {
  753. return false;
  754. }
  755. SecurityManager security = System.getSecurityManager();
  756. if (security != null) {
  757. security.checkRead(path);
  758. }
  759. return isFileImpl(properPath(true));
  760. }
  761. private native boolean isFileImpl(byte[] filePath);
  762. /**
  763. * Returns whether or not this file is a hidden file as defined by the
  764. * operating system. The notion of "hidden" is system-dependent. For Unix
  765. * systems a file is considered hidden if its name starts with a ".". For
  766. * Windows systems there is an explicit flag in the file system for this
  767. * purpose.
  768. *
  769. * @return {@code true} if the file is hidden, {@code false} otherwise.
  770. * @throws SecurityException
  771. * if a {@code SecurityManager} is installed and it denies read
  772. * access to this file.
  773. */
  774. public boolean isHidden() {
  775. if (path.length() == 0) {
  776. return false;
  777. }
  778. SecurityManager security = System.getSecurityManager();
  779. if (security != null) {
  780. security.checkRead(path);
  781. }
  782. return isHiddenImpl(properPath(true));
  783. }
  784. private native boolean isHiddenImpl(byte[] filePath);
  785. private native boolean isReadOnlyImpl(byte[] filePath);
  786. private native boolean isWriteOnlyImpl(byte[] filePath);
  787. private native byte[] getLinkImpl(byte[] filePath);
  788. /**
  789. * Returns the time when this file was last modified, measured in
  790. * milliseconds since January 1st, 1970, midnight.
  791. *
  792. * @return the time when this file was last modified.
  793. * @throws SecurityException
  794. * if a {@code SecurityManager} is installed and it denies read
  795. * access to this file.
  796. */
  797. public long lastModified() {
  798. SecurityManager security = System.getSecurityManager();
  799. if (security != null) {
  800. security.checkRead(path);
  801. }
  802. long result = lastModifiedImpl(properPath(true));
  803. /* Temporary code to handle both return cases until natives fixed */
  804. if (result == -1 || result == 0) {
  805. return 0;
  806. }
  807. return result;
  808. }
  809. private native long lastModifiedImpl(byte[] filePath);
  810. /**
  811. * Sets the time this file was last modified, measured in milliseconds since
  812. * January 1st, 1970, midnight.
  813. *
  814. * @param time
  815. * the last modification time for this file.
  816. * @return {@code true} if the operation is successful, {@code false}
  817. * otherwise.
  818. * @throws IllegalArgumentException
  819. * if {@code time < 0}.
  820. * @throws SecurityException
  821. * if a {@code SecurityManager} is installed and it denies write
  822. * access to this file.
  823. */
  824. public boolean setLastModified(long time) {
  825. if (time < 0) {
  826. throw new IllegalArgumentException(Messages.getString("luni.B2")); //$NON-NLS-1$
  827. }
  828. SecurityManager security = System.getSecurityManager();
  829. if (security != null) {
  830. security.checkWrite(path);
  831. }
  832. return (setLastModifiedImpl(properPath(true), time));
  833. }
  834. private native boolean setLastModifiedImpl(byte[] path, long time);
  835. /**
  836. * Marks this file or directory to be read-only as defined by the operating
  837. * system.
  838. *
  839. * @return {@code true} if the operation is successful, {@code false}
  840. * otherwise.
  841. * @throws SecurityException
  842. * if a {@code SecurityManager} is installed and it denies write
  843. * access to this file.
  844. */
  845. public boolean setReadOnly() {
  846. SecurityManager security = System.getSecurityManager();
  847. if (security != null) {
  848. security.checkWrite(path);
  849. }
  850. return (setReadOnlyImpl(properPath(true)));
  851. }
  852. private native boolean setReadOnlyImpl(byte[] path);
  853. /**
  854. * Returns the length of this file in bytes.
  855. *
  856. * @return the number of bytes in this file.
  857. * @throws SecurityException
  858. * if a {@code SecurityManager} is installed and it denies read
  859. * access to this file.
  860. */
  861. public long length() {
  862. SecurityManager security = System.getSecurityManager();
  863. if (security != null) {
  864. security.checkRead(path);
  865. }
  866. return lengthImpl(properPath(true));
  867. }
  868. private native long lengthImpl(byte[] filePath);
  869. /**
  870. * Returns an array of strings with the file names in the directory
  871. * represented by this file. The result is {@code null} if this file is not
  872. * a directory.
  873. * <p>
  874. * The entries {@code .} and {@code ..} representing the current and parent
  875. * directory are not returned as part of the list.
  876. *
  877. * @return an array of strings with file names or {@code null}.
  878. * @throws SecurityException
  879. * if a {@code SecurityManager} is installed and it denies read
  880. * access to this file.
  881. * @see #isDirectory
  882. * @see java.lang.SecurityManager#checkRead(FileDescriptor)
  883. */
  884. public java.lang.String[] list() {
  885. SecurityManager security = System.getSecurityManager();
  886. if (security != null) {
  887. security.checkRead(path);
  888. }
  889. if (path.length() == 0) {
  890. return null;
  891. }
  892. byte[] bs = properPath(true);
  893. if (!isDirectoryImpl(bs) || !existsImpl(bs) || isWriteOnlyImpl(bs)) {
  894. return null;
  895. }
  896. byte[][] implList = listImpl(bs);
  897. if (implList == null) {
  898. // empty list
  899. return new String[0];
  900. }
  901. String result[] = new String[implList.length];
  902. for (int index = 0; index < implList.length; index++) {
  903. result[index] = Util.toUTF8String(implList[index]);
  904. }
  905. return result;
  906. }
  907. /**
  908. * Returns an array of files contained in the directory represented by this
  909. * file. The result is {@code null} if this file is not a directory. The
  910. * paths of the files in the array are absolute if the path of this file is
  911. * absolute, they are relative otherwise.
  912. *
  913. * @return an array of files or {@code null}.
  914. * @throws SecurityException
  915. * if a {@code SecurityManager} is installed and it denies read
  916. * access to this file.
  917. * @see #list
  918. * @see #isDirectory
  919. */
  920. public File[] listFiles() {
  921. String[] tempNames = list();
  922. if (tempNames == null) {
  923. return null;
  924. }
  925. int resultLength = tempNames.length;
  926. File results[] = new File[resultLength];
  927. for (int i = 0; i < resultLength; i++) {
  928. results[i] = new File(this, tempNames[i]);
  929. }
  930. return results;
  931. }
  932. /**
  933. * Gets a list of the files in the directory represented by this file. This
  934. * list is then filtered through a FilenameFilter and files with matching
  935. * names are returned as an array of files. Returns {@code null} if this
  936. * file is not a directory. If {@code filter} is {@code null} then all
  937. * filenames match.
  938. * <p>
  939. * The entries {@code .} and {@code ..} representing the current and parent
  940. * directories are not returned as part of the list.
  941. *
  942. * @param filter
  943. * the filter to match names against, may be {@code null}.
  944. * @return an array of files or {@code null}.
  945. * @throws SecurityException
  946. * if a {@code SecurityManager} is installed and it denies read
  947. * access to this file.
  948. * @see #list(FilenameFilter filter)
  949. * @see #getPath
  950. * @see #isDirectory
  951. * @see java.lang.SecurityManager#checkRead(FileDescriptor)
  952. */
  953. public File[] listFiles(FilenameFilter filter) {
  954. String[] tempNames = list(filter);
  955. if (tempNames == null) {
  956. return null;
  957. }
  958. int resultLength = tempNames.length;
  959. File results[] = new File[resultLength];
  960. for (int i = 0; i < resultLength; i++) {
  961. results[i] = new File(this, tempNames[i]);
  962. }
  963. return results;
  964. }
  965. /**
  966. * Gets a list of the files in the directory represented by this file. This
  967. * list is then filtered through a FileFilter and matching files are
  968. * returned as an array of files. Returns {@code null} if this file is not a
  969. * directory. If {@code filter} is {@code null} then all files match.
  970. * <p>
  971. * The entries {@code .} and {@code ..} representing the current and parent
  972. * directories are not returned as part of the list.
  973. *
  974. * @param filter
  975. * the filter to match names against, may be {@code null}.
  976. * @return an array of files or {@code null}.
  977. * @throws SecurityException
  978. * if a {@code SecurityManager} is installed and it denies read
  979. * access to this file.
  980. * @see #getPath
  981. * @see #isDirectory
  982. * @see java.lang.SecurityManager#checkRead(FileDescriptor)
  983. */
  984. public File[] listFiles(FileFilter filter) {
  985. SecurityManager security = System.getSecurityManager();
  986. if (security != null) {
  987. security.checkRead(path);
  988. }
  989. if (path.length() == 0) {
  990. return null;
  991. }
  992. byte[] bs = properPath(true);
  993. if (!isDirectoryImpl(bs) || !existsImpl(bs) || isWriteOnlyImpl(bs)) {
  994. return null;
  995. }
  996. byte[][] implList = listImpl(bs);
  997. if (implList == null) {
  998. return new File[0];
  999. }
  1000. List<File> tempResult = new ArrayList<File>();
  1001. for (int index = 0; index < implList.length; index++) {
  1002. String aName = Util.toString(implList[index]);
  1003. File aFile = new File(this, aName);
  1004. if (filter == null || filter.accept(aFile)) {
  1005. tempResult.add(aFile);
  1006. }
  1007. }
  1008. return tempResult.toArray(new File[tempResult.size()]);
  1009. }
  1010. /**
  1011. * Gets a list of the files in the directory represented by this file. This
  1012. * list is then filtered through a FilenameFilter and the names of files
  1013. * with matching names are returned as an array of strings. Returns
  1014. * {@code null} if this file is not a directory. If {@code filter} is
  1015. * {@code null} then all filenames match.
  1016. * <p>
  1017. * The entries {@code .} and {@code ..} representing the current and parent
  1018. * directories are not returned as part of the list.
  1019. *
  1020. * @param filter
  1021. * the filter to match names against, may be {@code null}.
  1022. * @return an array of files or {@code null}.
  1023. * @throws SecurityException
  1024. * if a {@code SecurityManager} is installed and it denies read
  1025. * access to this file.
  1026. * @see #getPath
  1027. * @see #isDirectory
  1028. * @see java.lang.SecurityManager#checkRead(FileDescriptor)
  1029. */
  1030. public java.lang.String[] list(FilenameFilter filter) {
  1031. SecurityManager security = System.getSecurityManager();
  1032. if (security != null) {
  1033. security.checkRead(path);
  1034. }
  1035. if (path.length() == 0) {
  1036. return null;
  1037. }
  1038. byte[] bs = properPath(true);
  1039. if (!isDirectoryImpl(bs) || !existsImpl(bs) || isWriteOnlyImpl(bs)) {
  1040. return null;
  1041. }
  1042. byte[][] implList = listImpl(bs);
  1043. if (implList == null) {
  1044. // empty list
  1045. return new String[0];
  1046. }
  1047. List<String> tempResult = new ArrayList<String>();
  1048. for (int index = 0; index < implList.length; index++) {
  1049. String aName = Util.toString(implList[index]);
  1050. if (filter == null || filter.accept(this, aName)) {
  1051. tempResult.add(aName);
  1052. }
  1053. }
  1054. return tempResult.toArray(new String[tempResult.size()]);
  1055. }
  1056. private synchronized static native byte[][] listImpl(byte[] path);
  1057. /**
  1058. * Creates the directory named by the trailing filename of this file. Does
  1059. * not create the complete path required to create this directory.
  1060. *
  1061. * @return {@code true} if the directory has been created, {@code false}
  1062. * otherwise.
  1063. * @throws SecurityException
  1064. * if a {@code SecurityManager} is installed and it denies write
  1065. * access for this file.
  1066. * @see #mkdirs
  1067. */
  1068. public boolean mkdir() {
  1069. SecurityManager security = System.getSecurityManager();
  1070. if (security != null) {
  1071. security.checkWrite(path);
  1072. }
  1073. return mkdirImpl(properPath(true));
  1074. }
  1075. private native boolean mkdirImpl(byte[] filePath);
  1076. /**
  1077. * Creates the directory named by the trailing filename of this file,
  1078. * including the complete directory path required to create this directory.
  1079. *
  1080. * @return {@code true} if the necessary directories have been created,
  1081. * {@code false} if the target directory already exists or one of
  1082. * the directories can not be created.
  1083. * @throws SecurityException
  1084. * if a {@code SecurityManager} is installed and it denies write
  1085. * access for this file.
  1086. * @see #mkdir
  1087. */
  1088. public boolean mkdirs() {
  1089. /* If the terminal directory already exists, answer false */
  1090. if (exists()) {
  1091. return false;
  1092. }
  1093. /* If the receiver can be created, answer true */
  1094. if (mkdir()) {
  1095. return true;
  1096. }
  1097. String parentDir = getParent();
  1098. /* If there is no parent and we were not created, answer false */
  1099. if (parentDir == null) {
  1100. return false;
  1101. }
  1102. /* Otherwise, try to create a parent directory and then this directory */
  1103. return (new File(parentDir).mkdirs() && mkdir());
  1104. }
  1105. /**
  1106. * Creates a new, empty file on the file system according to the path
  1107. * information stored in this file.
  1108. *
  1109. * @return {@code true} if the file has been created, {@code false} if it
  1110. * already exists.
  1111. * @throws IOException
  1112. * if an I/O error occurs or the directory does not exist where
  1113. * the file should have been created.
  1114. * @throws SecurityException
  1115. * if a {@code SecurityManager} is installed and it denies write
  1116. * access for this file.
  1117. */
  1118. public boolean createNewFile() throws IOException {
  1119. SecurityManager security = System.getSecurityManager();
  1120. if (security != null) {
  1121. security.checkWrite(path);
  1122. }
  1123. if (0 == path.length()) {
  1124. throw new IOException(Messages.getString("luni.B3")); //$NON-NLS-1$
  1125. }
  1126. int result = newFileImpl(properPath(true));
  1127. switch (result) {
  1128. case 0:
  1129. return true;
  1130. case 1:
  1131. return false;
  1132. default:
  1133. throw new IOException(Messages.getString("luni.B4", path)); //$NON-NLS-1$
  1134. }
  1135. }
  1136. private native int newFileImpl(byte[] filePath);
  1137. /**
  1138. * Creates an empty temporary file using the given prefix and suffix as part
  1139. * of the file name. If suffix is {@code null}, {@code .tmp} is used. This
  1140. * method is a convenience method that calls
  1141. * {@link #createTempFile(String, String, File)} with the third argument
  1142. * being {@code null}.
  1143. *
  1144. * @param prefix
  1145. * the prefix to the temp file name.
  1146. * @param suffix
  1147. * the suffix to the temp file name.
  1148. * @return the temporary file.
  1149. * @throws IOException
  1150. * if an error occurs when writing the file.
  1151. */
  1152. public static File createTempFile(String prefix, String suffix)
  1153. throws IOException {
  1154. return createTempFile(prefix, suffix, null);
  1155. }
  1156. /**
  1157. * Creates an empty temporary file in the given directory using the given
  1158. * prefix and suffix as part of the file name.
  1159. *
  1160. * @param prefix
  1161. * the prefix to the temp file name.
  1162. * @param suffix
  1163. * the suffix to the temp file name.
  1164. * @param directory
  1165. * the location to which the temp file is to be written, or
  1166. * {@code null} for the default location for temporary files,
  1167. * which is taken from the "java.io.tmpdir" system property. It
  1168. * may be necessary to set this property to an existing, writable
  1169. * directory for this method to work properly.
  1170. * @return the temporary file.
  1171. * @throws IllegalArgumentException
  1172. * if the length of {@code prefix} is less than 3.
  1173. * @throws IOException
  1174. * if an error occurs when writing the file.
  1175. */
  1176. @SuppressWarnings("nls")
  1177. public static File createTempFile(String prefix, String suffix,
  1178. File directory) throws IOException {
  1179. // Force a prefix null check first
  1180. if (prefix.length() < 3) {
  1181. throw new IllegalArgumentException(Messages.getString("luni.B5"));
  1182. }
  1183. String newSuffix = suffix == null ? ".tmp" : suffix;
  1184. File tmpDirFile;
  1185. if (directory == null) {
  1186. String tmpDir = AccessController.doPrivileged(
  1187. new PriviAction<String>("java.io.tmpdir", "."));
  1188. tmpDirFile = new File(tmpDir);
  1189. } else {
  1190. tmpDirFile = directory;
  1191. }
  1192. File result;
  1193. do {
  1194. result = genTempFile(prefix, newSuffix, tmpDirFile);
  1195. } while (!result.createNewFile());
  1196. return result;
  1197. }
  1198. private static File genTempFile(String prefix, String suffix, File directory) {
  1199. int identify = 0;
  1200. synchronized (tempFileLocker) {
  1201. if (counter == 0) {
  1202. int newInt = new SecureRandom().nextInt();
  1203. counter = ((newInt / 65535) & 0xFFFF) + 0x2710;
  1204. counterBase = counter;
  1205. }
  1206. identify = counter++;
  1207. }
  1208. StringBuilder newName = new StringBuilder();
  1209. newName.append(prefix);
  1210. newName.append(counterBase);
  1211. newName.append(identify);
  1212. newName.append(suffix);
  1213. return new File(directory, newName.toString());
  1214. }
  1215. /**
  1216. * Returns a string representing the proper path for this file. If this file
  1217. * path is absolute, the user.dir property is not prepended, otherwise it
  1218. * is.
  1219. *
  1220. * @param internal
  1221. * is user.dir internal.
  1222. * @return the proper path.
  1223. */
  1224. byte[] properPath(boolean internal) {
  1225. if (properPath != null) {
  1226. return properPath;
  1227. }
  1228. if (isAbsolute()) {
  1229. byte[] pathBytes = Util.getUTF8Bytes(path);
  1230. return properPath = pathBytes;
  1231. }
  1232. // Check security by getting user.dir when the path is not absolute
  1233. String userdir;
  1234. if (internal) {
  1235. userdir = AccessController.doPrivileged(new PriviAction<String>(
  1236. "user.dir")); //$NON-NLS-1$
  1237. } else {
  1238. userdir = System.getProperty("user.dir"); //$NON-NLS-1$
  1239. }
  1240. if (path.length() == 0) {
  1241. return properPath = Util.getUTF8Bytes(userdir);
  1242. }
  1243. int length = userdir.length();
  1244. // Handle windows-like path
  1245. if (path.charAt(0) == '\\') {
  1246. if (length > 1 && userdir.charAt(1) == ':') {
  1247. return properPath = Util.getUTF8Bytes(userdir.substring(0, 2)
  1248. + path);
  1249. }
  1250. path = path.substring(1);
  1251. }
  1252. // Handle separator
  1253. String result = userdir;
  1254. if (userdir.charAt(length - 1) != separatorChar) {
  1255. if (path.charAt(0) != separatorChar) {
  1256. result += separator;
  1257. }
  1258. } else if (path.charAt(0) == separatorChar) {
  1259. result = result.substring(0, length - 2);
  1260. }
  1261. result += path;
  1262. return properPath = Util.getUTF8Bytes(result);
  1263. }
  1264. /**
  1265. * Renames this file to the name represented by the {@code dest} file. This
  1266. * works for both normal files and directories.
  1267. *
  1268. * @param dest
  1269. * the file containing the new name.
  1270. * @return {@code true} if the File was renamed, {@code false} otherwise.
  1271. * @throws SecurityException
  1272. * if a {@code SecurityManager} is installed and it denies write
  1273. * access for this file or the {@code dest} file.
  1274. */
  1275. public boolean renameTo(java.io.File dest) {
  1276. SecurityManager security = System.getSecurityManager();
  1277. if (security != null) {
  1278. security.checkWrite(path);
  1279. security.checkWrite(dest.path);
  1280. }

Large files files are truncated, but you can click here to view the full file