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