GNU Classpath (0.92) | |
Frames | No Frames |
1: /* File.java -- Class representing a file on disk 2: Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006 3: Free Software Foundation, Inc. 4: 5: This file is part of GNU Classpath. 6: 7: GNU Classpath is free software; you can redistribute it and/or modify 8: it under the terms of the GNU General Public License as published by 9: the Free Software Foundation; either version 2, or (at your option) 10: any later version. 11: 12: GNU Classpath is distributed in the hope that it will be useful, but 13: WITHOUT ANY WARRANTY; without even the implied warranty of 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15: General Public License for more details. 16: 17: You should have received a copy of the GNU General Public License 18: along with GNU Classpath; see the file COPYING. If not, write to the 19: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20: 02110-1301 USA. 21: 22: Linking this library statically or dynamically with other modules is 23: making a combined work based on this library. Thus, the terms and 24: conditions of the GNU General Public License cover the whole 25: combination. 26: 27: As a special exception, the copyright holders of this library give you 28: permission to link this library with independent modules to produce an 29: executable, regardless of the license terms of these independent 30: modules, and to copy and distribute the resulting executable under 31: terms of your choice, provided that you also meet, for each linked 32: independent module, the terms and conditions of the license of that 33: module. An independent module is a module which is not derived from 34: or based on this library. If you modify this library, you may extend 35: this exception to your version of the library, but you are not 36: obligated to do so. If you do not wish to do so, delete this 37: exception statement from your version. */ 38: 39: 40: package java.io; 41: 42: import gnu.classpath.SystemProperties; 43: 44: import java.net.MalformedURLException; 45: import java.net.URI; 46: import java.net.URISyntaxException; 47: import java.net.URL; 48: 49: /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 50: * "The Java Language Specification", ISBN 0-201-63451-1 51: * Status: Complete to version 1.3. 52: */ 53: 54: /** 55: * This class represents a file or directory on a local disk. It provides 56: * facilities for dealing with a variety of systems that use various 57: * types of path separators ("/" versus "\", for example). It also 58: * contains method useful for creating and deleting files and directories. 59: * 60: * @author Aaron M. Renn (arenn@urbanophile.com) 61: * @author Tom Tromey (tromey@cygnus.com) 62: */ 63: public class File implements Serializable, Comparable 64: { 65: private static final long serialVersionUID = 301077366599181567L; 66: 67: /** 68: * This is the path separator string for the current host. This field 69: * contains the value of the <code>file.separator</code> system property. 70: * An example separator string would be "/" on the GNU system. 71: */ 72: public static final String separator = SystemProperties.getProperty("file.separator"); 73: private static final String dupSeparator = separator + separator; 74: 75: /** 76: * This is the first character of the file separator string. On many 77: * hosts (for example, on the GNU system), this represents the entire 78: * separator string. The complete separator string is obtained from the 79: * <code>file.separator</code>system property. 80: */ 81: public static final char separatorChar = separator.charAt(0); 82: 83: /** 84: * This is the string that is used to separate the host name from the 85: * path name in paths that include the host name. It is the value of 86: * the <code>path.separator</code> system property. 87: */ 88: public static final String pathSeparator 89: = SystemProperties.getProperty("path.separator"); 90: 91: /** 92: * This is the first character of the string used to separate the host name 93: * from the path name in paths that include a host. The separator string 94: * is taken from the <code>path.separator</code> system property. 95: */ 96: public static final char pathSeparatorChar = pathSeparator.charAt(0); 97: 98: /** 99: * This is the path to the file set when the object is created. It 100: * may be an absolute or relative path name. 101: */ 102: private String path; 103: 104: 105: /** 106: * The time (millisecond), when the last temporary file was created. 107: */ 108: private static long last_tmp; 109: 110: /** 111: * The number of files, created during the current millisecond. 112: */ 113: private static int n_created; 114: 115: /** 116: * This method tests whether or not the current thread is allowed to 117: * to read the file pointed to by this object. This will be true if and 118: * and only if 1) the file exists and 2) the <code>SecurityManager</code> 119: * (if any) allows access to the file via it's <code>checkRead</code> 120: * method 3) the file is readable. 121: * 122: * @return <code>true</code> if reading is allowed, 123: * <code>false</code> otherwise 124: * 125: * @exception SecurityException If the <code>SecurityManager</code> 126: * does not allow access to the file 127: */ 128: public boolean canRead() 129: { 130: // Test for existence. This also does the SecurityManager check 131: if (!exists()) 132: return false; 133: 134: return VMFile.canRead(path); 135: } 136: 137: /** 138: * This method test whether or not the current thread is allowed to 139: * write to this object. This will be true if and only if 1) The 140: * <code>SecurityManager</code> (if any) allows write access to the 141: * file and 2) The file exists and 3) The file is writable. To determine 142: * whether or not a non-existent file can be created, check the parent 143: * directory for write access. 144: * 145: * @return <code>true</code> if writing is allowed, <code>false</code> 146: * otherwise 147: * 148: * @exception SecurityException If the <code>SecurityManager</code> 149: * does not allow access to the file 150: */ 151: public boolean canWrite() 152: { 153: // First do a SecurityCheck before doing anything else. 154: checkWrite(); 155: 156: // Test for existence. This is required by the spec 157: if (! VMFile.exists(path)) 158: return false; 159: 160: if (VMFile.isDirectory(path)) 161: return VMFile.canWriteDirectory(this); 162: else 163: return VMFile.canWrite(path); 164: } 165: 166: /** 167: * This method creates a new file of zero length with the same name as 168: * the path of this <code>File</code> object if an only if that file 169: * does not already exist. 170: * <p> 171: * A <code>SecurityManager.checkWrite</code> check is done prior 172: * to performing this action. 173: * 174: * @return <code>true</code> if the file was created, <code>false</code> if 175: * the file alread existed. 176: * 177: * @exception IOException If an I/O error occurs 178: * @exception SecurityException If the <code>SecurityManager</code> will 179: * not allow this operation to be performed. 180: * 181: * @since 1.2 182: */ 183: public boolean createNewFile() throws IOException 184: { 185: checkWrite(); 186: return VMFile.create(path); 187: } 188: /** 189: * This method deletes the file represented by this object. If this file 190: * is a directory, it must be empty in order for the delete to succeed. 191: * 192: * @return <code>true</code> if the file was deleted, <code>false</code> 193: * otherwise 194: * 195: * @exception SecurityException If deleting of the file is not allowed 196: */ 197: public synchronized boolean delete() 198: { 199: SecurityManager s = System.getSecurityManager(); 200: 201: if (s != null) 202: s.checkDelete(path); 203: 204: return VMFile.delete(path); 205: } 206: 207: /** 208: * This method tests two <code>File</code> objects for equality by 209: * comparing the path of the specified <code>File</code> against the path 210: * of this object. The two objects are equal if an only if 1) The 211: * argument is not null 2) The argument is a <code>File</code> object and 212: * 3) The path of the <code>File</code>argument is equal to the path 213: * of this object. 214: * <p> 215: * The paths of the files are determined by calling the 216: * <code>getPath()</code> 217: * method on each object. 218: * 219: * @return <code>true</code> if the two objects are equal, 220: * <code>false</code> otherwise. 221: */ 222: public boolean equals(Object obj) 223: { 224: if (! (obj instanceof File)) 225: return false; 226: 227: File other = (File) obj; 228: 229: if (VMFile.IS_CASE_SENSITIVE) 230: return path.equals(other.path); 231: else 232: return path.equalsIgnoreCase(other.path); 233: } 234: 235: /** 236: * This method tests whether or not the file represented by the object 237: * actually exists on the filesystem. 238: * 239: * @return <code>true</code> if the file exists, <code>false</code>otherwise. 240: * 241: * @exception SecurityException If reading of the file is not permitted 242: */ 243: public boolean exists() 244: { 245: checkRead(); 246: return VMFile.exists(path); 247: } 248: 249: /** 250: * This method initializes a new <code>File</code> object to represent 251: * a file with the specified path. 252: * 253: * @param name The path name of the file 254: */ 255: public File(String name) 256: { 257: path = normalizePath (name); 258: } 259: 260: // Remove duplicate and redundant separator characters. 261: private String normalizePath(String p) 262: { 263: // On Windows, convert any '/' to '\'. This appears to be the same logic 264: // that Sun's Win32 Java performs. 265: if (separatorChar == '\\') 266: { 267: p = p.replace ('/', '\\'); 268: // We have to special case the "\c:" prefix. 269: if (p.length() > 2 && p.charAt(0) == '\\' && 270: ((p.charAt(1) >= 'a' && p.charAt(1) <= 'z') || 271: (p.charAt(1) >= 'A' && p.charAt(1) <= 'Z')) && 272: p.charAt(2) == ':') 273: p = p.substring(1); 274: } 275: 276: int dupIndex = p.indexOf(dupSeparator); 277: int plen = p.length(); 278: 279: // Special case: permit Windows UNC path prefix. 280: if (dupSeparator.equals("\\\\") && dupIndex == 0) 281: dupIndex = p.indexOf(dupSeparator, 1); 282: 283: if (dupIndex == -1) 284: { 285: // Ignore trailing separator (though on Windows "a:\", for 286: // example, is a valid and minimal path). 287: if (plen > 1 && p.charAt (plen - 1) == separatorChar) 288: { 289: if (! (separatorChar == '\\' && plen == 3 && p.charAt (1) == ':')) 290: return p.substring (0, plen - 1); 291: } 292: else 293: return p; 294: } 295: 296: StringBuffer newpath = new StringBuffer(plen); 297: int last = 0; 298: while (dupIndex != -1) 299: { 300: newpath.append(p.substring(last, dupIndex)); 301: // Ignore the duplicate path characters. 302: while (p.charAt(dupIndex) == separatorChar) 303: { 304: dupIndex++; 305: if (dupIndex == plen) 306: return newpath.toString(); 307: } 308: newpath.append(separatorChar); 309: last = dupIndex; 310: dupIndex = p.indexOf(dupSeparator, last); 311: } 312: 313: // Again, ignore possible trailing separator (except special cases 314: // like "a:\" on Windows). 315: int end; 316: if (plen > 1 && p.charAt (plen - 1) == separatorChar) 317: { 318: if (separatorChar == '\\' && plen == 3 && p.charAt (1) == ':') 319: end = plen; 320: else 321: end = plen - 1; 322: } 323: else 324: end = plen; 325: newpath.append(p.substring(last, end)); 326: 327: return newpath.toString(); 328: } 329: 330: /** 331: * This method initializes a new <code>File</code> object to represent 332: * a file in the specified named directory. The path name to the file 333: * will be the directory name plus the separator string plus the file 334: * name. If the directory path name ends in the separator string, another 335: * separator string will still be appended. 336: * 337: * @param dirPath The path to the directory the file resides in 338: * @param name The name of the file 339: */ 340: public File(String dirPath, String name) 341: { 342: if (name == null) 343: throw new NullPointerException(); 344: if (dirPath != null) 345: { 346: if (dirPath.length() > 0) 347: { 348: // Try to be smart about the number of separator characters. 349: if (dirPath.charAt(dirPath.length() - 1) == separatorChar 350: || name.length() == 0) 351: path = normalizePath(dirPath + name); 352: else 353: path = normalizePath(dirPath + separatorChar + name); 354: } 355: else 356: { 357: // If dirPath is empty, use a system dependant 358: // default prefix. 359: // Note that the leading separators in name have 360: // to be chopped off, to prevent them forming 361: // a UNC prefix on Windows. 362: if (separatorChar == '\\' /* TODO use ON_WINDOWS */) 363: { 364: int skip = 0; 365: while(name.length() > skip 366: && (name.charAt(skip) == separatorChar 367: || name.charAt(skip) == '/')) 368: { 369: skip++; 370: } 371: name = name.substring(skip); 372: } 373: path = normalizePath(separatorChar + name); 374: } 375: } 376: else 377: path = normalizePath(name); 378: } 379: 380: /** 381: * This method initializes a new <code>File</code> object to represent 382: * a file in the specified directory. If the <code>directory</code> 383: * argument is <code>null</code>, the file is assumed to be in the 384: * current directory as specified by the <code>user.dir</code> system 385: * property 386: * 387: * @param directory The directory this file resides in 388: * @param name The name of the file 389: */ 390: public File(File directory, String name) 391: { 392: this (directory == null ? null : directory.path, name); 393: } 394: 395: /** 396: * This method initializes a new <code>File</code> object to represent 397: * a file corresponding to the specified <code>file:</code> protocol URI. 398: * 399: * @param uri The URI 400: * @throws IllegalArgumentException if the URI is not hierarchical 401: */ 402: public File(URI uri) 403: { 404: if (uri == null) 405: throw new NullPointerException("uri is null"); 406: 407: if (!uri.getScheme().equals("file")) 408: throw new IllegalArgumentException("invalid uri protocol"); 409: 410: String name = uri.getPath(); 411: if (name == null) 412: throw new IllegalArgumentException("URI \"" + uri 413: + "\" is not hierarchical"); 414: path = normalizePath(name); 415: } 416: 417: /** 418: * This method returns the path of this file as an absolute path name. 419: * If the path name is already absolute, then it is returned. Otherwise 420: * the value returned is the current directory plus the separatory 421: * string plus the path of the file. The current directory is determined 422: * from the <code>user.dir</code> system property. 423: * 424: * @return The absolute path of this file 425: */ 426: public String getAbsolutePath() 427: { 428: if (isAbsolute()) 429: return path; 430: else if (separatorChar == '\\' 431: && path.length() > 0 && path.charAt (0) == '\\') 432: { 433: // On Windows, even if the path starts with a '\\' it is not 434: // really absolute until we prefix the drive specifier from 435: // the current working directory to it. 436: return System.getProperty ("user.dir").substring (0, 2) + path; 437: } 438: else if (separatorChar == '\\' 439: && path.length() > 1 && path.charAt (1) == ':' 440: && ((path.charAt (0) >= 'a' && path.charAt (0) <= 'z') 441: || (path.charAt (0) >= 'A' && path.charAt (0) <= 'Z'))) 442: { 443: // On Windows, a process has a current working directory for 444: // each drive and a path like "G:foo\bar" would mean the 445: // absolute path "G:\wombat\foo\bar" if "\wombat" is the 446: // working directory on the G drive. 447: String drvDir = null; 448: try 449: { 450: drvDir = new File (path.substring (0, 2)).getCanonicalPath(); 451: } 452: catch (IOException e) 453: { 454: drvDir = path.substring (0, 2) + "\\"; 455: } 456: 457: // Note: this would return "C:\\." for the path "C:.", if "\" 458: // is the working folder on the C drive, but this is 459: // consistent with what Sun's JRE 1.4.1.01 actually returns! 460: if (path.length() > 2) 461: return drvDir + '\\' + path.substring (2, path.length()); 462: else 463: return drvDir; 464: } 465: else if (path.equals("")) 466: return System.getProperty ("user.dir"); 467: else 468: return System.getProperty ("user.dir") + separatorChar + path; 469: } 470: 471: /** 472: * This method returns a <code>File</code> object representing the 473: * absolute path of this object. 474: * 475: * @return A <code>File</code> with the absolute path of the object. 476: * 477: * @since 1.2 478: */ 479: public File getAbsoluteFile() 480: { 481: return new File(getAbsolutePath()); 482: } 483: 484: /** 485: * This method returns a canonical representation of the pathname of 486: * this file. The actual form of the canonical representation is 487: * system-dependent. On the GNU system, conversion to canonical 488: * form involves the removal of redundant separators, references to 489: * "." and "..", and symbolic links. 490: * <p> 491: * Note that this method, unlike the other methods which return path 492: * names, can throw an IOException. This is because native method 493: * might be required in order to resolve the canonical path 494: * 495: * @exception IOException If an error occurs 496: */ 497: public String getCanonicalPath() throws IOException 498: { 499: // On Windows, getAbsolutePath might end up calling us, so we 500: // have to special case that call to avoid infinite recursion. 501: if (separatorChar == '\\' && path.length() == 2 && 502: ((path.charAt(0) >= 'a' && path.charAt(0) <= 'z') || 503: (path.charAt(0) >= 'A' && path.charAt(0) <= 'Z')) && 504: path.charAt(1) == ':') 505: { 506: return VMFile.toCanonicalForm(path); 507: } 508: // Call getAbsolutePath first to make sure that we do the 509: // current directory handling, because the native code 510: // may have a different idea of the current directory. 511: return VMFile.toCanonicalForm(getAbsolutePath()); 512: } 513: 514: /** 515: * This method returns a <code>File</code> object representing the 516: * canonical path of this object. 517: * 518: * @return A <code>File</code> instance representing the canonical path of 519: * this object. 520: * 521: * @exception IOException If an error occurs. 522: * 523: * @since 1.2 524: */ 525: public File getCanonicalFile() throws IOException 526: { 527: return new File(getCanonicalPath()); 528: } 529: 530: /** 531: * This method returns the name of the file. This is everything in the 532: * complete path of the file after the last instance of the separator 533: * string. 534: * 535: * @return The file name 536: */ 537: public String getName() 538: { 539: return VMFile.getName(path); 540: } 541: 542: /** 543: * This method returns a <code>String</code> the represents this file's 544: * parent. <code>null</code> is returned if the file has no parent. The 545: * parent is determined via a simple operation which removes the name 546: * after the last file separator character, as determined by the platform. 547: * 548: * @return The parent directory of this file 549: */ 550: public String getParent() 551: { 552: String prefix = null; 553: int nameSeqIndex = 0; 554: 555: if (path.equals("")) 556: return null; 557: 558: // The "prefix", if present, is the leading "/" on UNIX and 559: // either the drive specifier (e.g. "C:") or the leading "\\" 560: // of a UNC network path on Windows. 561: if (separatorChar == '/' && path.charAt (0) == '/') 562: { 563: prefix = "/"; 564: nameSeqIndex = 1; 565: } 566: else if (separatorChar == '\\' && path.length() > 1) 567: { 568: if ((path.charAt (0) == '\\' && path.charAt (1) == '\\') 569: || (((path.charAt (0) >= 'a' && path.charAt (0) <= 'z') 570: || (path.charAt (0) >= 'A' && path.charAt (0) <= 'Z')) 571: && path.charAt (1) == ':')) 572: { 573: prefix = path.substring (0, 2); 574: nameSeqIndex = 2; 575: } 576: } 577: 578: // According to the JDK docs, the returned parent path is the 579: // portion of the name sequence before the last separator 580: // character, if found, prefixed by the prefix, otherwise null. 581: if (nameSeqIndex < path.length()) 582: { 583: String nameSeq = path.substring (nameSeqIndex, path.length()); 584: int last = nameSeq.lastIndexOf (separatorChar); 585: if (last == -1) 586: return prefix; 587: else if (last == (nameSeq.length() - 1)) 588: // Note: The path would not have a trailing separator 589: // except for cases like "C:\" on Windows (see 590: // normalizePath( )), where Sun's JRE 1.4 returns null. 591: return null; 592: else if (last == 0) 593: last++; 594: 595: if (prefix != null) 596: return prefix + nameSeq.substring (0, last); 597: else 598: return nameSeq.substring (0, last); 599: } 600: else 601: // Sun's JRE 1.4 returns null if the prefix is the only 602: // component of the path - so "/" gives null on UNIX and 603: // "C:", "\\", etc. return null on Windows. 604: return null; 605: } 606: 607: /** 608: * This method returns a <code>File</code> object representing the parent 609: * file of this one. 610: * 611: * @return a <code>File</code> for the parent of this object. 612: * <code>null</code> 613: * will be returned if this object does not have a parent. 614: * 615: * @since 1.2 616: */ 617: public File getParentFile() 618: { 619: String parent = getParent(); 620: return parent != null ? new File(parent) : null; 621: } 622: 623: /** 624: * Returns the path name that represents this file. May be a relative 625: * or an absolute path name 626: * 627: * @return The pathname of this file 628: */ 629: public String getPath() 630: { 631: return path; 632: } 633: 634: /** 635: * This method returns a hash code representing this file. It is the 636: * hash code of the path of this file (as returned by <code>getPath()</code>) 637: * exclusived or-ed with the value 1234321. 638: * 639: * @return The hash code for this object 640: */ 641: public int hashCode() 642: { 643: if (VMFile.IS_CASE_SENSITIVE) 644: return path.hashCode() ^ 1234321; 645: else 646: return path.toLowerCase().hashCode() ^ 1234321; 647: } 648: 649: /** 650: * This method returns true if this object represents an absolute file 651: * path and false if it does not. The definition of an absolute path varies 652: * by system. As an example, on GNU systems, a path is absolute if it starts 653: * with a "/". 654: * 655: * @return <code>true</code> if this object represents an absolute 656: * file name, <code>false</code> otherwise. 657: */ 658: public boolean isAbsolute() 659: { 660: if (separatorChar == '\\') 661: return path.startsWith(dupSeparator) || 662: (path.length() > 2 && 663: ((path.charAt(0) >= 'a' && path.charAt(0) <= 'z') || 664: (path.charAt(0) >= 'A' && path.charAt(0) <= 'Z')) && 665: path.charAt(1) == ':' && 666: path.charAt(2) == '\\'); 667: else 668: return path.startsWith(separator); 669: } 670: 671: /** 672: * This method tests whether or not the file represented by this object 673: * is a directory. In order for this method to return <code>true</code>, 674: * the file represented by this object must exist and be a directory. 675: * 676: * @return <code>true</code> if this file is a directory, <code>false</code> 677: * otherwise 678: * 679: * @exception SecurityException If reading of the file is not permitted 680: */ 681: public boolean isDirectory() 682: { 683: checkRead(); 684: return VMFile.isDirectory(path); 685: } 686: 687: /** 688: * This method tests whether or not the file represented by this object 689: * is a "plain" file. A file is a plain file if and only if it 1) Exists, 690: * 2) Is not a directory or other type of special file. 691: * 692: * @return <code>true</code> if this is a plain file, <code>false</code> 693: * otherwise 694: * 695: * @exception SecurityException If reading of the file is not permitted 696: */ 697: public boolean isFile() 698: { 699: checkRead(); 700: return VMFile.isFile(path); 701: } 702: 703: /** 704: * This method tests whether or not this file represents a "hidden" file. 705: * On GNU systems, a file is hidden if its name begins with a "." 706: * character. Files with these names are traditionally not shown with 707: * directory listing tools. 708: * 709: * @return <code>true</code> if the file is hidden, <code>false</code> 710: * otherwise. 711: * 712: * @since 1.2 713: */ 714: public boolean isHidden() 715: { 716: return VMFile.isHidden(path); 717: } 718: 719: /** 720: * This method returns the last modification time of this file. The 721: * time value returned is an abstract value that should not be interpreted 722: * as a specified time value. It is only useful for comparing to other 723: * such time values returned on the same system. In that case, the larger 724: * value indicates a more recent modification time. 725: * <p> 726: * If the file does not exist, then a value of 0 is returned. 727: * 728: * @return The last modification time of the file 729: * 730: * @exception SecurityException If reading of the file is not permitted 731: */ 732: public long lastModified() 733: { 734: checkRead(); 735: return VMFile.lastModified(path); 736: } 737: 738: /** 739: * This method returns the length of the file represented by this object, 740: * or 0 if the specified file does not exist. 741: * 742: * @return The length of the file 743: * 744: * @exception SecurityException If reading of the file is not permitted 745: */ 746: public long length() 747: { 748: checkRead(); 749: return VMFile.length(path); 750: } 751: 752: /** 753: * This method returns a array of <code>String</code>'s representing the 754: * list of files is then directory represented by this object. If this 755: * object represents a non-directory file or a non-existent file, then 756: * <code>null</code> is returned. The list of files will not contain 757: * any names such as "." or ".." which indicate the current or parent 758: * directory. Also, the names are not guaranteed to be sorted. 759: * <p> 760: * In this form of the <code>list()</code> method, a filter is specified 761: * that allows the caller to control which files are returned in the 762: * list. The <code>FilenameFilter</code> specified is called for each 763: * file returned to determine whether or not that file should be included 764: * in the list. 765: * <p> 766: * A <code>SecurityManager</code> check is made prior to reading the 767: * directory. If read access to the directory is denied, an exception 768: * will be thrown. 769: * 770: * @param filter An object which will identify files to exclude from 771: * the directory listing. 772: * 773: * @return An array of files in the directory, or <code>null</code> 774: * if this object does not represent a valid directory. 775: * 776: * @exception SecurityException If read access is not allowed to the 777: * directory by the <code>SecurityManager</code> 778: */ 779: public String[] list(FilenameFilter filter) 780: { 781: checkRead(); 782: 783: if (!exists() || !isDirectory()) 784: return null; 785: 786: // Get the list of files 787: String files[] = VMFile.list(path); 788: 789: // Check if an error occured in listInternal(). 790: if (files == null) 791: return null; 792: 793: if (filter == null) 794: return files; 795: 796: // Apply the filter 797: int count = 0; 798: for (int i = 0; i < files.length; i++) 799: { 800: if (filter.accept(this, files[i])) 801: ++count; 802: else 803: files[i] = null; 804: } 805: 806: String[] retfiles = new String[count]; 807: count = 0; 808: for (int i = 0; i < files.length; i++) 809: if (files[i] != null) 810: retfiles[count++] = files[i]; 811: 812: return retfiles; 813: } 814: 815: /** 816: * This method returns a array of <code>String</code>'s representing the 817: * list of files is then directory represented by this object. If this 818: * object represents a non-directory file or a non-existent file, then 819: * <code>null</code> is returned. The list of files will not contain 820: * any names such as "." or ".." which indicate the current or parent 821: * directory. Also, the names are not guaranteed to be sorted. 822: * <p> 823: * A <code>SecurityManager</code> check is made prior to reading the 824: * directory. If read access to the directory is denied, an exception 825: * will be thrown. 826: * 827: * @return An array of files in the directory, or <code>null</code> if 828: * this object does not represent a valid directory. 829: * 830: * @exception SecurityException If read access is not allowed to the 831: * directory by the <code>SecurityManager</code> 832: */ 833: public String[] list() 834: { 835: return list(null); 836: } 837: 838: /** 839: * This method returns an array of <code>File</code> objects representing 840: * all the files in the directory represented by this object. If this 841: * object does not represent a directory, <code>null</code> is returned. 842: * Each of the returned <code>File</code> object is constructed with this 843: * object as its parent. 844: * <p> 845: * A <code>SecurityManager</code> check is made prior to reading the 846: * directory. If read access to the directory is denied, an exception 847: * will be thrown. 848: * 849: * @return An array of <code>File</code> objects for this directory. 850: * 851: * @exception SecurityException If the <code>SecurityManager</code> denies 852: * access to this directory. 853: * 854: * @since 1.2 855: */ 856: public File[] listFiles() 857: { 858: return listFiles((FilenameFilter) null); 859: } 860: 861: /** 862: * This method returns an array of <code>File</code> objects representing 863: * all the files in the directory represented by this object. If this 864: * object does not represent a directory, <code>null</code> is returned. 865: * Each of the returned <code>File</code> object is constructed with this 866: * object as its parent. 867: * <p> 868: * In this form of the <code>listFiles()</code> method, a filter is specified 869: * that allows the caller to control which files are returned in the 870: * list. The <code>FilenameFilter</code> specified is called for each 871: * file returned to determine whether or not that file should be included 872: * in the list. 873: * <p> 874: * A <code>SecurityManager</code> check is made prior to reading the 875: * directory. If read access to the directory is denied, an exception 876: * will be thrown. 877: * 878: * @return An array of <code>File</code> objects for this directory. 879: * 880: * @exception SecurityException If the <code>SecurityManager</code> denies 881: * access to this directory. 882: * 883: * @since 1.2 884: */ 885: public File[] listFiles(FilenameFilter filter) 886: { 887: String[] filelist = list(filter); 888: 889: if (filelist == null) 890: return null; 891: 892: File[] fobjlist = new File [filelist.length]; 893: 894: for (int i = 0; i < filelist.length; i++) 895: fobjlist [i] = new File(this, filelist [i]); 896: 897: return fobjlist; 898: } 899: 900: /** 901: * This method returns an array of <code>File</code> objects representing 902: * all the files in the directory represented by this object. If this 903: * object does not represent a directory, <code>null</code> is returned. 904: * Each of the returned <code>File</code> object is constructed with this 905: * object as its parent. 906: * <p> 907: * In this form of the <code>listFiles()</code> method, a filter is specified 908: * that allows the caller to control which files are returned in the 909: * list. The <code>FileFilter</code> specified is called for each 910: * file returned to determine whether or not that file should be included 911: * in the list. 912: * <p> 913: * A <code>SecurityManager</code> check is made prior to reading the 914: * directory. If read access to the directory is denied, an exception 915: * will be thrown. 916: * 917: * @return An array of <code>File</code> objects for this directory. 918: * 919: * @exception SecurityException If the <code>SecurityManager</code> denies 920: * access to this directory. 921: * 922: * @since 1.2 923: */ 924: public File[] listFiles(FileFilter filter) 925: { 926: File[] fobjlist = listFiles((FilenameFilter) null); 927: 928: if (fobjlist == null) 929: return null; 930: 931: if (filter == null) 932: return fobjlist; 933: 934: int count = 0; 935: for (int i = 0; i < fobjlist.length; i++) 936: if (filter.accept(fobjlist[i]) == true) 937: ++count; 938: 939: File[] final_list = new File[count]; 940: count = 0; 941: for (int i = 0; i < fobjlist.length; i++) 942: if (filter.accept(fobjlist[i]) == true) 943: { 944: final_list[count] = fobjlist[i]; 945: ++count; 946: } 947: 948: return final_list; 949: } 950: 951: /** 952: * This method returns a <code>String</code> that is the path name of the 953: * file as returned by <code>getPath</code>. 954: * 955: * @return A <code>String</code> representation of this file 956: */ 957: public String toString() 958: { 959: return path; 960: } 961: 962: /** 963: * @return A <code>URI</code> for this object. 964: */ 965: public URI toURI() 966: { 967: String abspath = getAbsolutePath(); 968: 969: if (isDirectory() || path.equals("")) 970: abspath = abspath + separatorChar; 971: 972: if (separatorChar == '\\') 973: abspath = separatorChar + abspath; 974: 975: try 976: { 977: return new URI("file", null, null, -1, 978: abspath.replace(separatorChar, '/'), 979: null, null); 980: } 981: catch (URISyntaxException use) 982: { 983: // Can't happen. 984: throw (InternalError) new InternalError("Unconvertible file: " 985: + this).initCause(use); 986: } 987: } 988: 989: /** 990: * This method returns a <code>URL</code> with the <code>file:</code> 991: * protocol that represents this file. The exact form of this URL is 992: * system dependent. 993: * 994: * @return A <code>URL</code> for this object. 995: * 996: * @exception MalformedURLException If the URL cannot be created 997: * successfully. 998: */ 999: public URL toURL() throws MalformedURLException 1000: { 1001: // On Win32, Sun's JDK returns URLs of the form "file:/c:/foo/bar.txt", 1002: // while on UNIX, it returns URLs of the form "file:/foo/bar.txt". 1003: if (separatorChar == '\\') 1004: return new URL ("file:/" + getAbsolutePath().replace ('\\', '/') 1005: + (isDirectory() ? "/" : "")); 1006: else 1007: return new URL ("file:" + getAbsolutePath() 1008: + (isDirectory() ? "/" : "")); 1009: } 1010: 1011: 1012: /** 1013: * This method creates a directory for the path represented by this object. 1014: * 1015: * @return <code>true</code> if the directory was created, 1016: * <code>false</code> otherwise 1017: * 1018: * @exception SecurityException If write access is not allowed to this file 1019: */ 1020: public boolean mkdir() 1021: { 1022: checkWrite(); 1023: return VMFile.mkdir(path); 1024: } 1025: 1026: /** 1027: * This method creates a directory for the path represented by this file. 1028: * It will also create any intervening parent directories if necessary. 1029: * 1030: * @return <code>true</code> if the directory was created, 1031: * <code>false</code> otherwise 1032: * 1033: * @exception SecurityException If write access is not allowed to this file 1034: */ 1035: public boolean mkdirs() 1036: { 1037: String parent = getParent(); 1038: if (parent == null) 1039: { 1040: return mkdir(); 1041: } 1042: 1043: File f = new File(parent); 1044: if (!f.exists()) 1045: { 1046: boolean rc = f.mkdirs(); 1047: if (rc == false) 1048: return false; 1049: } 1050: 1051: return mkdir(); 1052: } 1053: 1054: /** 1055: * This method creates a temporary file in the specified directory. If 1056: * the directory name is null, then this method uses the system temporary 1057: * directory. The files created are guaranteed not to currently exist and 1058: * the same file name will never be used twice in the same virtual 1059: * machine instance. 1060: * The system temporary directory is determined by examinging the 1061: * <code>java.io.tmpdir</code> system property. 1062: * <p> 1063: * The <code>prefix</code> parameter is a sequence of at least three 1064: * characters that are used as the start of the generated filename. The 1065: * <code>suffix</code> parameter is a sequence of characters that is used 1066: * to terminate the file name. This parameter may be <code>null</code> 1067: * and if it is, the suffix defaults to ".tmp". 1068: * <p> 1069: * If a <code>SecurityManager</code> exists, then its <code>checkWrite</code> 1070: * method is used to verify that this operation is permitted. 1071: * 1072: * @param prefix The character prefix to use in generating the path name. 1073: * @param suffix The character suffix to use in generating the path name. 1074: * @param directory The directory to create the file in, or 1075: * <code>null</code> for the default temporary directory 1076: * 1077: * @exception IllegalArgumentException If the patterns is not valid 1078: * @exception SecurityException If there is no permission to perform 1079: * this operation 1080: * @exception IOException If an error occurs 1081: * 1082: * @since 1.2 1083: */ 1084: public static synchronized File createTempFile(String prefix, String suffix, 1085: File directory) 1086: throws IOException 1087: { 1088: // Grab the system temp directory if necessary 1089: if (directory == null) 1090: { 1091: String dirname = System.getProperty("java.io.tmpdir"); 1092: if (dirname == null) 1093: throw new IOException("Cannot determine system temporary directory"); 1094: 1095: directory = new File(dirname); 1096: if (! VMFile.exists(directory.path)) 1097: throw new IOException("System temporary directory " 1098: + directory.getName() + " does not exist."); 1099: if (! VMFile.isDirectory(directory.path)) 1100: throw new IOException("System temporary directory " 1101: + directory.getName() 1102: + " is not really a directory."); 1103: } 1104: 1105: // Check if prefix is at least 3 characters long 1106: if (prefix.length() < 3) 1107: throw new IllegalArgumentException("Prefix too short: " + prefix); 1108: 1109: // Set default value of suffix 1110: if (suffix == null) 1111: suffix = ".tmp"; 1112: 1113: // Now identify a file name and make sure it doesn't exist. 1114: File file; 1115: if (!VMFile.IS_DOS_8_3) 1116: { 1117: do 1118: { 1119: long now = System.currentTimeMillis(); 1120: if (now > last_tmp) 1121: { 1122: // The last temporary file was created more than 1 ms ago. 1123: last_tmp = now; 1124: n_created = 0; 1125: } 1126: else 1127: n_created++; 1128: 1129: String name = Long.toHexString(now); 1130: if (n_created > 0) 1131: name += '_'+Integer.toHexString(n_created); 1132: String filename = prefix + name + suffix; 1133: file = new File(directory, filename); 1134: } 1135: while (VMFile.exists(file.path)); 1136: } 1137: else 1138: { 1139: // make sure prefix is not longer than 7 characters 1140: if (prefix.length() >= 8) 1141: throw new IllegalArgumentException("Prefix too long: " + prefix + "(valid length 3..7)"); 1142: 1143: long mask = 0x000000ffffFFFFL >> (prefix.length() * 4); 1144: do 1145: { 1146: int n = (int) (System.currentTimeMillis() & mask); 1147: String filename = prefix + java.lang.Integer.toHexString(n) + suffix; 1148: file = new File(directory, filename); 1149: } 1150: while (VMFile.exists(file.path)); 1151: } 1152: 1153: // Verify that we are allowed to create this file 1154: SecurityManager sm = System.getSecurityManager(); 1155: if (sm != null) 1156: sm.checkWrite(file.getAbsolutePath()); 1157: 1158: // Now create the file and return our file object 1159: // XXX - FIXME race condition. 1160: VMFile.create(file.getAbsolutePath()); 1161: return file; 1162: } 1163: 1164: /** 1165: * This method sets the file represented by this object to be read only. 1166: * A read only file or directory cannot be modified. Please note that 1167: * GNU systems allow read only files to be deleted if the directory it 1168: * is contained in is writable. 1169: * 1170: * @return <code>true</code> if the operation succeeded, <code>false</code> 1171: * otherwise. 1172: * 1173: * @exception SecurityException If the <code>SecurityManager</code> does 1174: * not allow this operation. 1175: * 1176: * @since 1.2 1177: */ 1178: public boolean setReadOnly() 1179: { 1180: // Do a security check before trying to do anything else. 1181: checkWrite(); 1182: 1183: // Test for existence. 1184: if (! VMFile.exists(path)) 1185: return false; 1186: 1187: return VMFile.setReadOnly(path); 1188: } 1189: 1190: /** 1191: * This method returns an array of filesystem roots. Some operating systems 1192: * have volume oriented filesystem. This method provides a mechanism for 1193: * determining which volumes exist. GNU systems use a single hierarchical 1194: * filesystem, so will have only one "/" filesystem root. 1195: * 1196: * @return An array of <code>File</code> objects for each filesystem root 1197: * available. 1198: * 1199: * @since 1.2 1200: */ 1201: public static File[] listRoots() 1202: { 1203: File[] roots = VMFile.listRoots(); 1204: 1205: SecurityManager s = System.getSecurityManager(); 1206: if (s != null) 1207: { 1208: // Only return roots to which the security manager permits read access. 1209: int count = roots.length; 1210: for (int i = 0; i < roots.length; i++) 1211: { 1212: try 1213: { 1214: s.checkRead (roots[i].path); 1215: } 1216: catch (SecurityException sx) 1217: { 1218: roots[i] = null; 1219: count--; 1220: } 1221: } 1222: if (count != roots.length) 1223: { 1224: File[] newRoots = new File[count]; 1225: int k = 0; 1226: for (int i = 0; i < roots.length; i++) 1227: { 1228: if (roots[i] != null) 1229: newRoots[k++] = roots[i]; 1230: } 1231: roots = newRoots; 1232: } 1233: } 1234: return roots; 1235: } 1236: 1237: /** 1238: * This method creates a temporary file in the system temporary directory. 1239: * The files created are guaranteed not to currently exist and the same file 1240: * name will never be used twice in the same virtual machine instance. The 1241: * system temporary directory is determined by examinging the 1242: * <code>java.io.tmpdir</code> system property. 1243: * <p> 1244: * The <code>prefix</code> parameter is a sequence of at least three 1245: * characters that are used as the start of the generated filename. The 1246: * <code>suffix</code> parameter is a sequence of characters that is used 1247: * to terminate the file name. This parameter may be <code>null</code> 1248: * and if it is, the suffix defaults to ".tmp". 1249: * <p> 1250: * If a <code>SecurityManager</code> exists, then its <code>checkWrite</code> 1251: * method is used to verify that this operation is permitted. 1252: * <p> 1253: * This method is identical to calling 1254: * <code>createTempFile(prefix, suffix, null)</code>. 1255: * 1256: * @param prefix The character prefix to use in generating the path name. 1257: * @param suffix The character suffix to use in generating the path name. 1258: * 1259: * @exception IllegalArgumentException If the prefix or suffix are not valid. 1260: * @exception SecurityException If there is no permission to perform 1261: * this operation 1262: * @exception IOException If an error occurs 1263: */ 1264: public static File createTempFile(String prefix, String suffix) 1265: throws IOException 1266: { 1267: return createTempFile(prefix, suffix, null); 1268: } 1269: 1270: /** 1271: * This method compares the specified <code>File</code> to this one 1272: * to test for equality. It does this by comparing the canonical path names 1273: * of the files. 1274: * <p> 1275: * The canonical paths of the files are determined by calling the 1276: * <code>getCanonicalPath</code> method on each object. 1277: * <p> 1278: * This method returns a 0 if the specified <code>Object</code> is equal 1279: * to this one, a negative value if it is less than this one 1280: * a positive value if it is greater than this one. 1281: * 1282: * @return An integer as described above 1283: * 1284: * @since 1.2 1285: */ 1286: public int compareTo(File other) 1287: { 1288: if (VMFile.IS_CASE_SENSITIVE) 1289: return path.compareTo (other.path); 1290: else 1291: return path.compareToIgnoreCase (other.path); 1292: } 1293: 1294: /** 1295: * This method compares the specified <code>Object</code> to this one 1296: * to test for equality. It does this by comparing the canonical path names 1297: * of the files. This method is identical to <code>compareTo(File)</code> 1298: * except that if the <code>Object</code> passed to it is not a 1299: * <code>File</code>, it throws a <code>ClassCastException</code> 1300: * <p> 1301: * The canonical paths of the files are determined by calling the 1302: * <code>getCanonicalPath</code> method on each object. 1303: * <p> 1304: * This method returns a 0 if the specified <code>Object</code> is equal 1305: * to this one, a negative value if it is less than this one 1306: * a positive value if it is greater than this one. 1307: * 1308: * @return An integer as described above 1309: * 1310: * @exception ClassCastException If the passed <code>Object</code> is 1311: * not a <code>File</code> 1312: * 1313: * @since 1.2 1314: */ 1315: public int compareTo(Object obj) 1316: { 1317: return compareTo((File) obj); 1318: } 1319: 1320: /** 1321: * This method renames the file represented by this object to the path 1322: * of the file represented by the argument <code>File</code>. 1323: * 1324: * @param dest The <code>File</code> object representing the target name 1325: * 1326: * @return <code>true</code> if the rename succeeds, <code>false</code> 1327: * otherwise. 1328: * 1329: * @exception SecurityException If write access is not allowed to the 1330: * file by the <code>SecurityMananger</code>. 1331: */ 1332: public synchronized boolean renameTo(File dest) 1333: { 1334: checkWrite(); 1335: dest.checkWrite(); 1336: // Call our native rename method 1337: return VMFile.renameTo(path, dest.path); 1338: } 1339: 1340: /** 1341: * This method sets the modification time on the file to the specified 1342: * value. This is specified as the number of seconds since midnight 1343: * on January 1, 1970 GMT. 1344: * 1345: * @param time The desired modification time. 1346: * 1347: * @return <code>true</code> if the operation succeeded, <code>false</code> 1348: * otherwise. 1349: * 1350: * @exception IllegalArgumentException If the specified time is negative. 1351: * @exception SecurityException If the <code>SecurityManager</code> will 1352: * not allow this operation. 1353: * 1354: * @since 1.2 1355: */ 1356: public boolean setLastModified(long time) 1357: { 1358: if (time < 0) 1359: throw new IllegalArgumentException("Negative modification time: " + time); 1360: 1361: checkWrite(); 1362: return VMFile.setLastModified(path, time); 1363: } 1364: 1365: private void checkWrite() 1366: { 1367: // Check the SecurityManager 1368: SecurityManager s = System.getSecurityManager(); 1369: 1370: if (s != null) 1371: s.checkWrite(path); 1372: } 1373: 1374: private void checkRead() 1375: { 1376: // Check the SecurityManager 1377: SecurityManager s = System.getSecurityManager(); 1378: 1379: if (s != null) 1380: s.checkRead(path); 1381: } 1382: 1383: /** 1384: * Calling this method requests that the file represented by this object 1385: * be deleted when the virtual machine exits. Note that this request cannot 1386: * be cancelled. Also, it will only be carried out if the virtual machine 1387: * exits normally. 1388: * 1389: * @exception SecurityException If deleting of the file is not allowed 1390: * 1391: * @since 1.2 1392: */ 1393: public void deleteOnExit() 1394: { 1395: // Check the SecurityManager 1396: SecurityManager sm = System.getSecurityManager(); 1397: if (sm != null) 1398: sm.checkDelete(path); 1399: 1400: DeleteFileHelper.add(this); 1401: } 1402: 1403: private void writeObject(ObjectOutputStream oos) throws IOException 1404: { 1405: oos.defaultWriteObject(); 1406: oos.writeChar(separatorChar); 1407: } 1408: 1409: private void readObject(ObjectInputStream ois) 1410: throws ClassNotFoundException, IOException 1411: { 1412: ois.defaultReadObject(); 1413: 1414: // If the file was from an OS with a different dir separator, 1415: // fixup the path to use the separator on this OS. 1416: char oldSeparatorChar = ois.readChar(); 1417: 1418: if (oldSeparatorChar != separatorChar) 1419: path = path.replace(oldSeparatorChar, separatorChar); 1420: } 1421: 1422: } // class File
GNU Classpath (0.92) |