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