GNU Classpath (0.19) | ||
Frames | No Frames |
1: /* File.java -- Class representing a file on disk 2: Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005 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 than 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: */ 401: public File(URI uri) 402: { 403: if (uri == null) 404: throw new NullPointerException("uri is null"); 405: 406: if (!uri.getScheme().equals("file")) 407: throw new IllegalArgumentException("invalid uri protocol"); 408: 409: path = normalizePath(uri.getPath()); 410: } 411: 412: /** 413: * This method returns the path of this file as an absolute path name. 414: * If the path name is already absolute, then it is returned. Otherwise 415: * the value returned is the current directory plus the separatory 416: * string plus the path of the file. The current directory is determined 417: * from the <code>user.dir</code> system property. 418: * 419: * @return The absolute path of this file 420: */ 421: public String getAbsolutePath() 422: { 423: if (isAbsolute()) 424: return path; 425: else if (separatorChar == '\\' 426: && path.length() > 0 && path.charAt (0) == '\\') 427: { 428: // On Windows, even if the path starts with a '\\' it is not 429: // really absolute until we prefix the drive specifier from 430: // the current working directory to it. 431: return System.getProperty ("user.dir").substring (0, 2) + path; 432: } 433: else if (separatorChar == '\\' 434: && path.length() > 1 && path.charAt (1) == ':' 435: && ((path.charAt (0) >= 'a' && path.charAt (0) <= 'z') 436: || (path.charAt (0) >= 'A' && path.charAt (0) <= 'Z'))) 437: { 438: // On Windows, a process has a current working directory for 439: // each drive and a path like "G:foo\bar" would mean the 440: // absolute path "G:\wombat\foo\bar" if "\wombat" is the 441: // working directory on the G drive. 442: String drvDir = null; 443: try 444: { 445: drvDir = new File (path.substring (0, 2)).getCanonicalPath(); 446: } 447: catch (IOException e) 448: { 449: drvDir = path.substring (0, 2) + "\\"; 450: } 451: 452: // Note: this would return "C:\\." for the path "C:.", if "\" 453: // is the working folder on the C drive, but this is 454: // consistent with what Sun's JRE 1.4.1.01 actually returns! 455: if (path.length() > 2) 456: return drvDir + '\\' + path.substring (2, path.length()); 457: else 458: return drvDir; 459: } 460: else 461: return System.getProperty ("user.dir") + separatorChar + path; 462: } 463: 464: /** 465: * This method returns a <code>File</code> object representing the 466: * absolute path of this object. 467: * 468: * @return A <code>File</code> with the absolute path of the object. 469: * 470: * @since 1.2 471: */ 472: public File getAbsoluteFile() 473: { 474: return new File(getAbsolutePath()); 475: } 476: 477: /** 478: * This method returns a canonical representation of the pathname of 479: * this file. The actual form of the canonical representation is 480: * different. On the GNU system, the canonical form differs from the 481: * absolute form in that all relative file references to "." and ".." 482: * are resolved and removed. 483: * <p> 484: * Note that this method, unlike the other methods which return path 485: * names, can throw an IOException. This is because native method 486: * might be required in order to resolve the canonical path 487: * 488: * @exception IOException If an error occurs 489: */ 490: public String getCanonicalPath() throws IOException 491: { 492: // On Windows, getAbsolutePath might end up calling us, so we 493: // have to special case that call to avoid infinite recursion. 494: if (separatorChar == '\\' && path.length() == 2 && 495: ((path.charAt(0) >= 'a' && path.charAt(0) <= 'z') || 496: (path.charAt(0) >= 'A' && path.charAt(0) <= 'Z')) && 497: path.charAt(1) == ':') 498: { 499: return VMFile.toCanonicalForm(path); 500: } 501: // Call getAbsolutePath first to make sure that we do the 502: // current directory handling, because the native code 503: // may have a different idea of the current directory. 504: return VMFile.toCanonicalForm(getAbsolutePath()); 505: } 506: 507: /** 508: * This method returns a <code>File</code> object representing the 509: * canonical path of this object. 510: * 511: * @return A <code>File</code> instance representing the canonical path of 512: * this object. 513: * 514: * @exception IOException If an error occurs. 515: * 516: * @since 1.2 517: */ 518: public File getCanonicalFile() throws IOException 519: { 520: return new File(getCanonicalPath()); 521: } 522: 523: /** 524: * This method returns the name of the file. This is everything in the 525: * complete path of the file after the last instance of the separator 526: * string. 527: * 528: * @return The file name 529: */ 530: public String getName() 531: { 532: return VMFile.getName(path); 533: } 534: 535: /** 536: * This method returns a <code>String</code> the represents this file's 537: * parent. <code>null</code> is returned if the file has no parent. The 538: * parent is determined via a simple operation which removes the 539: * 540: * @return The parent directory of this file 541: */ 542: public String getParent() 543: { 544: String prefix = null; 545: int nameSeqIndex = 0; 546: 547: // The "prefix", if present, is the leading "/" on UNIX and 548: // either the drive specifier (e.g. "C:") or the leading "\\" 549: // of a UNC network path on Windows. 550: if (separatorChar == '/' && path.charAt (0) == '/') 551: { 552: prefix = "/"; 553: nameSeqIndex = 1; 554: } 555: else if (separatorChar == '\\' && path.length() > 1) 556: { 557: if ((path.charAt (0) == '\\' && path.charAt (1) == '\\') 558: || (((path.charAt (0) >= 'a' && path.charAt (0) <= 'z') 559: || (path.charAt (0) >= 'A' && path.charAt (0) <= 'Z')) 560: && path.charAt (1) == ':')) 561: { 562: prefix = path.substring (0, 2); 563: nameSeqIndex = 2; 564: } 565: } 566: 567: // According to the JDK docs, the returned parent path is the 568: // portion of the name sequence before the last separator 569: // character, if found, prefixed by the prefix, otherwise null. 570: if (nameSeqIndex < path.length()) 571: { 572: String nameSeq = path.substring (nameSeqIndex, path.length()); 573: int last = nameSeq.lastIndexOf (separatorChar); 574: if (last == -1) 575: return prefix; 576: else if (last == (nameSeq.length() - 1)) 577: // Note: The path would not have a trailing separator 578: // except for cases like "C:\" on Windows (see 579: // normalizePath( )), where Sun's JRE 1.4 returns null. 580: return null; 581: else if (last == 0) 582: last++; 583: 584: if (prefix != null) 585: return prefix + nameSeq.substring (0, last); 586: else 587: return nameSeq.substring (0, last); 588: } 589: else 590: // Sun's JRE 1.4 returns null if the prefix is the only 591: // component of the path - so "/" gives null on UNIX and 592: // "C:", "\\", etc. return null on Windows. 593: return null; 594: } 595: 596: /** 597: * This method returns a <code>File</code> object representing the parent 598: * file of this one. 599: * 600: * @return a <code>File</code> for the parent of this object. 601: * <code>null</code> 602: * will be returned if this object does not have a parent. 603: * 604: * @since 1.2 605: */ 606: public File getParentFile() 607: { 608: String parent = getParent(); 609: return parent != null ? new File(parent) : null; 610: } 611: 612: /** 613: * Returns the path name that represents this file. May be a relative 614: * or an absolute path name 615: * 616: * @return The pathname of this file 617: */ 618: public String getPath() 619: { 620: return path; 621: } 622: 623: /** 624: * This method returns a hash code representing this file. It is the 625: * hash code of the path of this file (as returned by <code>getPath()</code>) 626: * exclusived or-ed with the value 1234321. 627: * 628: * @return The hash code for this object 629: */ 630: public int hashCode() 631: { 632: if (VMFile.IS_CASE_SENSITIVE) 633: return path.hashCode() ^ 1234321; 634: else 635: return path.toLowerCase().hashCode() ^ 1234321; 636: } 637: 638: /** 639: * This method returns true if this object represents an absolute file 640: * path and false if it does not. The definition of an absolute path varies 641: * by system. As an example, on GNU systems, a path is absolute if it starts 642: * with a "/". 643: * 644: * @return <code>true</code> if this object represents an absolute 645: * file name, <code>false</code> otherwise. 646: */ 647: public boolean isAbsolute() 648: { 649: if (separatorChar == '\\') 650: return path.startsWith(dupSeparator) || 651: (path.length() > 2 && 652: ((path.charAt(0) >= 'a' && path.charAt(0) <= 'z') || 653: (path.charAt(0) >= 'A' && path.charAt(0) <= 'Z')) && 654: path.charAt(1) == ':' && 655: path.charAt(2) == '\\'); 656: else 657: return path.startsWith(separator); 658: } 659: 660: /** 661: * This method tests whether or not the file represented by this object 662: * is a directory. In order for this method to return <code>true</code>, 663: * the file represented by this object must exist and be a directory. 664: * 665: * @return <code>true</code> if this file is a directory, <code>false</code> 666: * otherwise 667: * 668: * @exception SecurityException If reading of the file is not permitted 669: */ 670: public boolean isDirectory() 671: { 672: checkRead(); 673: return VMFile.isDirectory(path); 674: } 675: 676: /** 677: * This method tests whether or not the file represented by this object 678: * is a "plain" file. A file is a plain file if and only if it 1) Exists, 679: * 2) Is not a directory or other type of special file. 680: * 681: * @return <code>true</code> if this is a plain file, <code>false</code> 682: * otherwise 683: * 684: * @exception SecurityException If reading of the file is not permitted 685: */ 686: public boolean isFile() 687: { 688: checkRead(); 689: return VMFile.isFile(path); 690: } 691: 692: /** 693: * This method tests whether or not this file represents a "hidden" file. 694: * On GNU systems, a file is hidden if its name begins with a "." 695: * character. Files with these names are traditionally not shown with 696: * directory listing tools. 697: * 698: * @return <code>true</code> if the file is hidden, <code>false</code> 699: * otherwise. 700: * 701: * @since 1.2 702: */ 703: public boolean isHidden() 704: { 705: return VMFile.isHidden(path); 706: } 707: 708: /** 709: * This method returns the last modification time of this file. The 710: * time value returned is an abstract value that should not be interpreted 711: * as a specified time value. It is only useful for comparing to other 712: * such time values returned on the same system. In that case, the larger 713: * value indicates a more recent modification time. 714: * <p> 715: * If the file does not exist, then a value of 0 is returned. 716: * 717: * @return The last modification time of the file 718: * 719: * @exception SecurityException If reading of the file is not permitted 720: */ 721: public long lastModified() 722: { 723: checkRead(); 724: return VMFile.lastModified(path); 725: } 726: 727: /** 728: * This method returns the length of the file represented by this object, 729: * or 0 if the specified file does not exist. 730: * 731: * @return The length of the file 732: * 733: * @exception SecurityException If reading of the file is not permitted 734: */ 735: public long length() 736: { 737: checkRead(); 738: return VMFile.length(path); 739: } 740: 741: /** 742: * This method returns a array of <code>String</code>'s representing the 743: * list of files is then directory represented by this object. If this 744: * object represents a non-directory file or a non-existent file, then 745: * <code>null</code> is returned. The list of files will not contain 746: * any names such as "." or ".." which indicate the current or parent 747: * directory. Also, the names are not guaranteed to be sorted. 748: * <p> 749: * In this form of the <code>list()</code> method, a filter is specified 750: * that allows the caller to control which files are returned in the 751: * list. The <code>FilenameFilter</code> specified is called for each 752: * file returned to determine whether or not that file should be included 753: * in the list. 754: * <p> 755: * A <code>SecurityManager</code> check is made prior to reading the 756: * directory. If read access to the directory is denied, an exception 757: * will be thrown. 758: * 759: * @param filter An object which will identify files to exclude from 760: * the directory listing. 761: * 762: * @return An array of files in the directory, or <code>null</code> 763: * if this object does not represent a valid directory. 764: * 765: * @exception SecurityException If read access is not allowed to the 766: * directory by the <code>SecurityManager</code> 767: */ 768: public String[] list(FilenameFilter filter) 769: { 770: checkRead(); 771: 772: if (!exists() || !isDirectory()) 773: return null; 774: 775: // Get the list of files 776: String files[] = VMFile.list(path); 777: 778: // Check if an error occured in listInternal(). 779: if (files == null) 780: return null; 781: 782: if (filter == null) 783: return files; 784: 785: // Apply the filter 786: int count = 0; 787: for (int i = 0; i < files.length; i++) 788: { 789: if (filter.accept(this, files[i])) 790: ++count; 791: else 792: files[i] = null; 793: } 794: 795: String[] retfiles = new String[count]; 796: count = 0; 797: for (int i = 0; i < files.length; i++) 798: if (files[i] != null) 799: retfiles[count++] = files[i]; 800: 801: return retfiles; 802: } 803: 804: /** 805: * This method returns a array of <code>String</code>'s representing the 806: * list of files is then directory represented by this object. If this 807: * object represents a non-directory file or a non-existent file, then 808: * <code>null</code> is returned. The list of files will not contain 809: * any names such as "." or ".." which indicate the current or parent 810: * directory. Also, the names are not guaranteed to be sorted. 811: * <p> 812: * A <code>SecurityManager</code> check is made prior to reading the 813: * directory. If read access to the directory is denied, an exception 814: * will be thrown. 815: * 816: * @return An array of files in the directory, or <code>null</code> if 817: * this object does not represent a valid directory. 818: * 819: * @exception SecurityException If read access is not allowed to the 820: * directory by the <code>SecurityManager</code> 821: */ 822: public String[] list() 823: { 824: return list(null); 825: } 826: 827: /** 828: * This method returns an array of <code>File</code> objects representing 829: * all the files in the directory represented by this object. If this 830: * object does not represent a directory, <code>null</code> is returned. 831: * Each of the returned <code>File</code> object is constructed with this 832: * object as its parent. 833: * <p> 834: * A <code>SecurityManager</code> check is made prior to reading the 835: * directory. If read access to the directory is denied, an exception 836: * will be thrown. 837: * 838: * @return An array of <code>File</code> objects for this directory. 839: * 840: * @exception SecurityException If the <code>SecurityManager</code> denies 841: * access to this directory. 842: * 843: * @since 1.2 844: */ 845: public File[] listFiles() 846: { 847: return listFiles((FilenameFilter) null); 848: } 849: 850: /** 851: * This method returns an array of <code>File</code> objects representing 852: * all the files in the directory represented by this object. If this 853: * object does not represent a directory, <code>null</code> is returned. 854: * Each of the returned <code>File</code> object is constructed with this 855: * object as its parent. 856: * <p> 857: * In this form of the <code>listFiles()</code> method, a filter is specified 858: * that allows the caller to control which files are returned in the 859: * list. The <code>FilenameFilter</code> specified is called for each 860: * file returned to determine whether or not that file should be included 861: * in the list. 862: * <p> 863: * A <code>SecurityManager</code> check is made prior to reading the 864: * directory. If read access to the directory is denied, an exception 865: * will be thrown. 866: * 867: * @return An array of <code>File</code> objects for this directory. 868: * 869: * @exception SecurityException If the <code>SecurityManager</code> denies 870: * access to this directory. 871: * 872: * @since 1.2 873: */ 874: public File[] listFiles(FilenameFilter filter) 875: { 876: String[] filelist = list(filter); 877: 878: if (filelist == null) 879: return null; 880: 881: File[] fobjlist = new File [filelist.length]; 882: 883: for (int i = 0; i < filelist.length; i++) 884: fobjlist [i] = new File(this, filelist [i]); 885: 886: return fobjlist; 887: } 888: 889: /** 890: * This method returns an array of <code>File</code> objects representing 891: * all the files in the directory represented by this object. If this 892: * object does not represent a directory, <code>null</code> is returned. 893: * Each of the returned <code>File</code> object is constructed with this 894: * object as its parent. 895: * <p> 896: * In this form of the <code>listFiles()</code> method, a filter is specified 897: * that allows the caller to control which files are returned in the 898: * list. The <code>FileFilter</code> specified is called for each 899: * file returned to determine whether or not that file should be included 900: * in the list. 901: * <p> 902: * A <code>SecurityManager</code> check is made prior to reading the 903: * directory. If read access to the directory is denied, an exception 904: * will be thrown. 905: * 906: * @return An array of <code>File</code> objects for this directory. 907: * 908: * @exception SecurityException If the <code>SecurityManager</code> denies 909: * access to this directory. 910: * 911: * @since 1.2 912: */ 913: public File[] listFiles(FileFilter filter) 914: { 915: File[] fobjlist = listFiles((FilenameFilter) null); 916: 917: if (fobjlist == null) 918: return null; 919: 920: if (filter == null) 921: return fobjlist; 922: 923: int count = 0; 924: for (int i = 0; i < fobjlist.length; i++) 925: if (filter.accept(fobjlist[i]) == true) 926: ++count; 927: 928: File[] final_list = new File[count]; 929: count = 0; 930: for (int i = 0; i < fobjlist.length; i++) 931: if (filter.accept(fobjlist[i]) == true) 932: { 933: final_list[count] = fobjlist[i]; 934: ++count; 935: } 936: 937: return final_list; 938: } 939: 940: /** 941: * This method returns a <code>String</code> that is the path name of the 942: * file as returned by <code>getPath</code>. 943: * 944: * @return A <code>String</code> representation of this file 945: */ 946: public String toString() 947: { 948: return path; 949: } 950: 951: /** 952: * @return A <code>URI</code> for this object. 953: */ 954: public URI toURI() 955: { 956: String abspath = getAbsolutePath(); 957: 958: if (isDirectory()) 959: abspath = abspath + separatorChar; 960: 961: if (separatorChar == '\\') 962: abspath = separatorChar + abspath; 963: 964: try 965: { 966: return new URI("file", null, null, -1, 967: abspath.replace(separatorChar, '/'), 968: null, null); 969: } 970: catch (URISyntaxException use) 971: { 972: // Can't happen. 973: throw (InternalError) new InternalError("Unconvertible file: " 974: + this).initCause(use); 975: } 976: } 977: 978: /** 979: * This method returns a <code>URL</code> with the <code>file:</code> 980: * protocol that represents this file. The exact form of this URL is 981: * system dependent. 982: * 983: * @return A <code>URL</code> for this object. 984: * 985: * @exception MalformedURLException If the URL cannot be created 986: * successfully. 987: */ 988: public URL toURL() throws MalformedURLException 989: { 990: // On Win32, Sun's JDK returns URLs of the form "file:/c:/foo/bar.txt", 991: // while on UNIX, it returns URLs of the form "file:/foo/bar.txt". 992: if (separatorChar == '\\') 993: return new URL ("file:/" + getAbsolutePath().replace ('\\', '/') 994: + (isDirectory() ? "/" : "")); 995: else 996: return new URL ("file:" + getAbsolutePath() 997: + (isDirectory() ? "/" : "")); 998: } 999: 1000: 1001: /** 1002: * This method creates a directory for the path represented by this object. 1003: * 1004: * @return <code>true</code> if the directory was created, 1005: * <code>false</code> otherwise 1006: * 1007: * @exception SecurityException If write access is not allowed to this file 1008: */ 1009: public boolean mkdir() 1010: { 1011: checkWrite(); 1012: return VMFile.mkdir(path); 1013: } 1014: 1015: /** 1016: * This method creates a directory for the path represented by this file. 1017: * It will also create any intervening parent directories if necessary. 1018: * 1019: * @return <code>true</code> if the directory was created, 1020: * <code>false</code> otherwise 1021: * 1022: * @exception SecurityException If write access is not allowed to this file 1023: */ 1024: public boolean mkdirs() 1025: { 1026: String parent = getParent(); 1027: if (parent == null) 1028: { 1029: return mkdir(); 1030: } 1031: 1032: File f = new File(parent); 1033: if (!f.exists()) 1034: { 1035: boolean rc = f.mkdirs(); 1036: if (rc == false) 1037: return false; 1038: } 1039: 1040: return mkdir(); 1041: } 1042: 1043: /** 1044: * This method creates a temporary file in the specified directory. If 1045: * the directory name is null, then this method uses the system temporary 1046: * directory. The files created are guaranteed not to currently exist and 1047: * the same file name will never be used twice in the same virtual 1048: * machine instance. 1049: * The system temporary directory is determined by examinging the 1050: * <code>java.io.tmpdir</code> system property. 1051: * <p> 1052: * The <code>prefix</code> parameter is a sequence of at least three 1053: * characters that are used as the start of the generated filename. The 1054: * <code>suffix</code> parameter is a sequence of characters that is used 1055: * to terminate the file name. This parameter may be <code>null</code> 1056: * and if it is, the suffix defaults to ".tmp". 1057: * <p> 1058: * If a <code>SecurityManager</code> exists, then its <code>checkWrite</code> 1059: * method is used to verify that this operation is permitted. 1060: * 1061: * @param prefix The character prefix to use in generating the path name. 1062: * @param suffix The character suffix to use in generating the path name. 1063: * @param directory The directory to create the file in, or 1064: * <code>null</code> for the default temporary directory 1065: * 1066: * @exception IllegalArgumentException If the patterns is not valid 1067: * @exception SecurityException If there is no permission to perform 1068: * this operation 1069: * @exception IOException If an error occurs 1070: * 1071: * @since 1.2 1072: */ 1073: public static synchronized File createTempFile(String prefix, String suffix, 1074: File directory) 1075: throws IOException 1076: { 1077: // Grab the system temp directory if necessary 1078: if (directory == null) 1079: { 1080: String dirname = System.getProperty("java.io.tmpdir"); 1081: if (dirname == null) 1082: throw new IOException("Cannot determine system temporary directory"); 1083: 1084: directory = new File(dirname); 1085: if (! VMFile.exists(directory.path)) 1086: throw new IOException("System temporary directory " 1087: + directory.getName() + " does not exist."); 1088: if (! VMFile.isDirectory(directory.path)) 1089: throw new IOException("System temporary directory " 1090: + directory.getName() 1091: + " is not really a directory."); 1092: } 1093: 1094: // Check if prefix is at least 3 characters long 1095: if (prefix.length() < 3) 1096: throw new IllegalArgumentException("Prefix too short: " + prefix); 1097: 1098: // Set default value of suffix 1099: if (suffix == null) 1100: suffix = ".tmp"; 1101: 1102: // Now identify a file name and make sure it doesn't exist. 1103: File file; 1104: if (!VMFile.IS_DOS_8_3) 1105: { 1106: do 1107: { 1108: long now = System.currentTimeMillis(); 1109: if (now > last_tmp) 1110: { 1111: // The last temporary file was created more than 1 ms ago. 1112: last_tmp = now; 1113: n_created = 0; 1114: } 1115: else 1116: n_created++; 1117: 1118: String name = Long.toHexString(now); 1119: if (n_created > 0) 1120: name += '_'+Integer.toHexString(n_created); 1121: String filename = prefix + name + suffix; 1122: file = new File(directory, filename); 1123: } 1124: while (VMFile.exists(file.path)); 1125: } 1126: else 1127: { 1128: // make sure prefix is not longer than 7 characters 1129: if (prefix.length() >= 8) 1130: throw new IllegalArgumentException("Prefix too long: " + prefix + "(valid length 3..7)"); 1131: 1132: long mask = 0x000000ffffFFFFL >> (prefix.length() * 4); 1133: do 1134: { 1135: int n = (int) (System.currentTimeMillis() & mask); 1136: String filename = prefix + java.lang.Integer.toHexString(n) + suffix; 1137: file = new File(directory, filename); 1138: } 1139: while (VMFile.exists(file.path)); 1140: } 1141: 1142: // Verify that we are allowed to create this file 1143: SecurityManager sm = System.getSecurityManager(); 1144: if (sm != null) 1145: sm.checkWrite(file.getAbsolutePath()); 1146: 1147: // Now create the file and return our file object 1148: // XXX - FIXME race condition. 1149: VMFile.create(file.getAbsolutePath()); 1150: return file; 1151: } 1152: 1153: /** 1154: * This method sets the file represented by this object to be read only. 1155: * A read only file or directory cannot be modified. Please note that 1156: * GNU systems allow read only files to be deleted if the directory it 1157: * is contained in is writable. 1158: * 1159: * @return <code>true</code> if the operation succeeded, <code>false</code> 1160: * otherwise. 1161: * 1162: * @exception SecurityException If the <code>SecurityManager</code> does 1163: * not allow this operation. 1164: * 1165: * @since 1.2 1166: */ 1167: public boolean setReadOnly() 1168: { 1169: // Do a security check before trying to do anything else. 1170: checkWrite(); 1171: 1172: // Test for existence. 1173: if (! VMFile.exists(path)) 1174: return false; 1175: 1176: return VMFile.setReadOnly(path); 1177: } 1178: 1179: /** 1180: * This method returns an array of filesystem roots. Some operating systems 1181: * have volume oriented filesystem. This method provides a mechanism for 1182: * determining which volumes exist. GNU systems use a single hierarchical 1183: * filesystem, so will have only one "/" filesystem root. 1184: * 1185: * @return An array of <code>File</code> objects for each filesystem root 1186: * available. 1187: * 1188: * @since 1.2 1189: */ 1190: public static File[] listRoots() 1191: { 1192: return VMFile.listRoots(); 1193: } 1194: 1195: /** 1196: * This method creates a temporary file in the system temporary directory. 1197: * The files created are guaranteed not to currently exist and the same file 1198: * name will never be used twice in the same virtual machine instance. The 1199: * system temporary directory is determined by examinging the 1200: * <code>java.io.tmpdir</code> system property. 1201: * <p> 1202: * The <code>prefix</code> parameter is a sequence of at least three 1203: * characters that are used as the start of the generated filename. The 1204: * <code>suffix</code> parameter is a sequence of characters that is used 1205: * to terminate the file name. This parameter may be <code>null</code> 1206: * and if it is, the suffix defaults to ".tmp". 1207: * <p> 1208: * If a <code>SecurityManager</code> exists, then its <code>checkWrite</code> 1209: * method is used to verify that this operation is permitted. 1210: * <p> 1211: * This method is identical to calling 1212: * <code>createTempFile(prefix, suffix, null)</code>. 1213: * 1214: * @param prefix The character prefix to use in generating the path name. 1215: * @param suffix The character suffix to use in generating the path name. 1216: * 1217: * @exception IllegalArgumentException If the prefix or suffix are not valid. 1218: * @exception SecurityException If there is no permission to perform 1219: * this operation 1220: * @exception IOException If an error occurs 1221: */ 1222: public static File createTempFile(String prefix, String suffix) 1223: throws IOException 1224: { 1225: return createTempFile(prefix, suffix, null); 1226: } 1227: 1228: /** 1229: * This method compares the specified <code>File</code> to this one 1230: * to test for equality. It does this by comparing the canonical path names 1231: * of the files. 1232: * <p> 1233: * The canonical paths of the files are determined by calling the 1234: * <code>getCanonicalPath</code> method on each object. 1235: * <p> 1236: * This method returns a 0 if the specified <code>Object</code> is equal 1237: * to this one, a negative value if it is less than this one 1238: * a positive value if it is greater than this one. 1239: * 1240: * @return An integer as described above 1241: * 1242: * @since 1.2 1243: */ 1244: public int compareTo(File other) 1245: { 1246: if (VMFile.IS_CASE_SENSITIVE) 1247: return path.compareTo (other.path); 1248: else 1249: return path.compareToIgnoreCase (other.path); 1250: } 1251: 1252: /** 1253: * This method compares the specified <code>Object</code> to this one 1254: * to test for equality. It does this by comparing the canonical path names 1255: * of the files. This method is identical to <code>compareTo(File)</code> 1256: * except that if the <code>Object</code> passed to it is not a 1257: * <code>File</code>, it throws a <code>ClassCastException</code> 1258: * <p> 1259: * The canonical paths of the files are determined by calling the 1260: * <code>getCanonicalPath</code> method on each object. 1261: * <p> 1262: * This method returns a 0 if the specified <code>Object</code> is equal 1263: * to this one, a negative value if it is less than this one 1264: * a positive value if it is greater than this one. 1265: * 1266: * @return An integer as described above 1267: * 1268: * @exception ClassCastException If the passed <code>Object</code> is 1269: * not a <code>File</code> 1270: * 1271: * @since 1.2 1272: */ 1273: public int compareTo(Object obj) 1274: { 1275: return compareTo((File) obj); 1276: } 1277: 1278: /** 1279: * This method renames the file represented by this object to the path 1280: * of the file represented by the argument <code>File</code>. 1281: * 1282: * @param dest The <code>File</code> object representing the target name 1283: * 1284: * @return <code>true</code> if the rename succeeds, <code>false</code> 1285: * otherwise. 1286: * 1287: * @exception SecurityException If write access is not allowed to the 1288: * file by the <code>SecurityMananger</code>. 1289: */ 1290: public synchronized boolean renameTo(File dest) 1291: { 1292: checkWrite(); 1293: dest.checkWrite(); 1294: // Call our native rename method 1295: return VMFile.renameTo(path, dest.path); 1296: } 1297: 1298: /** 1299: * This method sets the modification time on the file to the specified 1300: * value. This is specified as the number of seconds since midnight 1301: * on January 1, 1970 GMT. 1302: * 1303: * @param time The desired modification time. 1304: * 1305: * @return <code>true</code> if the operation succeeded, <code>false</code> 1306: * otherwise. 1307: * 1308: * @exception IllegalArgumentException If the specified time is negative. 1309: * @exception SecurityException If the <code>SecurityManager</code> will 1310: * not allow this operation. 1311: * 1312: * @since 1.2 1313: */ 1314: public boolean setLastModified(long time) 1315: { 1316: if (time < 0) 1317: throw new IllegalArgumentException("Negative modification time: " + time); 1318: 1319: checkWrite(); 1320: return VMFile.setLastModified(path, time); 1321: } 1322: 1323: private void checkWrite() 1324: { 1325: // Check the SecurityManager 1326: SecurityManager s = System.getSecurityManager(); 1327: 1328: if (s != null) 1329: s.checkWrite(path); 1330: } 1331: 1332: private void checkRead() 1333: { 1334: // Check the SecurityManager 1335: SecurityManager s = System.getSecurityManager(); 1336: 1337: if (s != null) 1338: s.checkRead(path); 1339: } 1340: 1341: /** 1342: * Calling this method requests that the file represented by this object 1343: * be deleted when the virtual machine exits. Note that this request cannot 1344: * be cancelled. Also, it will only be carried out if the virtual machine 1345: * exits normally. 1346: * 1347: * @exception SecurityException If deleting of the file is not allowed 1348: * 1349: * @since 1.2 1350: */ 1351: public void deleteOnExit() 1352: { 1353: // Check the SecurityManager 1354: SecurityManager sm = System.getSecurityManager(); 1355: if (sm != null) 1356: sm.checkDelete(path); 1357: 1358: DeleteFileHelper.add(this); 1359: } 1360: 1361: private void writeObject(ObjectOutputStream oos) throws IOException 1362: { 1363: oos.defaultWriteObject(); 1364: oos.writeChar(separatorChar); 1365: } 1366: 1367: private void readObject(ObjectInputStream ois) 1368: throws ClassNotFoundException, IOException 1369: { 1370: ois.defaultReadObject(); 1371: 1372: // If the file was from an OS with a different dir separator, 1373: // fixup the path to use the separator on this OS. 1374: char oldSeparatorChar = ois.readChar(); 1375: 1376: if (oldSeparatorChar != separatorChar) 1377: path = path.replace(oldSeparatorChar, separatorChar); 1378: } 1379: 1380: } // class File
GNU Classpath (0.19) |