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 gnu.java.lang.CPStringBuilder;
  45: 
  46: import java.net.MalformedURLException;
  47: import java.net.URI;
  48: import java.net.URISyntaxException;
  49: import java.net.URL;
  50: 
  51: /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
  52:  * "The Java Language Specification", ISBN 0-201-63451-1
  53:  * Status:  Complete to version 1.3.
  54:  */
  55: 
  56: /**
  57:  * This class represents a file or directory on a local disk.  It provides
  58:  * facilities for dealing with a variety of systems that use various
  59:  * types of path separators ("/" versus "\", for example).  It also
  60:  * contains method useful for creating and deleting files and directories.
  61:  *
  62:  * @author Aaron M. Renn (arenn@urbanophile.com)
  63:  * @author Tom Tromey (tromey@cygnus.com)
  64:  */
  65: public class File implements Serializable, Comparable<File>
  66: {
  67:   private static final long serialVersionUID = 301077366599181567L;
  68: 
  69:   /**
  70:    * This is the path separator string for the current host. This field
  71:    * contains the value of the <code>file.separator</code> system property.
  72:    * An example separator string would be "/" on the GNU system.
  73:    */
  74:   public static final String separator = SystemProperties.getProperty("file.separator");
  75:   private static final String dupSeparator = separator + separator;
  76: 
  77:   /**
  78:    * This is the first character of the file separator string.  On many
  79:    * hosts (for example, on the GNU system), this represents the entire 
  80:    * separator string.  The complete separator string is obtained from the
  81:    * <code>file.separator</code>system property.
  82:    */
  83:   public static final char separatorChar = separator.charAt(0);
  84:   
  85:   /**
  86:    * This is the string that is used to separate the host name from the
  87:    * path name in paths that include the host name.  It is the value of
  88:    * the <code>path.separator</code> system property.
  89:    */
  90:   public static final String pathSeparator
  91:     = SystemProperties.getProperty("path.separator");
  92:   
  93:   /**
  94:    * This is the first character of the string used to separate the host name
  95:    * from the path name in paths that include a host.  The separator string
  96:    * is taken from the <code>path.separator</code> system property.
  97:    */
  98:   public static final char pathSeparatorChar = pathSeparator.charAt(0);
  99: 
 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:    *
 704:    * @since 1.2
 705:    */
 706:   public boolean isHidden()
 707:   {
 708:     return VMFile.isHidden(path);
 709:   }
 710: 
 711:   /**
 712:    * This method returns the last modification time of this file.  The
 713:    * time value returned is an abstract value that should not be interpreted
 714:    * as a specified time value.  It is only useful for comparing to other
 715:    * such time values returned on the same system.  In that case, the larger
 716:    * value indicates a more recent modification time. 
 717:    * <p>
 718:    * If the file does not exist, then a value of 0 is returned.
 719:    *
 720:    * @return The last modification time of the file
 721:    *
 722:    * @exception SecurityException If reading of the file is not permitted
 723:    */
 724:   public long lastModified()
 725:   {
 726:     checkRead();
 727:     return VMFile.lastModified(path);
 728:   }
 729: 
 730:   /**
 731:    * This method returns the length of the file represented by this object,
 732:    * or 0 if the specified file does not exist.
 733:    *
 734:    * @return The length of the file
 735:    *
 736:    * @exception SecurityException If reading of the file is not permitted
 737:    */
 738:   public long length()
 739:   {
 740:     checkRead();
 741:     return VMFile.length(path);
 742:   }
 743: 
 744:   /**
 745:    * This method returns a array of <code>String</code>'s representing the
 746:    * list of files is then directory represented by this object.  If this
 747:    * object represents a non-directory file or a non-existent file, then
 748:    * <code>null</code> is returned.  The list of files will not contain
 749:    * any names such as "." or ".." which indicate the current or parent
 750:    * directory.  Also, the names are not guaranteed to be sorted.
 751:    * <p>
 752:    * In this form of the <code>list()</code> method, a filter is specified
 753:    * that allows the caller to control which files are returned in the
 754:    * list.  The <code>FilenameFilter</code> specified is called for each
 755:    * file returned to determine whether or not that file should be included
 756:    * in the list.
 757:    * <p>
 758:    * A <code>SecurityManager</code> check is made prior to reading the
 759:    * directory.  If read access to the directory is denied, an exception
 760:    * will be thrown.
 761:    *
 762:    * @param filter An object which will identify files to exclude from 
 763:    * the directory listing.
 764:    *
 765:    * @return An array of files in the directory, or <code>null</code> 
 766:    * if this object does not represent a valid directory.
 767:    * 
 768:    * @exception SecurityException If read access is not allowed to the 
 769:    * directory by the <code>SecurityManager</code>
 770:    */
 771:   public String[] list(FilenameFilter filter)
 772:   {
 773:     checkRead();
 774: 
 775:     if (!exists() || !isDirectory())
 776:       return null;
 777:     
 778:     // Get the list of files
 779:     String files[] = VMFile.list(path);
 780:     
 781:     // Check if an error occured in listInternal().
 782:     // This is an unreadable directory, pretend there is nothing inside.
 783:     if (files == null)
 784:       return new String[0];
 785: 
 786:     if (filter == null)
 787:       return files;
 788:     
 789:     // Apply the filter
 790:     int count = 0;
 791:     for (int i = 0; i < files.length; i++)
 792:       {
 793:         if (filter.accept(this, files[i]))
 794:         ++count;
 795:         else
 796:         files[i] = null;
 797:       }
 798: 
 799:     String[] retfiles = new String[count];
 800:     count = 0;
 801:     for (int i = 0; i < files.length; i++)
 802:       if (files[i] != null)
 803:         retfiles[count++] = files[i];
 804: 
 805:     return retfiles;
 806:   }
 807: 
 808:   /**
 809:    * This method returns a array of <code>String</code>'s representing the
 810:    * list of files is then directory represented by this object.  If this
 811:    * object represents a non-directory file or a non-existent file, then
 812:    * <code>null</code> is returned.  The list of files will not contain
 813:    * any names such as "." or ".." which indicate the current or parent
 814:    * directory.  Also, the names are not guaranteed to be sorted.
 815:    * <p>
 816:    * A <code>SecurityManager</code> check is made prior to reading the
 817:    * directory.  If read access to the directory is denied, an exception
 818:    * will be thrown.
 819:    *
 820:    * @return An array of files in the directory, or <code>null</code> if 
 821:    * this object does not represent a valid directory.
 822:    * 
 823:    * @exception SecurityException If read access is not allowed to the 
 824:    * directory by the <code>SecurityManager</code>
 825:    */
 826:   public String[] list()
 827:   {
 828:     return list(null);
 829:   }
 830: 
 831:   /**
 832:    * This method returns an array of <code>File</code> objects representing
 833:    * all the files in the directory represented by this object. If this
 834:    * object does not represent a directory, <code>null</code> is returned.
 835:    * Each of the returned <code>File</code> object is constructed with this
 836:    * object as its parent.
 837:    * <p>
 838:    * A <code>SecurityManager</code> check is made prior to reading the
 839:    * directory.  If read access to the directory is denied, an exception
 840:    * will be thrown.
 841:    *
 842:    * @return An array of <code>File</code> objects for this directory.
 843:    *
 844:    * @exception SecurityException If the <code>SecurityManager</code> denies
 845:    * access to this directory.
 846:    *
 847:    * @since 1.2
 848:    */
 849:   public File[] listFiles()
 850:   {
 851:     return listFiles((FilenameFilter) null);
 852:   }
 853:   
 854:   /**
 855:    * This method returns an array of <code>File</code> objects representing
 856:    * all the files in the directory represented by this object. If this
 857:    * object does not represent a directory, <code>null</code> is returned.
 858:    * Each of the returned <code>File</code> object is constructed with this
 859:    * object as its parent.
 860:    * <p> 
 861:    * In this form of the <code>listFiles()</code> method, a filter is specified
 862:    * that allows the caller to control which files are returned in the
 863:    * list.  The <code>FilenameFilter</code> specified is called for each
 864:    * file returned to determine whether or not that file should be included
 865:    * in the list.
 866:    * <p>
 867:    * A <code>SecurityManager</code> check is made prior to reading the
 868:    * directory.  If read access to the directory is denied, an exception
 869:    * will be thrown.
 870:    *
 871:    * @return An array of <code>File</code> objects for this directory.
 872:    *
 873:    * @exception SecurityException If the <code>SecurityManager</code> denies
 874:    * access to this directory.
 875:    *
 876:    * @since 1.2
 877:    */
 878:   public File[] listFiles(FilenameFilter filter)
 879:   {
 880:     String[] filelist = list(filter);
 881:     
 882:     if (filelist == null)
 883:       return null;
 884: 
 885:     File[] fobjlist = new File [filelist.length];
 886: 
 887:     for (int i = 0; i < filelist.length; i++)
 888:       fobjlist [i] = new File(this, filelist [i]);
 889: 
 890:     return fobjlist;
 891:   }
 892: 
 893:   /**
 894:    * This method returns an array of <code>File</code> objects representing
 895:    * all the files in the directory represented by this object. If this
 896:    * object does not represent a directory, <code>null</code> is returned.
 897:    * Each of the returned <code>File</code> object is constructed with this
 898:    * object as its parent.
 899:    * <p> 
 900:    * In this form of the <code>listFiles()</code> method, a filter is specified
 901:    * that allows the caller to control which files are returned in the
 902:    * list.  The <code>FileFilter</code> specified is called for each
 903:    * file returned to determine whether or not that file should be included
 904:    * in the list.
 905:    * <p>
 906:    * A <code>SecurityManager</code> check is made prior to reading the
 907:    * directory.  If read access to the directory is denied, an exception
 908:    * will be thrown.
 909:    *
 910:    * @return An array of <code>File</code> objects for this directory.
 911:    *
 912:    * @exception SecurityException If the <code>SecurityManager</code> denies
 913:    * access to this directory.
 914:    *
 915:    * @since 1.2
 916:    */
 917:   public File[] listFiles(FileFilter filter)
 918:   {
 919:     File[] fobjlist = listFiles((FilenameFilter) null);
 920: 
 921:     if (fobjlist == null)
 922:       return null;
 923: 
 924:     if (filter == null)
 925:       return fobjlist;
 926: 
 927:     int count = 0;
 928:     for (int i = 0; i < fobjlist.length; i++)
 929:       if (filter.accept(fobjlist[i]) == true)
 930:         ++count;
 931: 
 932:     File[] final_list = new File[count];
 933:     count = 0;
 934:     for (int i = 0; i < fobjlist.length; i++)
 935:       if (filter.accept(fobjlist[i]) == true)
 936:         {
 937:           final_list[count] = fobjlist[i];
 938:           ++count;
 939:         }
 940: 
 941:     return final_list;
 942:   }
 943: 
 944:   /**
 945:    * This method returns a <code>String</code> that is the path name of the
 946:    * file as returned by <code>getPath</code>.
 947:    *
 948:    * @return A <code>String</code> representation of this file
 949:    */
 950:   public String toString()
 951:   {
 952:     return path;
 953:   }
 954: 
 955:   /**
 956:    * @return A <code>URI</code> for this object.
 957:    */
 958:   public URI toURI()
 959:   {
 960:     String abspath = getAbsolutePath();
 961:        
 962:     if (isDirectory() || path.equals(""))
 963:       abspath = abspath + separatorChar;
 964: 
 965:     if (separatorChar == '\\')
 966:       abspath = separatorChar + abspath;
 967:         
 968:     try
 969:       {
 970:         return new URI("file", null, null, -1,
 971:                        abspath.replace(separatorChar, '/'),
 972:                        null, null);
 973:       }
 974:     catch (URISyntaxException use)
 975:       {
 976:         // Can't happen.
 977:         throw (InternalError) new InternalError("Unconvertible file: "
 978:                         + this).initCause(use);
 979:       }
 980:   }
 981: 
 982:   /**
 983:    * This method returns a <code>URL</code> with the <code>file:</code>
 984:    * protocol that represents this file.  The exact form of this URL is
 985:    * system dependent.
 986:    *
 987:    * @return A <code>URL</code> for this object.
 988:    *
 989:    * @exception MalformedURLException If the URL cannot be created 
 990:    * successfully.
 991:    */
 992:   public URL toURL() throws MalformedURLException
 993:   {
 994:     return VMFile.toURL(this);
 995:   }
 996: 
 997: 
 998:   /**
 999:    * This method creates a directory for the path represented by this object.
1000:    *
1001:    * @return <code>true</code> if the directory was created, 
1002:    * <code>false</code> otherwise
1003:    *
1004:    * @exception SecurityException If write access is not allowed to this file
1005:    */
1006:   public boolean mkdir()
1007:   {
1008:     checkWrite();
1009:     return VMFile.mkdir(path);
1010:   }
1011: 
1012:   /**
1013:    * This method creates a directory for the path represented by this file.
1014:    * It will also create any intervening parent directories if necessary.
1015:    *
1016:    * @return <code>true</code> if the directory was created, 
1017:    * <code>false</code> otherwise
1018:    *
1019:    * @exception SecurityException If write access is not allowed to this file
1020:    */
1021:   public boolean mkdirs()
1022:   {
1023:     String parent = getParent();
1024:     if (parent == null)
1025:       {
1026:         return mkdir();
1027:       }
1028:       
1029:     File f = new File(parent);
1030:     if (!f.exists())
1031:       {
1032:         boolean rc = f.mkdirs();
1033:         if (rc == false)
1034:           return false;
1035:       }
1036: 
1037:     return mkdir();
1038:   }
1039: 
1040:   /**
1041:    * This method creates a temporary file in the specified directory.  If 
1042:    * the directory name is null, then this method uses the system temporary 
1043:    * directory. The files created are guaranteed not to currently exist and 
1044:    * the same file name will never be used twice in the same virtual 
1045:    * machine instance.  
1046:    * The system temporary directory is determined by examinging the 
1047:    * <code>java.io.tmpdir</code> system property.
1048:    * <p>
1049:    * The <code>prefix</code> parameter is a sequence of at least three
1050:    * characters that are used as the start of the generated filename.  The
1051:    * <code>suffix</code> parameter is a sequence of characters that is used
1052:    * to terminate the file name.  This parameter may be <code>null</code>
1053:    * and if it is, the suffix defaults to ".tmp".
1054:    * <p>
1055:    * If a <code>SecurityManager</code> exists, then its <code>checkWrite</code>
1056:    * method is used to verify that this operation is permitted.
1057:    *
1058:    * @param prefix The character prefix to use in generating the path name.
1059:    * @param suffix The character suffix to use in generating the path name.
1060:    * @param directory The directory to create the file in, or 
1061:    * <code>null</code> for the default temporary directory
1062:    *
1063:    * @exception IllegalArgumentException If the patterns is not valid
1064:    * @exception SecurityException If there is no permission to perform 
1065:    * this operation
1066:    * @exception IOException If an error occurs
1067:    *
1068:    * @since 1.2
1069:    */
1070:   public static synchronized File createTempFile(String prefix, String suffix,
1071:                     File directory)
1072:     throws IOException
1073:   {
1074:     // Grab the system temp directory if necessary
1075:     if (directory == null)
1076:       {
1077:         String dirname = System.getProperty("java.io.tmpdir");
1078:         if (dirname == null)
1079:           throw new IOException("Cannot determine system temporary directory"); 
1080:     
1081:         directory = new File(dirname);
1082:         if (! VMFile.exists(directory.path))
1083:           throw new IOException("System temporary directory "
1084:                                 + directory.getName() + " does not exist.");
1085:         if (! VMFile.isDirectory(directory.path))
1086:           throw new IOException("System temporary directory "
1087:                                 + directory.getName()
1088:                                 + " is not really a directory.");
1089:       }
1090: 
1091:     // Check if prefix is at least 3 characters long
1092:     if (prefix.length() < 3)
1093:       throw new IllegalArgumentException("Prefix too short: " + prefix);
1094: 
1095:     // Set default value of suffix
1096:     if (suffix == null)
1097:       suffix = ".tmp";
1098: 
1099:     // Now identify a file name and make sure it doesn't exist.
1100:     File file;
1101:     if (!VMFile.IS_DOS_8_3)
1102:       { 
1103:         do
1104:           {
1105:             long now = System.currentTimeMillis();
1106:             if (now > last_tmp)
1107:               {
1108:                 // The last temporary file was created more than 1 ms ago.
1109:                 last_tmp = now;
1110:                 n_created = 0;
1111:               }
1112:             else
1113:               n_created++;
1114:             
1115:             String name = Long.toHexString(now);
1116:             if (n_created > 0)
1117:               name += '_'+Integer.toHexString(n_created);
1118:             String filename = prefix + name + suffix;
1119:             file = new File(directory, filename);
1120:           }
1121:         while (VMFile.exists(file.path));
1122:       }
1123:     else
1124:       {
1125:         // make sure prefix is not longer than 7 characters
1126:         if (prefix.length() >= 8)
1127:           throw new IllegalArgumentException("Prefix too long: " + prefix + "(valid length 3..7)");
1128: 
1129:         long mask = 0x000000ffffFFFFL >> (prefix.length() * 4);
1130:         do
1131:           {
1132:             int n = (int) (System.currentTimeMillis() & mask);
1133:             String filename = prefix + java.lang.Integer.toHexString(n) + suffix;
1134:             file = new File(directory, filename);
1135:           }
1136:         while (VMFile.exists(file.path));
1137:       }
1138: 
1139:     // Verify that we are allowed to create this file
1140:     SecurityManager sm = System.getSecurityManager();
1141:     if (sm != null)
1142:       sm.checkWrite(file.getAbsolutePath());
1143: 
1144:     // Now create the file and return our file object
1145:     // XXX - FIXME race condition.
1146:     VMFile.create(file.getAbsolutePath()); 
1147:     return file;
1148:   }
1149: 
1150:   /**
1151:    * This method sets the owner's read permission for the File represented by
1152:    * this object.
1153:    * 
1154:    * It is the same as calling <code>setReadable(readable, true)</code>.
1155:    * 
1156:    * @param <code>readable</code> <code>true</code> to set read permission,
1157:    * <code>false</code> to unset the read permission.
1158:    * @return <code>true</code> if the file permissions are changed,
1159:    * <code>false</code> otherwise.
1160:    * @exception SecurityException If write access of the file is not permitted.
1161:    * @see #setReadable(boolean, boolean)
1162:    * @since 1.6
1163:    */
1164:   public boolean setReadable(boolean readable)
1165:   {
1166:     return setReadable(readable, true);
1167:   }
1168:   
1169:   /**
1170:    * This method sets the read permissions for the File represented by
1171:    * this object.
1172:    * 
1173:    * If <code>ownerOnly</code> is set to <code>true</code> then only the
1174:    * read permission bit for the owner of the file is changed.
1175:    * 
1176:    * If <code>ownerOnly</code> is set to <code>false</code>, the file
1177:    * permissions are changed so that the file can be read by everyone.
1178:    * 
1179:    * On unix like systems this sets the <code>user</code>, <code>group</code>
1180:    * and <code>other</code> read bits and is equal to call
1181:    * <code>chmod a+r</code> on the file.
1182:    * 
1183:    * @param <code>readable</code> <code>true</code> to set read permission,
1184:    * <code>false</code> to unset the read permission.
1185:    * @param <code>ownerOnly</code> <code>true</code> to set read permission
1186:    * for owner only, <code>false</code> for all.
1187:    * @return <code>true</code> if the file permissions are changed,
1188:    * <code>false</code> otherwise.
1189:    * @exception SecurityException If write access of the file is not permitted.
1190:    * @see #setReadable(boolean)
1191:    * @since 1.6
1192:    */
1193:   public boolean setReadable(boolean readable, boolean ownerOnly)
1194:   {
1195:     checkWrite();
1196:     return VMFile.setReadable(path, readable, ownerOnly);
1197:   }
1198:   
1199:   /**
1200:    * This method sets the owner's write permission for the File represented by
1201:    * this object.
1202:    * 
1203:    * It is the same as calling <code>setWritable(readable, true)</code>. 
1204:    * 
1205:    * @param <code>writable</code> <code>true</code> to set write permission,
1206:    * <code>false</code> to unset write permission.
1207:    * @return <code>true</code> if the file permissions are changed,
1208:    * <code>false</code> otherwise.
1209:    * @exception SecurityException If write access of the file is not permitted.
1210:    * @see #setWritable(boolean, boolean)
1211:    * @since 1.6
1212:    */
1213:   public boolean setWritable(boolean writable)
1214:   {
1215:     return setWritable(writable, true);
1216:   }
1217:   
1218:   /**
1219:    * This method sets the write permissions for the File represented by
1220:    * this object.
1221:    * 
1222:    * If <code>ownerOnly</code> is set to <code>true</code> then only the
1223:    * write permission bit for the owner of the file is changed.
1224:    * 
1225:    * If <code>ownerOnly</code> is set to <code>false</code>, the file
1226:    * permissions are changed so that the file can be written by everyone.
1227:    * 
1228:    * On unix like systems this set the <code>user</code>, <code>group</code>
1229:    * and <code>other</code> write bits and is equal to call
1230:    * <code>chmod a+w</code> on the file.
1231:    * 
1232:    * @param <code>writable</code> <code>true</code> to set write permission,
1233:    * <code>false</code> to unset write permission.
1234:    * @param <code>ownerOnly</code> <code>true</code> to set write permission
1235:    * for owner only, <code>false</code> for all. 
1236:    * @return <code>true</code> if the file permissions are changed,
1237:    * <code>false</code> otherwise.
1238:    * @exception SecurityException If write access of the file is not permitted.
1239:    * @see #setWritable(boolean)
1240:    * @since 1.6
1241:    */
1242:   public boolean setWritable(boolean writable, boolean ownerOnly)
1243:   {
1244:     checkWrite();
1245:     return VMFile.setWritable(path, writable, ownerOnly);
1246:   }
1247:   
1248:   /**
1249:    * This method sets the owner's execute permission for the File represented
1250:    * by this object.
1251:    * 
1252:    * It is the same as calling <code>setExecutable(readable, true)</code>. 
1253:    * 
1254:    * @param <code>executable</code> <code>true</code> to set execute permission,
1255:    * <code>false</code> to unset execute permission.
1256:    * @return <code>true</code> if the file permissions are changed,
1257:    * <code>false</code> otherwise.
1258:    * @exception SecurityException If write access of the file is not permitted.
1259:    * @see #setExecutable(boolean, boolean)
1260:    * @since 1.6
1261:    */
1262:   public boolean setExecutable(boolean executable) 
1263:   {
1264:     return setExecutable(executable, true);
1265:   }
1266:   
1267:   /**
1268:    * This method sets the execute permissions for the File represented by
1269:    * this object.
1270:    * 
1271:    * If <code>ownerOnly</code> is set to <code>true</code> then only the
1272:    * execute permission bit for the owner of the file is changed.
1273:    * 
1274:    * If <code>ownerOnly</code> is set to <code>false</code>, the file
1275:    * permissions are changed so that the file can be executed by everyone.
1276:    * 
1277:    * On unix like systems this set the <code>user</code>, <code>group</code>
1278:    * and <code>other</code> write bits and is equal to call
1279:    * <code>chmod a+x</code> on the file.
1280:    * 
1281:    * @param <code>executable</code> <code>true</code> to set write permission,
1282:    * <code>false</code> to unset write permission.
1283:    * @param <code>ownerOnly</code> <code>true</code> to set write permission
1284:    * for owner only, <code>false</code> for all. 
1285:    * @return <code>true</code> if the file permissions are changed,
1286:    * <code>false</code> otherwise.
1287:    * @exception SecurityException If write access of the file is not permitted.
1288:    * @see #setExecutable(boolean)
1289:    * @since 1.6
1290:    */
1291:   public boolean setExecutable(boolean executable, boolean ownerOnly)
1292:   {
1293:     checkWrite();
1294:     return VMFile.setExecutable(path, executable, ownerOnly);
1295:   }
1296: 
1297:   /**
1298:    * Get the total space for the partition pointed by this file path, in bytes.
1299:    * 
1300:    * @return the total number of bytes in this partition. 
1301:    * @since 1.6
1302:    */
1303:   public long getTotalSpace()
1304:   {
1305:     // check security manager.
1306:     SecurityManager s = System.getSecurityManager();
1307:     if (s != null)
1308:       s.checkPermission(new RuntimePermission("getFileSystemAttributes"));
1309:     checkRead();
1310:     
1311:     return VMFile.getTotalSpace(path);
1312:   }
1313:   
1314:   /**
1315:    * Get the free space in the partition pointed by this file path, in bytes.
1316:    * 
1317:    * @return the number of free bytes in this partition. 
1318:    * @since 1.6
1319:    */
1320:   public long getFreeSpace()
1321:   {
1322:     // check security manager.
1323:     SecurityManager s = System.getSecurityManager();
1324:     if (s != null)
1325:       s.checkPermission(new RuntimePermission("getFileSystemAttributes"));
1326:     checkRead();
1327:     
1328:     return VMFile.getFreeSpace(path);
1329:   }
1330:   
1331:   /**
1332:    * Get the usable space in the partition pointed by this file path, in bytes.
1333:    * This is not necessarily the same as the number returned by
1334:    * {@link #getFreeSpace()}.
1335:    * 
1336:    * <strong>Implementation note</strong>: Unlike the RI, on Linux and UNIX
1337:    * like systems this methods take into account the reserved space for the
1338:    * "root" user. This means that the returned results will be a little
1339:    * different if a normal user or root perform the query.
1340:    * 
1341:    * Also, the bytes returned should be interpreted as an hint, and may be
1342:    * different at each call of this method or even right after the method
1343:    * returns.
1344:    * 
1345:    * @return the number of usable bytes in this partition. 
1346:    * @since 1.6
1347:    */
1348:   public long getUsableSpace()
1349:   {
1350:     // check security manager.
1351:     SecurityManager s = System.getSecurityManager();
1352:     if (s != null)
1353:       s.checkPermission(new RuntimePermission("getFileSystemAttributes"));
1354:     checkRead();
1355:     
1356:     // root users can use the reserved extra space
1357:     String user = System.getProperty("user.name");
1358:     if (user != null && user.equals("root"))
1359:       return VMFile.getFreeSpace(path);
1360:     
1361:     return VMFile.getUsableSpace(path);
1362:   }
1363:   
1364:   /**
1365:    * This method sets the file represented by this object to be read only.
1366:    * A read only file or directory cannot be modified.  Please note that 
1367:    * GNU systems allow read only files to be deleted if the directory it
1368:    * is contained in is writable.
1369:    *
1370:    * @return <code>true</code> if the operation succeeded, <code>false</code>
1371:    * otherwise.
1372:    *
1373:    * @exception SecurityException If the <code>SecurityManager</code> does
1374:    * not allow this operation.
1375:    *
1376:    * @since 1.2
1377:    */
1378:   public boolean setReadOnly()
1379:   {
1380:     // Do a security check before trying to do anything else.
1381:     checkWrite();
1382: 
1383:     // Test for existence.
1384:     if (! VMFile.exists(path))
1385:       return false;
1386: 
1387:     return VMFile.setReadOnly(path);
1388:   }
1389: 
1390:   /**
1391:    * This method returns an array of filesystem roots.  Some operating systems
1392:    * have volume oriented filesystem.  This method provides a mechanism for
1393:    * determining which volumes exist.  GNU systems use a single hierarchical
1394:    * filesystem, so will have only one "/" filesystem root.
1395:    *
1396:    * @return An array of <code>File</code> objects for each filesystem root
1397:    * available.
1398:    *
1399:    * @since 1.2
1400:    */
1401:   public static File[] listRoots()
1402:   {
1403:     File[] roots = VMFile.listRoots();
1404:     
1405:     SecurityManager s = System.getSecurityManager();
1406:     if (s != null)
1407:       {
1408:     // Only return roots to which the security manager permits read access.
1409:     int count = roots.length;
1410:     for (int i = 0; i < roots.length; i++)
1411:       {
1412:         try
1413:           {
1414:             s.checkRead (roots[i].path);        
1415:           }
1416:         catch (SecurityException sx)
1417:           {
1418:             roots[i] = null;
1419:         count--;
1420:           }
1421:       }
1422:     if (count != roots.length)
1423:       {
1424:         File[] newRoots = new File[count];
1425:         int k = 0;
1426:         for (int i = 0; i < roots.length; i++)
1427:           {
1428:             if (roots[i] != null)
1429:           newRoots[k++] = roots[i];
1430:           }
1431:         roots = newRoots;
1432:       }
1433:       }
1434:     return roots;
1435:   }
1436: 
1437:   /**
1438:    * This method creates a temporary file in the system temporary directory. 
1439:    * The files created are guaranteed not to currently exist and the same file
1440:    * name will never be used twice in the same virtual machine instance.  The
1441:    * system temporary directory is determined by examinging the 
1442:    * <code>java.io.tmpdir</code> system property.
1443:    * <p>
1444:    * The <code>prefix</code> parameter is a sequence of at least three
1445:    * characters that are used as the start of the generated filename.  The
1446:    * <code>suffix</code> parameter is a sequence of characters that is used
1447:    * to terminate the file name.  This parameter may be <code>null</code>
1448:    * and if it is, the suffix defaults to ".tmp".
1449:    * <p>
1450:    * If a <code>SecurityManager</code> exists, then its <code>checkWrite</code>
1451:    * method is used to verify that this operation is permitted.
1452:    * <p>
1453:    * This method is identical to calling 
1454:    * <code>createTempFile(prefix, suffix, null)</code>.
1455:    *
1456:    * @param prefix The character prefix to use in generating the path name.
1457:    * @param suffix The character suffix to use in generating the path name.
1458:    *
1459:    * @exception IllegalArgumentException If the prefix or suffix are not valid.
1460:    * @exception SecurityException If there is no permission to perform 
1461:    * this operation
1462:    * @exception IOException If an error occurs
1463:    */
1464:   public static File createTempFile(String prefix, String suffix)
1465:     throws IOException
1466:   {
1467:     return createTempFile(prefix, suffix, null);
1468:   }
1469: 
1470:   /**
1471:    * This method compares the specified <code>File</code> to this one
1472:    * to test for equality.  It does this by comparing the canonical path names
1473:    * of the files. 
1474:    * <p>
1475:    * The canonical paths of the files are determined by calling the
1476:    * <code>getCanonicalPath</code> method on each object.
1477:    * <p>
1478:    * This method returns a 0 if the specified <code>Object</code> is equal
1479:    * to this one, a negative value if it is less than this one 
1480:    * a positive value if it is greater than this one.
1481:    *
1482:    * @return An integer as described above
1483:    *
1484:    * @since 1.2
1485:    */
1486:   public int compareTo(File other)
1487:   {
1488:     if (VMFile.IS_CASE_SENSITIVE)
1489:       return path.compareTo (other.path);
1490:     else
1491:       return path.compareToIgnoreCase (other.path);
1492:   }
1493: 
1494:   /**
1495:    * This method renames the file represented by this object to the path
1496:    * of the file represented by the argument <code>File</code>.
1497:    *
1498:    * @param dest The <code>File</code> object representing the target name
1499:    *
1500:    * @return <code>true</code> if the rename succeeds, <code>false</code> 
1501:    * otherwise.
1502:    *
1503:    * @exception SecurityException If write access is not allowed to the 
1504:    * file by the <code>SecurityMananger</code>.
1505:    */
1506:   public synchronized boolean renameTo(File dest)
1507:   {
1508:     checkWrite();
1509:     dest.checkWrite();
1510:     // Call our native rename method
1511:     return VMFile.renameTo(path, dest.path);
1512:   }
1513: 
1514:   /**
1515:    * This method sets the modification time on the file to the specified
1516:    * value.  This is specified as the number of seconds since midnight
1517:    * on January 1, 1970 GMT.
1518:    *
1519:    * @param time The desired modification time.
1520:    *
1521:    * @return <code>true</code> if the operation succeeded, <code>false</code>
1522:    * otherwise.
1523:    *
1524:    * @exception IllegalArgumentException If the specified time is negative.
1525:    * @exception SecurityException If the <code>SecurityManager</code> will
1526:    * not allow this operation.
1527:    *
1528:    * @since 1.2
1529:    */
1530:   public boolean setLastModified(long time) 
1531:   {
1532:     if (time < 0)
1533:       throw new IllegalArgumentException("Negative modification time: " + time);
1534: 
1535:     checkWrite();
1536:     return VMFile.setLastModified(path, time);
1537:   }
1538: 
1539:   private void checkWrite()
1540:   {
1541:     // Check the SecurityManager
1542:     SecurityManager s = System.getSecurityManager();
1543:     
1544:     if (s != null)
1545:       s.checkWrite(path);
1546:   }
1547: 
1548:   private void checkRead()
1549:   {
1550:     // Check the SecurityManager
1551:     SecurityManager s = System.getSecurityManager();
1552:     
1553:     if (s != null)
1554:       s.checkRead(path);
1555:   }
1556: 
1557:   private void checkExec()
1558:   {
1559:     // Check the SecurityManager
1560:     SecurityManager s = System.getSecurityManager();
1561:     
1562:     if (s != null)
1563:       s.checkExec(path);
1564:   }
1565:   
1566:   /** 
1567:    * Calling this method requests that the file represented by this object
1568:    * be deleted when the virtual machine exits.  Note that this request cannot
1569:    * be cancelled.  Also, it will only be carried out if the virtual machine
1570:    * exits normally.
1571:    *
1572:    * @exception SecurityException If deleting of the file is not allowed
1573:    *
1574:    * @since 1.2 
1575:    */
1576:   public void deleteOnExit()
1577:   {
1578:     // Check the SecurityManager
1579:     SecurityManager sm = System.getSecurityManager();
1580:     if (sm != null)
1581:       sm.checkDelete(path);
1582: 
1583:     DeleteFileHelper.add(this);
1584:   }
1585: 
1586:   private void writeObject(ObjectOutputStream oos) throws IOException
1587:   {
1588:     oos.defaultWriteObject();
1589:     oos.writeChar(separatorChar);
1590:   }
1591: 
1592:   private void readObject(ObjectInputStream ois)
1593:     throws ClassNotFoundException, IOException
1594:   {
1595:     ois.defaultReadObject();
1596: 
1597:     // If the file was from an OS with a different dir separator,
1598:     // fixup the path to use the separator on this OS.
1599:     char oldSeparatorChar = ois.readChar();
1600:     
1601:     if (oldSeparatorChar != separatorChar)
1602:       path = path.replace(oldSeparatorChar, separatorChar);
1603:   }
1604:   
1605: } // class File