Source for java.io.File

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