PageRenderTime 62ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://bitbucket.org/varialus/dissonance
Java | 1746 lines | 1593 code | 36 blank | 117 comment | 15 complexity | 3e43d0c76dc76fa9e43340dde688e757 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. *
  413. * @see java.lang.SecurityManager#checkPropertyAccess
  414. */
  415. public String getAbsolutePath() {
  416. byte[] absolute = properPath(false);
  417. return Util.toUTF8String(absolute);
  418. }
  419. /**
  420. * Returns a new file constructed using the absolute path of this file.
  421. *
  422. * @return a new file from this file's absolute path.
  423. * @see java.lang.SecurityManager#checkPropertyAccess
  424. */
  425. public File getAbsoluteFile() {
  426. return new File(this.getAbsolutePath());
  427. }
  428. /**
  429. * Returns the absolute path of this file with all references resolved. An
  430. * <em>absolute</em> path is one that begins at the root of the file
  431. * system. The canonical path is one in which all references have been
  432. * resolved. For the cases of '..' and '.', where the file system supports
  433. * parent and working directory respectively, these are removed and replaced
  434. * with a direct directory reference. If the file does not exist,
  435. * getCanonicalPath() may not resolve any references and simply returns an
  436. * absolute path name or throws an IOException.
  437. *
  438. * @return the canonical path of this file.
  439. * @throws IOException
  440. * if an I/O error occurs.
  441. * @see java.lang.SecurityManager#checkPropertyAccess
  442. */
  443. public String getCanonicalPath() throws IOException {
  444. byte[] result = properPath(false);
  445. String absPath = Util.toUTF8String(result);
  446. String canonPath = FileCanonPathCache.get(absPath);
  447. if (canonPath != null) {
  448. return canonPath;
  449. }
  450. if(separatorChar == '/') {
  451. // resolve the full path first
  452. result = resolveLink(result, result.length, false);
  453. // resolve the parent directories
  454. result = resolve(result);
  455. }
  456. int numSeparators = 1;
  457. for (int i = 0; i < result.length; i++) {
  458. if (result[i] == separatorChar) {
  459. numSeparators++;
  460. }
  461. }
  462. int sepLocations[] = new int[numSeparators];
  463. int rootLoc = 0;
  464. if (separatorChar != '/') {
  465. if (result[0] == '\\') {
  466. rootLoc = (result.length > 1 && result[1] == '\\') ? 1 : 0;
  467. } else {
  468. rootLoc = 2; // skip drive i.e. c:
  469. }
  470. }
  471. byte newResult[] = new byte[result.length + 1];
  472. int newLength = 0, lastSlash = 0, foundDots = 0;
  473. sepLocations[lastSlash] = rootLoc;
  474. for (int i = 0; i <= result.length; i++) {
  475. if (i < rootLoc) {
  476. newResult[newLength++] = result[i];
  477. } else {
  478. if (i == result.length || result[i] == separatorChar) {
  479. if (i == result.length && foundDots == 0) {
  480. break;
  481. }
  482. if (foundDots == 1) {
  483. /* Don't write anything, just reset and continue */
  484. foundDots = 0;
  485. continue;
  486. }
  487. if (foundDots > 1) {
  488. /* Go back N levels */
  489. lastSlash = lastSlash > (foundDots - 1) ? lastSlash
  490. - (foundDots - 1) : 0;
  491. newLength = sepLocations[lastSlash] + 1;
  492. foundDots = 0;
  493. continue;
  494. }
  495. sepLocations[++lastSlash] = newLength;
  496. newResult[newLength++] = (byte) separatorChar;
  497. continue;
  498. }
  499. if (result[i] == '.') {
  500. foundDots++;
  501. continue;
  502. }
  503. /* Found some dots within text, write them out */
  504. if (foundDots > 0) {
  505. for (int j = 0; j < foundDots; j++) {
  506. newResult[newLength++] = (byte) '.';
  507. }
  508. }
  509. newResult[newLength++] = result[i];
  510. foundDots = 0;
  511. }
  512. }
  513. // remove trailing slash
  514. if (newLength > (rootLoc + 1)
  515. && newResult[newLength - 1] == separatorChar) {
  516. newLength--;
  517. }
  518. newResult[newLength] = 0;
  519. newResult = getCanonImpl(newResult);
  520. newLength = newResult.length;
  521. canonPath = Util.toUTF8String(newResult, 0, newLength);
  522. FileCanonPathCache.put(absPath, canonPath);
  523. return canonPath;
  524. }
  525. /*
  526. * Resolve symbolic links in the parent directories.
  527. */
  528. private byte[] resolve(byte[] newResult) throws IOException {
  529. int last = 1, nextSize, linkSize;
  530. byte[] linkPath = newResult, bytes;
  531. boolean done, inPlace;
  532. for (int i = 1; i <= newResult.length; i++) {
  533. if (i == newResult.length || newResult[i] == separatorChar) {
  534. done = i >= newResult.length - 1;
  535. // if there is only one segment, do nothing
  536. if (done && linkPath.length == 1) {
  537. return newResult;
  538. }
  539. inPlace = false;
  540. if (linkPath == newResult) {
  541. bytes = newResult;
  542. // if there are no symbolic links, terminate the C string
  543. // instead of copying
  544. if (!done) {
  545. inPlace = true;
  546. newResult[i] = '\0';
  547. }
  548. } else {
  549. nextSize = i - last + 1;
  550. linkSize = linkPath.length;
  551. if (linkPath[linkSize - 1] == separatorChar) {
  552. linkSize--;
  553. }
  554. bytes = new byte[linkSize + nextSize];
  555. System.arraycopy(linkPath, 0, bytes, 0, linkSize);
  556. System.arraycopy(newResult, last - 1, bytes, linkSize,
  557. nextSize);
  558. // the full path has already been resolved
  559. }
  560. if (done) {
  561. return bytes;
  562. }
  563. linkPath = resolveLink(bytes, inPlace ? i : bytes.length, true);
  564. if (inPlace) {
  565. newResult[i] = '/';
  566. }
  567. last = i + 1;
  568. }
  569. }
  570. throw new InternalError();
  571. }
  572. /*
  573. * Resolve a symbolic link. While the path resolves to an existing path,
  574. * keep resolving. If an absolute link is found, resolve the parent
  575. * directories if resolveAbsolute is true.
  576. */
  577. private byte[] resolveLink(byte[] pathBytes, int length,
  578. boolean resolveAbsolute) throws IOException {
  579. boolean restart = false;
  580. byte[] linkBytes, temp;
  581. do {
  582. linkBytes = getLinkImpl(pathBytes);
  583. if (linkBytes == pathBytes) {
  584. break;
  585. }
  586. if (linkBytes[0] == separatorChar) {
  587. // link to an absolute path, if resolving absolute paths,
  588. // resolve the parent dirs again
  589. restart = resolveAbsolute;
  590. pathBytes = linkBytes;
  591. } else {
  592. int last = length - 1;
  593. while (pathBytes[last] != separatorChar) {
  594. last--;
  595. }
  596. last++;
  597. temp = new byte[last + linkBytes.length];
  598. System.arraycopy(pathBytes, 0, temp, 0, last);
  599. System.arraycopy(linkBytes, 0, temp, last, linkBytes.length);
  600. pathBytes = temp;
  601. }
  602. length = pathBytes.length;
  603. } while (existsImpl(pathBytes));
  604. // resolve the parent directories
  605. if (restart) {
  606. return resolve(pathBytes);
  607. }
  608. return pathBytes;
  609. }
  610. /**
  611. * Returns a new file created using the canonical path of this file.
  612. * Equivalent to {@code new File(this.getCanonicalPath())}.
  613. *
  614. * @return the new file constructed from this file's canonical path.
  615. * @throws IOException
  616. * if an I/O error occurs.
  617. * @see java.lang.SecurityManager#checkPropertyAccess
  618. */
  619. public File getCanonicalFile() throws IOException {
  620. return new File(getCanonicalPath());
  621. }
  622. private native byte[] getCanonImpl(byte[] filePath);
  623. /**
  624. * Returns the name of the file or directory represented by this file.
  625. *
  626. * @return this file's name or an empty string if there is no name part in
  627. * the file's path.
  628. */
  629. public String getName() {
  630. int separatorIndex = path.lastIndexOf(separator);
  631. return (separatorIndex < 0) ? path : path.substring(separatorIndex + 1,
  632. path.length());
  633. }
  634. /**
  635. * Returns the pathname of the parent of this file. This is the path up to
  636. * but not including the last name. {@code null} is returned if there is no
  637. * parent.
  638. *
  639. * @return this file's parent pathname or {@code null}.
  640. */
  641. public String getParent() {
  642. int length = path.length(), firstInPath = 0;
  643. if (separatorChar == '\\' && length > 2 && path.charAt(1) == ':') {
  644. firstInPath = 2;
  645. }
  646. int index = path.lastIndexOf(separatorChar);
  647. if (index == -1 && firstInPath > 0) {
  648. index = 2;
  649. }
  650. if (index == -1 || path.charAt(length - 1) == separatorChar) {
  651. return null;
  652. }
  653. if (path.indexOf(separatorChar) == index
  654. && path.charAt(firstInPath) == separatorChar) {
  655. return path.substring(0, index + 1);
  656. }
  657. return path.substring(0, index);
  658. }
  659. /**
  660. * Returns a new file made from the pathname of the parent of this file.
  661. * This is the path up to but not including the last name. {@code null} is
  662. * returned when there is no parent.
  663. *
  664. * @return a new file representing this file's parent or {@code null}.
  665. */
  666. public File getParentFile() {
  667. String tempParent = getParent();
  668. if (tempParent == null) {
  669. return null;
  670. }
  671. return new File(tempParent);
  672. }
  673. /**
  674. * Returns the path of this file.
  675. *
  676. * @return this file's path.
  677. */
  678. public String getPath() {
  679. return path;
  680. }
  681. /**
  682. * Answers the partition size indicated by the path name.
  683. *
  684. * @return the partition size counted in bytes, 0L if the path does not
  685. * exist
  686. */
  687. public long getTotalSpace() {
  688. SecurityManager security = System.getSecurityManager();
  689. if (security != null) {
  690. security.checkPermission(new RuntimePermission(
  691. "getFileSystemAttributes")); //$NON-NLS-1$
  692. security.checkRead(path);
  693. }
  694. return getTotalSpaceImpl(properPath(true));
  695. }
  696. private native long getTotalSpaceImpl(byte[] filePath);
  697. /**
  698. * Answers the available bytes of the partition indicated by the path name.
  699. * This method checks write permission and other restrictions and offers a
  700. * more precise estimate than getFreeSpace(). If the operating system does
  701. * not support this information, the result will be the same as the one
  702. * returned by getFreeSpace().
  703. *
  704. * @return the available bytes of the partition considering platform
  705. * dependent permissions
  706. */
  707. public long getUsableSpace() {
  708. SecurityManager security = System.getSecurityManager();
  709. if (security != null) {
  710. security.checkPermission(new RuntimePermission(
  711. "getFileSystemAttributes")); //$NON-NLS-1$
  712. security.checkRead(path);
  713. }
  714. return getUsableSpaceImpl(properPath(true));
  715. }
  716. private native long getUsableSpaceImpl(byte[] filePath);
  717. /**
  718. * Answers the available bytes of the partition indicated by the path name.
  719. *
  720. * @return the available bytes of the partition
  721. */
  722. public long getFreeSpace() {
  723. SecurityManager security = System.getSecurityManager();
  724. if (security != null) {
  725. security.checkPermission(new RuntimePermission(
  726. "getFileSystemAttributes")); //$NON-NLS-1$
  727. security.checkRead(path);
  728. }
  729. return getFreeSpaceImpl(properPath(true));
  730. }
  731. private native long getFreeSpaceImpl(byte[] filePath);
  732. /**
  733. * Returns an integer hash code for the receiver. Any two objects for which
  734. * {@code equals} returns {@code true} must return the same hash code.
  735. *
  736. * @return this files's hash value.
  737. * @see #equals
  738. */
  739. @Override
  740. public int hashCode() {
  741. if (caseSensitive) {
  742. return path.hashCode() ^ 1234321;
  743. }
  744. return path.toLowerCase(Locale.ENGLISH).hashCode() ^ 1234321;
  745. }
  746. /**
  747. * Indicates if this file's pathname is absolute. Whether a pathname is
  748. * absolute is platform specific. On UNIX, absolute paths must start with
  749. * the character '/'; on Windows it is absolute if either it starts with
  750. * '\\' (to represent a file server), or a letter followed by a colon.
  751. *
  752. * @return {@code true} if this file's pathname is absolute, {@code false}
  753. * otherwise.
  754. * @see #getPath
  755. */
  756. public boolean isAbsolute() {
  757. if (File.separatorChar == '\\') {
  758. // for windows
  759. if (path.length() > 1 && path.charAt(0) == File.separatorChar
  760. && path.charAt(1) == File.separatorChar) {
  761. return true;
  762. }
  763. if (path.length() > 2) {
  764. if (Character.isLetter(path.charAt(0)) && path.charAt(1) == ':'
  765. && (path.charAt(2) == '/' || path.charAt(2) == '\\')) {
  766. return true;
  767. }
  768. }
  769. return false;
  770. }
  771. // for Linux
  772. return (path.length() > 0 && path.charAt(0) == File.separatorChar);
  773. }
  774. /**
  775. * Indicates if this file represents a <em>directory</em> on the
  776. * underlying file system.
  777. *
  778. * @return {@code true} if this file is a directory, {@code false}
  779. * otherwise.
  780. * @throws SecurityException
  781. * if a {@code SecurityManager} is installed and it denies read
  782. * access to this file.
  783. */
  784. public boolean isDirectory() {
  785. if (path.length() == 0) {
  786. return false;
  787. }
  788. SecurityManager security = System.getSecurityManager();
  789. if (security != null) {
  790. security.checkRead(path);
  791. }
  792. return isDirectoryImpl(properPath(true));
  793. }
  794. private native boolean isDirectoryImpl(byte[] filePath);
  795. /**
  796. * Indicates if this file represents a <em>file</em> on the underlying
  797. * file system.
  798. *
  799. * @return {@code true} if this file is a file, {@code false} otherwise.
  800. * @throws SecurityException
  801. * if a {@code SecurityManager} is installed and it denies read
  802. * access to this file.
  803. */
  804. public boolean isFile() {
  805. if (path.length() == 0) {
  806. return false;
  807. }
  808. SecurityManager security = System.getSecurityManager();
  809. if (security != null) {
  810. security.checkRead(path);
  811. }
  812. return isFileImpl(properPath(true));
  813. }
  814. private native boolean isFileImpl(byte[] filePath);
  815. /**
  816. * Returns whether or not this file is a hidden file as defined by the
  817. * operating system. The notion of "hidden" is system-dependent. For Unix
  818. * systems a file is considered hidden if its name starts with a ".". For
  819. * Windows systems there is an explicit flag in the file system for this
  820. * purpose.
  821. *
  822. * @return {@code true} if the file is hidden, {@code false} otherwise.
  823. * @throws SecurityException
  824. * if a {@code SecurityManager} is installed and it denies read
  825. * access to this file.
  826. */
  827. public boolean isHidden() {
  828. if (path.length() == 0) {
  829. return false;
  830. }
  831. SecurityManager security = System.getSecurityManager();
  832. if (security != null) {
  833. security.checkRead(path);
  834. }
  835. return isHiddenImpl(properPath(true));
  836. }
  837. private native boolean isHiddenImpl(byte[] filePath);
  838. private native boolean isReadOnlyImpl(byte[] filePath);
  839. private native boolean isWriteOnlyImpl(byte[] filePath);
  840. private native byte[] getLinkImpl(byte[] filePath);
  841. /**
  842. * Returns the time when this file was last modified, measured in
  843. * milliseconds since January 1st, 1970, midnight.
  844. *
  845. * @return the time when this file was last modified.
  846. * @throws SecurityException
  847. * if a {@code SecurityManager} is installed and it denies read
  848. * access to this file.
  849. */
  850. public long lastModified() {
  851. SecurityManager security = System.getSecurityManager();
  852. if (security != null) {
  853. security.checkRead(path);
  854. }
  855. long result = lastModifiedImpl(properPath(true));
  856. /* Temporary code to handle both return cases until natives fixed */
  857. if (result == -1 || result == 0) {
  858. return 0;
  859. }
  860. return result;
  861. }
  862. private native long lastModifiedImpl(byte[] filePath);
  863. /**
  864. * Sets the time this file was last modified, measured in milliseconds since
  865. * January 1st, 1970, midnight.
  866. *
  867. * @param time
  868. * the last modification time for this file.
  869. * @return {@code true} if the operation is successful, {@code false}
  870. * otherwise.
  871. * @throws IllegalArgumentException
  872. * if {@code time < 0}.
  873. * @throws SecurityException
  874. * if a {@code SecurityManager} is installed and it denies write
  875. * access to this file.
  876. */
  877. public boolean setLastModified(long time) {
  878. if (time < 0) {
  879. throw new IllegalArgumentException(Messages.getString("luni.B2")); //$NON-NLS-1$
  880. }
  881. SecurityManager security = System.getSecurityManager();
  882. if (security != null) {
  883. security.checkWrite(path);
  884. }
  885. return (setLastModifiedImpl(properPath(true), time));
  886. }
  887. private native boolean setLastModifiedImpl(byte[] path, long time);
  888. /**
  889. * Marks this file or directory to be read-only as defined by the operating
  890. * system.
  891. *
  892. * @return {@code true} if the operation is successful, {@code false}
  893. * otherwise.
  894. * @throws SecurityException
  895. * if a {@code SecurityManager} is installed and it denies write
  896. * access to this file.
  897. */
  898. public boolean setReadOnly() {
  899. SecurityManager security = System.getSecurityManager();
  900. if (security != null) {
  901. security.checkWrite(path);
  902. }
  903. return (setReadOnlyImpl(properPath(true)));
  904. }
  905. private native boolean setReadOnlyImpl(byte[] path);
  906. /**
  907. * Manipulates the read permission of the abstract path designated by this
  908. * file object.
  909. *
  910. * @param readable
  911. * To allow read permission if true, otherwise disallow
  912. * @param ownerOnly
  913. * To manipulate read permission only for owner if true,
  914. * otherwise for everyone. The manipulation will apply to
  915. * everyone regardless of this value if the underlying system
  916. * does not distinguish owner and other users.
  917. * @return true if and only if the operation succeeded. If the user does not
  918. * have permission to change the access permissions of this abstract
  919. * pathname the operation will fail. If the underlying file system
  920. * does not support read permission and the value of readable is
  921. * false, this operation will fail.
  922. * @throws SecurityException -
  923. * If a security manager exists and
  924. * SecurityManager.checkWrite(java.lang.String) disallows write
  925. * permission to this file object
  926. * @since 1.6
  927. */
  928. public boolean setReadable(boolean readable, boolean ownerOnly) {
  929. checkWrite();
  930. return (setReadableImpl(properPath(true), readable, ownerOnly));
  931. }
  932. /**
  933. * A convenience method for setReadable(boolean, boolean). An invocation of
  934. * this method is the same as file.setReadable(readable, true).
  935. *
  936. * @param readable
  937. * To allow read permission if true, otherwise disallow
  938. * @return true if and only if the operation succeeded. If the user does not
  939. * have permission to change the access permissions of this abstract
  940. * pathname the operation will fail. If the underlying file system
  941. * does not support read permission and the value of readable is
  942. * false, this operation will fail.
  943. * @throws SecurityException -
  944. * If a security manager exists and
  945. * SecurityManager.checkWrite(java.lang.String) disallows write
  946. * permission to this file object
  947. * @since 1.6
  948. */
  949. public boolean setReadable(boolean readable) {
  950. return setReadable(readable, true);
  951. }
  952. private native boolean setReadableImpl(byte[] path, boolean readable,
  953. boolean ownerOnly);
  954. /**
  955. * Manipulates the write permission of the abstract path designated by this
  956. * file object.
  957. *
  958. * @param writable
  959. * To allow write permission if true, otherwise disallow
  960. * @param ownerOnly
  961. * To manipulate write permission only for owner if true,
  962. * otherwise for everyone. The manipulation will apply to
  963. * everyone regardless of this value if the underlying system
  964. * does not distinguish owner and other users.
  965. * @return true if and only if the operation succeeded. If the user does not
  966. * have permission to change the access permissions of this abstract
  967. * pathname the operation will fail.
  968. * @throws SecurityException -
  969. * If a security manager exists and
  970. * SecurityManager.checkWrite(java.lang.String) disallows write
  971. * permission to this file object
  972. * @since 1.6
  973. */
  974. public boolean setWritable(boolean writable, boolean ownerOnly) {
  975. checkWrite();
  976. return (setWritableImpl(properPath(true), writable, ownerOnly));
  977. }
  978. private native boolean setWritableImpl(byte[] path, boolean writable,
  979. boolean ownerOnly);
  980. /**
  981. * A convenience method for setWritable(boolean, boolean). An invocation of
  982. * this method is the same as file.setWritable(writable, true).
  983. *
  984. * @param writable
  985. * To allow write permission if true, otherwise disallow
  986. * @return true if and only if the operation succeeded. If the user does not
  987. * have permission to change the access permissions of this abstract
  988. * pathname the operation will fail.
  989. * @throws SecurityException -
  990. * If a security manager exists and
  991. * SecurityManager.checkWrite(java.lang.String) disallows write
  992. * permission to this file object
  993. * @since 1.6
  994. */
  995. public boolean setWritable(boolean writable) {
  996. return setWritable(writable, true);
  997. }
  998. /**
  999. * Returns the length of this file in bytes.
  1000. *
  1001. * @return the number of bytes in this file.
  1002. * @throws SecurityException
  1003. * if a {@code SecurityManager} is installed and it denies read
  1004. * access to this file.
  1005. */
  1006. public long length() {
  1007. SecurityManager security = System.getSecurityManager();
  1008. if (security != null) {
  1009. security.checkRead(path);
  1010. }
  1011. return lengthImpl(properPath(true));
  1012. }
  1013. private native long lengthImpl(byte[] filePath);
  1014. /**
  1015. * Returns an array of strings with the file names in the directory
  1016. * represented by this file. The result is {@code null} if this file is not
  1017. * a directory.
  1018. * <p>
  1019. * The entries {@code .} and {@code ..} representing the current and parent
  1020. * directory are not returned as part of the list.
  1021. *
  1022. * @return an array of strings with file names or {@code null}.
  1023. * @throws SecurityException
  1024. * if a {@code SecurityManager} is installed and it denies read
  1025. * access to this file.
  1026. * @see #isDirectory
  1027. * @see java.lang.SecurityManager#checkRead(FileDescriptor)
  1028. */
  1029. public java.lang.String[] list() {
  1030. SecurityManager security = System.getSecurityManager();
  1031. if (security != null) {
  1032. security.checkRead(path);
  1033. }
  1034. if (path.length() == 0) {
  1035. return null;
  1036. }
  1037. byte[] bs = properPath(true);
  1038. if (!isDirectoryImpl(bs) || !existsImpl(bs) || isWriteOnlyImpl(bs)) {
  1039. return null;
  1040. }
  1041. byte[][] implList = listImpl(bs);
  1042. if (implList == null) {
  1043. // empty list
  1044. return new String[0];
  1045. }
  1046. String result[] = new String[implList.length];
  1047. for (int index = 0; index < implList.length; index++) {
  1048. result[index] = Util.toUTF8String(implList[index]);
  1049. }
  1050. return result;
  1051. }
  1052. /**
  1053. * Returns an array of files contained in the directory represented by this
  1054. * file. The result is {@code null} if this file is not a directory. The
  1055. * paths of the files in the array are absolute if the path of this file is
  1056. * absolute, they are relative otherwise.
  1057. *
  1058. * @return an array of files or {@code null}.
  1059. * @throws SecurityException
  1060. * if a {@code SecurityManager} is installed and it denies read
  1061. * access to this file.
  1062. * @see #list
  1063. * @see #isDirectory
  1064. */
  1065. public File[] listFiles() {
  1066. String[] tempNames = list();
  1067. if (tempNames == null) {
  1068. return null;
  1069. }
  1070. int resultLength = tempNames.length;
  1071. File results[] = new File[resultLength];
  1072. for (int i = 0; i < resultLength; i++) {
  1073. results[i] = new File(this, tempNames[i]);
  1074. }
  1075. return results;
  1076. }
  1077. /**
  1078. * Gets a list of the files in the directory represented by this file. This
  1079. * list is then filtered through a FilenameFilter and files with matching
  1080. * names are returned as an array of files. Returns {@code null} if this
  1081. * file is not a directory. If {@code filter} is {@code null} then all
  1082. * filenames match.
  1083. * <p>
  1084. * The entries {@code .} and {@code ..} representing the current and parent
  1085. * directories are not returned as part of the list.
  1086. *
  1087. * @param filter
  1088. * the filter to match names against, may be {@code null}.
  1089. * @return an array of files or {@code null}.
  1090. * @throws SecurityException
  1091. * if a {@code SecurityManager} is installed and it denies read
  1092. * access to this file.
  1093. * @see #list(FilenameFilter filter)
  1094. * @see #getPath
  1095. * @see #isDirectory
  1096. * @see java.lang.SecurityManager#checkRead(FileDescriptor)
  1097. */
  1098. public File[] listFiles(FilenameFilter filter) {
  1099. String[] tempNames = list(filter);
  1100. if (tempNames == null) {
  1101. return null;
  1102. }
  1103. int resultLength = tempNames.length;
  1104. File results[] = new File[resultLength];
  1105. for (int i = 0; i < resultLength; i++) {
  1106. results[i] = new File(this, tempNames[i]);
  1107. }
  1108. return results;
  1109. }
  1110. /**
  1111. * Gets a list of the files in the directory represented by this file. This
  1112. * list is then filtered through a FileFilter and matching files are
  1113. * returned as an array of files. Returns {@code null} if this file is not a
  1114. * directory. If {@code filter} is {@code null} then all files match.
  1115. * <p>
  1116. * The entries {@code .} and {@code ..} representing the current and parent
  1117. * directories are not returned as part of the list.
  1118. *
  1119. * @param filter
  1120. * the filter to match names against, may be {@code null}.
  1121. * @return an array of files or {@code null}.
  1122. * @throws SecurityException
  1123. * if a {@code SecurityManager} is installed and it denies read
  1124. * access to this file.
  1125. * @see #getPath
  1126. * @see #isDirectory
  1127. * @see java.lang.SecurityManager#checkRead(FileDescriptor)
  1128. */
  1129. public File[] listFiles(FileFilter filter) {
  1130. SecurityManager security = System.getSecurityManager();
  1131. if (security != null) {
  1132. security.checkRead(path);
  1133. }
  1134. if (path.length() == 0) {
  1135. return null;
  1136. }
  1137. byte[] bs = properPath(true);
  1138. if (!isDirectoryImpl(bs) || !existsImpl(bs) || isWriteOnlyImpl(bs)) {
  1139. return null;
  1140. }
  1141. byte[][] implList = listImpl(bs);
  1142. if (implList == null) {
  1143. return new File[0];
  1144. }
  1145. List<File> tempResult = new ArrayList<File>();
  1146. for (int index = 0; index < implList.length; index++) {
  1147. String aName = Util.toString(implList[index]);
  1148. File aFile = new File(this, aName);
  1149. if (filter == null || filter.accept(aFile)) {
  1150. tempResult.add(aFile);
  1151. }
  1152. }
  1153. return tempResult.toArray(new File[tempResult.size()]);
  1154. }
  1155. /**
  1156. * Gets a list of the files in the directory represented by this file. This
  1157. * list is then filtered through a FilenameFilter and the names of files
  1158. * with matching names are returned as an array of strings. Returns
  1159. * {@code null} if this file is not a directory. If {@code filter} is
  1160. * {@code null} then all filenames match.
  1161. * <p>
  1162. * The entries {@code .} and {@code ..} representing the current and parent
  1163. * directories are not returned as part of the list.
  1164. *
  1165. * @param filter
  1166. * the filter to match names against, may be {@code null}.
  1167. * @return an array of files or {@code null}.
  1168. * @throws SecurityException
  1169. * if a {@code SecurityManager} is installed and it denies read
  1170. * access to this file.
  1171. * @see #getPath
  1172. * @see #isDirectory
  1173. * @see java.lang.SecurityManager#checkRead(FileDescriptor)
  1174. */
  1175. public java.lang.String[] list(FilenameFilter filter) {
  1176. SecurityManager security = System.getSecurityManager();
  1177. if (security != null) {
  1178. security.checkRead(path);
  1179. }
  1180. if (path.length() == 0) {
  1181. return null;
  1182. }
  1183. byte[] bs = properPath(true);
  1184. if (!isDirectoryImpl(bs) || !existsImpl(bs) || isWriteOnlyImpl(bs)) {
  1185. return null;
  1186. }
  1187. byte[][] implList = listImpl(bs);
  1188. if (implList == null) {
  1189. // empty list
  1190. return new String[0];
  1191. }
  1192. List<String> tempResult = new ArrayList<String>();
  1193. for (int index = 0; index < implList.length; index++) {
  1194. String aName = Util.toString(implList[index]);
  1195. if (filter == null || filter.accept(this, aName)) {
  1196. tempResult.add(aName);
  1197. }
  1198. }
  1199. return tempResult.toArray(new String[tempResult.size()]);
  1200. }
  1201. private synchronized static native byte[][] listImpl(byte[] path);
  1202. /**
  1203. * Creates the directory named by the trailing filename of this file. Does
  1204. * not create the complete path required to create this directory.
  1205. *
  1206. * @return {@code true} if the directory has been created, {@code false}
  1207. * otherwise.
  1208. * @throws SecurityException
  1209. * if a {@code SecurityManager} is installed and it denies write
  1210. * access for this file.
  1211. * @see #mkdirs
  1212. */
  1213. public boolean mkdir() {
  1214. SecurityManager security = System.getSecurityManager();
  1215. if (security != null) {
  1216. security.checkWrite(path);
  1217. }
  1218. return mkdirImpl(properPath(true));
  1219. }
  1220. private native boolean mkdirImpl(byte[] filePath);
  1221. /**
  1222. * Creates the directory named by the trailing filename of this file,
  1223. * including the complete directory path required to create this directory.
  1224. *
  1225. * @return {@code true} if the necessary directories have been created,
  1226. * {@code false} if the target directory already exists or one of
  1227. * the directories can not be created.
  1228. * @throws SecurityException
  1229. * if a {@code SecurityManager} is installed and it denies write
  1230. * access for this file.
  1231. * @see #mkdir
  1232. */
  1233. public boolean mkdirs() {
  1234. /* If the terminal directory already exists, answer false */
  1235. if (exists()) {
  1236. return false;
  1237. }
  1238. /* If the receiver can be created, answer true */
  1239. if (mkdir()) {
  1240. return true;
  1241. }
  1242. String parentDir = getParent();
  1243. /* If there is no parent and we were not created, answer false */
  1244. if (parentDir == null) {
  1245. return false;
  1246. }
  1247. /* Otherwise, try to create a parent directory and then this directory */
  1248. return (new File(parentDir).mkdirs() && mkdir());
  1249. }
  1250. /**
  1251. * Creates a new, empty file on the file system according to the path
  1252. * information stored in this file.
  1253. *
  1254. * @return {@code true} if the file has been created, {@code false} if it
  1255. * already exists.
  1256. * @throws IOException
  1257. * if an I/O error occurs or the directory does not exist where
  1258. * the file should have been created.
  1259. * @throws SecurityException
  1260. * if a {@code SecurityManager} is installed and it denies write
  1261. * access for this file.
  1262. */
  1263. public boolean createNewFile() throws IOException {
  1264. SecurityManager security = System.getSecurityManager();
  1265. if (security != null) {
  1266. security.checkWrite(path);
  1267. }
  1268. if (0 == path.length()) {
  1269. throw new IOException(Messages.getString("luni.B3")); //$NON-NLS-1$
  1270. }
  1271. int result

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