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