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