Save This Page
Home » apache-harmony-6.0-src-r917296-snapshot » java » io » [javadoc | source]
    1   /*
    2    *  Licensed to the Apache Software Foundation (ASF) under one or more
    3    *  contributor license agreements.  See the NOTICE file distributed with
    4    *  this work for additional information regarding copyright ownership.
    5    *  The ASF licenses this file to You under the Apache License, Version 2.0
    6    *  (the "License"); you may not use this file except in compliance with
    7    *  the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    *  Unless required by applicable law or agreed to in writing, software
   12    *  distributed under the License is distributed on an "AS IS" BASIS,
   13    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    *  See the License for the specific language governing permissions and
   15    *  limitations under the License.
   16    */
   17   
   18   package java.io;
   19   
   20   import java.net.URI;
   21   import java.net.URISyntaxException;
   22   import java.net.URL;
   23   import java.security.AccessController;
   24   import java.security.SecureRandom;
   25   import java.util.ArrayList;
   26   import java.util.List;
   27   
   28   import org.apache.harmony.luni.internal.io.FileCanonPathCache;
   29   import org.apache.harmony.luni.util.DeleteOnExit;
   30   import org.apache.harmony.luni.internal.nls.Messages;
   31   import org.apache.harmony.luni.util.PriviAction;
   32   import org.apache.harmony.luni.util.Util;
   33   
   34   /**
   35    * An "abstract" representation of a file system entity identified by a
   36    * pathname. The pathname may be absolute (relative to the root directory
   37    * of the file system) or relative to the current directory in which the program
   38    * is running.
   39    * <p>
   40    * This class provides methods for querying/changing information about the file
   41    * as well as directory listing capabilities if the file represents a directory.
   42    * <p>
   43    * When manipulating file paths, the static fields of this class may be used to
   44    * determine the platform specific separators.
   45    * 
   46    * @see java.io.Serializable
   47    * @see java.lang.Comparable
   48    */
   49   public class File implements Serializable, Comparable<File> {
   50   
   51       private static final long serialVersionUID = 301077366599181567L;
   52   
   53       private static final String EMPTY_STRING = ""; //$NON-NLS-1$
   54   
   55       private String path;
   56   
   57       transient byte[] properPath;
   58   
   59       /**
   60        * The system dependent file separator character.
   61        */
   62       public static final char separatorChar;
   63   
   64       /**
   65        * The system dependent file separator string. The initial value of this
   66        * field is the system property "file.separator".
   67        */
   68       public static final String separator;
   69   
   70       /**
   71        * The system dependent path separator character.
   72        */
   73       public static final char pathSeparatorChar;
   74   
   75       /**
   76        * The system dependent path separator string. The initial value of this
   77        * field is the system property "path.separator".
   78        */
   79       public static final String pathSeparator;
   80   
   81       /* Temp file counter */
   82       private static int counter;
   83   
   84       private static boolean caseSensitive;
   85   
   86       private static native void oneTimeInitialization();
   87   
   88       static {
   89           oneTimeInitialization();
   90   
   91           // The default protection domain grants access to these properties
   92           separatorChar = System.getProperty("file.separator", "\\").charAt(0); //$NON-NLS-1$ //$NON-NLS-2$
   93           pathSeparatorChar = System.getProperty("path.separator", ";").charAt(0); //$NON-NLS-1$//$NON-NLS-2$
   94           separator = new String(new char[] { separatorChar }, 0, 1);
   95           pathSeparator = new String(new char[] { pathSeparatorChar }, 0, 1);
   96           caseSensitive = isCaseSensitiveImpl();
   97       }
   98   
   99       /**
  100        * Constructs a new file using the specified directory and name.
  101        * 
  102        * @param dir
  103        *            the directory where the file is stored.
  104        * @param name
  105        *            the file's name.
  106        * @throws NullPointerException
  107        *             if {@code name} is {@code null}.
  108        */
  109       public File(File dir, String name) {
  110           if (name == null) {
  111               throw new NullPointerException();
  112           }
  113           if (dir == null) {
  114               this.path = fixSlashes(name);
  115           } else {
  116               this.path = calculatePath(dir.getPath(), name);
  117           }
  118       }
  119   
  120       /**
  121        * Constructs a new file using the specified path.
  122        * 
  123        * @param path
  124        *            the path to be used for the file.
  125        */
  126       public File(String path) {
  127           // path == null check & NullPointerException thrown by fixSlashes
  128           this.path = fixSlashes(path);
  129       }
  130   
  131       /**
  132        * Constructs a new File using the specified directory path and file name,
  133        * placing a path separator between the two.
  134        * 
  135        * @param dirPath
  136        *            the path to the directory where the file is stored.
  137        * @param name
  138        *            the file's name.
  139        * @throws NullPointerException
  140        *             if {@code name} is {@code null}.
  141        */
  142       public File(String dirPath, String name) {
  143           if (name == null) {
  144               throw new NullPointerException();
  145           }
  146           if (dirPath == null) {
  147               this.path = fixSlashes(name);
  148           } else {
  149               this.path = calculatePath(dirPath, name);
  150           }
  151       }
  152   
  153       /**
  154        * Constructs a new File using the path of the specified URI. {@code uri}
  155        * needs to be an absolute and hierarchical Unified Resource Identifier with
  156        * file scheme and non-empty path component, but with undefined authority,
  157        * query or fragment components.
  158        * 
  159        * @param uri
  160        *            the Unified Resource Identifier that is used to construct this
  161        *            file.
  162        * @throws IllegalArgumentException
  163        *             if {@code uri} does not comply with the conditions above.
  164        * @see #toURI
  165        * @see java.net.URI
  166        */
  167       public File(URI uri) {
  168           // check pre-conditions
  169           checkURI(uri);
  170           this.path = fixSlashes(uri.getPath());
  171       }
  172   
  173       private String calculatePath(String dirPath, String name) {
  174           dirPath = fixSlashes(dirPath);
  175           if (!name.equals(EMPTY_STRING) || dirPath.equals(EMPTY_STRING)) {
  176               // Remove all the proceeding separator chars from name
  177               name = fixSlashes(name);
  178   
  179               int separatorIndex = 0;
  180               while ((separatorIndex < name.length())
  181                       && (name.charAt(separatorIndex) == separatorChar)) {
  182                   separatorIndex++;
  183               }
  184               if (separatorIndex > 0) {
  185                   name = name.substring(separatorIndex, name.length());
  186               }
  187   
  188               // Ensure there is a separator char between dirPath and name
  189               if (dirPath.length() > 0
  190                       && (dirPath.charAt(dirPath.length() - 1) == separatorChar)) {
  191                   return dirPath + name;
  192               }
  193               return dirPath + separatorChar + name;
  194           }
  195   
  196           return dirPath;
  197       }
  198   
  199       @SuppressWarnings("nls")
  200       private void checkURI(URI uri) {
  201           if (!uri.isAbsolute()) {
  202               throw new IllegalArgumentException(Messages.getString("luni.AD", uri));
  203           } else if (!uri.getRawSchemeSpecificPart().startsWith("/")) {
  204               throw new IllegalArgumentException(Messages.getString("luni.AE", uri));
  205           }
  206   
  207           String temp = uri.getScheme();
  208           if (temp == null || !temp.equals("file")) {
  209               throw new IllegalArgumentException(Messages.getString("luni.AF", uri));
  210           }
  211   
  212           temp = uri.getRawPath();
  213           if (temp == null || temp.length() == 0) {
  214               throw new IllegalArgumentException(Messages.getString("luni.B0", uri));
  215           }
  216   
  217           if (uri.getRawAuthority() != null) {
  218               throw new IllegalArgumentException(Messages.getString("luni.B1",
  219                       new String[] { "authority", uri.toString() }));
  220           }
  221   
  222           if (uri.getRawQuery() != null) {
  223               throw new IllegalArgumentException(Messages.getString("luni.B1",
  224                       new String[] { "query", uri.toString() }));
  225           }
  226   
  227           if (uri.getRawFragment() != null) {
  228               throw new IllegalArgumentException(Messages.getString("luni.B1",
  229                       new String[] { "fragment", uri.toString() }));
  230           }
  231       }
  232   
  233       private static native byte[][] rootsImpl();
  234   
  235       private static native boolean isCaseSensitiveImpl();
  236   
  237       /**
  238        * Lists the file system roots. The Java platform may support zero or more
  239        * file systems, each with its own platform-dependent root. Further, the
  240        * canonical pathname of any file on the system will always begin with one
  241        * of the returned file system roots.
  242        * 
  243        * @return the array of file system roots.
  244        */
  245       public static File[] listRoots() {
  246           byte[][] rootsList = rootsImpl();
  247           if (rootsList == null) {
  248               return new File[0];
  249           }
  250           File result[] = new File[rootsList.length];
  251           for (int i = 0; i < rootsList.length; i++) {
  252               result[i] = new File(Util.toString(rootsList[i]));
  253           }
  254           return result;
  255       }
  256   
  257       /**
  258        * The purpose of this method is to take a path and fix the slashes up. This
  259        * includes changing them all to the current platforms fileSeparator and
  260        * removing duplicates.
  261        */
  262       private String fixSlashes(String origPath) {
  263           int uncIndex = 1;
  264           int length = origPath.length(), newLength = 0;
  265           if (separatorChar == '/') {
  266               uncIndex = 0;
  267           } else if (length > 2 && origPath.charAt(1) == ':') {
  268               uncIndex = 2;
  269           }
  270   
  271           boolean foundSlash = false;
  272           char newPath[] = origPath.toCharArray();
  273           for (int i = 0; i < length; i++) {
  274               char pathChar = newPath[i];
  275               if ((separatorChar == '\\' && pathChar == '\\')
  276                   || pathChar == '/') {
  277                   /* UNC Name requires 2 leading slashes */
  278                   if ((foundSlash && i == uncIndex) || !foundSlash) {
  279                       newPath[newLength++] = separatorChar;
  280                       foundSlash = true;
  281                   }
  282               } else {
  283                   // check for leading slashes before a drive
  284                   if (pathChar == ':'
  285                           && uncIndex > 0
  286                           && (newLength == 2 || (newLength == 3 && newPath[1] == separatorChar))
  287                           && newPath[0] == separatorChar) {
  288                       newPath[0] = newPath[newLength - 1];
  289                       newLength = 1;
  290                       // allow trailing slash after drive letter
  291                       uncIndex = 2;
  292                   }
  293                   newPath[newLength++] = pathChar;
  294                   foundSlash = false;
  295               }
  296           }
  297           // remove trailing slash
  298           if (foundSlash
  299                   && (newLength > (uncIndex + 1) || (newLength == 2 && newPath[0] != separatorChar))) {
  300               newLength--;
  301           }
  302   
  303           return new String(newPath, 0, newLength);
  304       }
  305   
  306       /**
  307        * Indicates whether the current context is allowed to read from this file.
  308        * 
  309        * @return {@code true} if this file can be read, {@code false} otherwise.
  310        * @throws SecurityException
  311        *             if a {@code SecurityManager} is installed and it denies the
  312        *             read request.
  313        */
  314       public boolean canRead() {
  315           if (path.length() == 0) {
  316               return false;
  317           }
  318           SecurityManager security = System.getSecurityManager();
  319           if (security != null) {
  320               security.checkRead(path);
  321           }
  322           byte[] pp = properPath(true);
  323           return existsImpl(pp) && !isWriteOnlyImpl(pp);
  324       }
  325   
  326       /**
  327        * Indicates whether the current context is allowed to write to this file.
  328        * 
  329        * @return {@code true} if this file can be written, {@code false}
  330        *         otherwise.
  331        * @throws SecurityException
  332        *             if a {@code SecurityManager} is installed and it denies the
  333        *             write request.
  334        */
  335       public boolean canWrite() {
  336           SecurityManager security = System.getSecurityManager();
  337           if (security != null) {
  338               security.checkWrite(path);
  339           }
  340   
  341           // Cannot use exists() since that does an unwanted read-check.
  342           boolean exists = false;
  343           if (path.length() > 0) {
  344               exists = existsImpl(properPath(true));
  345           }
  346           return exists && !isReadOnlyImpl(properPath(true));
  347       }
  348   
  349       /**
  350        * Returns the relative sort ordering of the paths for this file and the
  351        * file {@code another}. The ordering is platform dependent.
  352        * 
  353        * @param another
  354        *            a file to compare this file to
  355        * @return an int determined by comparing the two paths. Possible values are
  356        *         described in the Comparable interface.
  357        * @see Comparable
  358        */
  359       public int compareTo(File another) {
  360           if (caseSensitive) {
  361               return this.getPath().compareTo(another.getPath());
  362           }
  363           return this.getPath().compareToIgnoreCase(another.getPath());
  364       }
  365   
  366       /**
  367        * Deletes this file. Directories must be empty before they will be deleted.
  368        * 
  369        * @return {@code true} if this file was deleted, {@code false} otherwise.
  370        * @throws SecurityException
  371        *             if a {@code SecurityManager} is installed and it denies the
  372        *             request.
  373        * @see java.lang.SecurityManager#checkDelete
  374        */
  375       public boolean delete() {
  376           SecurityManager security = System.getSecurityManager();
  377           if (security != null) {
  378               security.checkDelete(path);
  379           }
  380           byte[] propPath = properPath(true);
  381           if ((path.length() != 0) && isDirectoryImpl(propPath)) {
  382               return deleteDirImpl(propPath);
  383           }
  384           return deleteFileImpl(propPath);
  385       }
  386   
  387       private native boolean deleteDirImpl(byte[] filePath);
  388   
  389       private native boolean deleteFileImpl(byte[] filePath);
  390   
  391       /**
  392        * Schedules this file to be automatically deleted once the virtual machine
  393        * terminates. This will only happen when the virtual machine terminates
  394        * normally as described by the Java Language Specification section 12.9.
  395        * 
  396        * @throws SecurityException
  397        *             if a {@code SecurityManager} is installed and it denies the
  398        *             request.
  399        */
  400       public void deleteOnExit() {
  401           SecurityManager security = System.getSecurityManager();
  402           if (security != null) {
  403               security.checkDelete(path);
  404           }
  405   
  406           DeleteOnExit.addFile(Util.toUTF8String(properPath(true)));
  407       }
  408   
  409       /**
  410        * Compares {@code obj} to this file and returns {@code true} if they
  411        * represent the <em>same</em> object using a path specific comparison.
  412        * 
  413        * @param obj
  414        *            the object to compare this file with.
  415        * @return {@code true} if {@code obj} is the same as this object,
  416        *         {@code false} otherwise.
  417        */
  418       @Override
  419       public boolean equals(Object obj) {
  420           if (!(obj instanceof File)) {
  421               return false;
  422           }
  423           if (!caseSensitive) {
  424               return path.equalsIgnoreCase(((File) obj).getPath());
  425           }
  426           return path.equals(((File) obj).getPath());
  427       }
  428   
  429       /**
  430        * Returns a boolean indicating whether this file can be found on the
  431        * underlying file system.
  432        * 
  433        * @return {@code true} if this file exists, {@code false} otherwise.
  434        * @throws SecurityException
  435        *             if a {@code SecurityManager} is installed and it denies read
  436        *             access to this file.
  437        * @see #getPath
  438        * @see java.lang.SecurityManager#checkRead(FileDescriptor)
  439        */
  440       public boolean exists() {
  441           if (path.length() == 0) {
  442               return false;
  443           }
  444           SecurityManager security = System.getSecurityManager();
  445           if (security != null) {
  446               security.checkRead(path);
  447           }
  448           return existsImpl(properPath(true));
  449       }
  450   
  451       private native boolean existsImpl(byte[] filePath);
  452   
  453       /**
  454        * Returns the absolute path of this file.
  455        * 
  456        * @return the absolute file path.
  457        * 
  458        * @see java.lang.SecurityManager#checkPropertyAccess
  459        */
  460       public String getAbsolutePath() {
  461           byte[] absolute = properPath(false);
  462           return Util.toUTF8String(absolute);
  463       }
  464   
  465       /**
  466        * Returns a new file constructed using the absolute path of this file.
  467        * 
  468        * @return a new file from this file's absolute path.
  469        * @see java.lang.SecurityManager#checkPropertyAccess
  470        */
  471       public File getAbsoluteFile() {
  472           return new File(this.getAbsolutePath());
  473       }
  474   
  475       /**
  476        * Returns the absolute path of this file with all references resolved. An
  477        * <em>absolute</em> path is one that begins at the root of the file
  478        * system. The canonical path is one in which all references have been
  479        * resolved. For the cases of '..' and '.', where the file system supports
  480        * parent and working directory respectively, these are removed and replaced
  481        * with a direct directory reference. If the file does not exist,
  482        * getCanonicalPath() may not resolve any references and simply returns an
  483        * absolute path name or throws an IOException.
  484        * 
  485        * @return the canonical path of this file.
  486        * @throws IOException
  487        *             if an I/O error occurs.
  488        * @see java.lang.SecurityManager#checkPropertyAccess
  489        */
  490       public String getCanonicalPath() throws IOException {
  491           byte[] result = properPath(false);
  492           String absPath = Util.toUTF8String(result);
  493           String canonPath = FileCanonPathCache.get(absPath);
  494   
  495           if (canonPath != null) {
  496               return canonPath;
  497           }
  498           if(separatorChar == '/') {
  499               // resolve the full path first
  500               result = resolveLink(result, result.length, false);
  501               // resolve the parent directories
  502               result = resolve(result);
  503           }
  504           int numSeparators = 1;
  505           for (int i = 0; i < result.length; i++) {
  506               if (result[i] == separatorChar) {
  507                   numSeparators++;
  508               }
  509           }
  510           int sepLocations[] = new int[numSeparators];
  511           int rootLoc = 0;
  512           if (separatorChar != '/') {
  513               if (result[0] == '\\') {
  514                   rootLoc = (result.length > 1 && result[1] == '\\') ? 1 : 0;
  515               } else {
  516                   rootLoc = 2; // skip drive i.e. c:
  517               }
  518           }
  519           byte newResult[] = new byte[result.length + 1];
  520           int newLength = 0, lastSlash = 0, foundDots = 0;
  521           sepLocations[lastSlash] = rootLoc;
  522           for (int i = 0; i <= result.length; i++) {
  523               if (i < rootLoc) {
  524                   newResult[newLength++] = result[i];
  525               } else {
  526                   if (i == result.length || result[i] == separatorChar) {
  527                       if (i == result.length && foundDots == 0) {
  528                           break;
  529                       }
  530                       if (foundDots == 1) {
  531                           /* Don't write anything, just reset and continue */
  532                           foundDots = 0;
  533                           continue;
  534                       }
  535                       if (foundDots > 1) {
  536                           /* Go back N levels */
  537                           lastSlash = lastSlash > (foundDots - 1) ? lastSlash
  538                                   - (foundDots - 1) : 0;
  539                           newLength = sepLocations[lastSlash] + 1;
  540                           foundDots = 0;
  541                           continue;
  542                       }
  543                       sepLocations[++lastSlash] = newLength;
  544                       newResult[newLength++] = (byte) separatorChar;
  545                       continue;
  546                   }
  547                   if (result[i] == '.') {
  548                       foundDots++;
  549                       continue;
  550                   }
  551                   /* Found some dots within text, write them out */
  552                   if (foundDots > 0) {
  553                       for (int j = 0; j < foundDots; j++) {
  554                           newResult[newLength++] = (byte) '.';
  555                       }
  556                   }
  557                   newResult[newLength++] = result[i];
  558                   foundDots = 0;
  559               }
  560           }
  561           // remove trailing slash
  562           if (newLength > (rootLoc + 1)
  563                   && newResult[newLength - 1] == separatorChar) {
  564               newLength--;
  565           }
  566           newResult[newLength] = 0;
  567           newResult = getCanonImpl(newResult);
  568           newLength = newResult.length;
  569           canonPath = Util.toUTF8String(newResult, 0, newLength);
  570           FileCanonPathCache.put(absPath, canonPath);
  571           return canonPath;
  572       }
  573       
  574       /*
  575        * Resolve symbolic links in the parent directories.
  576        */
  577       private byte[] resolve(byte[] newResult) throws IOException {
  578           int last = 1, nextSize, linkSize;
  579           byte[] linkPath = newResult, bytes;
  580           boolean done, inPlace;
  581           for (int i = 1; i <= newResult.length; i++) {
  582               if (i == newResult.length || newResult[i] == separatorChar) {
  583                   done = i >= newResult.length - 1;
  584                   // if there is only one segment, do nothing
  585                   if (done && linkPath.length == 1) {
  586                       return newResult;
  587                   }
  588                   inPlace = false;
  589                   if (linkPath == newResult) {
  590                       bytes = newResult;
  591                       // if there are no symbolic links, terminate the C string
  592                       // instead of copying
  593                       if (!done) {
  594                           inPlace = true;
  595                           newResult[i] = '\0';
  596                       }
  597                   } else {
  598                       nextSize = i - last + 1;
  599                       linkSize = linkPath.length;
  600                       if (linkPath[linkSize - 1] == separatorChar) {
  601                           linkSize--;
  602                       }
  603                       bytes = new byte[linkSize + nextSize];
  604                       System.arraycopy(linkPath, 0, bytes, 0, linkSize);
  605                       System.arraycopy(newResult, last - 1, bytes, linkSize,
  606                               nextSize);
  607                       // the full path has already been resolved
  608                   }
  609                   if (done) {
  610                       return bytes;
  611                   }
  612                   linkPath = resolveLink(bytes, inPlace ? i : bytes.length, true);
  613                   if (inPlace) {
  614                       newResult[i] = '/';
  615                   }
  616                   last = i + 1;
  617               }
  618           }
  619           throw new InternalError();
  620       }
  621   
  622       /*
  623        * Resolve a symbolic link. While the path resolves to an existing path,
  624        * keep resolving. If an absolute link is found, resolve the parent
  625        * directories if resolveAbsolute is true.
  626        */
  627       private byte[] resolveLink(byte[] pathBytes, int length,
  628               boolean resolveAbsolute) throws IOException {
  629           boolean restart = false;
  630           byte[] linkBytes, temp;
  631           do {
  632               linkBytes = getLinkImpl(pathBytes);
  633               if (linkBytes == pathBytes) {
  634                   break;
  635               }
  636               if (linkBytes[0] == separatorChar) {
  637                   // link to an absolute path, if resolving absolute paths,
  638                   // resolve the parent dirs again
  639                   restart = resolveAbsolute;
  640                   pathBytes = linkBytes;
  641               } else {
  642                   int last = length - 1;
  643                   while (pathBytes[last] != separatorChar) {
  644                       last--;
  645                   }
  646                   last++;
  647                   temp = new byte[last + linkBytes.length];
  648                   System.arraycopy(pathBytes, 0, temp, 0, last);
  649                   System.arraycopy(linkBytes, 0, temp, last, linkBytes.length);
  650                   pathBytes = temp;
  651               }
  652               length = pathBytes.length;
  653           } while (existsImpl(pathBytes));
  654           // resolve the parent directories
  655           if (restart) {
  656               return resolve(pathBytes);
  657           }
  658           return pathBytes;
  659       }
  660   
  661       /**
  662        * Returns a new file created using the canonical path of this file.
  663        * Equivalent to {@code new File(this.getCanonicalPath())}.
  664        * 
  665        * @return the new file constructed from this file's canonical path.
  666        * @throws IOException
  667        *             if an I/O error occurs.
  668        * @see java.lang.SecurityManager#checkPropertyAccess
  669        */
  670       public File getCanonicalFile() throws IOException {
  671           return new File(getCanonicalPath());
  672       }
  673   
  674       private native byte[] getCanonImpl(byte[] filePath);
  675   
  676       /**
  677        * Returns the name of the file or directory represented by this file.
  678        * 
  679        * @return this file's name or an empty string if there is no name part in
  680        *         the file's path.
  681        */
  682       public String getName() {
  683           int separatorIndex = path.lastIndexOf(separator);
  684           return (separatorIndex < 0) ? path : path.substring(separatorIndex + 1,
  685                   path.length());
  686       }
  687   
  688       /**
  689        * Returns the pathname of the parent of this file. This is the path up to
  690        * but not including the last name. {@code null} is returned if there is no
  691        * parent.
  692        * 
  693        * @return this file's parent pathname or {@code null}.
  694        */
  695       public String getParent() {
  696           int length = path.length(), firstInPath = 0;
  697           if (separatorChar == '\\' && length > 2 && path.charAt(1) == ':') {
  698               firstInPath = 2;
  699           }
  700           int index = path.lastIndexOf(separatorChar);
  701           if (index == -1 && firstInPath > 0) {
  702               index = 2;
  703           }
  704           if (index == -1 || path.charAt(length - 1) == separatorChar) {
  705               return null;
  706           }
  707           if (path.indexOf(separatorChar) == index
  708                   && path.charAt(firstInPath) == separatorChar) {
  709               return path.substring(0, index + 1);
  710           }
  711           return path.substring(0, index);
  712       }
  713   
  714       /**
  715        * Returns a new file made from the pathname of the parent of this file.
  716        * This is the path up to but not including the last name. {@code null} is
  717        * returned when there is no parent.
  718        * 
  719        * @return a new file representing this file's parent or {@code null}.
  720        */
  721       public File getParentFile() {
  722           String tempParent = getParent();
  723           if (tempParent == null) {
  724               return null;
  725           }
  726           return new File(tempParent);
  727       }
  728   
  729       /**
  730        * Returns the path of this file.
  731        * 
  732        * @return this file's path.
  733        */
  734       public String getPath() {
  735           return path;
  736       }
  737       
  738   	/**
  739   	 * Answers the partition size indicated by the path name.
  740   	 * 
  741   	 * @return the partition size counted in bytes, 0L if the path does not
  742   	 *         exist
  743   	 */
  744   	public long getTotalSpace() {
  745   		SecurityManager security = System.getSecurityManager();
  746   		if (security != null) {
  747   			security.checkPermission(new RuntimePermission(
  748   					"getFileSystemAttributes")); //$NON-NLS-1$
  749   		}
  750   		return getTotalSpaceImpl(properPath(true));
  751   	}
  752   
  753   	private native long getTotalSpaceImpl(byte[] filePath);
  754   	
  755   	/**
  756   	 * Answers the available bytes of the partition indicated by the path name.
  757   	 * This method checks write permission and other restrictions and offers a
  758   	 * more precise estimate than getFreeSpace(). If the operating system does
  759   	 * not support this information, the result will be the same as the one
  760   	 * returned by getFreeSpace().
  761   	 * 
  762   	 * @return the available bytes of the partition considering platform
  763   	 *         dependent permissions
  764   	 */
  765   	public long getUsableSpace() {
  766   		SecurityManager security = System.getSecurityManager();
  767   		if (security != null) {
  768   			security.checkPermission(new RuntimePermission(
  769   					"getFileSystemAttributes")); //$NON-NLS-1$
  770   		}
  771   		return getUsableSpaceImpl(properPath(true));
  772   	}
  773   
  774   	private native long getUsableSpaceImpl(byte[] filePath);
  775   
  776   	/**
  777   	 * Answers the available bytes of the partition indicated by the path name.
  778   	 * 
  779   	 * @return the available bytes of the partition
  780   	 */
  781   	public long getFreeSpace() {
  782   		SecurityManager security = System.getSecurityManager();
  783   		if (security != null) {
  784   			security.checkPermission(new RuntimePermission(
  785   					"getFileSystemAttributes")); //$NON-NLS-1$
  786   		}
  787   		return getFreeSpaceImpl(properPath(true));
  788   	}
  789   
  790   	private native long getFreeSpaceImpl(byte[] filePath);
  791   
  792       /**
  793        * Returns an integer hash code for the receiver. Any two objects for which
  794        * {@code equals} returns {@code true} must return the same hash code.
  795        * 
  796        * @return this files's hash value.
  797        * @see #equals
  798        */
  799       @Override
  800       public int hashCode() {
  801           if (caseSensitive) {
  802               return path.hashCode() ^ 1234321;
  803           }
  804           return path.toLowerCase().hashCode() ^ 1234321;
  805       }
  806   
  807       /**
  808        * Indicates if this file's pathname is absolute. Whether a pathname is
  809        * absolute is platform specific. On UNIX, absolute paths must start with
  810        * the character '/'; on Windows it is absolute if either it starts with
  811        * '\\' (to represent a file server), or a letter followed by a colon.
  812        * 
  813        * @return {@code true} if this file's pathname is absolute, {@code false}
  814        *         otherwise.
  815        * @see #getPath
  816        */
  817       public boolean isAbsolute() {
  818           if (File.separatorChar == '\\') {
  819               // for windows
  820               if (path.length() > 1 && path.charAt(0) == File.separatorChar
  821                       && path.charAt(1) == File.separatorChar) {
  822                   return true;
  823               }
  824               if (path.length() > 2) {
  825                   if (Character.isLetter(path.charAt(0)) && path.charAt(1) == ':'
  826                           && (path.charAt(2) == '/' || path.charAt(2) == '\\')) {
  827                       return true;
  828                   }
  829               }
  830               return false;
  831           }
  832   
  833           // for Linux
  834           return (path.length() > 0 && path.charAt(0) == File.separatorChar);
  835       }
  836   
  837       /**
  838        * Indicates if this file represents a <em>directory</em> on the
  839        * underlying file system.
  840        * 
  841        * @return {@code true} if this file is a directory, {@code false}
  842        *         otherwise.
  843        * @throws SecurityException
  844        *             if a {@code SecurityManager} is installed and it denies read
  845        *             access to this file.
  846        */
  847       public boolean isDirectory() {
  848           if (path.length() == 0) {
  849               return false;
  850           }
  851           SecurityManager security = System.getSecurityManager();
  852           if (security != null) {
  853               security.checkRead(path);
  854           }
  855           return isDirectoryImpl(properPath(true));
  856       }
  857   
  858       private native boolean isDirectoryImpl(byte[] filePath);
  859   
  860       /**
  861        * Indicates if this file represents a <em>file</em> on the underlying
  862        * file system.
  863        * 
  864        * @return {@code true} if this file is a file, {@code false} otherwise.
  865        * @throws SecurityException
  866        *             if a {@code SecurityManager} is installed and it denies read
  867        *             access to this file.
  868        */
  869       public boolean isFile() {
  870           if (path.length() == 0) {
  871               return false;
  872           }
  873           SecurityManager security = System.getSecurityManager();
  874           if (security != null) {
  875               security.checkRead(path);
  876           }
  877           return isFileImpl(properPath(true));
  878       }
  879   
  880       private native boolean isFileImpl(byte[] filePath);
  881   
  882       /**
  883        * Returns whether or not this file is a hidden file as defined by the
  884        * operating system. The notion of "hidden" is system-dependent. For Unix
  885        * systems a file is considered hidden if its name starts with a ".". For
  886        * Windows systems there is an explicit flag in the file system for this
  887        * purpose.
  888        * 
  889        * @return {@code true} if the file is hidden, {@code false} otherwise.
  890        * @throws SecurityException
  891        *             if a {@code SecurityManager} is installed and it denies read
  892        *             access to this file.
  893        */
  894       public boolean isHidden() {
  895           if (path.length() == 0) {
  896               return false;
  897           }
  898           SecurityManager security = System.getSecurityManager();
  899           if (security != null) {
  900               security.checkRead(path);
  901           }
  902           return isHiddenImpl(properPath(true));
  903       }
  904   
  905       private native boolean isHiddenImpl(byte[] filePath);
  906   
  907       private native boolean isReadOnlyImpl(byte[] filePath);
  908   
  909       private native boolean isWriteOnlyImpl(byte[] filePath);
  910   
  911       private native byte[] getLinkImpl(byte[] filePath);
  912   
  913       /**
  914        * Returns the time when this file was last modified, measured in
  915        * milliseconds since January 1st, 1970, midnight.
  916        * 
  917        * @return the time when this file was last modified.
  918        * @throws SecurityException
  919        *             if a {@code SecurityManager} is installed and it denies read
  920        *             access to this file.
  921        */
  922       public long lastModified() {
  923           SecurityManager security = System.getSecurityManager();
  924           if (security != null) {
  925               security.checkRead(path);
  926           }
  927           long result = lastModifiedImpl(properPath(true));
  928           /* Temporary code to handle both return cases until natives fixed */
  929           if (result == -1 || result == 0) {
  930               return 0;
  931           }
  932           return result;
  933       }
  934   
  935       private native long lastModifiedImpl(byte[] filePath);
  936   
  937       /**
  938        * Sets the time this file was last modified, measured in milliseconds since
  939        * January 1st, 1970, midnight.
  940        * 
  941        * @param time
  942        *            the last modification time for this file.
  943        * @return {@code true} if the operation is successful, {@code false}
  944        *         otherwise.
  945        * @throws IllegalArgumentException
  946        *             if {@code time < 0}.
  947        * @throws SecurityException
  948        *             if a {@code SecurityManager} is installed and it denies write
  949        *             access to this file.
  950        */
  951       public boolean setLastModified(long time) {
  952           if (time < 0) {
  953               throw new IllegalArgumentException(Messages.getString("luni.B2")); //$NON-NLS-1$
  954           }
  955           SecurityManager security = System.getSecurityManager();
  956           if (security != null) {
  957               security.checkWrite(path);
  958           }
  959           return (setLastModifiedImpl(properPath(true), time));
  960       }
  961   
  962       private native boolean setLastModifiedImpl(byte[] path, long time);
  963   
  964       /**
  965        * Marks this file or directory to be read-only as defined by the operating
  966        * system.
  967        * 
  968        * @return {@code true} if the operation is successful, {@code false}
  969        *         otherwise.
  970        * @throws SecurityException
  971        *             if a {@code SecurityManager} is installed and it denies write
  972        *             access to this file.
  973        */
  974       public boolean setReadOnly() {
  975           SecurityManager security = System.getSecurityManager();
  976           if (security != null) {
  977               security.checkWrite(path);
  978           }
  979           return (setReadOnlyImpl(properPath(true)));
  980       }
  981   
  982       private native boolean setReadOnlyImpl(byte[] path);
  983   
  984       /**
  985   	 * Manipulates the read permission of the abstract path designated by this
  986   	 * file object.
  987   	 * 
  988   	 * @param readable
  989   	 *            To allow read permission if true, otherwise disallow
  990   	 * @param ownerOnly
  991   	 *            To manipulate read permission only for owner if true,
  992   	 *            otherwise for everyone. The manipulation will apply to
  993   	 *            everyone regardless of this value if the underlying system
  994   	 *            does not distinguish owner and other users.
  995   	 * @return true if and only if the operation succeeded. If the user does not
  996   	 *         have permission to change the access permissions of this abstract
  997   	 *         pathname the operation will fail. If the underlying file system
  998   	 *         does not support read permission and the value of readable is
  999   	 *         false, this operation will fail.
 1000   	 * @throws SecurityException -
 1001   	 *             If a security manager exists and
 1002   	 *             SecurityManager.checkWrite(java.lang.String) disallows write
 1003   	 *             permission to this file object
 1004   	 * @since 1.6
 1005   	 */
 1006   	public boolean setReadable(boolean readable, boolean ownerOnly) {
 1007   		checkWrite();
 1008   		return (setReadableImpl(properPath(true), readable, ownerOnly));
 1009   	}
 1010   
 1011   	/**
 1012   	 * A convenience method for setReadable(boolean, boolean). An invocation of
 1013   	 * this method is the same as file.setReadable(readable, true).
 1014   	 * 
 1015   	 * @param readable
 1016   	 *            To allow read permission if true, otherwise disallow
 1017   	 * @return true if and only if the operation succeeded. If the user does not
 1018   	 *         have permission to change the access permissions of this abstract
 1019   	 *         pathname the operation will fail. If the underlying file system
 1020   	 *         does not support read permission and the value of readable is
 1021   	 *         false, this operation will fail.
 1022   	 * @throws SecurityException -
 1023   	 *             If a security manager exists and
 1024   	 *             SecurityManager.checkWrite(java.lang.String) disallows write
 1025   	 *             permission to this file object
 1026   	 * @since 1.6
 1027   	 */
 1028   	public boolean setReadable(boolean readable) {
 1029   		return setReadable(readable, true);
 1030   	}
 1031   	
 1032   	private native boolean setReadableImpl(byte[] path, boolean readable,
 1033   			boolean ownerOnly);
 1034   	
 1035   	/**
 1036   	 * Manipulates the write permission of the abstract path designated by this
 1037   	 * file object.
 1038   	 * 
 1039   	 * @param writable
 1040   	 *            To allow write permission if true, otherwise disallow
 1041   	 * @param ownerOnly
 1042   	 *            To manipulate write permission only for owner if true,
 1043   	 *            otherwise for everyone. The manipulation will apply to
 1044   	 *            everyone regardless of this value if the underlying system
 1045   	 *            does not distinguish owner and other users.
 1046   	 * @return true if and only if the operation succeeded. If the user does not
 1047   	 *         have permission to change the access permissions of this abstract
 1048   	 *         pathname the operation will fail.
 1049   	 * @throws SecurityException -
 1050   	 *             If a security manager exists and
 1051   	 *             SecurityManager.checkWrite(java.lang.String) disallows write
 1052   	 *             permission to this file object
 1053   	 * @since 1.6
 1054   	 */
 1055   	public boolean setWritable(boolean writable, boolean ownerOnly) {
 1056   		checkWrite();
 1057   		return (setWritableImpl(properPath(true), writable, ownerOnly));
 1058   	}
 1059   
 1060   	private native boolean setWritableImpl(byte[] path, boolean writable,
 1061   			boolean ownerOnly);
 1062   
 1063   	/**
 1064   	 * A convenience method for setWritable(boolean, boolean). An invocation of
 1065   	 * this method is the same as file.setWritable(writable, true).
 1066   	 * 
 1067   	 * @param writable
 1068   	 *            To allow write permission if true, otherwise disallow
 1069   	 * @return true if and only if the operation succeeded. If the user does not
 1070   	 *         have permission to change the access permissions of this abstract
 1071   	 *         pathname the operation will fail.
 1072   	 * @throws SecurityException -
 1073   	 *             If a security manager exists and
 1074   	 *             SecurityManager.checkWrite(java.lang.String) disallows write
 1075   	 *             permission to this file object
 1076   	 * @since 1.6
 1077   	 */
 1078   	public boolean setWritable(boolean writable) {
 1079   		return setWritable(writable, true);
 1080   	}
 1081   	
 1082       /**
 1083        * Returns the length of this file in bytes.
 1084        * 
 1085        * @return the number of bytes in this file.
 1086        * @throws SecurityException
 1087        *             if a {@code SecurityManager} is installed and it denies read
 1088        *             access to this file.
 1089        */
 1090       public long length() {
 1091           SecurityManager security = System.getSecurityManager();
 1092           if (security != null) {
 1093               security.checkRead(path);
 1094           }
 1095           return lengthImpl(properPath(true));
 1096       }
 1097   
 1098       private native long lengthImpl(byte[] filePath);
 1099   
 1100       /**
 1101        * Returns an array of strings with the file names in the directory
 1102        * represented by this file. The result is {@code null} if this file is not
 1103        * a directory.
 1104        * <p>
 1105        * The entries {@code .} and {@code ..} representing the current and parent
 1106        * directory are not returned as part of the list.
 1107        *
 1108        * @return an array of strings with file names or {@code null}.
 1109        * @throws SecurityException
 1110        *             if a {@code SecurityManager} is installed and it denies read
 1111        *             access to this file.
 1112        * @see #isDirectory
 1113        * @see java.lang.SecurityManager#checkRead(FileDescriptor)
 1114        */
 1115       public java.lang.String[] list() {
 1116           SecurityManager security = System.getSecurityManager();
 1117           if (security != null) {
 1118               security.checkRead(path);
 1119           }
 1120   
 1121           if (path.length() == 0) {
 1122               return null;
 1123           }
 1124   
 1125           byte[] bs = properPath(true);
 1126           if (!isDirectoryImpl(bs) || !existsImpl(bs) || isWriteOnlyImpl(bs)) {
 1127               return null;
 1128           }
 1129   
 1130           byte[][] implList = listImpl(bs);
 1131           if (implList == null) {
 1132               // empty list
 1133               return new String[0];
 1134           }
 1135           String result[] = new String[implList.length];
 1136           for (int index = 0; index < implList.length; index++) {
 1137               result[index] = Util.toUTF8String(implList[index]);
 1138           }
 1139           return result;
 1140       }
 1141   
 1142       /**
 1143        * Returns an array of files contained in the directory represented by this
 1144        * file. The result is {@code null} if this file is not a directory. The
 1145        * paths of the files in the array are absolute if the path of this file is
 1146        * absolute, they are relative otherwise.
 1147        * 
 1148        * @return an array of files or {@code null}.
 1149        * @throws SecurityException
 1150        *             if a {@code SecurityManager} is installed and it denies read
 1151        *             access to this file.
 1152        * @see #list
 1153        * @see #isDirectory
 1154        */
 1155       public File[] listFiles() {
 1156           String[] tempNames = list();
 1157           if (tempNames == null) {
 1158               return null;
 1159           }
 1160           int resultLength = tempNames.length;
 1161           File results[] = new File[resultLength];
 1162           for (int i = 0; i < resultLength; i++) {
 1163               results[i] = new File(this, tempNames[i]);
 1164           }
 1165           return results;
 1166       }
 1167   
 1168       /**
 1169        * Gets a list of the files in the directory represented by this file. This
 1170        * list is then filtered through a FilenameFilter and files with matching
 1171        * names are returned as an array of files. Returns {@code null} if this
 1172        * file is not a directory. If {@code filter} is {@code null} then all
 1173        * filenames match.
 1174        * <p>
 1175        * The entries {@code .} and {@code ..} representing the current and parent
 1176        * directories are not returned as part of the list.
 1177        *
 1178        * @param filter
 1179        *            the filter to match names against, may be {@code null}.
 1180        * @return an array of files or {@code null}.
 1181        * @throws SecurityException
 1182        *             if a {@code SecurityManager} is installed and it denies read
 1183        *             access to this file.
 1184        * @see #list(FilenameFilter filter)
 1185        * @see #getPath
 1186        * @see #isDirectory
 1187        * @see java.lang.SecurityManager#checkRead(FileDescriptor)
 1188        */
 1189       public File[] listFiles(FilenameFilter filter) {
 1190           String[] tempNames = list(filter);
 1191           if (tempNames == null) {
 1192               return null;
 1193           }
 1194           int resultLength = tempNames.length;
 1195           File results[] = new File[resultLength];
 1196           for (int i = 0; i < resultLength; i++) {
 1197               results[i] = new File(this, tempNames[i]);
 1198           }
 1199           return results;
 1200       }
 1201   
 1202       /**
 1203        * Gets a list of the files in the directory represented by this file. This
 1204        * list is then filtered through a FileFilter and matching files are
 1205        * returned as an array of files. Returns {@code null} if this file is not a
 1206        * directory. If {@code filter} is {@code null} then all files match.
 1207        * <p>
 1208        * The entries {@code .} and {@code ..} representing the current and parent
 1209        * directories are not returned as part of the list.
 1210        *
 1211        * @param filter
 1212        *            the filter to match names against, may be {@code null}.
 1213        * @return an array of files or {@code null}.
 1214        * @throws SecurityException
 1215        *             if a {@code SecurityManager} is installed and it denies read
 1216        *             access to this file.
 1217        * @see #getPath
 1218        * @see #isDirectory
 1219        * @see java.lang.SecurityManager#checkRead(FileDescriptor)
 1220        */
 1221       public File[] listFiles(FileFilter filter) {
 1222           SecurityManager security = System.getSecurityManager();
 1223           if (security != null) {
 1224               security.checkRead(path);
 1225           }
 1226   
 1227           if (path.length() == 0) {
 1228               return null;
 1229           }
 1230   
 1231           byte[] bs = properPath(true);
 1232           if (!isDirectoryImpl(bs) || !existsImpl(bs) || isWriteOnlyImpl(bs)) {
 1233               return null;
 1234           }
 1235   
 1236           byte[][] implList = listImpl(bs);
 1237           if (implList == null) {
 1238               return new File[0];
 1239           }
 1240           List<File> tempResult = new ArrayList<File>();
 1241           for (int index = 0; index < implList.length; index++) {
 1242               String aName = Util.toString(implList[index]);
 1243               File aFile = new File(this, aName);
 1244               if (filter == null || filter.accept(aFile)) {
 1245                   tempResult.add(aFile);
 1246               }
 1247           }
 1248           return tempResult.toArray(new File[tempResult.size()]);
 1249       }
 1250   
 1251       /**
 1252        * Gets a list of the files in the directory represented by this file. This
 1253        * list is then filtered through a FilenameFilter and the names of files
 1254        * with matching names are returned as an array of strings. Returns
 1255        * {@code null} if this file is not a directory. If {@code filter} is
 1256        * {@code null} then all filenames match.
 1257        * <p>
 1258        * The entries {@code .} and {@code ..} representing the current and parent
 1259        * directories are not returned as part of the list.
 1260        * 
 1261        * @param filter
 1262        *            the filter to match names against, may be {@code null}.
 1263        * @return an array of files or {@code null}.
 1264        * @throws SecurityException
 1265        *             if a {@code SecurityManager} is installed and it denies read
 1266        *             access to this file.
 1267        * @see #getPath
 1268        * @see #isDirectory
 1269        * @see java.lang.SecurityManager#checkRead(FileDescriptor)
 1270        */
 1271       public java.lang.String[] list(FilenameFilter filter) {
 1272           SecurityManager security = System.getSecurityManager();
 1273           if (security != null) {
 1274               security.checkRead(path);
 1275           }
 1276   
 1277           if (path.length() == 0) {
 1278               return null;
 1279           }
 1280   
 1281           byte[] bs = properPath(true);
 1282           if (!isDirectoryImpl(bs) || !existsImpl(bs) || isWriteOnlyImpl(bs)) {
 1283               return null;
 1284           }
 1285   
 1286           byte[][] implList = listImpl(bs);
 1287           if (implList == null) {
 1288               // empty list
 1289               return new String[0];
 1290           }
 1291           List<String> tempResult = new ArrayList<String>();
 1292           for (int index = 0; index < implList.length; index++) {
 1293               String aName = Util.toString(implList[index]);
 1294               if (filter == null || filter.accept(this, aName)) {
 1295                   tempResult.add(aName);
 1296               }
 1297           }
 1298   
 1299           return tempResult.toArray(new String[tempResult.size()]);
 1300       }
 1301   
 1302       private synchronized static native byte[][] listImpl(byte[] path);
 1303   
 1304       /**
 1305        * Creates the directory named by the trailing filename of this file. Does
 1306        * not create the complete path required to create this directory.
 1307        * 
 1308        * @return {@code true} if the directory has been created, {@code false}
 1309        *         otherwise.
 1310        * @throws SecurityException
 1311        *             if a {@code SecurityManager} is installed and it denies write
 1312        *             access for this file.
 1313        * @see #mkdirs
 1314        */
 1315       public boolean mkdir() {
 1316           SecurityManager security = System.getSecurityManager();
 1317           if (security != null) {
 1318               security.checkWrite(path);
 1319           }
 1320           return mkdirImpl(properPath(true));
 1321       }
 1322   
 1323       private native boolean mkdirImpl(byte[] filePath);
 1324   
 1325       /**
 1326        * Creates the directory named by the trailing filename of this file,
 1327        * including the complete directory path required to create this directory.
 1328        * 
 1329        * @return {@code true} if the necessary directories have been created,
 1330        *         {@code false} if the target directory already exists or one of
 1331        *         the directories can not be created.
 1332        * @throws SecurityException
 1333        *             if a {@code SecurityManager} is installed and it denies write
 1334        *             access for this file.
 1335        * @see #mkdir
 1336        */
 1337       public boolean mkdirs() {
 1338           /* If the terminal directory already exists, answer false */
 1339           if (exists()) {
 1340               return false;
 1341           }
 1342   
 1343           /* If the receiver can be created, answer true */
 1344           if (mkdir()) {
 1345               return true;
 1346           }
 1347   
 1348           String parentDir = getParent();
 1349           /* If there is no parent and we were not created, answer false */
 1350           if (parentDir == null) {
 1351               return false;
 1352           }
 1353   
 1354           /* Otherwise, try to create a parent directory and then this directory */
 1355           return (new File(parentDir).mkdirs() && mkdir());
 1356       }
 1357   
 1358       /**
 1359        * Creates a new, empty file on the file system according to the path
 1360        * information stored in this file.
 1361        * 
 1362        * @return {@code true} if the file has been created, {@code false} if it
 1363        *         already exists.
 1364        * @throws IOException
 1365        *             if an I/O error occurs or the directory does not exist where
 1366        *             the file should have been created.
 1367        * @throws SecurityException
 1368        *             if a {@code SecurityManager} is installed and it denies write
 1369        *             access for this file.
 1370        */
 1371       public boolean createNewFile() throws IOException {
 1372           SecurityManager security = System.getSecurityManager();
 1373           if (security != null) {
 1374               security.checkWrite(path);
 1375           }
 1376           if (0 == path.length()) {
 1377               throw new IOException(Messages.getString("luni.B3")); //$NON-NLS-1$
 1378           }
 1379           int result = newFileImpl(properPath(true));
 1380           switch (result) {
 1381               case 0:
 1382                   return true;
 1383               case 1:
 1384                   return false;
 1385               default:
 1386                   throw new IOException(Messages.getString("luni.B4", path)); //$NON-NLS-1$
 1387           }
 1388       }
 1389   
 1390       private native int newFileImpl(byte[] filePath);
 1391   
 1392       /**
 1393        * Creates an empty temporary file using the given prefix and suffix as part
 1394        * of the file name. If suffix is {@code null}, {@code .tmp} is used. This
 1395        * method is a convenience method that calls
 1396        * {@link #createTempFile(String, String, File)} with the third argument
 1397        * being {@code null}.
 1398        * 
 1399        * @param prefix
 1400        *            the prefix to the temp file name.
 1401        * @param suffix
 1402        *            the suffix to the temp file name.
 1403        * @return the temporary file.
 1404        * @throws IOException
 1405        *             if an error occurs when writing the file.
 1406        */
 1407       public static File createTempFile(String prefix, String suffix)
 1408               throws IOException {
 1409           return createTempFile(prefix, suffix, null);
 1410       }
 1411   
 1412       /**
 1413        * Creates an empty temporary file in the given directory using the given
 1414        * prefix and suffix as part of the file name.
 1415        * 
 1416        * @param prefix
 1417        *            the prefix to the temp file name.
 1418        * @param suffix
 1419        *            the suffix to the temp file name.
 1420        * @param directory
 1421        *            the location to which the temp file is to be written, or
 1422        *            {@code null} for the default location for temporary files,
 1423        *            which is taken from the "java.io.tmpdir" system property. It
 1424        *            may be necessary to set this property to an existing, writable
 1425        *            directory for this method to work properly.
 1426        * @return the temporary file.
 1427        * @throws IllegalArgumentException
 1428        *             if the length of {@code prefix} is less than 3.
 1429        * @throws IOException
 1430        *             if an error occurs when writing the file.
 1431        */
 1432       @SuppressWarnings("nls")
 1433       public static File createTempFile(String prefix, String suffix,
 1434               File directory) throws IOException {
 1435           // Force a prefix null check first
 1436           if (prefix.length() < 3) {
 1437               throw new IllegalArgumentException(Messages.getString("luni.B5"));
 1438           }
 1439           String newSuffix = suffix == null ? ".tmp" : suffix;
 1440           File tmpDirFile;
 1441           if (directory == null) {
 1442               String tmpDir = AccessController.doPrivileged(
 1443                   new PriviAction<String>("java.io.tmpdir", "."));
 1444               tmpDirFile = new File(tmpDir);
 1445           } else {
 1446               tmpDirFile = directory;
 1447           }
 1448           File result;
 1449           do {
 1450               result = genTempFile(prefix, newSuffix, tmpDirFile);
 1451           } while (!result.createNewFile());
 1452           return result;
 1453       }
 1454   
 1455       private static File genTempFile(String prefix, String suffix, File directory) {
 1456           if (counter == 0) {
 1457               int newInt = new SecureRandom().nextInt();
 1458               counter = ((newInt / 65535) & 0xFFFF) + 0x2710;
 1459           }
 1460           StringBuilder newName = new StringBuilder();
 1461           newName.append(prefix);
 1462           newName.append(counter++);
 1463           newName.append(suffix);
 1464           return new File(directory, newName.toString());
 1465       }
 1466   
 1467       /**
 1468        * Returns a string representing the proper path for this file. If this file
 1469        * path is absolute, the user.dir property is not prepended, otherwise it
 1470        * is.
 1471        * 
 1472        * @param internal
 1473        *            is user.dir internal.
 1474        * @return the proper path.
 1475        */
 1476       byte[] properPath(boolean internal) {
 1477           if (properPath != null) {
 1478               return properPath;
 1479           }
 1480   
 1481           if (isAbsolute()) {
 1482               byte[] pathBytes = Util.getUTF8Bytes(path);
 1483               return properPath = pathBytes;
 1484           }
 1485           // Check security by getting user.dir when the path is not absolute
 1486           String userdir;
 1487           if (internal) {
 1488               userdir = AccessController.doPrivileged(new PriviAction<String>(
 1489                       "user.dir")); //$NON-NLS-1$
 1490           } else {
 1491               userdir = System.getProperty("user.dir"); //$NON-NLS-1$
 1492           }
 1493   
 1494           if (path.length() == 0) {
 1495               return properPath = Util.getUTF8Bytes(userdir);
 1496           }
 1497           int length = userdir.length();
 1498   
 1499           // Handle windows-like path
 1500           if (path.charAt(0) == '\\') {
 1501               if (length > 1 && userdir.charAt(1) == ':') {
 1502                   return properPath = Util.getUTF8Bytes(userdir.substring(0, 2)
 1503                           + path);
 1504               }
 1505               path = path.substring(1);
 1506           }
 1507   
 1508           // Handle separator
 1509           String result = userdir;
 1510           if (userdir.charAt(length - 1) != separatorChar) {
 1511               if (path.charAt(0) != separatorChar) {
 1512                   result += separator;
 1513               }
 1514           } else if (path.charAt(0) == separatorChar) {
 1515               result = result.substring(0, length - 2);
 1516   
 1517           }
 1518           result += path;
 1519           return properPath = Util.getUTF8Bytes(result);
 1520       }
 1521   
 1522       /**
 1523        * Renames this file to the name represented by the {@code dest} file. This
 1524        * works for both normal files and directories.
 1525        * 
 1526        * @param dest
 1527        *            the file containing the new name.
 1528        * @return {@code true} if the File was renamed, {@code false} otherwise.
 1529        * @throws SecurityException
 1530        *             if a {@code SecurityManager} is installed and it denies write
 1531        *             access for this file or the {@code dest} file.
 1532        */
 1533       public boolean renameTo(java.io.File dest) {
 1534           SecurityManager security = System.getSecurityManager();
 1535           if (security != null) {
 1536               security.checkWrite(path);
 1537               security.checkWrite(dest.path);
 1538           }
 1539           return renameToImpl(properPath(true), dest.properPath(true));
 1540       }
 1541   
 1542       private native boolean renameToImpl(byte[] pathExist, byte[] pathNew);
 1543   
 1544       /**
 1545        * Returns a string containing a concise, human-readable description of this
 1546        * file.
 1547        * 
 1548        * @return a printable representation of this file.
 1549        */
 1550       @Override
 1551       public String toString() {
 1552           return path;
 1553       }
 1554   
 1555       /**
 1556        * Returns a Uniform Resource Identifier for this file. The URI is system
 1557        * dependent and may not be transferable between different operating / file
 1558        * systems.
 1559        * 
 1560        * @return an URI for this file.
 1561        */
 1562       @SuppressWarnings("nls")
 1563       public URI toURI() {
 1564           String name = getAbsoluteName();
 1565           try {
 1566               if (!name.startsWith("/")) {
 1567                   // start with sep.
 1568                   return new URI("file", null, new StringBuilder(
 1569                           name.length() + 1).append('/').append(name).toString(),
 1570                           null, null);
 1571               } else if (name.startsWith("//")) {
 1572                   return new URI("file", "", name, null); // UNC path
 1573               }
 1574               return new URI("file", null, name, null, null);
 1575           } catch (URISyntaxException e) {
 1576               // this should never happen
 1577               return null;
 1578           }
 1579       }
 1580   
 1581       /**
 1582        * Returns a Uniform Resource Locator for this file. The URL is system
 1583        * dependent and may not be transferable between different operating / file
 1584        * systems.
 1585        * 
 1586        * @return a URL for this file.
 1587        * @throws java.net.MalformedURLException
 1588        *             if the path cannot be transformed into a URL.
 1589        *
 1590        * @deprecated use {@link #toURI} and {@link java.net.URI#toURL} to get
 1591        * correct escaping of illegal characters.
 1592        */
 1593       @Deprecated
 1594       @SuppressWarnings("nls")
 1595       public URL toURL() throws java.net.MalformedURLException {
 1596           String name = getAbsoluteName();
 1597           if (!name.startsWith("/")) {
 1598               // start with sep.
 1599               return new URL(
 1600                       "file", EMPTY_STRING, -1, new StringBuilder(name.length() + 1) //$NON-NLS-1$ 
 1601                               .append('/').append(name).toString(), null);
 1602           } else if (name.startsWith("//")) {
 1603               return new URL("file:" + name); // UNC path
 1604           }
 1605           return new URL("file", EMPTY_STRING, -1, name, null);
 1606       }
 1607   
 1608       private String getAbsoluteName() {
 1609           File f = getAbsoluteFile();
 1610           String name = f.getPath();
 1611   
 1612           if (f.isDirectory() && name.charAt(name.length() - 1) != separatorChar) {
 1613               // Directories must end with a slash
 1614               name = new StringBuilder(name.length() + 1).append(name)
 1615                       .append('/').toString();
 1616           }
 1617           if (separatorChar != '/') { // Must convert slashes.
 1618               name = name.replace(separatorChar, '/');
 1619           }
 1620           return name;
 1621       }
 1622   
 1623       private void writeObject(ObjectOutputStream stream) throws IOException {
 1624           stream.defaultWriteObject();
 1625           stream.writeChar(separatorChar);
 1626   
 1627       }
 1628   
 1629       private void readObject(ObjectInputStream stream) throws IOException,
 1630               ClassNotFoundException {
 1631           stream.defaultReadObject();
 1632           char inSeparator = stream.readChar();
 1633           path = path.replace(inSeparator, separatorChar);
 1634       }
 1635       
 1636       /**
 1637   	 * Manipulates the execute permission of the abstract path designated by
 1638   	 * this file object.
 1639   	 * 
 1640   	 * @param executable
 1641   	 *            To allow execute permission if true, otherwise disallow
 1642   	 * @param ownerOnly
 1643   	 *            To manipulate execute permission only for owner if true,
 1644   	 *            otherwise for everyone. The manipulation will apply to
 1645   	 *            everyone regardless of this value if the underlying system
 1646   	 *            does not distinguish owner and other users.
 1647   	 * @return true if and only if the operation succeeded. If the user does not
 1648   	 *         have permission to change the access permissions of this abstract
 1649   	 *         pathname the operation will fail. If the underlying file system
 1650   	 *         does not support execute permission and the value of executable
 1651   	 *         is false, this operation will fail.
 1652   	 * @throws SecurityException -
 1653   	 *             If a security manager exists and
 1654   	 *             SecurityManager.checkWrite(java.lang.String) disallows write
 1655   	 *             permission to this file object
 1656   	 * @since 1.6
 1657   	 */
 1658   	public boolean setExecutable(boolean executable, boolean ownerOnly) {
 1659   		checkWrite();
 1660   		return (setExecutableImpl(properPath(true), executable, ownerOnly));
 1661   	}
 1662   
 1663   	/**
 1664   	 * A convenience method for setExecutable(boolean, boolean). An invocation
 1665   	 * of this method is the same as file.setExecutable(executable, true).
 1666   	 * 
 1667   	 * @param executable
 1668   	 *            To allow execute permission if true, otherwise disallow
 1669   	 * @return true if and only if the operation succeeded. If the user does not
 1670   	 *         have permission to change the access permissions of this abstract
 1671   	 *         pathname the operation will fail. If the underlying file system
 1672   	 *         does not support execute permission and the value of executable
 1673   	 *         is false, this operation will fail.
 1674   	 * @throws SecurityException -
 1675   	 *             If a security manager exists and
 1676   	 *             SecurityManager.checkWrite(java.lang.String) disallows write
 1677   	 *             permission to this file object
 1678   	 * @since 1.6
 1679   	 */
 1680   	public boolean setExecutable(boolean executable) {
 1681   		return setExecutable(executable, true);
 1682   	}
 1683   
 1684   	private native boolean setExecutableImpl(byte[] path, boolean executable,
 1685   			boolean ownerOnly);
 1686   	
 1687   	  
 1688   
 1689       /**
 1690        * Answers a boolean indicating whether or not the current context is
 1691        * allowed to execute this File.
 1692        * 
 1693        * @return <code>true</code> if this File can be executed,
 1694        *         <code>false</code> otherwise.
 1695        * 
 1696        * @throws SecurityException
 1697        *             If a security manager exists and
 1698        *             SecurityManager.checkExec(java.lang.String) disallows read
 1699        *             permission to this file object
 1700        * @see java.lang.SecurityManager#checkExec(String)
 1701        * 
 1702        * @since 1.6
 1703        */
 1704       public boolean canExecute() {
 1705           checkExec();
 1706           return exists() && isExecutableImpl(properPath(true));
 1707       }
 1708   
 1709       private native boolean isExecutableImpl(byte[] filePath);
 1710   
 1711       private void checkExec() {
 1712           SecurityManager security = System.getSecurityManager();
 1713           if (security != null) {
 1714               security.checkExec(path);
 1715           }
 1716       }
 1717   
 1718       private void checkWrite() {
 1719   		SecurityManager security = System.getSecurityManager();
 1720   		if (security != null) {
 1721   			security.checkWrite(path);
 1722   		}
 1723   	}
 1724   
 1725   }

Save This Page
Home » apache-harmony-6.0-src-r917296-snapshot » java » io » [javadoc | source]