PageRenderTime 71ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 1ms

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

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