PageRenderTime 66ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

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

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

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