emul/compact/src/main/java/java/io/File.java
branchjdk7-b147
changeset 1258 724f3e1ea53e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/emul/compact/src/main/java/java/io/File.java	Sat Sep 07 13:51:24 2013 +0200
     1.3 @@ -0,0 +1,2076 @@
     1.4 +/*
     1.5 + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.  Oracle designates this
    1.11 + * particular file as subject to the "Classpath" exception as provided
    1.12 + * by Oracle in the LICENSE file that accompanied this code.
    1.13 + *
    1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 + * version 2 for more details (a copy is included in the LICENSE file that
    1.18 + * accompanied this code).
    1.19 + *
    1.20 + * You should have received a copy of the GNU General Public License version
    1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 + *
    1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.25 + * or visit www.oracle.com if you need additional information or have any
    1.26 + * questions.
    1.27 + */
    1.28 +
    1.29 +package java.io;
    1.30 +
    1.31 +import java.net.URI;
    1.32 +import java.net.URL;
    1.33 +import java.net.MalformedURLException;
    1.34 +import java.net.URISyntaxException;
    1.35 +import java.util.List;
    1.36 +import java.util.ArrayList;
    1.37 +import java.security.AccessController;
    1.38 +import java.security.SecureRandom;
    1.39 +import java.nio.file.Path;
    1.40 +import java.nio.file.FileSystems;
    1.41 +import sun.security.action.GetPropertyAction;
    1.42 +
    1.43 +/**
    1.44 + * An abstract representation of file and directory pathnames.
    1.45 + *
    1.46 + * <p> User interfaces and operating systems use system-dependent <em>pathname
    1.47 + * strings</em> to name files and directories.  This class presents an
    1.48 + * abstract, system-independent view of hierarchical pathnames.  An
    1.49 + * <em>abstract pathname</em> has two components:
    1.50 + *
    1.51 + * <ol>
    1.52 + * <li> An optional system-dependent <em>prefix</em> string,
    1.53 + *      such as a disk-drive specifier, <code>"/"</code>&nbsp;for the UNIX root
    1.54 + *      directory, or <code>"\\\\"</code>&nbsp;for a Microsoft Windows UNC pathname, and
    1.55 + * <li> A sequence of zero or more string <em>names</em>.
    1.56 + * </ol>
    1.57 + *
    1.58 + * The first name in an abstract pathname may be a directory name or, in the
    1.59 + * case of Microsoft Windows UNC pathnames, a hostname.  Each subsequent name
    1.60 + * in an abstract pathname denotes a directory; the last name may denote
    1.61 + * either a directory or a file.  The <em>empty</em> abstract pathname has no
    1.62 + * prefix and an empty name sequence.
    1.63 + *
    1.64 + * <p> The conversion of a pathname string to or from an abstract pathname is
    1.65 + * inherently system-dependent.  When an abstract pathname is converted into a
    1.66 + * pathname string, each name is separated from the next by a single copy of
    1.67 + * the default <em>separator character</em>.  The default name-separator
    1.68 + * character is defined by the system property <code>file.separator</code>, and
    1.69 + * is made available in the public static fields <code>{@link
    1.70 + * #separator}</code> and <code>{@link #separatorChar}</code> of this class.
    1.71 + * When a pathname string is converted into an abstract pathname, the names
    1.72 + * within it may be separated by the default name-separator character or by any
    1.73 + * other name-separator character that is supported by the underlying system.
    1.74 + *
    1.75 + * <p> A pathname, whether abstract or in string form, may be either
    1.76 + * <em>absolute</em> or <em>relative</em>.  An absolute pathname is complete in
    1.77 + * that no other information is required in order to locate the file that it
    1.78 + * denotes.  A relative pathname, in contrast, must be interpreted in terms of
    1.79 + * information taken from some other pathname.  By default the classes in the
    1.80 + * <code>java.io</code> package always resolve relative pathnames against the
    1.81 + * current user directory.  This directory is named by the system property
    1.82 + * <code>user.dir</code>, and is typically the directory in which the Java
    1.83 + * virtual machine was invoked.
    1.84 + *
    1.85 + * <p> The <em>parent</em> of an abstract pathname may be obtained by invoking
    1.86 + * the {@link #getParent} method of this class and consists of the pathname's
    1.87 + * prefix and each name in the pathname's name sequence except for the last.
    1.88 + * Each directory's absolute pathname is an ancestor of any <tt>File</tt>
    1.89 + * object with an absolute abstract pathname which begins with the directory's
    1.90 + * absolute pathname.  For example, the directory denoted by the abstract
    1.91 + * pathname <tt>"/usr"</tt> is an ancestor of the directory denoted by the
    1.92 + * pathname <tt>"/usr/local/bin"</tt>.
    1.93 + *
    1.94 + * <p> The prefix concept is used to handle root directories on UNIX platforms,
    1.95 + * and drive specifiers, root directories and UNC pathnames on Microsoft Windows platforms,
    1.96 + * as follows:
    1.97 + *
    1.98 + * <ul>
    1.99 + *
   1.100 + * <li> For UNIX platforms, the prefix of an absolute pathname is always
   1.101 + * <code>"/"</code>.  Relative pathnames have no prefix.  The abstract pathname
   1.102 + * denoting the root directory has the prefix <code>"/"</code> and an empty
   1.103 + * name sequence.
   1.104 + *
   1.105 + * <li> For Microsoft Windows platforms, the prefix of a pathname that contains a drive
   1.106 + * specifier consists of the drive letter followed by <code>":"</code> and
   1.107 + * possibly followed by <code>"\\"</code> if the pathname is absolute.  The
   1.108 + * prefix of a UNC pathname is <code>"\\\\"</code>; the hostname and the share
   1.109 + * name are the first two names in the name sequence.  A relative pathname that
   1.110 + * does not specify a drive has no prefix.
   1.111 + *
   1.112 + * </ul>
   1.113 + *
   1.114 + * <p> Instances of this class may or may not denote an actual file-system
   1.115 + * object such as a file or a directory.  If it does denote such an object
   1.116 + * then that object resides in a <i>partition</i>.  A partition is an
   1.117 + * operating system-specific portion of storage for a file system.  A single
   1.118 + * storage device (e.g. a physical disk-drive, flash memory, CD-ROM) may
   1.119 + * contain multiple partitions.  The object, if any, will reside on the
   1.120 + * partition <a name="partName">named</a> by some ancestor of the absolute
   1.121 + * form of this pathname.
   1.122 + *
   1.123 + * <p> A file system may implement restrictions to certain operations on the
   1.124 + * actual file-system object, such as reading, writing, and executing.  These
   1.125 + * restrictions are collectively known as <i>access permissions</i>.  The file
   1.126 + * system may have multiple sets of access permissions on a single object.
   1.127 + * For example, one set may apply to the object's <i>owner</i>, and another
   1.128 + * may apply to all other users.  The access permissions on an object may
   1.129 + * cause some methods in this class to fail.
   1.130 + *
   1.131 + * <p> Instances of the <code>File</code> class are immutable; that is, once
   1.132 + * created, the abstract pathname represented by a <code>File</code> object
   1.133 + * will never change.
   1.134 + *
   1.135 + * <h4>Interoperability with {@code java.nio.file} package</h4>
   1.136 + *
   1.137 + * <p> The <a href="../../java/nio/file/package-summary.html">{@code java.nio.file}</a>
   1.138 + * package defines interfaces and classes for the Java virtual machine to access
   1.139 + * files, file attributes, and file systems. This API may be used to overcome
   1.140 + * many of the limitations of the {@code java.io.File} class.
   1.141 + * The {@link #toPath toPath} method may be used to obtain a {@link
   1.142 + * Path} that uses the abstract path represented by a {@code File} object to
   1.143 + * locate a file. The resulting {@code Path} may be used with the {@link
   1.144 + * java.nio.file.Files} class to provide more efficient and extensive access to
   1.145 + * additional file operations, file attributes, and I/O exceptions to help
   1.146 + * diagnose errors when an operation on a file fails.
   1.147 + *
   1.148 + * @author  unascribed
   1.149 + * @since   JDK1.0
   1.150 + */
   1.151 +
   1.152 +public class File
   1.153 +    implements Serializable, Comparable<File>
   1.154 +{
   1.155 +
   1.156 +    /**
   1.157 +     * The FileSystem object representing the platform's local file system.
   1.158 +     */
   1.159 +    static private FileSystem fs = FileSystem.getFileSystem();
   1.160 +
   1.161 +    /**
   1.162 +     * This abstract pathname's normalized pathname string.  A normalized
   1.163 +     * pathname string uses the default name-separator character and does not
   1.164 +     * contain any duplicate or redundant separators.
   1.165 +     *
   1.166 +     * @serial
   1.167 +     */
   1.168 +    private String path;
   1.169 +
   1.170 +    /**
   1.171 +     * The length of this abstract pathname's prefix, or zero if it has no
   1.172 +     * prefix.
   1.173 +     */
   1.174 +    private transient int prefixLength;
   1.175 +
   1.176 +    /**
   1.177 +     * Returns the length of this abstract pathname's prefix.
   1.178 +     * For use by FileSystem classes.
   1.179 +     */
   1.180 +    int getPrefixLength() {
   1.181 +        return prefixLength;
   1.182 +    }
   1.183 +
   1.184 +    /**
   1.185 +     * The system-dependent default name-separator character.  This field is
   1.186 +     * initialized to contain the first character of the value of the system
   1.187 +     * property <code>file.separator</code>.  On UNIX systems the value of this
   1.188 +     * field is <code>'/'</code>; on Microsoft Windows systems it is <code>'\\'</code>.
   1.189 +     *
   1.190 +     * @see     java.lang.System#getProperty(java.lang.String)
   1.191 +     */
   1.192 +    public static final char separatorChar = fs.getSeparator();
   1.193 +
   1.194 +    /**
   1.195 +     * The system-dependent default name-separator character, represented as a
   1.196 +     * string for convenience.  This string contains a single character, namely
   1.197 +     * <code>{@link #separatorChar}</code>.
   1.198 +     */
   1.199 +    public static final String separator = "" + separatorChar;
   1.200 +
   1.201 +    /**
   1.202 +     * The system-dependent path-separator character.  This field is
   1.203 +     * initialized to contain the first character of the value of the system
   1.204 +     * property <code>path.separator</code>.  This character is used to
   1.205 +     * separate filenames in a sequence of files given as a <em>path list</em>.
   1.206 +     * On UNIX systems, this character is <code>':'</code>; on Microsoft Windows systems it
   1.207 +     * is <code>';'</code>.
   1.208 +     *
   1.209 +     * @see     java.lang.System#getProperty(java.lang.String)
   1.210 +     */
   1.211 +    public static final char pathSeparatorChar = fs.getPathSeparator();
   1.212 +
   1.213 +    /**
   1.214 +     * The system-dependent path-separator character, represented as a string
   1.215 +     * for convenience.  This string contains a single character, namely
   1.216 +     * <code>{@link #pathSeparatorChar}</code>.
   1.217 +     */
   1.218 +    public static final String pathSeparator = "" + pathSeparatorChar;
   1.219 +
   1.220 +
   1.221 +    /* -- Constructors -- */
   1.222 +
   1.223 +    /**
   1.224 +     * Internal constructor for already-normalized pathname strings.
   1.225 +     */
   1.226 +    private File(String pathname, int prefixLength) {
   1.227 +        this.path = pathname;
   1.228 +        this.prefixLength = prefixLength;
   1.229 +    }
   1.230 +
   1.231 +    /**
   1.232 +     * Internal constructor for already-normalized pathname strings.
   1.233 +     * The parameter order is used to disambiguate this method from the
   1.234 +     * public(File, String) constructor.
   1.235 +     */
   1.236 +    private File(String child, File parent) {
   1.237 +        assert parent.path != null;
   1.238 +        assert (!parent.path.equals(""));
   1.239 +        this.path = fs.resolve(parent.path, child);
   1.240 +        this.prefixLength = parent.prefixLength;
   1.241 +    }
   1.242 +
   1.243 +    /**
   1.244 +     * Creates a new <code>File</code> instance by converting the given
   1.245 +     * pathname string into an abstract pathname.  If the given string is
   1.246 +     * the empty string, then the result is the empty abstract pathname.
   1.247 +     *
   1.248 +     * @param   pathname  A pathname string
   1.249 +     * @throws  NullPointerException
   1.250 +     *          If the <code>pathname</code> argument is <code>null</code>
   1.251 +     */
   1.252 +    public File(String pathname) {
   1.253 +        if (pathname == null) {
   1.254 +            throw new NullPointerException();
   1.255 +        }
   1.256 +        this.path = fs.normalize(pathname);
   1.257 +        this.prefixLength = fs.prefixLength(this.path);
   1.258 +    }
   1.259 +
   1.260 +    /* Note: The two-argument File constructors do not interpret an empty
   1.261 +       parent abstract pathname as the current user directory.  An empty parent
   1.262 +       instead causes the child to be resolved against the system-dependent
   1.263 +       directory defined by the FileSystem.getDefaultParent method.  On Unix
   1.264 +       this default is "/", while on Microsoft Windows it is "\\".  This is required for
   1.265 +       compatibility with the original behavior of this class. */
   1.266 +
   1.267 +    /**
   1.268 +     * Creates a new <code>File</code> instance from a parent pathname string
   1.269 +     * and a child pathname string.
   1.270 +     *
   1.271 +     * <p> If <code>parent</code> is <code>null</code> then the new
   1.272 +     * <code>File</code> instance is created as if by invoking the
   1.273 +     * single-argument <code>File</code> constructor on the given
   1.274 +     * <code>child</code> pathname string.
   1.275 +     *
   1.276 +     * <p> Otherwise the <code>parent</code> pathname string is taken to denote
   1.277 +     * a directory, and the <code>child</code> pathname string is taken to
   1.278 +     * denote either a directory or a file.  If the <code>child</code> pathname
   1.279 +     * string is absolute then it is converted into a relative pathname in a
   1.280 +     * system-dependent way.  If <code>parent</code> is the empty string then
   1.281 +     * the new <code>File</code> instance is created by converting
   1.282 +     * <code>child</code> into an abstract pathname and resolving the result
   1.283 +     * against a system-dependent default directory.  Otherwise each pathname
   1.284 +     * string is converted into an abstract pathname and the child abstract
   1.285 +     * pathname is resolved against the parent.
   1.286 +     *
   1.287 +     * @param   parent  The parent pathname string
   1.288 +     * @param   child   The child pathname string
   1.289 +     * @throws  NullPointerException
   1.290 +     *          If <code>child</code> is <code>null</code>
   1.291 +     */
   1.292 +    public File(String parent, String child) {
   1.293 +        if (child == null) {
   1.294 +            throw new NullPointerException();
   1.295 +        }
   1.296 +        if (parent != null) {
   1.297 +            if (parent.equals("")) {
   1.298 +                this.path = fs.resolve(fs.getDefaultParent(),
   1.299 +                                       fs.normalize(child));
   1.300 +            } else {
   1.301 +                this.path = fs.resolve(fs.normalize(parent),
   1.302 +                                       fs.normalize(child));
   1.303 +            }
   1.304 +        } else {
   1.305 +            this.path = fs.normalize(child);
   1.306 +        }
   1.307 +        this.prefixLength = fs.prefixLength(this.path);
   1.308 +    }
   1.309 +
   1.310 +    /**
   1.311 +     * Creates a new <code>File</code> instance from a parent abstract
   1.312 +     * pathname and a child pathname string.
   1.313 +     *
   1.314 +     * <p> If <code>parent</code> is <code>null</code> then the new
   1.315 +     * <code>File</code> instance is created as if by invoking the
   1.316 +     * single-argument <code>File</code> constructor on the given
   1.317 +     * <code>child</code> pathname string.
   1.318 +     *
   1.319 +     * <p> Otherwise the <code>parent</code> abstract pathname is taken to
   1.320 +     * denote a directory, and the <code>child</code> pathname string is taken
   1.321 +     * to denote either a directory or a file.  If the <code>child</code>
   1.322 +     * pathname string is absolute then it is converted into a relative
   1.323 +     * pathname in a system-dependent way.  If <code>parent</code> is the empty
   1.324 +     * abstract pathname then the new <code>File</code> instance is created by
   1.325 +     * converting <code>child</code> into an abstract pathname and resolving
   1.326 +     * the result against a system-dependent default directory.  Otherwise each
   1.327 +     * pathname string is converted into an abstract pathname and the child
   1.328 +     * abstract pathname is resolved against the parent.
   1.329 +     *
   1.330 +     * @param   parent  The parent abstract pathname
   1.331 +     * @param   child   The child pathname string
   1.332 +     * @throws  NullPointerException
   1.333 +     *          If <code>child</code> is <code>null</code>
   1.334 +     */
   1.335 +    public File(File parent, String child) {
   1.336 +        if (child == null) {
   1.337 +            throw new NullPointerException();
   1.338 +        }
   1.339 +        if (parent != null) {
   1.340 +            if (parent.path.equals("")) {
   1.341 +                this.path = fs.resolve(fs.getDefaultParent(),
   1.342 +                                       fs.normalize(child));
   1.343 +            } else {
   1.344 +                this.path = fs.resolve(parent.path,
   1.345 +                                       fs.normalize(child));
   1.346 +            }
   1.347 +        } else {
   1.348 +            this.path = fs.normalize(child);
   1.349 +        }
   1.350 +        this.prefixLength = fs.prefixLength(this.path);
   1.351 +    }
   1.352 +
   1.353 +    /**
   1.354 +     * Creates a new <tt>File</tt> instance by converting the given
   1.355 +     * <tt>file:</tt> URI into an abstract pathname.
   1.356 +     *
   1.357 +     * <p> The exact form of a <tt>file:</tt> URI is system-dependent, hence
   1.358 +     * the transformation performed by this constructor is also
   1.359 +     * system-dependent.
   1.360 +     *
   1.361 +     * <p> For a given abstract pathname <i>f</i> it is guaranteed that
   1.362 +     *
   1.363 +     * <blockquote><tt>
   1.364 +     * new File(</tt><i>&nbsp;f</i><tt>.{@link #toURI() toURI}()).equals(</tt><i>&nbsp;f</i><tt>.{@link #getAbsoluteFile() getAbsoluteFile}())
   1.365 +     * </tt></blockquote>
   1.366 +     *
   1.367 +     * so long as the original abstract pathname, the URI, and the new abstract
   1.368 +     * pathname are all created in (possibly different invocations of) the same
   1.369 +     * Java virtual machine.  This relationship typically does not hold,
   1.370 +     * however, when a <tt>file:</tt> URI that is created in a virtual machine
   1.371 +     * on one operating system is converted into an abstract pathname in a
   1.372 +     * virtual machine on a different operating system.
   1.373 +     *
   1.374 +     * @param  uri
   1.375 +     *         An absolute, hierarchical URI with a scheme equal to
   1.376 +     *         <tt>"file"</tt>, a non-empty path component, and undefined
   1.377 +     *         authority, query, and fragment components
   1.378 +     *
   1.379 +     * @throws  NullPointerException
   1.380 +     *          If <tt>uri</tt> is <tt>null</tt>
   1.381 +     *
   1.382 +     * @throws  IllegalArgumentException
   1.383 +     *          If the preconditions on the parameter do not hold
   1.384 +     *
   1.385 +     * @see #toURI()
   1.386 +     * @see java.net.URI
   1.387 +     * @since 1.4
   1.388 +     */
   1.389 +    public File(URI uri) {
   1.390 +
   1.391 +        // Check our many preconditions
   1.392 +        if (!uri.isAbsolute())
   1.393 +            throw new IllegalArgumentException("URI is not absolute");
   1.394 +        if (uri.isOpaque())
   1.395 +            throw new IllegalArgumentException("URI is not hierarchical");
   1.396 +        String scheme = uri.getScheme();
   1.397 +        if ((scheme == null) || !scheme.equalsIgnoreCase("file"))
   1.398 +            throw new IllegalArgumentException("URI scheme is not \"file\"");
   1.399 +        if (uri.getAuthority() != null)
   1.400 +            throw new IllegalArgumentException("URI has an authority component");
   1.401 +        if (uri.getFragment() != null)
   1.402 +            throw new IllegalArgumentException("URI has a fragment component");
   1.403 +        if (uri.getQuery() != null)
   1.404 +            throw new IllegalArgumentException("URI has a query component");
   1.405 +        String p = uri.getPath();
   1.406 +        if (p.equals(""))
   1.407 +            throw new IllegalArgumentException("URI path component is empty");
   1.408 +
   1.409 +        // Okay, now initialize
   1.410 +        p = fs.fromURIPath(p);
   1.411 +        if (File.separatorChar != '/')
   1.412 +            p = p.replace('/', File.separatorChar);
   1.413 +        this.path = fs.normalize(p);
   1.414 +        this.prefixLength = fs.prefixLength(this.path);
   1.415 +    }
   1.416 +
   1.417 +
   1.418 +    /* -- Path-component accessors -- */
   1.419 +
   1.420 +    /**
   1.421 +     * Returns the name of the file or directory denoted by this abstract
   1.422 +     * pathname.  This is just the last name in the pathname's name
   1.423 +     * sequence.  If the pathname's name sequence is empty, then the empty
   1.424 +     * string is returned.
   1.425 +     *
   1.426 +     * @return  The name of the file or directory denoted by this abstract
   1.427 +     *          pathname, or the empty string if this pathname's name sequence
   1.428 +     *          is empty
   1.429 +     */
   1.430 +    public String getName() {
   1.431 +        int index = path.lastIndexOf(separatorChar);
   1.432 +        if (index < prefixLength) return path.substring(prefixLength);
   1.433 +        return path.substring(index + 1);
   1.434 +    }
   1.435 +
   1.436 +    /**
   1.437 +     * Returns the pathname string of this abstract pathname's parent, or
   1.438 +     * <code>null</code> if this pathname does not name a parent directory.
   1.439 +     *
   1.440 +     * <p> The <em>parent</em> of an abstract pathname consists of the
   1.441 +     * pathname's prefix, if any, and each name in the pathname's name
   1.442 +     * sequence except for the last.  If the name sequence is empty then
   1.443 +     * the pathname does not name a parent directory.
   1.444 +     *
   1.445 +     * @return  The pathname string of the parent directory named by this
   1.446 +     *          abstract pathname, or <code>null</code> if this pathname
   1.447 +     *          does not name a parent
   1.448 +     */
   1.449 +    public String getParent() {
   1.450 +        int index = path.lastIndexOf(separatorChar);
   1.451 +        if (index < prefixLength) {
   1.452 +            if ((prefixLength > 0) && (path.length() > prefixLength))
   1.453 +                return path.substring(0, prefixLength);
   1.454 +            return null;
   1.455 +        }
   1.456 +        return path.substring(0, index);
   1.457 +    }
   1.458 +
   1.459 +    /**
   1.460 +     * Returns the abstract pathname of this abstract pathname's parent,
   1.461 +     * or <code>null</code> if this pathname does not name a parent
   1.462 +     * directory.
   1.463 +     *
   1.464 +     * <p> The <em>parent</em> of an abstract pathname consists of the
   1.465 +     * pathname's prefix, if any, and each name in the pathname's name
   1.466 +     * sequence except for the last.  If the name sequence is empty then
   1.467 +     * the pathname does not name a parent directory.
   1.468 +     *
   1.469 +     * @return  The abstract pathname of the parent directory named by this
   1.470 +     *          abstract pathname, or <code>null</code> if this pathname
   1.471 +     *          does not name a parent
   1.472 +     *
   1.473 +     * @since 1.2
   1.474 +     */
   1.475 +    public File getParentFile() {
   1.476 +        String p = this.getParent();
   1.477 +        if (p == null) return null;
   1.478 +        return new File(p, this.prefixLength);
   1.479 +    }
   1.480 +
   1.481 +    /**
   1.482 +     * Converts this abstract pathname into a pathname string.  The resulting
   1.483 +     * string uses the {@link #separator default name-separator character} to
   1.484 +     * separate the names in the name sequence.
   1.485 +     *
   1.486 +     * @return  The string form of this abstract pathname
   1.487 +     */
   1.488 +    public String getPath() {
   1.489 +        return path;
   1.490 +    }
   1.491 +
   1.492 +
   1.493 +    /* -- Path operations -- */
   1.494 +
   1.495 +    /**
   1.496 +     * Tests whether this abstract pathname is absolute.  The definition of
   1.497 +     * absolute pathname is system dependent.  On UNIX systems, a pathname is
   1.498 +     * absolute if its prefix is <code>"/"</code>.  On Microsoft Windows systems, a
   1.499 +     * pathname is absolute if its prefix is a drive specifier followed by
   1.500 +     * <code>"\\"</code>, or if its prefix is <code>"\\\\"</code>.
   1.501 +     *
   1.502 +     * @return  <code>true</code> if this abstract pathname is absolute,
   1.503 +     *          <code>false</code> otherwise
   1.504 +     */
   1.505 +    public boolean isAbsolute() {
   1.506 +        return fs.isAbsolute(this);
   1.507 +    }
   1.508 +
   1.509 +    /**
   1.510 +     * Returns the absolute pathname string of this abstract pathname.
   1.511 +     *
   1.512 +     * <p> If this abstract pathname is already absolute, then the pathname
   1.513 +     * string is simply returned as if by the <code>{@link #getPath}</code>
   1.514 +     * method.  If this abstract pathname is the empty abstract pathname then
   1.515 +     * the pathname string of the current user directory, which is named by the
   1.516 +     * system property <code>user.dir</code>, is returned.  Otherwise this
   1.517 +     * pathname is resolved in a system-dependent way.  On UNIX systems, a
   1.518 +     * relative pathname is made absolute by resolving it against the current
   1.519 +     * user directory.  On Microsoft Windows systems, a relative pathname is made absolute
   1.520 +     * by resolving it against the current directory of the drive named by the
   1.521 +     * pathname, if any; if not, it is resolved against the current user
   1.522 +     * directory.
   1.523 +     *
   1.524 +     * @return  The absolute pathname string denoting the same file or
   1.525 +     *          directory as this abstract pathname
   1.526 +     *
   1.527 +     * @throws  SecurityException
   1.528 +     *          If a required system property value cannot be accessed.
   1.529 +     *
   1.530 +     * @see     java.io.File#isAbsolute()
   1.531 +     */
   1.532 +    public String getAbsolutePath() {
   1.533 +        return fs.resolve(this);
   1.534 +    }
   1.535 +
   1.536 +    /**
   1.537 +     * Returns the absolute form of this abstract pathname.  Equivalent to
   1.538 +     * <code>new&nbsp;File(this.{@link #getAbsolutePath})</code>.
   1.539 +     *
   1.540 +     * @return  The absolute abstract pathname denoting the same file or
   1.541 +     *          directory as this abstract pathname
   1.542 +     *
   1.543 +     * @throws  SecurityException
   1.544 +     *          If a required system property value cannot be accessed.
   1.545 +     *
   1.546 +     * @since 1.2
   1.547 +     */
   1.548 +    public File getAbsoluteFile() {
   1.549 +        String absPath = getAbsolutePath();
   1.550 +        return new File(absPath, fs.prefixLength(absPath));
   1.551 +    }
   1.552 +
   1.553 +    /**
   1.554 +     * Returns the canonical pathname string of this abstract pathname.
   1.555 +     *
   1.556 +     * <p> A canonical pathname is both absolute and unique.  The precise
   1.557 +     * definition of canonical form is system-dependent.  This method first
   1.558 +     * converts this pathname to absolute form if necessary, as if by invoking the
   1.559 +     * {@link #getAbsolutePath} method, and then maps it to its unique form in a
   1.560 +     * system-dependent way.  This typically involves removing redundant names
   1.561 +     * such as <tt>"."</tt> and <tt>".."</tt> from the pathname, resolving
   1.562 +     * symbolic links (on UNIX platforms), and converting drive letters to a
   1.563 +     * standard case (on Microsoft Windows platforms).
   1.564 +     *
   1.565 +     * <p> Every pathname that denotes an existing file or directory has a
   1.566 +     * unique canonical form.  Every pathname that denotes a nonexistent file
   1.567 +     * or directory also has a unique canonical form.  The canonical form of
   1.568 +     * the pathname of a nonexistent file or directory may be different from
   1.569 +     * the canonical form of the same pathname after the file or directory is
   1.570 +     * created.  Similarly, the canonical form of the pathname of an existing
   1.571 +     * file or directory may be different from the canonical form of the same
   1.572 +     * pathname after the file or directory is deleted.
   1.573 +     *
   1.574 +     * @return  The canonical pathname string denoting the same file or
   1.575 +     *          directory as this abstract pathname
   1.576 +     *
   1.577 +     * @throws  IOException
   1.578 +     *          If an I/O error occurs, which is possible because the
   1.579 +     *          construction of the canonical pathname may require
   1.580 +     *          filesystem queries
   1.581 +     *
   1.582 +     * @throws  SecurityException
   1.583 +     *          If a required system property value cannot be accessed, or
   1.584 +     *          if a security manager exists and its <code>{@link
   1.585 +     *          java.lang.SecurityManager#checkRead}</code> method denies
   1.586 +     *          read access to the file
   1.587 +     *
   1.588 +     * @since   JDK1.1
   1.589 +     * @see     Path#toRealPath
   1.590 +     */
   1.591 +    public String getCanonicalPath() throws IOException {
   1.592 +        return fs.canonicalize(fs.resolve(this));
   1.593 +    }
   1.594 +
   1.595 +    /**
   1.596 +     * Returns the canonical form of this abstract pathname.  Equivalent to
   1.597 +     * <code>new&nbsp;File(this.{@link #getCanonicalPath})</code>.
   1.598 +     *
   1.599 +     * @return  The canonical pathname string denoting the same file or
   1.600 +     *          directory as this abstract pathname
   1.601 +     *
   1.602 +     * @throws  IOException
   1.603 +     *          If an I/O error occurs, which is possible because the
   1.604 +     *          construction of the canonical pathname may require
   1.605 +     *          filesystem queries
   1.606 +     *
   1.607 +     * @throws  SecurityException
   1.608 +     *          If a required system property value cannot be accessed, or
   1.609 +     *          if a security manager exists and its <code>{@link
   1.610 +     *          java.lang.SecurityManager#checkRead}</code> method denies
   1.611 +     *          read access to the file
   1.612 +     *
   1.613 +     * @since 1.2
   1.614 +     * @see     Path#toRealPath
   1.615 +     */
   1.616 +    public File getCanonicalFile() throws IOException {
   1.617 +        String canonPath = getCanonicalPath();
   1.618 +        return new File(canonPath, fs.prefixLength(canonPath));
   1.619 +    }
   1.620 +
   1.621 +    private static String slashify(String path, boolean isDirectory) {
   1.622 +        String p = path;
   1.623 +        if (File.separatorChar != '/')
   1.624 +            p = p.replace(File.separatorChar, '/');
   1.625 +        if (!p.startsWith("/"))
   1.626 +            p = "/" + p;
   1.627 +        if (!p.endsWith("/") && isDirectory)
   1.628 +            p = p + "/";
   1.629 +        return p;
   1.630 +    }
   1.631 +
   1.632 +    /**
   1.633 +     * Converts this abstract pathname into a <code>file:</code> URL.  The
   1.634 +     * exact form of the URL is system-dependent.  If it can be determined that
   1.635 +     * the file denoted by this abstract pathname is a directory, then the
   1.636 +     * resulting URL will end with a slash.
   1.637 +     *
   1.638 +     * @return  A URL object representing the equivalent file URL
   1.639 +     *
   1.640 +     * @throws  MalformedURLException
   1.641 +     *          If the path cannot be parsed as a URL
   1.642 +     *
   1.643 +     * @see     #toURI()
   1.644 +     * @see     java.net.URI
   1.645 +     * @see     java.net.URI#toURL()
   1.646 +     * @see     java.net.URL
   1.647 +     * @since   1.2
   1.648 +     *
   1.649 +     * @deprecated This method does not automatically escape characters that
   1.650 +     * are illegal in URLs.  It is recommended that new code convert an
   1.651 +     * abstract pathname into a URL by first converting it into a URI, via the
   1.652 +     * {@link #toURI() toURI} method, and then converting the URI into a URL
   1.653 +     * via the {@link java.net.URI#toURL() URI.toURL} method.
   1.654 +     */
   1.655 +    @Deprecated
   1.656 +    public URL toURL() throws MalformedURLException {
   1.657 +        return new URL("file", "", slashify(getAbsolutePath(), isDirectory()));
   1.658 +    }
   1.659 +
   1.660 +    /**
   1.661 +     * Constructs a <tt>file:</tt> URI that represents this abstract pathname.
   1.662 +     *
   1.663 +     * <p> The exact form of the URI is system-dependent.  If it can be
   1.664 +     * determined that the file denoted by this abstract pathname is a
   1.665 +     * directory, then the resulting URI will end with a slash.
   1.666 +     *
   1.667 +     * <p> For a given abstract pathname <i>f</i>, it is guaranteed that
   1.668 +     *
   1.669 +     * <blockquote><tt>
   1.670 +     * new {@link #File(java.net.URI) File}(</tt><i>&nbsp;f</i><tt>.toURI()).equals(</tt><i>&nbsp;f</i><tt>.{@link #getAbsoluteFile() getAbsoluteFile}())
   1.671 +     * </tt></blockquote>
   1.672 +     *
   1.673 +     * so long as the original abstract pathname, the URI, and the new abstract
   1.674 +     * pathname are all created in (possibly different invocations of) the same
   1.675 +     * Java virtual machine.  Due to the system-dependent nature of abstract
   1.676 +     * pathnames, however, this relationship typically does not hold when a
   1.677 +     * <tt>file:</tt> URI that is created in a virtual machine on one operating
   1.678 +     * system is converted into an abstract pathname in a virtual machine on a
   1.679 +     * different operating system.
   1.680 +     *
   1.681 +     * <p> Note that when this abstract pathname represents a UNC pathname then
   1.682 +     * all components of the UNC (including the server name component) are encoded
   1.683 +     * in the {@code URI} path. The authority component is undefined, meaning
   1.684 +     * that it is represented as {@code null}. The {@link Path} class defines the
   1.685 +     * {@link Path#toUri toUri} method to encode the server name in the authority
   1.686 +     * component of the resulting {@code URI}. The {@link #toPath toPath} method
   1.687 +     * may be used to obtain a {@code Path} representing this abstract pathname.
   1.688 +     *
   1.689 +     * @return  An absolute, hierarchical URI with a scheme equal to
   1.690 +     *          <tt>"file"</tt>, a path representing this abstract pathname,
   1.691 +     *          and undefined authority, query, and fragment components
   1.692 +     * @throws SecurityException If a required system property value cannot
   1.693 +     * be accessed.
   1.694 +     *
   1.695 +     * @see #File(java.net.URI)
   1.696 +     * @see java.net.URI
   1.697 +     * @see java.net.URI#toURL()
   1.698 +     * @since 1.4
   1.699 +     */
   1.700 +    public URI toURI() {
   1.701 +        try {
   1.702 +            File f = getAbsoluteFile();
   1.703 +            String sp = slashify(f.getPath(), f.isDirectory());
   1.704 +            if (sp.startsWith("//"))
   1.705 +                sp = "//" + sp;
   1.706 +            return new URI("file", null, sp, null);
   1.707 +        } catch (URISyntaxException x) {
   1.708 +            throw new Error(x);         // Can't happen
   1.709 +        }
   1.710 +    }
   1.711 +
   1.712 +
   1.713 +    /* -- Attribute accessors -- */
   1.714 +
   1.715 +    /**
   1.716 +     * Tests whether the application can read the file denoted by this
   1.717 +     * abstract pathname.
   1.718 +     *
   1.719 +     * @return  <code>true</code> if and only if the file specified by this
   1.720 +     *          abstract pathname exists <em>and</em> can be read by the
   1.721 +     *          application; <code>false</code> otherwise
   1.722 +     *
   1.723 +     * @throws  SecurityException
   1.724 +     *          If a security manager exists and its <code>{@link
   1.725 +     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
   1.726 +     *          method denies read access to the file
   1.727 +     */
   1.728 +    public boolean canRead() {
   1.729 +        SecurityManager security = System.getSecurityManager();
   1.730 +        if (security != null) {
   1.731 +            security.checkRead(path);
   1.732 +        }
   1.733 +        return fs.checkAccess(this, FileSystem.ACCESS_READ);
   1.734 +    }
   1.735 +
   1.736 +    /**
   1.737 +     * Tests whether the application can modify the file denoted by this
   1.738 +     * abstract pathname.
   1.739 +     *
   1.740 +     * @return  <code>true</code> if and only if the file system actually
   1.741 +     *          contains a file denoted by this abstract pathname <em>and</em>
   1.742 +     *          the application is allowed to write to the file;
   1.743 +     *          <code>false</code> otherwise.
   1.744 +     *
   1.745 +     * @throws  SecurityException
   1.746 +     *          If a security manager exists and its <code>{@link
   1.747 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
   1.748 +     *          method denies write access to the file
   1.749 +     */
   1.750 +    public boolean canWrite() {
   1.751 +        SecurityManager security = System.getSecurityManager();
   1.752 +        if (security != null) {
   1.753 +            security.checkWrite(path);
   1.754 +        }
   1.755 +        return fs.checkAccess(this, FileSystem.ACCESS_WRITE);
   1.756 +    }
   1.757 +
   1.758 +    /**
   1.759 +     * Tests whether the file or directory denoted by this abstract pathname
   1.760 +     * exists.
   1.761 +     *
   1.762 +     * @return  <code>true</code> if and only if the file or directory denoted
   1.763 +     *          by this abstract pathname exists; <code>false</code> otherwise
   1.764 +     *
   1.765 +     * @throws  SecurityException
   1.766 +     *          If a security manager exists and its <code>{@link
   1.767 +     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
   1.768 +     *          method denies read access to the file or directory
   1.769 +     */
   1.770 +    public boolean exists() {
   1.771 +        SecurityManager security = System.getSecurityManager();
   1.772 +        if (security != null) {
   1.773 +            security.checkRead(path);
   1.774 +        }
   1.775 +        return ((fs.getBooleanAttributes(this) & FileSystem.BA_EXISTS) != 0);
   1.776 +    }
   1.777 +
   1.778 +    /**
   1.779 +     * Tests whether the file denoted by this abstract pathname is a
   1.780 +     * directory.
   1.781 +     *
   1.782 +     * <p> Where it is required to distinguish an I/O exception from the case
   1.783 +     * that the file is not a directory, or where several attributes of the
   1.784 +     * same file are required at the same time, then the {@link
   1.785 +     * java.nio.file.Files#readAttributes(Path,Class,LinkOption[])
   1.786 +     * Files.readAttributes} method may be used.
   1.787 +     *
   1.788 +     * @return <code>true</code> if and only if the file denoted by this
   1.789 +     *          abstract pathname exists <em>and</em> is a directory;
   1.790 +     *          <code>false</code> otherwise
   1.791 +     *
   1.792 +     * @throws  SecurityException
   1.793 +     *          If a security manager exists and its <code>{@link
   1.794 +     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
   1.795 +     *          method denies read access to the file
   1.796 +     */
   1.797 +    public boolean isDirectory() {
   1.798 +        SecurityManager security = System.getSecurityManager();
   1.799 +        if (security != null) {
   1.800 +            security.checkRead(path);
   1.801 +        }
   1.802 +        return ((fs.getBooleanAttributes(this) & FileSystem.BA_DIRECTORY)
   1.803 +                != 0);
   1.804 +    }
   1.805 +
   1.806 +    /**
   1.807 +     * Tests whether the file denoted by this abstract pathname is a normal
   1.808 +     * file.  A file is <em>normal</em> if it is not a directory and, in
   1.809 +     * addition, satisfies other system-dependent criteria.  Any non-directory
   1.810 +     * file created by a Java application is guaranteed to be a normal file.
   1.811 +     *
   1.812 +     * <p> Where it is required to distinguish an I/O exception from the case
   1.813 +     * that the file is not a normal file, or where several attributes of the
   1.814 +     * same file are required at the same time, then the {@link
   1.815 +     * java.nio.file.Files#readAttributes(Path,Class,LinkOption[])
   1.816 +     * Files.readAttributes} method may be used.
   1.817 +     *
   1.818 +     * @return  <code>true</code> if and only if the file denoted by this
   1.819 +     *          abstract pathname exists <em>and</em> is a normal file;
   1.820 +     *          <code>false</code> otherwise
   1.821 +     *
   1.822 +     * @throws  SecurityException
   1.823 +     *          If a security manager exists and its <code>{@link
   1.824 +     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
   1.825 +     *          method denies read access to the file
   1.826 +     */
   1.827 +    public boolean isFile() {
   1.828 +        SecurityManager security = System.getSecurityManager();
   1.829 +        if (security != null) {
   1.830 +            security.checkRead(path);
   1.831 +        }
   1.832 +        return ((fs.getBooleanAttributes(this) & FileSystem.BA_REGULAR) != 0);
   1.833 +    }
   1.834 +
   1.835 +    /**
   1.836 +     * Tests whether the file named by this abstract pathname is a hidden
   1.837 +     * file.  The exact definition of <em>hidden</em> is system-dependent.  On
   1.838 +     * UNIX systems, a file is considered to be hidden if its name begins with
   1.839 +     * a period character (<code>'.'</code>).  On Microsoft Windows systems, a file is
   1.840 +     * considered to be hidden if it has been marked as such in the filesystem.
   1.841 +     *
   1.842 +     * @return  <code>true</code> if and only if the file denoted by this
   1.843 +     *          abstract pathname is hidden according to the conventions of the
   1.844 +     *          underlying platform
   1.845 +     *
   1.846 +     * @throws  SecurityException
   1.847 +     *          If a security manager exists and its <code>{@link
   1.848 +     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
   1.849 +     *          method denies read access to the file
   1.850 +     *
   1.851 +     * @since 1.2
   1.852 +     */
   1.853 +    public boolean isHidden() {
   1.854 +        SecurityManager security = System.getSecurityManager();
   1.855 +        if (security != null) {
   1.856 +            security.checkRead(path);
   1.857 +        }
   1.858 +        return ((fs.getBooleanAttributes(this) & FileSystem.BA_HIDDEN) != 0);
   1.859 +    }
   1.860 +
   1.861 +    /**
   1.862 +     * Returns the time that the file denoted by this abstract pathname was
   1.863 +     * last modified.
   1.864 +     *
   1.865 +     * <p> Where it is required to distinguish an I/O exception from the case
   1.866 +     * where {@code 0L} is returned, or where several attributes of the
   1.867 +     * same file are required at the same time, or where the time of last
   1.868 +     * access or the creation time are required, then the {@link
   1.869 +     * java.nio.file.Files#readAttributes(Path,Class,LinkOption[])
   1.870 +     * Files.readAttributes} method may be used.
   1.871 +     *
   1.872 +     * @return  A <code>long</code> value representing the time the file was
   1.873 +     *          last modified, measured in milliseconds since the epoch
   1.874 +     *          (00:00:00 GMT, January 1, 1970), or <code>0L</code> if the
   1.875 +     *          file does not exist or if an I/O error occurs
   1.876 +     *
   1.877 +     * @throws  SecurityException
   1.878 +     *          If a security manager exists and its <code>{@link
   1.879 +     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
   1.880 +     *          method denies read access to the file
   1.881 +     */
   1.882 +    public long lastModified() {
   1.883 +        SecurityManager security = System.getSecurityManager();
   1.884 +        if (security != null) {
   1.885 +            security.checkRead(path);
   1.886 +        }
   1.887 +        return fs.getLastModifiedTime(this);
   1.888 +    }
   1.889 +
   1.890 +    /**
   1.891 +     * Returns the length of the file denoted by this abstract pathname.
   1.892 +     * The return value is unspecified if this pathname denotes a directory.
   1.893 +     *
   1.894 +     * <p> Where it is required to distinguish an I/O exception from the case
   1.895 +     * that {@code 0L} is returned, or where several attributes of the same file
   1.896 +     * are required at the same time, then the {@link
   1.897 +     * java.nio.file.Files#readAttributes(Path,Class,LinkOption[])
   1.898 +     * Files.readAttributes} method may be used.
   1.899 +     *
   1.900 +     * @return  The length, in bytes, of the file denoted by this abstract
   1.901 +     *          pathname, or <code>0L</code> if the file does not exist.  Some
   1.902 +     *          operating systems may return <code>0L</code> for pathnames
   1.903 +     *          denoting system-dependent entities such as devices or pipes.
   1.904 +     *
   1.905 +     * @throws  SecurityException
   1.906 +     *          If a security manager exists and its <code>{@link
   1.907 +     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
   1.908 +     *          method denies read access to the file
   1.909 +     */
   1.910 +    public long length() {
   1.911 +        SecurityManager security = System.getSecurityManager();
   1.912 +        if (security != null) {
   1.913 +            security.checkRead(path);
   1.914 +        }
   1.915 +        return fs.getLength(this);
   1.916 +    }
   1.917 +
   1.918 +
   1.919 +    /* -- File operations -- */
   1.920 +
   1.921 +    /**
   1.922 +     * Atomically creates a new, empty file named by this abstract pathname if
   1.923 +     * and only if a file with this name does not yet exist.  The check for the
   1.924 +     * existence of the file and the creation of the file if it does not exist
   1.925 +     * are a single operation that is atomic with respect to all other
   1.926 +     * filesystem activities that might affect the file.
   1.927 +     * <P>
   1.928 +     * Note: this method should <i>not</i> be used for file-locking, as
   1.929 +     * the resulting protocol cannot be made to work reliably. The
   1.930 +     * {@link java.nio.channels.FileLock FileLock}
   1.931 +     * facility should be used instead.
   1.932 +     *
   1.933 +     * @return  <code>true</code> if the named file does not exist and was
   1.934 +     *          successfully created; <code>false</code> if the named file
   1.935 +     *          already exists
   1.936 +     *
   1.937 +     * @throws  IOException
   1.938 +     *          If an I/O error occurred
   1.939 +     *
   1.940 +     * @throws  SecurityException
   1.941 +     *          If a security manager exists and its <code>{@link
   1.942 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
   1.943 +     *          method denies write access to the file
   1.944 +     *
   1.945 +     * @since 1.2
   1.946 +     */
   1.947 +    public boolean createNewFile() throws IOException {
   1.948 +        SecurityManager security = System.getSecurityManager();
   1.949 +        if (security != null) security.checkWrite(path);
   1.950 +        return fs.createFileExclusively(path);
   1.951 +    }
   1.952 +
   1.953 +    /**
   1.954 +     * Deletes the file or directory denoted by this abstract pathname.  If
   1.955 +     * this pathname denotes a directory, then the directory must be empty in
   1.956 +     * order to be deleted.
   1.957 +     *
   1.958 +     * <p> Note that the {@link java.nio.file.Files} class defines the {@link
   1.959 +     * java.nio.file.Files#delete(Path) delete} method to throw an {@link IOException}
   1.960 +     * when a file cannot be deleted. This is useful for error reporting and to
   1.961 +     * diagnose why a file cannot be deleted.
   1.962 +     *
   1.963 +     * @return  <code>true</code> if and only if the file or directory is
   1.964 +     *          successfully deleted; <code>false</code> otherwise
   1.965 +     *
   1.966 +     * @throws  SecurityException
   1.967 +     *          If a security manager exists and its <code>{@link
   1.968 +     *          java.lang.SecurityManager#checkDelete}</code> method denies
   1.969 +     *          delete access to the file
   1.970 +     */
   1.971 +    public boolean delete() {
   1.972 +        SecurityManager security = System.getSecurityManager();
   1.973 +        if (security != null) {
   1.974 +            security.checkDelete(path);
   1.975 +        }
   1.976 +        return fs.delete(this);
   1.977 +    }
   1.978 +
   1.979 +    /**
   1.980 +     * Requests that the file or directory denoted by this abstract
   1.981 +     * pathname be deleted when the virtual machine terminates.
   1.982 +     * Files (or directories) are deleted in the reverse order that
   1.983 +     * they are registered. Invoking this method to delete a file or
   1.984 +     * directory that is already registered for deletion has no effect.
   1.985 +     * Deletion will be attempted only for normal termination of the
   1.986 +     * virtual machine, as defined by the Java Language Specification.
   1.987 +     *
   1.988 +     * <p> Once deletion has been requested, it is not possible to cancel the
   1.989 +     * request.  This method should therefore be used with care.
   1.990 +     *
   1.991 +     * <P>
   1.992 +     * Note: this method should <i>not</i> be used for file-locking, as
   1.993 +     * the resulting protocol cannot be made to work reliably. The
   1.994 +     * {@link java.nio.channels.FileLock FileLock}
   1.995 +     * facility should be used instead.
   1.996 +     *
   1.997 +     * @throws  SecurityException
   1.998 +     *          If a security manager exists and its <code>{@link
   1.999 +     *          java.lang.SecurityManager#checkDelete}</code> method denies
  1.1000 +     *          delete access to the file
  1.1001 +     *
  1.1002 +     * @see #delete
  1.1003 +     *
  1.1004 +     * @since 1.2
  1.1005 +     */
  1.1006 +    public void deleteOnExit() {
  1.1007 +        SecurityManager security = System.getSecurityManager();
  1.1008 +        if (security != null) {
  1.1009 +            security.checkDelete(path);
  1.1010 +        }
  1.1011 +        DeleteOnExitHook.add(path);
  1.1012 +    }
  1.1013 +
  1.1014 +    /**
  1.1015 +     * Returns an array of strings naming the files and directories in the
  1.1016 +     * directory denoted by this abstract pathname.
  1.1017 +     *
  1.1018 +     * <p> If this abstract pathname does not denote a directory, then this
  1.1019 +     * method returns {@code null}.  Otherwise an array of strings is
  1.1020 +     * returned, one for each file or directory in the directory.  Names
  1.1021 +     * denoting the directory itself and the directory's parent directory are
  1.1022 +     * not included in the result.  Each string is a file name rather than a
  1.1023 +     * complete path.
  1.1024 +     *
  1.1025 +     * <p> There is no guarantee that the name strings in the resulting array
  1.1026 +     * will appear in any specific order; they are not, in particular,
  1.1027 +     * guaranteed to appear in alphabetical order.
  1.1028 +     *
  1.1029 +     * <p> Note that the {@link java.nio.file.Files} class defines the {@link
  1.1030 +     * java.nio.file.Files#newDirectoryStream(Path) newDirectoryStream} method to
  1.1031 +     * open a directory and iterate over the names of the files in the directory.
  1.1032 +     * This may use less resources when working with very large directories, and
  1.1033 +     * may be more responsive when working with remote directories.
  1.1034 +     *
  1.1035 +     * @return  An array of strings naming the files and directories in the
  1.1036 +     *          directory denoted by this abstract pathname.  The array will be
  1.1037 +     *          empty if the directory is empty.  Returns {@code null} if
  1.1038 +     *          this abstract pathname does not denote a directory, or if an
  1.1039 +     *          I/O error occurs.
  1.1040 +     *
  1.1041 +     * @throws  SecurityException
  1.1042 +     *          If a security manager exists and its {@link
  1.1043 +     *          SecurityManager#checkRead(String)} method denies read access to
  1.1044 +     *          the directory
  1.1045 +     */
  1.1046 +    public String[] list() {
  1.1047 +        SecurityManager security = System.getSecurityManager();
  1.1048 +        if (security != null) {
  1.1049 +            security.checkRead(path);
  1.1050 +        }
  1.1051 +        return fs.list(this);
  1.1052 +    }
  1.1053 +
  1.1054 +    /**
  1.1055 +     * Returns an array of strings naming the files and directories in the
  1.1056 +     * directory denoted by this abstract pathname that satisfy the specified
  1.1057 +     * filter.  The behavior of this method is the same as that of the
  1.1058 +     * {@link #list()} method, except that the strings in the returned array
  1.1059 +     * must satisfy the filter.  If the given {@code filter} is {@code null}
  1.1060 +     * then all names are accepted.  Otherwise, a name satisfies the filter if
  1.1061 +     * and only if the value {@code true} results when the {@link
  1.1062 +     * FilenameFilter#accept FilenameFilter.accept(File,&nbsp;String)} method
  1.1063 +     * of the filter is invoked on this abstract pathname and the name of a
  1.1064 +     * file or directory in the directory that it denotes.
  1.1065 +     *
  1.1066 +     * @param  filter
  1.1067 +     *         A filename filter
  1.1068 +     *
  1.1069 +     * @return  An array of strings naming the files and directories in the
  1.1070 +     *          directory denoted by this abstract pathname that were accepted
  1.1071 +     *          by the given {@code filter}.  The array will be empty if the
  1.1072 +     *          directory is empty or if no names were accepted by the filter.
  1.1073 +     *          Returns {@code null} if this abstract pathname does not denote
  1.1074 +     *          a directory, or if an I/O error occurs.
  1.1075 +     *
  1.1076 +     * @throws  SecurityException
  1.1077 +     *          If a security manager exists and its {@link
  1.1078 +     *          SecurityManager#checkRead(String)} method denies read access to
  1.1079 +     *          the directory
  1.1080 +     *
  1.1081 +     * @see java.nio.file.Files#newDirectoryStream(Path,String)
  1.1082 +     */
  1.1083 +    public String[] list(FilenameFilter filter) {
  1.1084 +        String names[] = list();
  1.1085 +        if ((names == null) || (filter == null)) {
  1.1086 +            return names;
  1.1087 +        }
  1.1088 +        List<String> v = new ArrayList<>();
  1.1089 +        for (int i = 0 ; i < names.length ; i++) {
  1.1090 +            if (filter.accept(this, names[i])) {
  1.1091 +                v.add(names[i]);
  1.1092 +            }
  1.1093 +        }
  1.1094 +        return v.toArray(new String[v.size()]);
  1.1095 +    }
  1.1096 +
  1.1097 +    /**
  1.1098 +     * Returns an array of abstract pathnames denoting the files in the
  1.1099 +     * directory denoted by this abstract pathname.
  1.1100 +     *
  1.1101 +     * <p> If this abstract pathname does not denote a directory, then this
  1.1102 +     * method returns {@code null}.  Otherwise an array of {@code File} objects
  1.1103 +     * is returned, one for each file or directory in the directory.  Pathnames
  1.1104 +     * denoting the directory itself and the directory's parent directory are
  1.1105 +     * not included in the result.  Each resulting abstract pathname is
  1.1106 +     * constructed from this abstract pathname using the {@link #File(File,
  1.1107 +     * String) File(File,&nbsp;String)} constructor.  Therefore if this
  1.1108 +     * pathname is absolute then each resulting pathname is absolute; if this
  1.1109 +     * pathname is relative then each resulting pathname will be relative to
  1.1110 +     * the same directory.
  1.1111 +     *
  1.1112 +     * <p> There is no guarantee that the name strings in the resulting array
  1.1113 +     * will appear in any specific order; they are not, in particular,
  1.1114 +     * guaranteed to appear in alphabetical order.
  1.1115 +     *
  1.1116 +     * <p> Note that the {@link java.nio.file.Files} class defines the {@link
  1.1117 +     * java.nio.file.Files#newDirectoryStream(Path) newDirectoryStream} method
  1.1118 +     * to open a directory and iterate over the names of the files in the
  1.1119 +     * directory. This may use less resources when working with very large
  1.1120 +     * directories.
  1.1121 +     *
  1.1122 +     * @return  An array of abstract pathnames denoting the files and
  1.1123 +     *          directories in the directory denoted by this abstract pathname.
  1.1124 +     *          The array will be empty if the directory is empty.  Returns
  1.1125 +     *          {@code null} if this abstract pathname does not denote a
  1.1126 +     *          directory, or if an I/O error occurs.
  1.1127 +     *
  1.1128 +     * @throws  SecurityException
  1.1129 +     *          If a security manager exists and its {@link
  1.1130 +     *          SecurityManager#checkRead(String)} method denies read access to
  1.1131 +     *          the directory
  1.1132 +     *
  1.1133 +     * @since  1.2
  1.1134 +     */
  1.1135 +    public File[] listFiles() {
  1.1136 +        String[] ss = list();
  1.1137 +        if (ss == null) return null;
  1.1138 +        int n = ss.length;
  1.1139 +        File[] fs = new File[n];
  1.1140 +        for (int i = 0; i < n; i++) {
  1.1141 +            fs[i] = new File(ss[i], this);
  1.1142 +        }
  1.1143 +        return fs;
  1.1144 +    }
  1.1145 +
  1.1146 +    /**
  1.1147 +     * Returns an array of abstract pathnames denoting the files and
  1.1148 +     * directories in the directory denoted by this abstract pathname that
  1.1149 +     * satisfy the specified filter.  The behavior of this method is the same
  1.1150 +     * as that of the {@link #listFiles()} method, except that the pathnames in
  1.1151 +     * the returned array must satisfy the filter.  If the given {@code filter}
  1.1152 +     * is {@code null} then all pathnames are accepted.  Otherwise, a pathname
  1.1153 +     * satisfies the filter if and only if the value {@code true} results when
  1.1154 +     * the {@link FilenameFilter#accept
  1.1155 +     * FilenameFilter.accept(File,&nbsp;String)} method of the filter is
  1.1156 +     * invoked on this abstract pathname and the name of a file or directory in
  1.1157 +     * the directory that it denotes.
  1.1158 +     *
  1.1159 +     * @param  filter
  1.1160 +     *         A filename filter
  1.1161 +     *
  1.1162 +     * @return  An array of abstract pathnames denoting the files and
  1.1163 +     *          directories in the directory denoted by this abstract pathname.
  1.1164 +     *          The array will be empty if the directory is empty.  Returns
  1.1165 +     *          {@code null} if this abstract pathname does not denote a
  1.1166 +     *          directory, or if an I/O error occurs.
  1.1167 +     *
  1.1168 +     * @throws  SecurityException
  1.1169 +     *          If a security manager exists and its {@link
  1.1170 +     *          SecurityManager#checkRead(String)} method denies read access to
  1.1171 +     *          the directory
  1.1172 +     *
  1.1173 +     * @since  1.2
  1.1174 +     * @see java.nio.file.Files#newDirectoryStream(Path,String)
  1.1175 +     */
  1.1176 +    public File[] listFiles(FilenameFilter filter) {
  1.1177 +        String ss[] = list();
  1.1178 +        if (ss == null) return null;
  1.1179 +        ArrayList<File> files = new ArrayList<>();
  1.1180 +        for (String s : ss)
  1.1181 +            if ((filter == null) || filter.accept(this, s))
  1.1182 +                files.add(new File(s, this));
  1.1183 +        return files.toArray(new File[files.size()]);
  1.1184 +    }
  1.1185 +
  1.1186 +    /**
  1.1187 +     * Returns an array of abstract pathnames denoting the files and
  1.1188 +     * directories in the directory denoted by this abstract pathname that
  1.1189 +     * satisfy the specified filter.  The behavior of this method is the same
  1.1190 +     * as that of the {@link #listFiles()} method, except that the pathnames in
  1.1191 +     * the returned array must satisfy the filter.  If the given {@code filter}
  1.1192 +     * is {@code null} then all pathnames are accepted.  Otherwise, a pathname
  1.1193 +     * satisfies the filter if and only if the value {@code true} results when
  1.1194 +     * the {@link FileFilter#accept FileFilter.accept(File)} method of the
  1.1195 +     * filter is invoked on the pathname.
  1.1196 +     *
  1.1197 +     * @param  filter
  1.1198 +     *         A file filter
  1.1199 +     *
  1.1200 +     * @return  An array of abstract pathnames denoting the files and
  1.1201 +     *          directories in the directory denoted by this abstract pathname.
  1.1202 +     *          The array will be empty if the directory is empty.  Returns
  1.1203 +     *          {@code null} if this abstract pathname does not denote a
  1.1204 +     *          directory, or if an I/O error occurs.
  1.1205 +     *
  1.1206 +     * @throws  SecurityException
  1.1207 +     *          If a security manager exists and its {@link
  1.1208 +     *          SecurityManager#checkRead(String)} method denies read access to
  1.1209 +     *          the directory
  1.1210 +     *
  1.1211 +     * @since  1.2
  1.1212 +     * @see java.nio.file.Files#newDirectoryStream(Path,java.nio.file.DirectoryStream.Filter)
  1.1213 +     */
  1.1214 +    public File[] listFiles(FileFilter filter) {
  1.1215 +        String ss[] = list();
  1.1216 +        if (ss == null) return null;
  1.1217 +        ArrayList<File> files = new ArrayList<>();
  1.1218 +        for (String s : ss) {
  1.1219 +            File f = new File(s, this);
  1.1220 +            if ((filter == null) || filter.accept(f))
  1.1221 +                files.add(f);
  1.1222 +        }
  1.1223 +        return files.toArray(new File[files.size()]);
  1.1224 +    }
  1.1225 +
  1.1226 +    /**
  1.1227 +     * Creates the directory named by this abstract pathname.
  1.1228 +     *
  1.1229 +     * @return  <code>true</code> if and only if the directory was
  1.1230 +     *          created; <code>false</code> otherwise
  1.1231 +     *
  1.1232 +     * @throws  SecurityException
  1.1233 +     *          If a security manager exists and its <code>{@link
  1.1234 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
  1.1235 +     *          method does not permit the named directory to be created
  1.1236 +     */
  1.1237 +    public boolean mkdir() {
  1.1238 +        SecurityManager security = System.getSecurityManager();
  1.1239 +        if (security != null) {
  1.1240 +            security.checkWrite(path);
  1.1241 +        }
  1.1242 +        return fs.createDirectory(this);
  1.1243 +    }
  1.1244 +
  1.1245 +    /**
  1.1246 +     * Creates the directory named by this abstract pathname, including any
  1.1247 +     * necessary but nonexistent parent directories.  Note that if this
  1.1248 +     * operation fails it may have succeeded in creating some of the necessary
  1.1249 +     * parent directories.
  1.1250 +     *
  1.1251 +     * @return  <code>true</code> if and only if the directory was created,
  1.1252 +     *          along with all necessary parent directories; <code>false</code>
  1.1253 +     *          otherwise
  1.1254 +     *
  1.1255 +     * @throws  SecurityException
  1.1256 +     *          If a security manager exists and its <code>{@link
  1.1257 +     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
  1.1258 +     *          method does not permit verification of the existence of the
  1.1259 +     *          named directory and all necessary parent directories; or if
  1.1260 +     *          the <code>{@link
  1.1261 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
  1.1262 +     *          method does not permit the named directory and all necessary
  1.1263 +     *          parent directories to be created
  1.1264 +     */
  1.1265 +    public boolean mkdirs() {
  1.1266 +        if (exists()) {
  1.1267 +            return false;
  1.1268 +        }
  1.1269 +        if (mkdir()) {
  1.1270 +            return true;
  1.1271 +        }
  1.1272 +        File canonFile = null;
  1.1273 +        try {
  1.1274 +            canonFile = getCanonicalFile();
  1.1275 +        } catch (IOException e) {
  1.1276 +            return false;
  1.1277 +        }
  1.1278 +
  1.1279 +        File parent = canonFile.getParentFile();
  1.1280 +        return (parent != null && (parent.mkdirs() || parent.exists()) &&
  1.1281 +                canonFile.mkdir());
  1.1282 +    }
  1.1283 +
  1.1284 +    /**
  1.1285 +     * Renames the file denoted by this abstract pathname.
  1.1286 +     *
  1.1287 +     * <p> Many aspects of the behavior of this method are inherently
  1.1288 +     * platform-dependent: The rename operation might not be able to move a
  1.1289 +     * file from one filesystem to another, it might not be atomic, and it
  1.1290 +     * might not succeed if a file with the destination abstract pathname
  1.1291 +     * already exists.  The return value should always be checked to make sure
  1.1292 +     * that the rename operation was successful.
  1.1293 +     *
  1.1294 +     * <p> Note that the {@link java.nio.file.Files} class defines the {@link
  1.1295 +     * java.nio.file.Files#move move} method to move or rename a file in a
  1.1296 +     * platform independent manner.
  1.1297 +     *
  1.1298 +     * @param  dest  The new abstract pathname for the named file
  1.1299 +     *
  1.1300 +     * @return  <code>true</code> if and only if the renaming succeeded;
  1.1301 +     *          <code>false</code> otherwise
  1.1302 +     *
  1.1303 +     * @throws  SecurityException
  1.1304 +     *          If a security manager exists and its <code>{@link
  1.1305 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
  1.1306 +     *          method denies write access to either the old or new pathnames
  1.1307 +     *
  1.1308 +     * @throws  NullPointerException
  1.1309 +     *          If parameter <code>dest</code> is <code>null</code>
  1.1310 +     */
  1.1311 +    public boolean renameTo(File dest) {
  1.1312 +        SecurityManager security = System.getSecurityManager();
  1.1313 +        if (security != null) {
  1.1314 +            security.checkWrite(path);
  1.1315 +            security.checkWrite(dest.path);
  1.1316 +        }
  1.1317 +        return fs.rename(this, dest);
  1.1318 +    }
  1.1319 +
  1.1320 +    /**
  1.1321 +     * Sets the last-modified time of the file or directory named by this
  1.1322 +     * abstract pathname.
  1.1323 +     *
  1.1324 +     * <p> All platforms support file-modification times to the nearest second,
  1.1325 +     * but some provide more precision.  The argument will be truncated to fit
  1.1326 +     * the supported precision.  If the operation succeeds and no intervening
  1.1327 +     * operations on the file take place, then the next invocation of the
  1.1328 +     * <code>{@link #lastModified}</code> method will return the (possibly
  1.1329 +     * truncated) <code>time</code> argument that was passed to this method.
  1.1330 +     *
  1.1331 +     * @param  time  The new last-modified time, measured in milliseconds since
  1.1332 +     *               the epoch (00:00:00 GMT, January 1, 1970)
  1.1333 +     *
  1.1334 +     * @return <code>true</code> if and only if the operation succeeded;
  1.1335 +     *          <code>false</code> otherwise
  1.1336 +     *
  1.1337 +     * @throws  IllegalArgumentException  If the argument is negative
  1.1338 +     *
  1.1339 +     * @throws  SecurityException
  1.1340 +     *          If a security manager exists and its <code>{@link
  1.1341 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
  1.1342 +     *          method denies write access to the named file
  1.1343 +     *
  1.1344 +     * @since 1.2
  1.1345 +     */
  1.1346 +    public boolean setLastModified(long time) {
  1.1347 +        if (time < 0) throw new IllegalArgumentException("Negative time");
  1.1348 +        SecurityManager security = System.getSecurityManager();
  1.1349 +        if (security != null) {
  1.1350 +            security.checkWrite(path);
  1.1351 +        }
  1.1352 +        return fs.setLastModifiedTime(this, time);
  1.1353 +    }
  1.1354 +
  1.1355 +    /**
  1.1356 +     * Marks the file or directory named by this abstract pathname so that
  1.1357 +     * only read operations are allowed.  After invoking this method the file
  1.1358 +     * or directory is guaranteed not to change until it is either deleted or
  1.1359 +     * marked to allow write access.  Whether or not a read-only file or
  1.1360 +     * directory may be deleted depends upon the underlying system.
  1.1361 +     *
  1.1362 +     * @return <code>true</code> if and only if the operation succeeded;
  1.1363 +     *          <code>false</code> otherwise
  1.1364 +     *
  1.1365 +     * @throws  SecurityException
  1.1366 +     *          If a security manager exists and its <code>{@link
  1.1367 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
  1.1368 +     *          method denies write access to the named file
  1.1369 +     *
  1.1370 +     * @since 1.2
  1.1371 +     */
  1.1372 +    public boolean setReadOnly() {
  1.1373 +        SecurityManager security = System.getSecurityManager();
  1.1374 +        if (security != null) {
  1.1375 +            security.checkWrite(path);
  1.1376 +        }
  1.1377 +        return fs.setReadOnly(this);
  1.1378 +    }
  1.1379 +
  1.1380 +    /**
  1.1381 +     * Sets the owner's or everybody's write permission for this abstract
  1.1382 +     * pathname.
  1.1383 +     *
  1.1384 +     * <p> The {@link java.nio.file.Files} class defines methods that operate on
  1.1385 +     * file attributes including file permissions. This may be used when finer
  1.1386 +     * manipulation of file permissions is required.
  1.1387 +     *
  1.1388 +     * @param   writable
  1.1389 +     *          If <code>true</code>, sets the access permission to allow write
  1.1390 +     *          operations; if <code>false</code> to disallow write operations
  1.1391 +     *
  1.1392 +     * @param   ownerOnly
  1.1393 +     *          If <code>true</code>, the write permission applies only to the
  1.1394 +     *          owner's write permission; otherwise, it applies to everybody.  If
  1.1395 +     *          the underlying file system can not distinguish the owner's write
  1.1396 +     *          permission from that of others, then the permission will apply to
  1.1397 +     *          everybody, regardless of this value.
  1.1398 +     *
  1.1399 +     * @return  <code>true</code> if and only if the operation succeeded. The
  1.1400 +     *          operation will fail if the user does not have permission to change
  1.1401 +     *          the access permissions of this abstract pathname.
  1.1402 +     *
  1.1403 +     * @throws  SecurityException
  1.1404 +     *          If a security manager exists and its <code>{@link
  1.1405 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
  1.1406 +     *          method denies write access to the named file
  1.1407 +     *
  1.1408 +     * @since 1.6
  1.1409 +     */
  1.1410 +    public boolean setWritable(boolean writable, boolean ownerOnly) {
  1.1411 +        SecurityManager security = System.getSecurityManager();
  1.1412 +        if (security != null) {
  1.1413 +            security.checkWrite(path);
  1.1414 +        }
  1.1415 +        return fs.setPermission(this, FileSystem.ACCESS_WRITE, writable, ownerOnly);
  1.1416 +    }
  1.1417 +
  1.1418 +    /**
  1.1419 +     * A convenience method to set the owner's write permission for this abstract
  1.1420 +     * pathname.
  1.1421 +     *
  1.1422 +     * <p> An invocation of this method of the form <tt>file.setWritable(arg)</tt>
  1.1423 +     * behaves in exactly the same way as the invocation
  1.1424 +     *
  1.1425 +     * <pre>
  1.1426 +     *     file.setWritable(arg, true) </pre>
  1.1427 +     *
  1.1428 +     * @param   writable
  1.1429 +     *          If <code>true</code>, sets the access permission to allow write
  1.1430 +     *          operations; if <code>false</code> to disallow write operations
  1.1431 +     *
  1.1432 +     * @return  <code>true</code> if and only if the operation succeeded.  The
  1.1433 +     *          operation will fail if the user does not have permission to
  1.1434 +     *          change the access permissions of this abstract pathname.
  1.1435 +     *
  1.1436 +     * @throws  SecurityException
  1.1437 +     *          If a security manager exists and its <code>{@link
  1.1438 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
  1.1439 +     *          method denies write access to the file
  1.1440 +     *
  1.1441 +     * @since 1.6
  1.1442 +     */
  1.1443 +    public boolean setWritable(boolean writable) {
  1.1444 +        return setWritable(writable, true);
  1.1445 +    }
  1.1446 +
  1.1447 +    /**
  1.1448 +     * Sets the owner's or everybody's read permission for this abstract
  1.1449 +     * pathname.
  1.1450 +     *
  1.1451 +     * <p> The {@link java.nio.file.Files} class defines methods that operate on
  1.1452 +     * file attributes including file permissions. This may be used when finer
  1.1453 +     * manipulation of file permissions is required.
  1.1454 +     *
  1.1455 +     * @param   readable
  1.1456 +     *          If <code>true</code>, sets the access permission to allow read
  1.1457 +     *          operations; if <code>false</code> to disallow read operations
  1.1458 +     *
  1.1459 +     * @param   ownerOnly
  1.1460 +     *          If <code>true</code>, the read permission applies only to the
  1.1461 +     *          owner's read permission; otherwise, it applies to everybody.  If
  1.1462 +     *          the underlying file system can not distinguish the owner's read
  1.1463 +     *          permission from that of others, then the permission will apply to
  1.1464 +     *          everybody, regardless of this value.
  1.1465 +     *
  1.1466 +     * @return  <code>true</code> if and only if the operation succeeded.  The
  1.1467 +     *          operation will fail if the user does not have permission to
  1.1468 +     *          change the access permissions of this abstract pathname.  If
  1.1469 +     *          <code>readable</code> is <code>false</code> and the underlying
  1.1470 +     *          file system does not implement a read permission, then the
  1.1471 +     *          operation will fail.
  1.1472 +     *
  1.1473 +     * @throws  SecurityException
  1.1474 +     *          If a security manager exists and its <code>{@link
  1.1475 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
  1.1476 +     *          method denies write access to the file
  1.1477 +     *
  1.1478 +     * @since 1.6
  1.1479 +     */
  1.1480 +    public boolean setReadable(boolean readable, boolean ownerOnly) {
  1.1481 +        SecurityManager security = System.getSecurityManager();
  1.1482 +        if (security != null) {
  1.1483 +            security.checkWrite(path);
  1.1484 +        }
  1.1485 +        return fs.setPermission(this, FileSystem.ACCESS_READ, readable, ownerOnly);
  1.1486 +    }
  1.1487 +
  1.1488 +    /**
  1.1489 +     * A convenience method to set the owner's read permission for this abstract
  1.1490 +     * pathname.
  1.1491 +     *
  1.1492 +     * <p>An invocation of this method of the form <tt>file.setReadable(arg)</tt>
  1.1493 +     * behaves in exactly the same way as the invocation
  1.1494 +     *
  1.1495 +     * <pre>
  1.1496 +     *     file.setReadable(arg, true) </pre>
  1.1497 +     *
  1.1498 +     * @param  readable
  1.1499 +     *          If <code>true</code>, sets the access permission to allow read
  1.1500 +     *          operations; if <code>false</code> to disallow read operations
  1.1501 +     *
  1.1502 +     * @return  <code>true</code> if and only if the operation succeeded.  The
  1.1503 +     *          operation will fail if the user does not have permission to
  1.1504 +     *          change the access permissions of this abstract pathname.  If
  1.1505 +     *          <code>readable</code> is <code>false</code> and the underlying
  1.1506 +     *          file system does not implement a read permission, then the
  1.1507 +     *          operation will fail.
  1.1508 +     *
  1.1509 +     * @throws  SecurityException
  1.1510 +     *          If a security manager exists and its <code>{@link
  1.1511 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
  1.1512 +     *          method denies write access to the file
  1.1513 +     *
  1.1514 +     * @since 1.6
  1.1515 +     */
  1.1516 +    public boolean setReadable(boolean readable) {
  1.1517 +        return setReadable(readable, true);
  1.1518 +    }
  1.1519 +
  1.1520 +    /**
  1.1521 +     * Sets the owner's or everybody's execute permission for this abstract
  1.1522 +     * pathname.
  1.1523 +     *
  1.1524 +     * <p> The {@link java.nio.file.Files} class defines methods that operate on
  1.1525 +     * file attributes including file permissions. This may be used when finer
  1.1526 +     * manipulation of file permissions is required.
  1.1527 +     *
  1.1528 +     * @param   executable
  1.1529 +     *          If <code>true</code>, sets the access permission to allow execute
  1.1530 +     *          operations; if <code>false</code> to disallow execute operations
  1.1531 +     *
  1.1532 +     * @param   ownerOnly
  1.1533 +     *          If <code>true</code>, the execute permission applies only to the
  1.1534 +     *          owner's execute permission; otherwise, it applies to everybody.
  1.1535 +     *          If the underlying file system can not distinguish the owner's
  1.1536 +     *          execute permission from that of others, then the permission will
  1.1537 +     *          apply to everybody, regardless of this value.
  1.1538 +     *
  1.1539 +     * @return  <code>true</code> if and only if the operation succeeded.  The
  1.1540 +     *          operation will fail if the user does not have permission to
  1.1541 +     *          change the access permissions of this abstract pathname.  If
  1.1542 +     *          <code>executable</code> is <code>false</code> and the underlying
  1.1543 +     *          file system does not implement an execute permission, then the
  1.1544 +     *          operation will fail.
  1.1545 +     *
  1.1546 +     * @throws  SecurityException
  1.1547 +     *          If a security manager exists and its <code>{@link
  1.1548 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
  1.1549 +     *          method denies write access to the file
  1.1550 +     *
  1.1551 +     * @since 1.6
  1.1552 +     */
  1.1553 +    public boolean setExecutable(boolean executable, boolean ownerOnly) {
  1.1554 +        SecurityManager security = System.getSecurityManager();
  1.1555 +        if (security != null) {
  1.1556 +            security.checkWrite(path);
  1.1557 +        }
  1.1558 +        return fs.setPermission(this, FileSystem.ACCESS_EXECUTE, executable, ownerOnly);
  1.1559 +    }
  1.1560 +
  1.1561 +    /**
  1.1562 +     * A convenience method to set the owner's execute permission for this abstract
  1.1563 +     * pathname.
  1.1564 +     *
  1.1565 +     * <p>An invocation of this method of the form <tt>file.setExcutable(arg)</tt>
  1.1566 +     * behaves in exactly the same way as the invocation
  1.1567 +     *
  1.1568 +     * <pre>
  1.1569 +     *     file.setExecutable(arg, true) </pre>
  1.1570 +     *
  1.1571 +     * @param   executable
  1.1572 +     *          If <code>true</code>, sets the access permission to allow execute
  1.1573 +     *          operations; if <code>false</code> to disallow execute operations
  1.1574 +     *
  1.1575 +     * @return   <code>true</code> if and only if the operation succeeded.  The
  1.1576 +     *           operation will fail if the user does not have permission to
  1.1577 +     *           change the access permissions of this abstract pathname.  If
  1.1578 +     *           <code>executable</code> is <code>false</code> and the underlying
  1.1579 +     *           file system does not implement an excute permission, then the
  1.1580 +     *           operation will fail.
  1.1581 +     *
  1.1582 +     * @throws  SecurityException
  1.1583 +     *          If a security manager exists and its <code>{@link
  1.1584 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
  1.1585 +     *          method denies write access to the file
  1.1586 +     *
  1.1587 +     * @since 1.6
  1.1588 +     */
  1.1589 +    public boolean setExecutable(boolean executable) {
  1.1590 +        return setExecutable(executable, true);
  1.1591 +    }
  1.1592 +
  1.1593 +    /**
  1.1594 +     * Tests whether the application can execute the file denoted by this
  1.1595 +     * abstract pathname.
  1.1596 +     *
  1.1597 +     * @return  <code>true</code> if and only if the abstract pathname exists
  1.1598 +     *          <em>and</em> the application is allowed to execute the file
  1.1599 +     *
  1.1600 +     * @throws  SecurityException
  1.1601 +     *          If a security manager exists and its <code>{@link
  1.1602 +     *          java.lang.SecurityManager#checkExec(java.lang.String)}</code>
  1.1603 +     *          method denies execute access to the file
  1.1604 +     *
  1.1605 +     * @since 1.6
  1.1606 +     */
  1.1607 +    public boolean canExecute() {
  1.1608 +        SecurityManager security = System.getSecurityManager();
  1.1609 +        if (security != null) {
  1.1610 +            security.checkExec(path);
  1.1611 +        }
  1.1612 +        return fs.checkAccess(this, FileSystem.ACCESS_EXECUTE);
  1.1613 +    }
  1.1614 +
  1.1615 +
  1.1616 +    /* -- Filesystem interface -- */
  1.1617 +
  1.1618 +    /**
  1.1619 +     * List the available filesystem roots.
  1.1620 +     *
  1.1621 +     * <p> A particular Java platform may support zero or more
  1.1622 +     * hierarchically-organized file systems.  Each file system has a
  1.1623 +     * {@code root} directory from which all other files in that file system
  1.1624 +     * can be reached.  Windows platforms, for example, have a root directory
  1.1625 +     * for each active drive; UNIX platforms have a single root directory,
  1.1626 +     * namely {@code "/"}.  The set of available filesystem roots is affected
  1.1627 +     * by various system-level operations such as the insertion or ejection of
  1.1628 +     * removable media and the disconnecting or unmounting of physical or
  1.1629 +     * virtual disk drives.
  1.1630 +     *
  1.1631 +     * <p> This method returns an array of {@code File} objects that denote the
  1.1632 +     * root directories of the available filesystem roots.  It is guaranteed
  1.1633 +     * that the canonical pathname of any file physically present on the local
  1.1634 +     * machine will begin with one of the roots returned by this method.
  1.1635 +     *
  1.1636 +     * <p> The canonical pathname of a file that resides on some other machine
  1.1637 +     * and is accessed via a remote-filesystem protocol such as SMB or NFS may
  1.1638 +     * or may not begin with one of the roots returned by this method.  If the
  1.1639 +     * pathname of a remote file is syntactically indistinguishable from the
  1.1640 +     * pathname of a local file then it will begin with one of the roots
  1.1641 +     * returned by this method.  Thus, for example, {@code File} objects
  1.1642 +     * denoting the root directories of the mapped network drives of a Windows
  1.1643 +     * platform will be returned by this method, while {@code File} objects
  1.1644 +     * containing UNC pathnames will not be returned by this method.
  1.1645 +     *
  1.1646 +     * <p> Unlike most methods in this class, this method does not throw
  1.1647 +     * security exceptions.  If a security manager exists and its {@link
  1.1648 +     * SecurityManager#checkRead(String)} method denies read access to a
  1.1649 +     * particular root directory, then that directory will not appear in the
  1.1650 +     * result.
  1.1651 +     *
  1.1652 +     * @return  An array of {@code File} objects denoting the available
  1.1653 +     *          filesystem roots, or {@code null} if the set of roots could not
  1.1654 +     *          be determined.  The array will be empty if there are no
  1.1655 +     *          filesystem roots.
  1.1656 +     *
  1.1657 +     * @since  1.2
  1.1658 +     * @see java.nio.file.FileStore
  1.1659 +     */
  1.1660 +    public static File[] listRoots() {
  1.1661 +        return fs.listRoots();
  1.1662 +    }
  1.1663 +
  1.1664 +
  1.1665 +    /* -- Disk usage -- */
  1.1666 +
  1.1667 +    /**
  1.1668 +     * Returns the size of the partition <a href="#partName">named</a> by this
  1.1669 +     * abstract pathname.
  1.1670 +     *
  1.1671 +     * @return  The size, in bytes, of the partition or <tt>0L</tt> if this
  1.1672 +     *          abstract pathname does not name a partition
  1.1673 +     *
  1.1674 +     * @throws  SecurityException
  1.1675 +     *          If a security manager has been installed and it denies
  1.1676 +     *          {@link RuntimePermission}<tt>("getFileSystemAttributes")</tt>
  1.1677 +     *          or its {@link SecurityManager#checkRead(String)} method denies
  1.1678 +     *          read access to the file named by this abstract pathname
  1.1679 +     *
  1.1680 +     * @since  1.6
  1.1681 +     */
  1.1682 +    public long getTotalSpace() {
  1.1683 +        SecurityManager sm = System.getSecurityManager();
  1.1684 +        if (sm != null) {
  1.1685 +            sm.checkPermission(new RuntimePermission("getFileSystemAttributes"));
  1.1686 +            sm.checkRead(path);
  1.1687 +        }
  1.1688 +        return fs.getSpace(this, FileSystem.SPACE_TOTAL);
  1.1689 +    }
  1.1690 +
  1.1691 +    /**
  1.1692 +     * Returns the number of unallocated bytes in the partition <a
  1.1693 +     * href="#partName">named</a> by this abstract path name.
  1.1694 +     *
  1.1695 +     * <p> The returned number of unallocated bytes is a hint, but not
  1.1696 +     * a guarantee, that it is possible to use most or any of these
  1.1697 +     * bytes.  The number of unallocated bytes is most likely to be
  1.1698 +     * accurate immediately after this call.  It is likely to be made
  1.1699 +     * inaccurate by any external I/O operations including those made
  1.1700 +     * on the system outside of this virtual machine.  This method
  1.1701 +     * makes no guarantee that write operations to this file system
  1.1702 +     * will succeed.
  1.1703 +     *
  1.1704 +     * @return  The number of unallocated bytes on the partition <tt>0L</tt>
  1.1705 +     *          if the abstract pathname does not name a partition.  This
  1.1706 +     *          value will be less than or equal to the total file system size
  1.1707 +     *          returned by {@link #getTotalSpace}.
  1.1708 +     *
  1.1709 +     * @throws  SecurityException
  1.1710 +     *          If a security manager has been installed and it denies
  1.1711 +     *          {@link RuntimePermission}<tt>("getFileSystemAttributes")</tt>
  1.1712 +     *          or its {@link SecurityManager#checkRead(String)} method denies
  1.1713 +     *          read access to the file named by this abstract pathname
  1.1714 +     *
  1.1715 +     * @since  1.6
  1.1716 +     */
  1.1717 +    public long getFreeSpace() {
  1.1718 +        SecurityManager sm = System.getSecurityManager();
  1.1719 +        if (sm != null) {
  1.1720 +            sm.checkPermission(new RuntimePermission("getFileSystemAttributes"));
  1.1721 +            sm.checkRead(path);
  1.1722 +        }
  1.1723 +        return fs.getSpace(this, FileSystem.SPACE_FREE);
  1.1724 +    }
  1.1725 +
  1.1726 +    /**
  1.1727 +     * Returns the number of bytes available to this virtual machine on the
  1.1728 +     * partition <a href="#partName">named</a> by this abstract pathname.  When
  1.1729 +     * possible, this method checks for write permissions and other operating
  1.1730 +     * system restrictions and will therefore usually provide a more accurate
  1.1731 +     * estimate of how much new data can actually be written than {@link
  1.1732 +     * #getFreeSpace}.
  1.1733 +     *
  1.1734 +     * <p> The returned number of available bytes is a hint, but not a
  1.1735 +     * guarantee, that it is possible to use most or any of these bytes.  The
  1.1736 +     * number of unallocated bytes is most likely to be accurate immediately
  1.1737 +     * after this call.  It is likely to be made inaccurate by any external
  1.1738 +     * I/O operations including those made on the system outside of this
  1.1739 +     * virtual machine.  This method makes no guarantee that write operations
  1.1740 +     * to this file system will succeed.
  1.1741 +     *
  1.1742 +     * @return  The number of available bytes on the partition or <tt>0L</tt>
  1.1743 +     *          if the abstract pathname does not name a partition.  On
  1.1744 +     *          systems where this information is not available, this method
  1.1745 +     *          will be equivalent to a call to {@link #getFreeSpace}.
  1.1746 +     *
  1.1747 +     * @throws  SecurityException
  1.1748 +     *          If a security manager has been installed and it denies
  1.1749 +     *          {@link RuntimePermission}<tt>("getFileSystemAttributes")</tt>
  1.1750 +     *          or its {@link SecurityManager#checkRead(String)} method denies
  1.1751 +     *          read access to the file named by this abstract pathname
  1.1752 +     *
  1.1753 +     * @since  1.6
  1.1754 +     */
  1.1755 +    public long getUsableSpace() {
  1.1756 +        SecurityManager sm = System.getSecurityManager();
  1.1757 +        if (sm != null) {
  1.1758 +            sm.checkPermission(new RuntimePermission("getFileSystemAttributes"));
  1.1759 +            sm.checkRead(path);
  1.1760 +        }
  1.1761 +        return fs.getSpace(this, FileSystem.SPACE_USABLE);
  1.1762 +    }
  1.1763 +
  1.1764 +    /* -- Temporary files -- */
  1.1765 +
  1.1766 +    private static class TempDirectory {
  1.1767 +        private TempDirectory() { }
  1.1768 +
  1.1769 +        // temporary directory location
  1.1770 +        private static final File tmpdir = new File(fs.normalize(AccessController
  1.1771 +            .doPrivileged(new GetPropertyAction("java.io.tmpdir"))));
  1.1772 +        static File location() {
  1.1773 +            return tmpdir;
  1.1774 +        }
  1.1775 +
  1.1776 +        // file name generation
  1.1777 +        private static final SecureRandom random = new SecureRandom();
  1.1778 +        static File generateFile(String prefix, String suffix, File dir) {
  1.1779 +            long n = random.nextLong();
  1.1780 +            if (n == Long.MIN_VALUE) {
  1.1781 +                n = 0;      // corner case
  1.1782 +            } else {
  1.1783 +                n = Math.abs(n);
  1.1784 +            }
  1.1785 +            return new File(dir, prefix + Long.toString(n) + suffix);
  1.1786 +        }
  1.1787 +    }
  1.1788 +
  1.1789 +    /**
  1.1790 +     * <p> Creates a new empty file in the specified directory, using the
  1.1791 +     * given prefix and suffix strings to generate its name.  If this method
  1.1792 +     * returns successfully then it is guaranteed that:
  1.1793 +     *
  1.1794 +     * <ol>
  1.1795 +     * <li> The file denoted by the returned abstract pathname did not exist
  1.1796 +     *      before this method was invoked, and
  1.1797 +     * <li> Neither this method nor any of its variants will return the same
  1.1798 +     *      abstract pathname again in the current invocation of the virtual
  1.1799 +     *      machine.
  1.1800 +     * </ol>
  1.1801 +     *
  1.1802 +     * This method provides only part of a temporary-file facility.  To arrange
  1.1803 +     * for a file created by this method to be deleted automatically, use the
  1.1804 +     * <code>{@link #deleteOnExit}</code> method.
  1.1805 +     *
  1.1806 +     * <p> The <code>prefix</code> argument must be at least three characters
  1.1807 +     * long.  It is recommended that the prefix be a short, meaningful string
  1.1808 +     * such as <code>"hjb"</code> or <code>"mail"</code>.  The
  1.1809 +     * <code>suffix</code> argument may be <code>null</code>, in which case the
  1.1810 +     * suffix <code>".tmp"</code> will be used.
  1.1811 +     *
  1.1812 +     * <p> To create the new file, the prefix and the suffix may first be
  1.1813 +     * adjusted to fit the limitations of the underlying platform.  If the
  1.1814 +     * prefix is too long then it will be truncated, but its first three
  1.1815 +     * characters will always be preserved.  If the suffix is too long then it
  1.1816 +     * too will be truncated, but if it begins with a period character
  1.1817 +     * (<code>'.'</code>) then the period and the first three characters
  1.1818 +     * following it will always be preserved.  Once these adjustments have been
  1.1819 +     * made the name of the new file will be generated by concatenating the
  1.1820 +     * prefix, five or more internally-generated characters, and the suffix.
  1.1821 +     *
  1.1822 +     * <p> If the <code>directory</code> argument is <code>null</code> then the
  1.1823 +     * system-dependent default temporary-file directory will be used.  The
  1.1824 +     * default temporary-file directory is specified by the system property
  1.1825 +     * <code>java.io.tmpdir</code>.  On UNIX systems the default value of this
  1.1826 +     * property is typically <code>"/tmp"</code> or <code>"/var/tmp"</code>; on
  1.1827 +     * Microsoft Windows systems it is typically <code>"C:\\WINNT\\TEMP"</code>.  A different
  1.1828 +     * value may be given to this system property when the Java virtual machine
  1.1829 +     * is invoked, but programmatic changes to this property are not guaranteed
  1.1830 +     * to have any effect upon the temporary directory used by this method.
  1.1831 +     *
  1.1832 +     * @param  prefix     The prefix string to be used in generating the file's
  1.1833 +     *                    name; must be at least three characters long
  1.1834 +     *
  1.1835 +     * @param  suffix     The suffix string to be used in generating the file's
  1.1836 +     *                    name; may be <code>null</code>, in which case the
  1.1837 +     *                    suffix <code>".tmp"</code> will be used
  1.1838 +     *
  1.1839 +     * @param  directory  The directory in which the file is to be created, or
  1.1840 +     *                    <code>null</code> if the default temporary-file
  1.1841 +     *                    directory is to be used
  1.1842 +     *
  1.1843 +     * @return  An abstract pathname denoting a newly-created empty file
  1.1844 +     *
  1.1845 +     * @throws  IllegalArgumentException
  1.1846 +     *          If the <code>prefix</code> argument contains fewer than three
  1.1847 +     *          characters
  1.1848 +     *
  1.1849 +     * @throws  IOException  If a file could not be created
  1.1850 +     *
  1.1851 +     * @throws  SecurityException
  1.1852 +     *          If a security manager exists and its <code>{@link
  1.1853 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
  1.1854 +     *          method does not allow a file to be created
  1.1855 +     *
  1.1856 +     * @since 1.2
  1.1857 +     */
  1.1858 +    public static File createTempFile(String prefix, String suffix,
  1.1859 +                                      File directory)
  1.1860 +        throws IOException
  1.1861 +    {
  1.1862 +        if (prefix.length() < 3)
  1.1863 +            throw new IllegalArgumentException("Prefix string too short");
  1.1864 +        if (suffix == null)
  1.1865 +            suffix = ".tmp";
  1.1866 +
  1.1867 +        File tmpdir = (directory != null) ? directory : TempDirectory.location();
  1.1868 +        SecurityManager sm = System.getSecurityManager();
  1.1869 +        File f;
  1.1870 +        do {
  1.1871 +            f = TempDirectory.generateFile(prefix, suffix, tmpdir);
  1.1872 +            if (sm != null) {
  1.1873 +                try {
  1.1874 +                    sm.checkWrite(f.getPath());
  1.1875 +                } catch (SecurityException se) {
  1.1876 +                    // don't reveal temporary directory location
  1.1877 +                    if (directory == null)
  1.1878 +                        throw new SecurityException("Unable to create temporary file");
  1.1879 +                    throw se;
  1.1880 +                }
  1.1881 +            }
  1.1882 +        } while (!fs.createFileExclusively(f.getPath()));
  1.1883 +        return f;
  1.1884 +    }
  1.1885 +
  1.1886 +    /**
  1.1887 +     * Creates an empty file in the default temporary-file directory, using
  1.1888 +     * the given prefix and suffix to generate its name. Invoking this method
  1.1889 +     * is equivalent to invoking <code>{@link #createTempFile(java.lang.String,
  1.1890 +     * java.lang.String, java.io.File)
  1.1891 +     * createTempFile(prefix,&nbsp;suffix,&nbsp;null)}</code>.
  1.1892 +     *
  1.1893 +     * <p> The {@link
  1.1894 +     * java.nio.file.Files#createTempFile(String,String,java.nio.file.attribute.FileAttribute[])
  1.1895 +     * Files.createTempFile} method provides an alternative method to create an
  1.1896 +     * empty file in the temporary-file directory. Files created by that method
  1.1897 +     * may have more restrictive access permissions to files created by this
  1.1898 +     * method and so may be more suited to security-sensitive applications.
  1.1899 +     *
  1.1900 +     * @param  prefix     The prefix string to be used in generating the file's
  1.1901 +     *                    name; must be at least three characters long
  1.1902 +     *
  1.1903 +     * @param  suffix     The suffix string to be used in generating the file's
  1.1904 +     *                    name; may be <code>null</code>, in which case the
  1.1905 +     *                    suffix <code>".tmp"</code> will be used
  1.1906 +     *
  1.1907 +     * @return  An abstract pathname denoting a newly-created empty file
  1.1908 +     *
  1.1909 +     * @throws  IllegalArgumentException
  1.1910 +     *          If the <code>prefix</code> argument contains fewer than three
  1.1911 +     *          characters
  1.1912 +     *
  1.1913 +     * @throws  IOException  If a file could not be created
  1.1914 +     *
  1.1915 +     * @throws  SecurityException
  1.1916 +     *          If a security manager exists and its <code>{@link
  1.1917 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
  1.1918 +     *          method does not allow a file to be created
  1.1919 +     *
  1.1920 +     * @since 1.2
  1.1921 +     * @see java.nio.file.Files#createTempDirectory(String,FileAttribute[])
  1.1922 +     */
  1.1923 +    public static File createTempFile(String prefix, String suffix)
  1.1924 +        throws IOException
  1.1925 +    {
  1.1926 +        return createTempFile(prefix, suffix, null);
  1.1927 +    }
  1.1928 +
  1.1929 +    /* -- Basic infrastructure -- */
  1.1930 +
  1.1931 +    /**
  1.1932 +     * Compares two abstract pathnames lexicographically.  The ordering
  1.1933 +     * defined by this method depends upon the underlying system.  On UNIX
  1.1934 +     * systems, alphabetic case is significant in comparing pathnames; on Microsoft Windows
  1.1935 +     * systems it is not.
  1.1936 +     *
  1.1937 +     * @param   pathname  The abstract pathname to be compared to this abstract
  1.1938 +     *                    pathname
  1.1939 +     *
  1.1940 +     * @return  Zero if the argument is equal to this abstract pathname, a
  1.1941 +     *          value less than zero if this abstract pathname is
  1.1942 +     *          lexicographically less than the argument, or a value greater
  1.1943 +     *          than zero if this abstract pathname is lexicographically
  1.1944 +     *          greater than the argument
  1.1945 +     *
  1.1946 +     * @since   1.2
  1.1947 +     */
  1.1948 +    public int compareTo(File pathname) {
  1.1949 +        return fs.compare(this, pathname);
  1.1950 +    }
  1.1951 +
  1.1952 +    /**
  1.1953 +     * Tests this abstract pathname for equality with the given object.
  1.1954 +     * Returns <code>true</code> if and only if the argument is not
  1.1955 +     * <code>null</code> and is an abstract pathname that denotes the same file
  1.1956 +     * or directory as this abstract pathname.  Whether or not two abstract
  1.1957 +     * pathnames are equal depends upon the underlying system.  On UNIX
  1.1958 +     * systems, alphabetic case is significant in comparing pathnames; on Microsoft Windows
  1.1959 +     * systems it is not.
  1.1960 +     *
  1.1961 +     * @param   obj   The object to be compared with this abstract pathname
  1.1962 +     *
  1.1963 +     * @return  <code>true</code> if and only if the objects are the same;
  1.1964 +     *          <code>false</code> otherwise
  1.1965 +     */
  1.1966 +    public boolean equals(Object obj) {
  1.1967 +        if ((obj != null) && (obj instanceof File)) {
  1.1968 +            return compareTo((File)obj) == 0;
  1.1969 +        }
  1.1970 +        return false;
  1.1971 +    }
  1.1972 +
  1.1973 +    /**
  1.1974 +     * Computes a hash code for this abstract pathname.  Because equality of
  1.1975 +     * abstract pathnames is inherently system-dependent, so is the computation
  1.1976 +     * of their hash codes.  On UNIX systems, the hash code of an abstract
  1.1977 +     * pathname is equal to the exclusive <em>or</em> of the hash code
  1.1978 +     * of its pathname string and the decimal value
  1.1979 +     * <code>1234321</code>.  On Microsoft Windows systems, the hash
  1.1980 +     * code is equal to the exclusive <em>or</em> of the hash code of
  1.1981 +     * its pathname string converted to lower case and the decimal
  1.1982 +     * value <code>1234321</code>.  Locale is not taken into account on
  1.1983 +     * lowercasing the pathname string.
  1.1984 +     *
  1.1985 +     * @return  A hash code for this abstract pathname
  1.1986 +     */
  1.1987 +    public int hashCode() {
  1.1988 +        return fs.hashCode(this);
  1.1989 +    }
  1.1990 +
  1.1991 +    /**
  1.1992 +     * Returns the pathname string of this abstract pathname.  This is just the
  1.1993 +     * string returned by the <code>{@link #getPath}</code> method.
  1.1994 +     *
  1.1995 +     * @return  The string form of this abstract pathname
  1.1996 +     */
  1.1997 +    public String toString() {
  1.1998 +        return getPath();
  1.1999 +    }
  1.2000 +
  1.2001 +    /**
  1.2002 +     * WriteObject is called to save this filename.
  1.2003 +     * The separator character is saved also so it can be replaced
  1.2004 +     * in case the path is reconstituted on a different host type.
  1.2005 +     * <p>
  1.2006 +     * @serialData  Default fields followed by separator character.
  1.2007 +     */
  1.2008 +    private synchronized void writeObject(java.io.ObjectOutputStream s)
  1.2009 +        throws IOException
  1.2010 +    {
  1.2011 +        s.defaultWriteObject();
  1.2012 +        s.writeChar(this.separatorChar); // Add the separator character
  1.2013 +    }
  1.2014 +
  1.2015 +    /**
  1.2016 +     * readObject is called to restore this filename.
  1.2017 +     * The original separator character is read.  If it is different
  1.2018 +     * than the separator character on this system, then the old separator
  1.2019 +     * is replaced by the local separator.
  1.2020 +     */
  1.2021 +    private synchronized void readObject(java.io.ObjectInputStream s)
  1.2022 +         throws IOException, ClassNotFoundException
  1.2023 +    {
  1.2024 +        ObjectInputStream.GetField fields = s.readFields();
  1.2025 +        String pathField = (String)fields.get("path", null);
  1.2026 +        char sep = s.readChar(); // read the previous separator char
  1.2027 +        if (sep != separatorChar)
  1.2028 +            pathField = pathField.replace(sep, separatorChar);
  1.2029 +        this.path = fs.normalize(pathField);
  1.2030 +        this.prefixLength = fs.prefixLength(this.path);
  1.2031 +    }
  1.2032 +
  1.2033 +    /** use serialVersionUID from JDK 1.0.2 for interoperability */
  1.2034 +    private static final long serialVersionUID = 301077366599181567L;
  1.2035 +
  1.2036 +    // -- Integration with java.nio.file --
  1.2037 +
  1.2038 +    private volatile transient Path filePath;
  1.2039 +
  1.2040 +    /**
  1.2041 +     * Returns a {@link Path java.nio.file.Path} object constructed from the
  1.2042 +     * this abstract path. The resulting {@code Path} is associated with the
  1.2043 +     * {@link java.nio.file.FileSystems#getDefault default-filesystem}.
  1.2044 +     *
  1.2045 +     * <p> The first invocation of this method works as if invoking it were
  1.2046 +     * equivalent to evaluating the expression:
  1.2047 +     * <blockquote><pre>
  1.2048 +     * {@link java.nio.file.FileSystems#getDefault FileSystems.getDefault}().{@link
  1.2049 +     * java.nio.file.FileSystem#getPath getPath}(this.{@link #getPath getPath}());
  1.2050 +     * </pre></blockquote>
  1.2051 +     * Subsequent invocations of this method return the same {@code Path}.
  1.2052 +     *
  1.2053 +     * <p> If this abstract pathname is the empty abstract pathname then this
  1.2054 +     * method returns a {@code Path} that may be used to access the current
  1.2055 +     * user directory.
  1.2056 +     *
  1.2057 +     * @return  a {@code Path} constructed from this abstract path
  1.2058 +     *
  1.2059 +     * @throws  java.nio.file.InvalidPathException
  1.2060 +     *          if a {@code Path} object cannot be constructed from the abstract
  1.2061 +     *          path (see {@link java.nio.file.FileSystem#getPath FileSystem.getPath})
  1.2062 +     *
  1.2063 +     * @since   1.7
  1.2064 +     * @see Path#toFile
  1.2065 +     */
  1.2066 +    public Path toPath() {
  1.2067 +        Path result = filePath;
  1.2068 +        if (result == null) {
  1.2069 +            synchronized (this) {
  1.2070 +                result = filePath;
  1.2071 +                if (result == null) {
  1.2072 +                    result = FileSystems.getDefault().getPath(path);
  1.2073 +                    filePath = result;
  1.2074 +                }
  1.2075 +            }
  1.2076 +        }
  1.2077 +        return result;
  1.2078 +    }
  1.2079 +}