001 /* File.java -- Class representing a file on disk 002 Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 003 Free Software Foundation, Inc. 004 005 This file is part of GNU Classpath. 006 007 GNU Classpath is free software; you can redistribute it and/or modify 008 it under the terms of the GNU General Public License as published by 009 the Free Software Foundation; either version 2, or (at your option) 010 any later version. 011 012 GNU Classpath is distributed in the hope that it will be useful, but 013 WITHOUT ANY WARRANTY; without even the implied warranty of 014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 General Public License for more details. 016 017 You should have received a copy of the GNU General Public License 018 along with GNU Classpath; see the file COPYING. If not, write to the 019 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 020 02110-1301 USA. 021 022 Linking this library statically or dynamically with other modules is 023 making a combined work based on this library. Thus, the terms and 024 conditions of the GNU General Public License cover the whole 025 combination. 026 027 As a special exception, the copyright holders of this library give you 028 permission to link this library with independent modules to produce an 029 executable, regardless of the license terms of these independent 030 modules, and to copy and distribute the resulting executable under 031 terms of your choice, provided that you also meet, for each linked 032 independent module, the terms and conditions of the license of that 033 module. An independent module is a module which is not derived from 034 or based on this library. If you modify this library, you may extend 035 this exception to your version of the library, but you are not 036 obligated to do so. If you do not wish to do so, delete this 037 exception statement from your version. */ 038 039 040 package java.io; 041 042 import java.net.MalformedURLException; 043 import java.net.URI; 044 import java.net.URISyntaxException; 045 import java.net.URL; 046 import gnu.classpath.Configuration; 047 048 /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 049 * "The Java Language Specification", ISBN 0-201-63451-1 050 * Status: Complete to version 1.3. 051 */ 052 053 /** 054 * This class represents a file or directory on a local disk. It provides 055 * facilities for dealing with a variety of systems that use various 056 * types of path separators ("/" versus "\", for example). It also 057 * contains method useful for creating and deleting files and directories. 058 * 059 * @author Aaron M. Renn (arenn@urbanophile.com) 060 * @author Tom Tromey (tromey@cygnus.com) 061 */ 062 public class File implements Serializable, Comparable<File> 063 { 064 private static final long serialVersionUID = 301077366599181567L; 065 066 // QUERY arguments to access function. 067 private final static int READ = 0; 068 private final static int WRITE = 1; 069 private final static int EXISTS = 2; 070 private final static int EXEC = 3; 071 072 // QUERY arguments to stat function. 073 private final static int DIRECTORY = 0; 074 private final static int ISFILE = 1; 075 private final static int ISHIDDEN = 2; 076 077 // QUERY arguments to attr function. 078 private final static int MODIFIED = 0; 079 private final static int LENGTH = 1; 080 081 private final native long attr (int query); 082 // On OSF1 V5.0, `stat' is a macro. It is easiest to use the name 083 // `_stat' instead. We do the same thing for `_access' just in 084 // case. 085 private final native boolean _access (int query); 086 private final native boolean _stat (int query); 087 088 /** 089 * This is the path separator string for the current host. This field 090 * contains the value of the <code>file.separator</code> system property. 091 * An example separator string would be "/" on the GNU system. 092 */ 093 public static final String separator = System.getProperty("file.separator"); 094 private static final String dupSeparator = separator + separator; 095 096 /** 097 * This is the first character of the file separator string. On many 098 * hosts (for example, on the GNU system), this represents the entire 099 * 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 1579