0001: /*
0002: * @(#)File.java 1.116 03/08/01
0003: *
0004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
0005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
0006: *
0007: * This program is free software; you can redistribute it and/or
0008: * modify it under the terms of the GNU General Public License version
0009: * 2 only, as published by the Free Software Foundation.
0010: *
0011: * This program is distributed in the hope that it will be useful, but
0012: * WITHOUT ANY WARRANTY; without even the implied warranty of
0013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014: * General Public License version 2 for more details (a copy is
0015: * included at /legal/license.txt).
0016: *
0017: * You should have received a copy of the GNU General Public License
0018: * version 2 along with this work; if not, write to the Free Software
0019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0020: * 02110-1301 USA
0021: *
0022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0023: * Clara, CA 95054 or visit www.sun.com if you need additional
0024: * information or have any questions.
0025: */
0026:
0027: package java.io;
0028:
0029: import java.net.URI;
0030: import java.net.URL;
0031: import java.net.MalformedURLException;
0032: import java.net.URISyntaxException;
0033: import java.util.ArrayList;
0034: import java.util.Map;
0035: import java.util.Hashtable;
0036: import java.util.Random;
0037: import java.security.AccessController;
0038: import java.security.AccessControlException;
0039: import sun.security.action.GetPropertyAction;
0040:
0041: // NOTE: This is a 2-version file (CDC/Foundation Profile).
0042: // Please make sure to verify if your change to this file is
0043: // also needed in the second version of this file:
0044: // src/share/classes/java/io/File.java
0045: // src/share/foundation/classes/java/io/File.java
0046:
0047: /**
0048: * An abstract representation of file and directory pathnames.
0049: *
0050: * <p> User interfaces and operating systems use system-dependent <em>pathname
0051: * strings</em> to name files and directories. This class presents an
0052: * abstract, system-independent view of hierarchical pathnames. An
0053: * <em>abstract pathname</em> has two components:
0054: *
0055: * <ol>
0056: * <li> An optional system-dependent <em>prefix</em> string,
0057: * such as a disk-drive specifier, <code>"/"</code> for the UNIX root
0058: * directory, or <code>"\\"</code> for a Microsoft Windows UNC pathname, and
0059: * <li> A sequence of zero or more string <em>names</em>.
0060: * </ol>
0061: *
0062: * Each name in an abstract pathname except for the last denotes a directory;
0063: * the last name may denote either a directory or a file. The <em>empty</em>
0064: * abstract pathname has no prefix and an empty name sequence.
0065: *
0066: * <p> The conversion of a pathname string to or from an abstract pathname is
0067: * inherently system-dependent. When an abstract pathname is converted into a
0068: * pathname string, each name is separated from the next by a single copy of
0069: * the default <em>separator character</em>. The default name-separator
0070: * character is defined by the system property <code>file.separator</code>, and
0071: * is made available in the public static fields <code>{@link
0072: * #separator}</code> and <code>{@link #separatorChar}</code> of this class.
0073: * When a pathname string is converted into an abstract pathname, the names
0074: * within it may be separated by the default name-separator character or by any
0075: * other name-separator character that is supported by the underlying system.
0076: *
0077: * <p> A pathname, whether abstract or in string form, may be either
0078: * <em>absolute</em> or <em>relative</em>. An absolute pathname is complete in
0079: * that no other information is required in order to locate the file that it
0080: * denotes. A relative pathname, in contrast, must be interpreted in terms of
0081: * information taken from some other pathname. By default the classes in the
0082: * <code>java.io</code> package always resolve relative pathnames against the
0083: * current user directory. This directory is named by the system property
0084: * <code>user.dir</code>, and is typically the directory in which the Java
0085: * virtual machine was invoked.
0086: *
0087: * <p> The prefix concept is used to handle root directories on UNIX platforms,
0088: * and drive specifiers, root directories and UNC pathnames on Microsoft Windows platforms,
0089: * as follows:
0090: *
0091: * <ul>
0092: *
0093: * <li> For UNIX platforms, the prefix of an absolute pathname is always
0094: * <code>"/"</code>. Relative pathnames have no prefix. The abstract pathname
0095: * denoting the root directory has the prefix <code>"/"</code> and an empty
0096: * name sequence.
0097: *
0098: * <li> For Microsoft Windows platforms, the prefix of a pathname that contains a drive
0099: * specifier consists of the drive letter followed by <code>":"</code> and
0100: * possibly followed by <code>"\"</code> if the pathname is absolute. The
0101: * prefix of a UNC pathname is <code>"\\"</code>; the hostname and the share
0102: * name are the first two names in the name sequence. A relative pathname that
0103: * does not specify a drive has no prefix.
0104: *
0105: * </ul>
0106: *
0107: * <p> Instances of the <code>File</code> class are immutable; that is, once
0108: * created, the abstract pathname represented by a <code>File</code> object
0109: * will never change.
0110: *
0111: * @version 1.116, 08/01/03
0112: * @author unascribed
0113: * @since JDK1.0
0114: */
0115:
0116: public class File implements java.io.Serializable, Comparable {
0117:
0118: /**
0119: * The FileSystem object representing the platform's local file system.
0120: */
0121: static private FileSystem fs = FileSystem.getFileSystem();
0122:
0123: /**
0124: * This abstract pathname's normalized pathname string. A normalized
0125: * pathname string uses the default name-separator character and does not
0126: * contain any duplicate or redundant separators.
0127: *
0128: * @serial
0129: */
0130: private String path;
0131:
0132: /**
0133: * The length of this abstract pathname's prefix, or zero if it has no
0134: * prefix.
0135: */
0136: private transient int prefixLength;
0137:
0138: /**
0139: * Returns the length of this abstract pathname's prefix.
0140: * For use by FileSystem classes.
0141: */
0142: int getPrefixLength() {
0143: return prefixLength;
0144: }
0145:
0146: /**
0147: * The system-dependent default name-separator character. This field is
0148: * initialized to contain the first character of the value of the system
0149: * property <code>file.separator</code>. On UNIX systems the value of this
0150: * field is <code>'/'</code>; on Microsoft Windows systems it is <code>'\'</code>.
0151: *
0152: * @see java.lang.System#getProperty(java.lang.String)
0153: */
0154: public static final char separatorChar = fs.getSeparator();
0155:
0156: /**
0157: * The system-dependent default name-separator character, represented as a
0158: * string for convenience. This string contains a single character, namely
0159: * <code>{@link #separatorChar}</code>.
0160: */
0161: public static final String separator = "" + separatorChar;
0162:
0163: /**
0164: * The system-dependent path-separator character. This field is
0165: * initialized to contain the first character of the value of the system
0166: * property <code>path.separator</code>. This character is used to
0167: * separate filenames in a sequence of files given as a <em>path list</em>.
0168: * On UNIX systems, this character is <code>':'</code>; on Microsoft Windows systems it
0169: * is <code>';'</code>.
0170: *
0171: * @see java.lang.System#getProperty(java.lang.String)
0172: */
0173: public static final char pathSeparatorChar = fs.getPathSeparator();
0174:
0175: /**
0176: * The system-dependent path-separator character, represented as a string
0177: * for convenience. This string contains a single character, namely
0178: * <code>{@link #pathSeparatorChar}</code>.
0179: */
0180: public static final String pathSeparator = "" + pathSeparatorChar;
0181:
0182: /* -- Constructors -- */
0183:
0184: /**
0185: * Internal constructor for already-normalized pathname strings.
0186: */
0187: private File(String pathname, int prefixLength) {
0188: this .path = pathname;
0189: this .prefixLength = prefixLength;
0190: }
0191:
0192: /**
0193: * Creates a new <code>File</code> instance by converting the given
0194: * pathname string into an abstract pathname. If the given string is
0195: * the empty string, then the result is the empty abstract pathname.
0196: *
0197: * @param pathname A pathname string
0198: * @throws NullPointerException
0199: * If the <code>pathname</code> argument is <code>null</code>
0200: */
0201: public File(String pathname) {
0202: if (pathname == null) {
0203: throw new NullPointerException();
0204: }
0205: this .path = fs.normalize(pathname);
0206: this .prefixLength = fs.prefixLength(this .path);
0207: }
0208:
0209: /* Note: The two-argument File constructors do not interpret an empty
0210: parent abstract pathname as the current user directory. An empty parent
0211: instead causes the child to be resolved against the system-dependent
0212: directory defined by the FileSystem.getDefaultParent method. On Unix
0213: this default is "/", while on Microsoft Windows it is "\\". This is required for
0214: compatibility with the original behavior of this class. */
0215:
0216: /**
0217: * Creates a new <code>File</code> instance from a parent pathname string
0218: * and a child pathname string.
0219: *
0220: * <p> If <code>parent</code> is <code>null</code> then the new
0221: * <code>File</code> instance is created as if by invoking the
0222: * single-argument <code>File</code> constructor on the given
0223: * <code>child</code> pathname string.
0224: *
0225: * <p> Otherwise the <code>parent</code> pathname string is taken to denote
0226: * a directory, and the <code>child</code> pathname string is taken to
0227: * denote either a directory or a file. If the <code>child</code> pathname
0228: * string is absolute then it is converted into a relative pathname in a
0229: * system-dependent way. If <code>parent</code> is the empty string then
0230: * the new <code>File</code> instance is created by converting
0231: * <code>child</code> into an abstract pathname and resolving the result
0232: * against a system-dependent default directory. Otherwise each pathname
0233: * string is converted into an abstract pathname and the child abstract
0234: * pathname is resolved against the parent.
0235: *
0236: * @param parent The parent pathname string
0237: * @param child The child pathname string
0238: * @throws NullPointerException
0239: * If <code>child</code> is <code>null</code>
0240: */
0241: public File(String parent, String child) {
0242: if (child == null) {
0243: throw new NullPointerException();
0244: }
0245: if (parent != null) {
0246: if (parent.equals("")) {
0247: this .path = fs.resolve(fs.getDefaultParent(), fs
0248: .normalize(child));
0249: } else {
0250: this .path = fs.resolve(fs.normalize(parent), fs
0251: .normalize(child));
0252: }
0253: } else {
0254: this .path = fs.normalize(child);
0255: }
0256: this .prefixLength = fs.prefixLength(this .path);
0257: }
0258:
0259: /**
0260: * Creates a new <code>File</code> instance from a parent abstract
0261: * pathname and a child pathname string.
0262: *
0263: * <p> If <code>parent</code> is <code>null</code> then the new
0264: * <code>File</code> instance is created as if by invoking the
0265: * single-argument <code>File</code> constructor on the given
0266: * <code>child</code> pathname string.
0267: *
0268: * <p> Otherwise the <code>parent</code> abstract pathname is taken to
0269: * denote a directory, and the <code>child</code> pathname string is taken
0270: * to denote either a directory or a file. If the <code>child</code>
0271: * pathname string is absolute then it is converted into a relative
0272: * pathname in a system-dependent way. If <code>parent</code> is the empty
0273: * abstract pathname then the new <code>File</code> instance is created by
0274: * converting <code>child</code> into an abstract pathname and resolving
0275: * the result against a system-dependent default directory. Otherwise each
0276: * pathname string is converted into an abstract pathname and the child
0277: * abstract pathname is resolved against the parent.
0278: *
0279: * @param parent The parent abstract pathname
0280: * @param child The child pathname string
0281: * @throws NullPointerException
0282: * If <code>child</code> is <code>null</code>
0283: */
0284: public File(File parent, String child) {
0285: if (child == null) {
0286: throw new NullPointerException();
0287: }
0288: if (parent != null) {
0289: if (parent.path.equals("")) {
0290: this .path = fs.resolve(fs.getDefaultParent(), fs
0291: .normalize(child));
0292: } else {
0293: this .path = fs
0294: .resolve(parent.path, fs.normalize(child));
0295: }
0296: } else {
0297: this .path = fs.normalize(child);
0298: }
0299: this .prefixLength = fs.prefixLength(this .path);
0300: }
0301:
0302: /**
0303: * Creates a new <tt>File</tt> instance by converting the given
0304: * <tt>file:</tt> URI into an abstract pathname.
0305: *
0306: * <p> The exact form of a <tt>file:</tt> URI is system-dependent, hence
0307: * the transformation performed by this constructor is also
0308: * system-dependent.
0309: *
0310: * <p> For a given abstract pathname <i>f</i> it is guaranteed that
0311: *
0312: * <blockquote><tt>
0313: * new File(</tt><i> f</i><tt>.{@link #toURI() toURI}()).equals(</tt><i> f</i><tt>.{@link #getAbsoluteFile() getAbsoluteFile}())
0314: * </tt></blockquote>
0315: *
0316: * so long as the original abstract pathname, the URI, and the new abstract
0317: * pathname are all created in (possibly different invocations of) the same
0318: * Java virtual machine. This relationship typically does not hold,
0319: * however, when a <tt>file:</tt> URI that is created in a virtual machine
0320: * on one operating system is converted into an abstract pathname in a
0321: * virtual machine on a different operating system.
0322: *
0323: * @param uri
0324: * An absolute, hierarchical URI with a scheme equal to
0325: * <tt>"file"</tt>, a non-empty path component, and undefined
0326: * authority, query, and fragment components
0327: *
0328: * @throws NullPointerException
0329: * If <tt>uri</tt> is <tt>null</tt>
0330: *
0331: * @throws IllegalArgumentException
0332: * If the preconditions on the parameter do not hold
0333: *
0334: * @see #toURI()
0335: * @see java.net.URI
0336: * @since 1.4
0337: */
0338:
0339: public File(URI uri) {
0340:
0341: // Check our many preconditions
0342: if (!uri.isAbsolute())
0343: throw new IllegalArgumentException("URI is not absolute");
0344: if (uri.isOpaque())
0345: throw new IllegalArgumentException(
0346: "URI is not hierarchical");
0347: String scheme = uri.getScheme();
0348: if ((scheme == null) || !scheme.equalsIgnoreCase("file"))
0349: throw new IllegalArgumentException(
0350: "URI scheme is not \"file\"");
0351: if (uri.getAuthority() != null)
0352: throw new IllegalArgumentException(
0353: "URI has an authority component");
0354: if (uri.getFragment() != null)
0355: throw new IllegalArgumentException(
0356: "URI has a fragment component");
0357: if (uri.getQuery() != null)
0358: throw new IllegalArgumentException(
0359: "URI has a query component");
0360: String p = uri.getPath();
0361: if (p.equals(""))
0362: throw new IllegalArgumentException(
0363: "URI path component is empty");
0364:
0365: // Okay, now initialize
0366: p = fs.fromURIPath(p);
0367: if (File.separatorChar != '/')
0368: p = p.replace('/', File.separatorChar);
0369: this .path = fs.normalize(p);
0370: this .prefixLength = fs.prefixLength(this .path);
0371: }
0372:
0373: /* -- Path-component accessors -- */
0374:
0375: /**
0376: * Returns the name of the file or directory denoted by this abstract
0377: * pathname. This is just the last name in the pathname's name
0378: * sequence. If the pathname's name sequence is empty, then the empty
0379: * string is returned.
0380: *
0381: * @return The name of the file or directory denoted by this abstract
0382: * pathname, or the empty string if this pathname's name sequence
0383: * is empty
0384: */
0385: public String getName() {
0386: int index = path.lastIndexOf(separatorChar);
0387: if (index < prefixLength)
0388: return path.substring(prefixLength);
0389: return path.substring(index + 1);
0390: }
0391:
0392: /**
0393: * Returns the pathname string of this abstract pathname's parent, or
0394: * <code>null</code> if this pathname does not name a parent directory.
0395: *
0396: * <p> The <em>parent</em> of an abstract pathname consists of the
0397: * pathname's prefix, if any, and each name in the pathname's name
0398: * sequence except for the last. If the name sequence is empty then
0399: * the pathname does not name a parent directory.
0400: *
0401: * @return The pathname string of the parent directory named by this
0402: * abstract pathname, or <code>null</code> if this pathname
0403: * does not name a parent
0404: */
0405: public String getParent() {
0406: int index = path.lastIndexOf(separatorChar);
0407: if (index < prefixLength) {
0408: if ((prefixLength > 0) && (path.length() > prefixLength))
0409: return path.substring(0, prefixLength);
0410: return null;
0411: }
0412: return path.substring(0, index);
0413: }
0414:
0415: /**
0416: * Returns the abstract pathname of this abstract pathname's parent,
0417: * or <code>null</code> if this pathname does not name a parent
0418: * directory.
0419: *
0420: * <p> The <em>parent</em> of an abstract pathname consists of the
0421: * pathname's prefix, if any, and each name in the pathname's name
0422: * sequence except for the last. If the name sequence is empty then
0423: * the pathname does not name a parent directory.
0424: *
0425: * @return The abstract pathname of the parent directory named by this
0426: * abstract pathname, or <code>null</code> if this pathname
0427: * does not name a parent
0428: *
0429: * @since 1.2
0430: */
0431: public File getParentFile() {
0432: String p = this .getParent();
0433: if (p == null)
0434: return null;
0435: return new File(p, this .prefixLength);
0436: }
0437:
0438: /**
0439: * Converts this abstract pathname into a pathname string. The resulting
0440: * string uses the {@link #separator default name-separator character} to
0441: * separate the names in the name sequence.
0442: *
0443: * @return The string form of this abstract pathname
0444: */
0445: public String getPath() {
0446: return path;
0447: }
0448:
0449: /* -- Path operations -- */
0450:
0451: /**
0452: * Tests whether this abstract pathname is absolute. The definition of
0453: * absolute pathname is system dependent. On UNIX systems, a pathname is
0454: * absolute if its prefix is <code>"/"</code>. On Microsoft Windows systems, a
0455: * pathname is absolute if its prefix is a drive specifier followed by
0456: * <code>"\\"</code>, or if its prefix is <code>"\\"</code>.
0457: *
0458: * @return <code>true</code> if this abstract pathname is absolute,
0459: * <code>false</code> otherwise
0460: */
0461: public boolean isAbsolute() {
0462: return fs.isAbsolute(this );
0463: }
0464:
0465: /**
0466: * Returns the absolute pathname string of this abstract pathname.
0467: *
0468: * <p> If this abstract pathname is already absolute, then the pathname
0469: * string is simply returned as if by the <code>{@link #getPath}</code>
0470: * method. If this abstract pathname is the empty abstract pathname then
0471: * the pathname string of the current user directory, which is named by the
0472: * system property <code>user.dir</code>, is returned. Otherwise this
0473: * pathname is resolved in a system-dependent way. On UNIX systems, a
0474: * relative pathname is made absolute by resolving it against the current
0475: * user directory. On Microsoft Windows systems, a relative pathname is made absolute
0476: * by resolving it against the current directory of the drive named by the
0477: * pathname, if any; if not, it is resolved against the current user
0478: * directory.
0479: *
0480: * @return The absolute pathname string denoting the same file or
0481: * directory as this abstract pathname
0482: *
0483: * @throws SecurityException
0484: * If a required system property value cannot be accessed.
0485: *
0486: * @see java.io.File#isAbsolute()
0487: */
0488: public String getAbsolutePath() {
0489: return fs.resolve(this );
0490: }
0491:
0492: /**
0493: * Returns the absolute form of this abstract pathname. Equivalent to
0494: * <code>new File(this.{@link #getAbsolutePath}())</code>.
0495: *
0496: * @return The absolute abstract pathname denoting the same file or
0497: * directory as this abstract pathname
0498: *
0499: * @throws SecurityException
0500: * If a required system property value cannot be accessed.
0501: *
0502: * @since 1.2
0503: */
0504: public File getAbsoluteFile() {
0505: return new File(getAbsolutePath());
0506: }
0507:
0508: /**
0509: * Returns the canonical pathname string of this abstract pathname.
0510: *
0511: * <p> A canonical pathname is both absolute and unique. The precise
0512: * definition of canonical form is system-dependent. This method first
0513: * converts this pathname to absolute form if necessary, as if by invoking the
0514: * {@link #getAbsolutePath} method, and then maps it to its unique form in a
0515: * system-dependent way. This typically involves removing redundant names
0516: * such as <tt>"."</tt> and <tt>".."</tt> from the pathname, resolving
0517: * symbolic links (on UNIX platforms), and converting drive letters to a
0518: * standard case (on Microsoft Windows platforms).
0519: *
0520: * <p> Every pathname that denotes an existing file or directory has a
0521: * unique canonical form. Every pathname that denotes a nonexistent file
0522: * or directory also has a unique canonical form. The canonical form of
0523: * the pathname of a nonexistent file or directory may be different from
0524: * the canonical form of the same pathname after the file or directory is
0525: * created. Similarly, the canonical form of the pathname of an existing
0526: * file or directory may be different from the canonical form of the same
0527: * pathname after the file or directory is deleted.
0528: *
0529: * @return The canonical pathname string denoting the same file or
0530: * directory as this abstract pathname
0531: *
0532: * @throws IOException
0533: * If an I/O error occurs, which is possible because the
0534: * construction of the canonical pathname may require
0535: * filesystem queries
0536: *
0537: * @throws SecurityException
0538: * If a required system property value cannot be accessed.
0539: *
0540: * @since JDK1.1
0541: */
0542: public String getCanonicalPath() throws IOException {
0543: return fs.canonicalize(fs.resolve(this ));
0544: }
0545:
0546: /**
0547: * Returns the canonical form of this abstract pathname. Equivalent to
0548: * <code>new File(this.{@link #getCanonicalPath}())</code>.
0549: *
0550: * @return The canonical pathname string denoting the same file or
0551: * directory as this abstract pathname
0552: *
0553: * @throws IOException
0554: * If an I/O error occurs, which is possible because the
0555: * construction of the canonical pathname may require
0556: * filesystem queries
0557: *
0558: * @throws SecurityException
0559: * If a required system property value cannot be accessed.
0560: *
0561: * @since 1.2
0562: */
0563: public File getCanonicalFile() throws IOException {
0564: return new File(getCanonicalPath());
0565: }
0566:
0567: private static String slashify(String path, boolean isDirectory) {
0568: String p = path;
0569: if (File.separatorChar != '/')
0570: p = p.replace(File.separatorChar, '/');
0571: if (!p.startsWith("/"))
0572: p = "/" + p;
0573: if (!p.endsWith("/") && isDirectory)
0574: p = p + "/";
0575: return p;
0576: }
0577:
0578: /**
0579: * Converts this abstract pathname into a <code>file:</code> URL. The
0580: * exact form of the URL is system-dependent. If it can be determined that
0581: * the file denoted by this abstract pathname is a directory, then the
0582: * resulting URL will end with a slash.
0583: *
0584: * <p> <b>Usage note:</b> This method does not automatically escape
0585: * characters that are illegal in URLs. It is recommended that new code
0586: * convert an abstract pathname into a URL by first converting it into a
0587: * URI, via the {@link #toURI() toURI} method, and then converting the URI
0588: * into a URL via the {@link java.net.URI#toURL() URI.toURL} method.
0589: *
0590: * @return A URL object representing the equivalent file URL
0591: *
0592: * @throws MalformedURLException
0593: * If the path cannot be parsed as a URL
0594: *
0595: * @see #toURI()
0596: * @see java.net.URI
0597: * @see java.net.URI#toURL()
0598: * @see java.net.URL
0599: * @since 1.2
0600: */
0601: public URL toURL() throws MalformedURLException {
0602: return new URL("file", "", slashify(getAbsolutePath(),
0603: isDirectory()));
0604: }
0605:
0606: /**
0607: * Constructs a <tt>file:</tt> URI that represents this abstract pathname.
0608: *
0609: * <p> The exact form of the URI is system-dependent. If it can be
0610: * determined that the file denoted by this abstract pathname is a
0611: * directory, then the resulting URI will end with a slash.
0612: *
0613: * <p> For a given abstract pathname <i>f</i>, it is guaranteed that
0614: *
0615: * <blockquote><tt>
0616: * new {@link #File(java.net.URI) File}(</tt><i> f</i><tt>.toURI()).equals(</tt><i> f</i><tt>.{@link #getAbsoluteFile() getAbsoluteFile}())
0617: * </tt></blockquote>
0618: *
0619: * so long as the original abstract pathname, the URI, and the new abstract
0620: * pathname are all created in (possibly different invocations of) the same
0621: * Java virtual machine. Due to the system-dependent nature of abstract
0622: * pathnames, however, this relationship typically does not hold when a
0623: * <tt>file:</tt> URI that is created in a virtual machine on one operating
0624: * system is converted into an abstract pathname in a virtual machine on a
0625: * different operating system.
0626: *
0627: * @return An absolute, hierarchical URI with a scheme equal to
0628: * <tt>"file"</tt>, a path representing this abstract pathname,
0629: * and undefined authority, query, and fragment components
0630: *
0631: * @see #File(java.net.URI)
0632: * @see java.net.URI
0633: * @see java.net.URI#toURL()
0634: * @since 1.4
0635: */
0636: public URI toURI() {
0637: try {
0638: File f = getAbsoluteFile();
0639: String sp = slashify(f.getPath(), f.isDirectory());
0640: if (sp.startsWith("//"))
0641: sp = "//" + sp;
0642: return new URI("file", null, sp, null);
0643: } catch (URISyntaxException x) {
0644: throw new Error(x); // Can't happen
0645: }
0646: }
0647:
0648: /* -- Attribute accessors -- */
0649:
0650: /**
0651: * Tests whether the application can read the file denoted by this
0652: * abstract pathname.
0653: *
0654: * @return <code>true</code> if and only if the file specified by this
0655: * abstract pathname exists <em>and</em> can be read by the
0656: * application; <code>false</code> otherwise
0657: *
0658: * @throws SecurityException
0659: * If a security manager exists and its <code>{@link
0660: * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
0661: * method denies read access to the file
0662: */
0663: public boolean canRead() {
0664: SecurityManager security = System.getSecurityManager();
0665: if (security != null) {
0666: security.checkRead(path);
0667: }
0668: return fs.checkAccess(this , false);
0669: }
0670:
0671: /**
0672: * Tests whether the application can modify to the file denoted by this
0673: * abstract pathname.
0674: *
0675: * @return <code>true</code> if and only if the file system actually
0676: * contains a file denoted by this abstract pathname <em>and</em>
0677: * the application is allowed to write to the file;
0678: * <code>false</code> otherwise.
0679: *
0680: * @throws SecurityException
0681: * If a security manager exists and its <code>{@link
0682: * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
0683: * method denies write access to the file
0684: */
0685: public boolean canWrite() {
0686: SecurityManager security = System.getSecurityManager();
0687: if (security != null) {
0688: security.checkWrite(path);
0689: }
0690: return fs.checkAccess(this , true);
0691: }
0692:
0693: /**
0694: * Tests whether the file or directory denoted by this abstract pathname
0695: * exists.
0696: *
0697: * @return <code>true</code> if and only if the file or directory denoted
0698: * by this abstract pathname exists; <code>false</code> otherwise
0699: *
0700: * @throws SecurityException
0701: * If a security manager exists and its <code>{@link
0702: * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
0703: * method denies read access to the file or directory
0704: */
0705: public boolean exists() {
0706: SecurityManager security = System.getSecurityManager();
0707: if (security != null) {
0708: security.checkRead(path);
0709: }
0710: return ((fs.getBooleanAttributes(this ) & FileSystem.BA_EXISTS) != 0);
0711: }
0712:
0713: /**
0714: * Tests whether the file denoted by this abstract pathname is a
0715: * directory.
0716: *
0717: * @return <code>true</code> if and only if the file denoted by this
0718: * abstract pathname exists <em>and</em> is a directory;
0719: * <code>false</code> otherwise
0720: *
0721: * @throws SecurityException
0722: * If a security manager exists and its <code>{@link
0723: * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
0724: * method denies read access to the file
0725: */
0726: public boolean isDirectory() {
0727: SecurityManager security = System.getSecurityManager();
0728: if (security != null) {
0729: security.checkRead(path);
0730: }
0731: return ((fs.getBooleanAttributes(this ) & FileSystem.BA_DIRECTORY) != 0);
0732: }
0733:
0734: /**
0735: * Tests whether the file denoted by this abstract pathname is a normal
0736: * file. A file is <em>normal</em> if it is not a directory and, in
0737: * addition, satisfies other system-dependent criteria. Any non-directory
0738: * file created by a Java application is guaranteed to be a normal file.
0739: *
0740: * @return <code>true</code> if and only if the file denoted by this
0741: * abstract pathname exists <em>and</em> is a normal file;
0742: * <code>false</code> otherwise
0743: *
0744: * @throws SecurityException
0745: * If a security manager exists and its <code>{@link
0746: * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
0747: * method denies read access to the file
0748: */
0749: public boolean isFile() {
0750: SecurityManager security = System.getSecurityManager();
0751: if (security != null) {
0752: security.checkRead(path);
0753: }
0754: return ((fs.getBooleanAttributes(this ) & FileSystem.BA_REGULAR) != 0);
0755: }
0756:
0757: /**
0758: * Tests whether the file named by this abstract pathname is a hidden
0759: * file. The exact definition of <em>hidden</em> is system-dependent. On
0760: * UNIX systems, a file is considered to be hidden if its name begins with
0761: * a period character (<code>'.'</code>). On Microsoft Windows systems, a file is
0762: * considered to be hidden if it has been marked as such in the filesystem.
0763: *
0764: * @return <code>true</code> if and only if the file denoted by this
0765: * abstract pathname is hidden according to the conventions of the
0766: * underlying platform
0767: *
0768: * @throws SecurityException
0769: * If a security manager exists and its <code>{@link
0770: * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
0771: * method denies read access to the file
0772: *
0773: * @since 1.2
0774: */
0775: public boolean isHidden() {
0776: SecurityManager security = System.getSecurityManager();
0777: if (security != null) {
0778: security.checkRead(path);
0779: }
0780: return ((fs.getBooleanAttributes(this ) & FileSystem.BA_HIDDEN) != 0);
0781: }
0782:
0783: /**
0784: * Returns the time that the file denoted by this abstract pathname was
0785: * last modified.
0786: *
0787: * @return A <code>long</code> value representing the time the file was
0788: * last modified, measured in milliseconds since the epoch
0789: * (00:00:00 GMT, January 1, 1970), or <code>0L</code> if the
0790: * file does not exist or if an I/O error occurs
0791: *
0792: * @throws SecurityException
0793: * If a security manager exists and its <code>{@link
0794: * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
0795: * method denies read access to the file
0796: */
0797: public long lastModified() {
0798: SecurityManager security = System.getSecurityManager();
0799: if (security != null) {
0800: security.checkRead(path);
0801: }
0802: return fs.getLastModifiedTime(this );
0803: }
0804:
0805: /**
0806: * Returns the length of the file denoted by this abstract pathname.
0807: * The return value is unspecified if this pathname denotes a directory.
0808: *
0809: * @return The length, in bytes, of the file denoted by this abstract
0810: * pathname, or <code>0L</code> if the file does not exist
0811: *
0812: * @throws SecurityException
0813: * If a security manager exists and its <code>{@link
0814: * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
0815: * method denies read access to the file
0816: */
0817: public long length() {
0818: SecurityManager security = System.getSecurityManager();
0819: if (security != null) {
0820: security.checkRead(path);
0821: }
0822: return fs.getLength(this );
0823: }
0824:
0825: /* -- File operations -- */
0826:
0827: /**
0828: * Atomically creates a new, empty file named by this abstract pathname if
0829: * and only if a file with this name does not yet exist. The check for the
0830: * existence of the file and the creation of the file if it does not exist
0831: * are a single operation that is atomic with respect to all other
0832: * filesystem activities that might affect the file.
0833: * <P>
0834: * Note: this method should <i>not</i> be used for file-locking, as
0835: * the resulting protocol cannot be made to work reliably.
0836: *
0837: * @return <code>true</code> if the named file does not exist and was
0838: * successfully created; <code>false</code> if the named file
0839: * already exists
0840: *
0841: * @throws IOException
0842: * If an I/O error occurred
0843: *
0844: * @throws SecurityException
0845: * If a security manager exists and its <code>{@link
0846: * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
0847: * method denies write access to the file
0848: *
0849: * @since 1.2
0850: */
0851: public boolean createNewFile() throws IOException {
0852: SecurityManager security = System.getSecurityManager();
0853: if (security != null)
0854: security.checkWrite(path);
0855: return fs.createFileExclusively(path);
0856: }
0857:
0858: /**
0859: * Deletes the file or directory denoted by this abstract pathname. If
0860: * this pathname denotes a directory, then the directory must be empty in
0861: * order to be deleted.
0862: *
0863: * @return <code>true</code> if and only if the file or directory is
0864: * successfully deleted; <code>false</code> otherwise
0865: *
0866: * @throws SecurityException
0867: * If a security manager exists and its <code>{@link
0868: * java.lang.SecurityManager#checkDelete}</code> method denies
0869: * delete access to the file
0870: */
0871: public boolean delete() {
0872: SecurityManager security = System.getSecurityManager();
0873: if (security != null) {
0874: security.checkDelete(path);
0875: }
0876: return fs.delete(this );
0877: }
0878:
0879: /**
0880: * Requests that the file or directory denoted by this abstract
0881: * pathname be deleted when the virtual machine terminates.
0882: * Deletion will be attempted only for normal termination of the
0883: * virtual machine, as defined by the Java Language Specification.
0884: *
0885: * <p> Once deletion has been requested, it is not possible to cancel the
0886: * request. This method should therefore be used with care.
0887: *
0888: * <P>
0889: * Note: this method should <i>not</i> be used for file-locking, as
0890: * the resulting protocol cannot be made to work reliably.
0891: *
0892: * @throws SecurityException
0893: * If a security manager exists and its <code>{@link
0894: * java.lang.SecurityManager#checkDelete}</code> method denies
0895: * delete access to the file
0896: *
0897: * @see #delete
0898: *
0899: * @since 1.2
0900: */
0901: public void deleteOnExit() {
0902: SecurityManager security = System.getSecurityManager();
0903: if (security != null) {
0904: security.checkDelete(path);
0905: }
0906: fs.deleteOnExit(this );
0907: }
0908:
0909: /**
0910: * Returns an array of strings naming the files and directories in the
0911: * directory denoted by this abstract pathname.
0912: *
0913: * <p> If this abstract pathname does not denote a directory, then this
0914: * method returns <code>null</code>. Otherwise an array of strings is
0915: * returned, one for each file or directory in the directory. Names
0916: * denoting the directory itself and the directory's parent directory are
0917: * not included in the result. Each string is a file name rather than a
0918: * complete path.
0919: *
0920: * <p> There is no guarantee that the name strings in the resulting array
0921: * will appear in any specific order; they are not, in particular,
0922: * guaranteed to appear in alphabetical order.
0923: *
0924: * @return An array of strings naming the files and directories in the
0925: * directory denoted by this abstract pathname. The array will be
0926: * empty if the directory is empty. Returns <code>null</code> if
0927: * this abstract pathname does not denote a directory, or if an
0928: * I/O error occurs.
0929: *
0930: * @throws SecurityException
0931: * If a security manager exists and its <code>{@link
0932: * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
0933: * method denies read access to the directory
0934: */
0935: public String[] list() {
0936: SecurityManager security = System.getSecurityManager();
0937: if (security != null) {
0938: security.checkRead(path);
0939: }
0940: return fs.list(this );
0941: }
0942:
0943: /**
0944: * Returns an array of strings naming the files and directories in the
0945: * directory denoted by this abstract pathname that satisfy the specified
0946: * filter. The behavior of this method is the same as that of the
0947: * <code>{@link #list()}</code> method, except that the strings in the
0948: * returned array must satisfy the filter. If the given
0949: * <code>filter</code> is <code>null</code> then all names are accepted.
0950: * Otherwise, a name satisfies the filter if and only if the value
0951: * <code>true</code> results when the <code>{@link
0952: * FilenameFilter#accept}</code> method of the filter is invoked on this
0953: * abstract pathname and the name of a file or directory in the directory
0954: * that it denotes.
0955: *
0956: * @param filter A filename filter
0957: *
0958: * @return An array of strings naming the files and directories in the
0959: * directory denoted by this abstract pathname that were accepted
0960: * by the given <code>filter</code>. The array will be empty if
0961: * the directory is empty or if no names were accepted by the
0962: * filter. Returns <code>null</code> if this abstract pathname
0963: * does not denote a directory, or if an I/O error occurs.
0964: *
0965: * @throws SecurityException
0966: * If a security manager exists and its <code>{@link
0967: * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
0968: * method denies read access to the directory
0969: */
0970: public String[] list(FilenameFilter filter) {
0971: String names[] = list();
0972: if ((names == null) || (filter == null)) {
0973: return names;
0974: }
0975: ArrayList v = new ArrayList();
0976: for (int i = 0; i < names.length; i++) {
0977: if (filter.accept(this , names[i])) {
0978: v.add(names[i]);
0979: }
0980: }
0981: return (String[]) (v.toArray(new String[0]));
0982: }
0983:
0984: /**
0985: * Returns an array of abstract pathnames denoting the files in the
0986: * directory denoted by this abstract pathname.
0987: *
0988: * <p> If this abstract pathname does not denote a directory, then this
0989: * method returns <code>null</code>. Otherwise an array of
0990: * <code>File</code> objects is returned, one for each file or directory in
0991: * the directory. Pathnames denoting the directory itself and the
0992: * directory's parent directory are not included in the result. Each
0993: * resulting abstract pathname is constructed from this abstract pathname
0994: * using the <code>{@link #File(java.io.File, java.lang.String)
0995: * File(File, String)}</code> constructor. Therefore if this pathname
0996: * is absolute then each resulting pathname is absolute; if this pathname
0997: * is relative then each resulting pathname will be relative to the same
0998: * directory.
0999: *
1000: * <p> There is no guarantee that the name strings in the resulting array
1001: * will appear in any specific order; they are not, in particular,
1002: * guaranteed to appear in alphabetical order.
1003: *
1004: * @return An array of abstract pathnames denoting the files and
1005: * directories in the directory denoted by this abstract
1006: * pathname. The array will be empty if the directory is
1007: * empty. Returns <code>null</code> if this abstract pathname
1008: * does not denote a directory, or if an I/O error occurs.
1009: *
1010: * @throws SecurityException
1011: * If a security manager exists and its <code>{@link
1012: * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
1013: * method denies read access to the directory
1014: *
1015: * @since 1.2
1016: */
1017: public File[] listFiles() {
1018: String[] ss = list();
1019: if (ss == null)
1020: return null;
1021: int n = ss.length;
1022: File[] fs = new File[n];
1023: for (int i = 0; i < n; i++) {
1024: fs[i] = new File(this .path, ss[i]);
1025: }
1026: return fs;
1027: }
1028:
1029: /**
1030: * Returns an array of abstract pathnames denoting the files and
1031: * directories in the directory denoted by this abstract pathname that
1032: * satisfy the specified filter. The behavior of this method is the
1033: * same as that of the <code>{@link #listFiles()}</code> method, except
1034: * that the pathnames in the returned array must satisfy the filter.
1035: * If the given <code>filter</code> is <code>null</code> then all
1036: * pathnames are accepted. Otherwise, a pathname satisfies the filter
1037: * if and only if the value <code>true</code> results when the
1038: * <code>{@link FilenameFilter#accept}</code> method of the filter is
1039: * invoked on this abstract pathname and the name of a file or
1040: * directory in the directory that it denotes.
1041: *
1042: * @param filter A filename filter
1043: *
1044: * @return An array of abstract pathnames denoting the files and
1045: * directories in the directory denoted by this abstract
1046: * pathname. The array will be empty if the directory is
1047: * empty. Returns <code>null</code> if this abstract pathname
1048: * does not denote a directory, or if an I/O error occurs.
1049: *
1050: * @throws SecurityException
1051: * If a security manager exists and its <code>{@link
1052: * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
1053: * method denies read access to the directory
1054: *
1055: * @since 1.2
1056: */
1057: public File[] listFiles(FilenameFilter filter) {
1058: String ss[] = list();
1059: if (ss == null)
1060: return null;
1061: ArrayList v = new ArrayList();
1062: for (int i = 0; i < ss.length; i++) {
1063: if ((filter == null) || filter.accept(this , ss[i])) {
1064: v.add(new File(this .path, ss[i]));
1065: }
1066: }
1067: return (File[]) (v.toArray(new File[0]));
1068: }
1069:
1070: /**
1071: * Returns an array of abstract pathnames denoting the files and
1072: * directories in the directory denoted by this abstract pathname that
1073: * satisfy the specified filter. The behavior of this method is the
1074: * same as that of the <code>{@link #listFiles()}</code> method, except
1075: * that the pathnames in the returned array must satisfy the filter.
1076: * If the given <code>filter</code> is <code>null</code> then all
1077: * pathnames are accepted. Otherwise, a pathname satisfies the filter
1078: * if and only if the value <code>true</code> results when the
1079: * <code>{@link FileFilter#accept(java.io.File)}</code> method of
1080: * the filter is invoked on the pathname.
1081: *
1082: * @param filter A file filter
1083: *
1084: * @return An array of abstract pathnames denoting the files and
1085: * directories in the directory denoted by this abstract
1086: * pathname. The array will be empty if the directory is
1087: * empty. Returns <code>null</code> if this abstract pathname
1088: * does not denote a directory, or if an I/O error occurs.
1089: *
1090: * @throws SecurityException
1091: * If a security manager exists and its <code>{@link
1092: * java.lang.SecurityManager#checkRead(java.lang.String)}</code>
1093: * method denies read access to the directory
1094: *
1095: * @since 1.2
1096: */
1097: public File[] listFiles(FileFilter filter) {
1098: String ss[] = list();
1099: if (ss == null)
1100: return null;
1101: ArrayList v = new ArrayList();
1102: for (int i = 0; i < ss.length; i++) {
1103: File f = new File(this .path, ss[i]);
1104: if ((filter == null) || filter.accept(f)) {
1105: v.add(f);
1106: }
1107: }
1108: return (File[]) (v.toArray(new File[0]));
1109: }
1110:
1111: /**
1112: * Creates the directory named by this abstract pathname.
1113: *
1114: * @return <code>true</code> if and only if the directory was
1115: * created; <code>false</code> otherwise
1116: *
1117: * @throws SecurityException
1118: * If a security manager exists and its <code>{@link
1119: * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1120: * method does not permit the named directory to be created
1121: */
1122: public boolean mkdir() {
1123: SecurityManager security = System.getSecurityManager();
1124: if (security != null) {
1125: security.checkWrite(path);
1126: }
1127: return fs.createDirectory(this );
1128: }
1129:
1130: /**
1131: * Creates the directory named by this abstract pathname, including any
1132: * necessary but nonexistent parent directories. Note that if this
1133: * operation fails it may have succeeded in creating some of the necessary
1134: * parent directories.
1135: *
1136: * @return <code>true</code> if and only if the directory was created,
1137: * along with all necessary parent directories; <code>false</code>
1138: * otherwise
1139: *
1140: * @throws SecurityException
1141: * If a security manager exists and its <code>{@link
1142: * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1143: * method does not permit the named directory and all necessary
1144: * parent directories and to be created
1145: */
1146: public boolean mkdirs() {
1147: if (exists()) {
1148: return false;
1149: }
1150: if (mkdir()) {
1151: return true;
1152: }
1153: File canonFile = null;
1154: try {
1155: canonFile = getCanonicalFile();
1156: } catch (IOException e) {
1157: return false;
1158: }
1159: String parent = canonFile.getParent();
1160: return (parent != null)
1161: && (new File(parent).mkdirs() && canonFile.mkdir());
1162: }
1163:
1164: /**
1165: * Renames the file denoted by this abstract pathname.
1166: *
1167: * <p> Whether or not this method can move a file from one filesystem
1168: * to another is platform-dependent. The return value should always
1169: * be checked to make sure that the rename operation was successful.
1170: *
1171: * @param dest The new abstract pathname for the named file
1172: *
1173: * @return <code>true</code> if and only if the renaming succeeded;
1174: * <code>false</code> otherwise
1175: *
1176: * @throws SecurityException
1177: * If a security manager exists and its <code>{@link
1178: * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1179: * method denies write access to either the old or new pathnames
1180: *
1181: * @throws NullPointerException
1182: * If parameter <code>dest</code> is <code>null</code>
1183: */
1184: public boolean renameTo(File dest) {
1185: SecurityManager security = System.getSecurityManager();
1186: if (security != null) {
1187: security.checkWrite(path);
1188: security.checkWrite(dest.path);
1189: }
1190: return fs.rename(this , dest);
1191: }
1192:
1193: /**
1194: * Sets the last-modified time of the file or directory named by this
1195: * abstract pathname.
1196: *
1197: * <p> All platforms support file-modification times to the nearest second,
1198: * but some provide more precision. The argument will be truncated to fit
1199: * the supported precision. If the operation succeeds and no intervening
1200: * operations on the file take place, then the next invocation of the
1201: * <code>{@link #lastModified}</code> method will return the (possibly
1202: * truncated) <code>time</code> argument that was passed to this method.
1203: *
1204: * @param time The new last-modified time, measured in milliseconds since
1205: * the epoch (00:00:00 GMT, January 1, 1970)
1206: *
1207: * @return <code>true</code> if and only if the operation succeeded;
1208: * <code>false</code> otherwise
1209: *
1210: * @throws IllegalArgumentException If the argument is negative
1211: *
1212: * @throws SecurityException
1213: * If a security manager exists and its <code>{@link
1214: * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1215: * method denies write access to the named file
1216: *
1217: * @since 1.2
1218: */
1219: public boolean setLastModified(long time) {
1220: if (time < 0)
1221: throw new IllegalArgumentException("Negative time");
1222: SecurityManager security = System.getSecurityManager();
1223: if (security != null) {
1224: security.checkWrite(path);
1225: }
1226: return fs.setLastModifiedTime(this , time);
1227: }
1228:
1229: /**
1230: * Marks the file or directory named by this abstract pathname so that
1231: * only read operations are allowed. After invoking this method the file
1232: * or directory is guaranteed not to change until it is either deleted or
1233: * marked to allow write access. Whether or not a read-only file or
1234: * directory may be deleted depends upon the underlying system.
1235: *
1236: * @return <code>true</code> if and only if the operation succeeded;
1237: * <code>false</code> otherwise
1238: *
1239: * @throws SecurityException
1240: * If a security manager exists and its <code>{@link
1241: * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1242: * method denies write access to the named file
1243: *
1244: * @since 1.2
1245: */
1246: public boolean setReadOnly() {
1247: SecurityManager security = System.getSecurityManager();
1248: if (security != null) {
1249: security.checkWrite(path);
1250: }
1251: return fs.setReadOnly(this );
1252: }
1253:
1254: /* -- Filesystem interface -- */
1255:
1256: /**
1257: * List the available filesystem roots.
1258: *
1259: * <p> A particular Java platform may support zero or more
1260: * hierarchically-organized file systems. Each file system has a
1261: * <code>root</code> directory from which all other files in that file
1262: * system can be reached. Windows platforms, for example, have a root
1263: * directory for each active drive; UNIX platforms have a single root
1264: * directory, namely <code>"/"</code>. The set of available filesystem
1265: * roots is affected by various system-level operations such the insertion
1266: * or ejection of removable media and the disconnecting or unmounting of
1267: * physical or virtual disk drives.
1268: *
1269: * <p> This method returns an array of <code>File</code> objects that
1270: * denote the root directories of the available filesystem roots. It is
1271: * guaranteed that the canonical pathname of any file physically present on
1272: * the local machine will begin with one of the roots returned by this
1273: * method.
1274: *
1275: * <p> The canonical pathname of a file that resides on some other machine
1276: * and is accessed via a remote-filesystem protocol such as SMB or NFS may
1277: * or may not begin with one of the roots returned by this method. If the
1278: * pathname of a remote file is syntactically indistinguishable from the
1279: * pathname of a local file then it will begin with one of the roots
1280: * returned by this method. Thus, for example, <code>File</code> objects
1281: * denoting the root directories of the mapped network drives of a Windows
1282: * platform will be returned by this method, while <code>File</code>
1283: * objects containing UNC pathnames will not be returned by this method.
1284: *
1285: * <p> Unlike most methods in this class, this method does not throw
1286: * security exceptions. If a security manager exists and its <code>{@link
1287: * java.lang.SecurityManager#checkRead(java.lang.String)}</code> method
1288: * denies read access to a particular root directory, then that directory
1289: * will not appear in the result.
1290: *
1291: * @return An array of <code>File</code> objects denoting the available
1292: * filesystem roots, or <code>null</code> if the set of roots
1293: * could not be determined. The array will be empty if there are
1294: * no filesystem roots.
1295: *
1296: * @since 1.2
1297: */
1298: public static File[] listRoots() {
1299: return fs.listRoots();
1300: }
1301:
1302: /* -- Temporary files -- */
1303:
1304: private static final Object tmpFileLock = new Object();
1305:
1306: private static int counter = -1; /* Protected by tmpFileLock */
1307:
1308: private static File generateFile(String prefix, String suffix,
1309: File dir) throws IOException {
1310: if (counter == -1) {
1311: counter = new Random().nextInt() & 0xffff;
1312: }
1313: counter++;
1314: return new File(dir, prefix + Integer.toString(counter)
1315: + suffix);
1316: }
1317:
1318: private static String tmpdir; /* Protected by tmpFileLock */
1319:
1320: private static String getTempDir() {
1321: if (tmpdir == null) {
1322: GetPropertyAction a = new GetPropertyAction(
1323: "java.io.tmpdir");
1324: tmpdir = ((String) AccessController.doPrivileged(a));
1325: }
1326: return tmpdir;
1327: }
1328:
1329: private static boolean checkAndCreate(String filename,
1330: SecurityManager sm) throws IOException {
1331: if (sm != null) {
1332: try {
1333: sm.checkWrite(filename);
1334: } catch (AccessControlException x) {
1335: /* Throwing the original AccessControlException could disclose
1336: the location of the default temporary directory, so we
1337: re-throw a more innocuous SecurityException */
1338: throw new SecurityException(
1339: "Unable to create temporary file");
1340: }
1341: }
1342: return fs.createFileExclusively(filename);
1343: }
1344:
1345: /**
1346: * <p> Creates a new empty file in the specified directory, using the
1347: * given prefix and suffix strings to generate its name. If this method
1348: * returns successfully then it is guaranteed that:
1349: *
1350: * <ol>
1351: * <li> The file denoted by the returned abstract pathname did not exist
1352: * before this method was invoked, and
1353: * <li> Neither this method nor any of its variants will return the same
1354: * abstract pathname again in the current invocation of the virtual
1355: * machine.
1356: * </ol>
1357: *
1358: * This method provides only part of a temporary-file facility. To arrange
1359: * for a file created by this method to be deleted automatically, use the
1360: * <code>{@link #deleteOnExit}</code> method.
1361: *
1362: * <p> The <code>prefix</code> argument must be at least three characters
1363: * long. It is recommended that the prefix be a short, meaningful string
1364: * such as <code>"hjb"</code> or <code>"mail"</code>. The
1365: * <code>suffix</code> argument may be <code>null</code>, in which case the
1366: * suffix <code>".tmp"</code> will be used.
1367: *
1368: * <p> To create the new file, the prefix and the suffix may first be
1369: * adjusted to fit the limitations of the underlying platform. If the
1370: * prefix is too long then it will be truncated, but its first three
1371: * characters will always be preserved. If the suffix is too long then it
1372: * too will be truncated, but if it begins with a period character
1373: * (<code>'.'</code>) then the period and the first three characters
1374: * following it will always be preserved. Once these adjustments have been
1375: * made the name of the new file will be generated by concatenating the
1376: * prefix, five or more internally-generated characters, and the suffix.
1377: *
1378: * <p> If the <code>directory</code> argument is <code>null</code> then the
1379: * system-dependent default temporary-file directory will be used. The
1380: * default temporary-file directory is specified by the system property
1381: * <code>java.io.tmpdir</code>. On UNIX systems the default value of this
1382: * property is typically <code>"/tmp"</code> or <code>"/var/tmp"</code>; on
1383: * Microsoft Windows systems it is typically <code>"c:\\temp"</code>. A different
1384: * value may be given to this system property when the Java virtual machine
1385: * is invoked, but programmatic changes to this property are not guaranteed
1386: * to have any effect upon the the temporary directory used by this method.
1387: *
1388: * @param prefix The prefix string to be used in generating the file's
1389: * name; must be at least three characters long
1390: *
1391: * @param suffix The suffix string to be used in generating the file's
1392: * name; may be <code>null</code>, in which case the
1393: * suffix <code>".tmp"</code> will be used
1394: *
1395: * @param directory The directory in which the file is to be created, or
1396: * <code>null</code> if the default temporary-file
1397: * directory is to be used
1398: *
1399: * @return An abstract pathname denoting a newly-created empty file
1400: *
1401: * @throws IllegalArgumentException
1402: * If the <code>prefix</code> argument contains fewer than three
1403: * characters
1404: *
1405: * @throws IOException If a file could not be created
1406: *
1407: * @throws SecurityException
1408: * If a security manager exists and its <code>{@link
1409: * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1410: * method does not allow a file to be created
1411: *
1412: * @since 1.2
1413: */
1414: public static File createTempFile(String prefix, String suffix,
1415: File directory) throws IOException {
1416: if (prefix == null)
1417: throw new NullPointerException();
1418: if (prefix.length() < 3)
1419: throw new IllegalArgumentException(
1420: "Prefix string too short");
1421: String s = (suffix == null) ? ".tmp" : suffix;
1422: synchronized (tmpFileLock) {
1423: if (directory == null) {
1424: directory = new File(getTempDir());
1425: }
1426: SecurityManager sm = System.getSecurityManager();
1427: File f;
1428: do {
1429: f = generateFile(prefix, s, directory);
1430: } while (!checkAndCreate(f.getPath(), sm));
1431: return f;
1432: }
1433: }
1434:
1435: /**
1436: * Creates an empty file in the default temporary-file directory, using
1437: * the given prefix and suffix to generate its name. Invoking this method
1438: * is equivalent to invoking <code>{@link #createTempFile(java.lang.String,
1439: * java.lang.String, java.io.File)
1440: * createTempFile(prefix, suffix, null)}</code>.
1441: *
1442: * @param prefix The prefix string to be used in generating the file's
1443: * name; must be at least three characters long
1444: *
1445: * @param suffix The suffix string to be used in generating the file's
1446: * name; may be <code>null</code>, in which case the
1447: * suffix <code>".tmp"</code> will be used
1448: *
1449: * @return An abstract pathname denoting a newly-created empty file
1450: *
1451: * @throws IllegalArgumentException
1452: * If the <code>prefix</code> argument contains fewer than three
1453: * characters
1454: *
1455: * @throws IOException If a file could not be created
1456: *
1457: * @throws SecurityException
1458: * If a security manager exists and its <code>{@link
1459: * java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
1460: * method does not allow a file to be created
1461: *
1462: * @since 1.2
1463: */
1464: public static File createTempFile(String prefix, String suffix)
1465: throws IOException {
1466: return createTempFile(prefix, suffix, null);
1467: }
1468:
1469: /* -- Basic infrastructure -- */
1470:
1471: /**
1472: * Compares two abstract pathnames lexicographically. The ordering
1473: * defined by this method depends upon the underlying system. On UNIX
1474: * systems, alphabetic case is significant in comparing pathnames; on Microsoft Windows
1475: * systems it is not.
1476: *
1477: * @param pathname The abstract pathname to be compared to this abstract
1478: * pathname
1479: *
1480: * @return Zero if the argument is equal to this abstract pathname, a
1481: * value less than zero if this abstract pathname is
1482: * lexicographically less than the argument, or a value greater
1483: * than zero if this abstract pathname is lexicographically
1484: * greater than the argument
1485: *
1486: * @since 1.2
1487: */
1488: public int compareTo(File pathname) {
1489: return fs.compare(this , pathname);
1490: }
1491:
1492: /**
1493: * Compares this abstract pathname to another object. If the other object
1494: * is an abstract pathname, then this function behaves like <code>{@link
1495: * #compareTo(File)}</code>. Otherwise, it throws a
1496: * <code>ClassCastException</code>, since abstract pathnames can only be
1497: * compared to abstract pathnames.
1498: *
1499: * @param o The <code>Object</code> to be compared to this abstract
1500: * pathname
1501: *
1502: * @return If the argument is an abstract pathname, returns zero
1503: * if the argument is equal to this abstract pathname, a value
1504: * less than zero if this abstract pathname is lexicographically
1505: * less than the argument, or a value greater than zero if this
1506: * abstract pathname is lexicographically greater than the
1507: * argument
1508: *
1509: * @throws <code>ClassCastException</code> if the argument is not an
1510: * abstract pathname
1511: *
1512: * @see java.lang.Comparable
1513: * @since 1.2
1514: */
1515: public int compareTo(Object o) {
1516: return compareTo((File) o);
1517: }
1518:
1519: /**
1520: * Tests this abstract pathname for equality with the given object.
1521: * Returns <code>true</code> if and only if the argument is not
1522: * <code>null</code> and is an abstract pathname that denotes the same file
1523: * or directory as this abstract pathname. Whether or not two abstract
1524: * pathnames are equal depends upon the underlying system. On UNIX
1525: * systems, alphabetic case is significant in comparing pathnames; on Microsoft Windows
1526: * systems it is not.
1527: *
1528: * @param obj The object to be compared with this abstract pathname
1529: *
1530: * @return <code>true</code> if and only if the objects are the same;
1531: * <code>false</code> otherwise
1532: */
1533: public boolean equals(Object obj) {
1534: if ((obj != null) && (obj instanceof File)) {
1535: return compareTo((File) obj) == 0;
1536: }
1537: return false;
1538: }
1539:
1540: /**
1541: * Computes a hash code for this abstract pathname. Because equality of
1542: * abstract pathnames is inherently system-dependent, so is the computation
1543: * of their hash codes. On UNIX systems, the hash code of an abstract
1544: * pathname is equal to the exclusive <em>or</em> of its pathname string
1545: * and the decimal value <code>1234321</code>. On Microsoft Windows systems, the hash
1546: * code is equal to the exclusive <em>or</em> of its pathname string,
1547: * convered to lower case, and the decimal value <code>1234321</code>.
1548: *
1549: * @return A hash code for this abstract pathname
1550: */
1551: public int hashCode() {
1552: return fs.hashCode(this );
1553: }
1554:
1555: /**
1556: * Returns the pathname string of this abstract pathname. This is just the
1557: * string returned by the <code>{@link #getPath}</code> method.
1558: *
1559: * @return The string form of this abstract pathname
1560: */
1561: public String toString() {
1562: return getPath();
1563: }
1564:
1565: /**
1566: * WriteObject is called to save this filename.
1567: * The separator character is saved also so it can be replaced
1568: * in case the path is reconstituted on a different host type.
1569: */
1570: private synchronized void writeObject(java.io.ObjectOutputStream s)
1571: throws IOException {
1572: s.defaultWriteObject();
1573: s.writeChar(this .separatorChar); // Add the separator character
1574: }
1575:
1576: /**
1577: * readObject is called to restore this filename.
1578: * The original separator character is read. If it is different
1579: * than the separator character on this system, then the old seperator
1580: * is replaced by the local separator.
1581: */
1582: private synchronized void readObject(java.io.ObjectInputStream s)
1583: throws IOException, ClassNotFoundException {
1584: s.defaultReadObject();
1585: char sep = s.readChar(); // read the previous seperator char
1586: if (sep != separatorChar)
1587: this .path = this .path.replace(sep, separatorChar);
1588: this .path = fs.normalize(this .path);
1589: this .prefixLength = fs.prefixLength(this .path);
1590: }
1591:
1592: /** use serialVersionUID from JDK 1.0.2 for interoperability */
1593: private static final long serialVersionUID = 301077366599181567L;
1594:
1595: }
|