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