/* File.java -- Class representing a file on disk
- Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004
+ Free Software Foundation, Inc.
This file is part of GNU Classpath.
package java.io;
import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.net.URL;
+import gnu.classpath.Configuration;
import gnu.gcj.runtime.FileDeleter;
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* types of path separators ("/" versus "\", for example). It also
* contains method useful for creating and deleting files and directories.
*
- * @author Aaron M. Renn <arenn@urbanophile.com>
- * @author Tom Tromey <tromey@cygnus.com>
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
*/
public class File implements Serializable, Comparable
{
* An example separator string would be "/" on the GNU system.
*/
public static final String separator = System.getProperty("file.separator");
+ private static final String dupSeparator = separator + separator;
/**
* This is the first character of the file separator string. On many
* is taken from the <code>path.separator</code> system property.
*/
public static final char pathSeparatorChar = pathSeparator.charAt(0);
-
static final String tmpdir = System.getProperty("java.io.tmpdir");
static int maxPathLen;
static boolean caseSensitive;
- static String dupSeparator = separator + separator;
static
{
+ if (Configuration.INIT_LOAD_LIBRARY)
+ {
+ System.loadLibrary("javaio");
+ }
+
init_native();
}
// We keep a counter for use by createTempFile. We choose the first
// value randomly to try to avoid clashes with other VMs.
- private static long counter = Double.doubleToLongBits (Math.random ());
+ private static long counter = Double.doubleToLongBits (Math.random());
/**
* This method tests whether or not the current thread is allowed to
* @exception SecurityException If the <code>SecurityManager</code>
* does not allow access to the file
*/
- public boolean canRead ()
+ public boolean canRead()
{
checkRead();
return _access (READ);
* @exception SecurityException If the <code>SecurityManager</code>
* does not allow access to the file
*/
- public boolean canWrite ()
+ public boolean canWrite()
{
checkWrite();
return _access (WRITE);
* the path of this <code>File</code> object if an only if that file
* does not already exist.
* <p>
- * A <code>SecurityManager</code>checkWrite</code> check is done prior
+ * A <code>SecurityManager.checkWrite</code> check is done prior
* to performing this action.
*
* @return <code>true</code> if the file was created, <code>false</code> if
/*
* This native method handles the actual deleting of the file
*/
- private native boolean performDelete ();
+ private native boolean performDelete();
/**
* This method deletes the file represented by this object. If this file
*
* @exception SecurityException If deleting of the file is not allowed
*/
- public synchronized boolean delete ()
+ public synchronized boolean delete()
{
- SecurityManager s = System.getSecurityManager ();
+ SecurityManager s = System.getSecurityManager();
if (s != null)
- s.checkDelete (path);
+ s.checkDelete(path);
- return performDelete ();
+ return performDelete();
}
/**
* @return <code>true</code> if the two objects are equal,
* <code>false</code> otherwise.
*/
- public boolean equals (Object obj)
+ public boolean equals(Object obj)
{
if (! (obj instanceof File))
return false;
File other = (File) obj;
+
if (caseSensitive)
return path.equals(other.path);
else
*
* @exception SecurityException If reading of the file is not permitted
*/
- public boolean exists ()
+ public boolean exists()
{
checkRead();
return _access (EXISTS);
*
* @param name The path name of the file
*/
- public File (String name)
+ public File(String name)
{
path = normalizePath (name);
}
// On Windows, convert any '/' to '\'. This appears to be the same logic
// that Sun's Win32 Java performs.
if (separatorChar == '\\')
- p = p.replace ('/', '\\');
+ {
+ p = p.replace ('/', '\\');
+ // We have to special case the "\c:" prefix.
+ if (p.length() > 2 && p.charAt(0) == '\\' &&
+ ((p.charAt(1) >= 'a' && p.charAt(1) <= 'z') ||
+ (p.charAt(1) >= 'A' && p.charAt(1) <= 'Z')) &&
+ p.charAt(2) == ':')
+ p = p.substring(1);
+ }
int dupIndex = p.indexOf(dupSeparator);
int plen = p.length();
* name. If the directory path name ends in the separator string, another
* separator string will still be appended.
*
- * @param dirname The path to the directory the file resides in
+ * @param dirPath The path to the directory the file resides in
* @param name The name of the file
*/
- public File (String dirPath, String name)
+ public File(String dirPath, String name)
{
if (name == null)
- throw new NullPointerException ();
- if (dirPath != null && dirPath.length() > 0)
+ throw new NullPointerException();
+ if (dirPath != null)
{
- // Try to be smart about the number of separator characters.
- if (dirPath.charAt(dirPath.length() - 1) == separatorChar
- || name.length() == 0)
- path = normalizePath(dirPath + name);
+ if (dirPath.length() > 0)
+ {
+ // Try to be smart about the number of separator characters.
+ if (dirPath.charAt(dirPath.length() - 1) == separatorChar
+ || name.length() == 0)
+ path = normalizePath(dirPath + name);
+ else
+ path = normalizePath(dirPath + separatorChar + name);
+ }
else
- path = normalizePath(dirPath + separatorChar + name);
+ {
+ // If dirPath is empty, use a system dependant
+ // default prefix.
+ // Note that the leading separators in name have
+ // to be chopped off, to prevent them forming
+ // a UNC prefix on Windows.
+ if (separatorChar == '\\' /* TODO use ON_WINDOWS */)
+ {
+ int skip = 0;
+ while(name.length() > skip
+ && (name.charAt(skip) == separatorChar
+ || name.charAt(skip) == '/'))
+ {
+ skip++;
+ }
+ name = name.substring(skip);
+ }
+ path = normalizePath(separatorChar + name);
+ }
}
else
path = normalizePath(name);
* @param directory The directory this file resides in
* @param name The name of the file
*/
- public File (File directory, String name)
+ public File(File directory, String name)
{
this (directory == null ? null : directory.path, name);
}
/**
+ * This method initializes a new <code>File</code> object to represent
+ * a file corresponding to the specified <code>file:</code> protocol URI.
+ *
+ * @param uri The uri.
+ */
+ public File(URI uri)
+ {
+ if (uri == null)
+ throw new NullPointerException("uri is null");
+
+ if (!uri.getScheme().equals("file"))
+ throw new IllegalArgumentException("invalid uri protocol");
+
+ path = normalizePath(uri.getPath());
+ }
+
+ /**
* This method returns the path of this file as an absolute path name.
* If the path name is already absolute, then it is returned. Otherwise
* the value returned is the current directory plus the separatory
*
* @return The absolute path of this file
*/
- public String getAbsolutePath ()
+ public String getAbsolutePath()
{
- if (isAbsolute ())
+ if (isAbsolute())
return path;
else if (separatorChar == '\\'
- && path.length () > 0 && path.charAt (0) == '\\')
+ && path.length() > 0 && path.charAt (0) == '\\')
{
// On Windows, even if the path starts with a '\\' it is not
// really absolute until we prefix the drive specifier from
return System.getProperty ("user.dir").substring (0, 2) + path;
}
else if (separatorChar == '\\'
- && path.length () > 1 && path.charAt (1) == ':'
+ && path.length() > 1 && path.charAt (1) == ':'
&& ((path.charAt (0) >= 'a' && path.charAt (0) <= 'z')
|| (path.charAt (0) >= 'A' && path.charAt (0) <= 'Z')))
{
String drvDir = null;
try
{
- drvDir = new File (path.substring (0, 2)).getCanonicalPath ();
+ drvDir = new File (path.substring (0, 2)).getCanonicalPath();
}
catch (IOException e)
{
// Note: this would return "C:\\." for the path "C:.", if "\"
// is the working folder on the C drive, but this is
// consistent with what Sun's JRE 1.4.1.01 actually returns!
- if (path.length () > 2)
- return drvDir + '\\' + path.substring (2, path.length ());
+ if (path.length() > 2)
+ return drvDir + '\\' + path.substring (2, path.length());
else
return drvDir;
}
*
* @since 1.2
*/
- public File getAbsoluteFile ()
+ public File getAbsoluteFile()
{
- return new File (getAbsolutePath());
+ return new File(getAbsolutePath());
}
/**
*
* @exception IOException If an error occurs
*/
- public native String getCanonicalPath () throws IOException;
+ public native String getCanonicalPath() throws IOException;
/**
* This method returns a <code>File</code> object representing the
*
* @since 1.2
*/
- public File getCanonicalFile () throws IOException
+ public File getCanonicalFile() throws IOException
{
- return new File (getCanonicalPath());
+ return new File(getCanonicalPath());
}
/**
*
* @return The file name
*/
- public String getName ()
+ public String getName()
{
int nameSeqIndex = 0;
- if (separatorChar == '\\' && path.length () > 1)
+ if (separatorChar == '\\' && path.length() > 1)
{
// On Windows, ignore the drive specifier or the leading '\\'
// of a UNC network path, if any (a.k.a. the "prefix").
|| (path.charAt (0) >= 'A' && path.charAt (0) <= 'Z'))
&& path.charAt (1) == ':'))
{
- if (path.length () > 2)
+ if (path.length() > 2)
nameSeqIndex = 2;
else
return "";
*
* @return The parent directory of this file
*/
- public String getParent ()
+ public String getParent()
{
String prefix = null;
int nameSeqIndex = 0;
prefix = "/";
nameSeqIndex = 1;
}
- else if (separatorChar == '\\' && path.length () > 1)
+ else if (separatorChar == '\\' && path.length() > 1)
{
if ((path.charAt (0) == '\\' && path.charAt (1) == '\\')
|| (((path.charAt (0) >= 'a' && path.charAt (0) <= 'z')
// According to the JDK docs, the returned parent path is the
// portion of the name sequence before the last separator
// character, if found, prefixed by the prefix, otherwise null.
- if (nameSeqIndex < path.length ())
+ if (nameSeqIndex < path.length())
{
- String nameSeq = path.substring (nameSeqIndex, path.length ());
+ String nameSeq = path.substring (nameSeqIndex, path.length());
int last = nameSeq.lastIndexOf (separatorChar);
if (last == -1)
return prefix;
- else if (last == (nameSeq.length () - 1))
+ else if (last == (nameSeq.length() - 1))
// Note: The path would not have a trailing separator
// except for cases like "C:\" on Windows (see
// normalizePath( )), where Sun's JRE 1.4 returns null.
* This method returns a <code>File</code> object representing the parent
* file of this one.
*
- * @param A <code>File</code> for the parent of this object.
+ * @return a <code>File</code> for the parent of this object.
* <code>null</code>
* will be returned if this object does not have a parent.
*
* @since 1.2
*/
- public File getParentFile ()
+ public File getParentFile()
{
- String parent = getParent ();
- return (parent == null ? null : new File (parent));
+ String parent = getParent();
+ return parent != null ? new File(parent) : null;
}
/**
*
* @return The pathname of this file
*/
- public String getPath ()
+ public String getPath()
{
return path;
}
*
* @return The hash code for this object
*/
- public int hashCode ()
+ public int hashCode()
{
if (caseSensitive)
- return (path.hashCode() ^ 1234321);
+ return path.hashCode() ^ 1234321;
else
- return (path.toLowerCase().hashCode() ^ 1234321);
+ return path.toLowerCase().hashCode() ^ 1234321;
}
/**
* @return <code>true</code> if this object represents an absolute
* file name, <code>false</code> otherwise.
*/
- public native boolean isAbsolute ();
+ public native boolean isAbsolute();
/**
* This method tests whether or not the file represented by this object
*
* @exception SecurityException If reading of the file is not permitted
*/
- public boolean isDirectory ()
+ public boolean isDirectory()
{
checkRead();
return _stat (DIRECTORY);
*
* @exception SecurityException If reading of the file is not permitted
*/
- public boolean isFile ()
+ public boolean isFile()
{
checkRead();
return _stat (ISFILE);
*
* @since 1.2
*/
- public boolean isHidden ()
+ public boolean isHidden()
{
checkRead();
return _stat (ISHIDDEN);
*
* @exception SecurityException If reading of the file is not permitted
*/
- public long lastModified ()
+ public long lastModified()
{
checkRead();
return attr (MODIFIED);
*
* @exception SecurityException If reading of the file is not permitted
*/
- public long length ()
+ public long length()
{
checkRead();
return attr (LENGTH);
* This native function actually produces the list of file in this
* directory
*/
-
private final native Object[] performList (FilenameFilter filter,
FileFilter fileFilter,
Class result_type);
* @exception SecurityException If read access is not allowed to the
* directory by the <code>SecurityManager</code>
*/
- public String[] list (FilenameFilter filter)
+ public String[] list(FilenameFilter filter)
{
checkRead();
return (String[]) performList (filter, null, String.class);
* @exception SecurityException If read access is not allowed to the
* directory by the <code>SecurityManager</code>
*/
- public String[] list ()
+ public String[] list()
{
checkRead();
return (String[]) performList (null, null, String.class);
*
* @since 1.2
*/
- public File[] listFiles ()
+ public File[] listFiles()
{
checkRead();
return (File[]) performList (null, null, File.class);
*
* @since 1.2
*/
- public File[] listFiles (FilenameFilter filter)
+ public File[] listFiles(FilenameFilter filter)
{
checkRead();
return (File[]) performList (filter, null, File.class);
*
* @since 1.2
*/
- public File[] listFiles (FileFilter filter)
+ public File[] listFiles(FileFilter filter)
{
checkRead();
return (File[]) performList (null, filter, File.class);
*
* @return A <code>String</code> representation of this file
*/
- public String toString ()
+ public String toString()
{
return path;
}
/**
+ * @return A <code>URI</code> for this object.
+ */
+ public URI toURI()
+ {
+ String abspath = getAbsolutePath();
+
+ if (isDirectory())
+ abspath = abspath + separator;
+
+ try
+ {
+ return new URI("file", "", abspath.replace(separatorChar, '/'));
+ }
+ catch (URISyntaxException use)
+ {
+ // Can't happen.
+ throw new RuntimeException(use);
+ }
+ }
+
+ /**
* This method returns a <code>URL</code> with the <code>file:</code>
* protocol that represents this file. The exact form of this URL is
* system dependent.
* @exception MalformedURLException If the URL cannot be created
* successfully.
*/
- public URL toURL () throws MalformedURLException
+ public URL toURL() throws MalformedURLException
{
// On Win32, Sun's JDK returns URLs of the form "file:/c:/foo/bar.txt",
// while on UNIX, it returns URLs of the form "file:/foo/bar.txt".
if (separatorChar == '\\')
- return new URL ("file:/" + getAbsolutePath ().replace ('\\', '/')
+ return new URL ("file:/" + getAbsolutePath().replace ('\\', '/')
+ (isDirectory() ? "/" : ""));
else
- return new URL ("file:" + getAbsolutePath ()
+ return new URL ("file:" + getAbsolutePath()
+ (isDirectory() ? "/" : ""));
}
/*
* This native method actually creates the directory
*/
- private final native boolean performMkdir ();
+ private final native boolean performMkdir();
/**
* This method creates a directory for the path represented by this object.
*
* @exception SecurityException If write access is not allowed to this file
*/
- public boolean mkdir ()
+ public boolean mkdir()
{
checkWrite();
- return performMkdir ();
+ return performMkdir();
}
private static boolean mkdirs (File x)
*
* @exception SecurityException If write access is not allowed to this file
*/
- public boolean mkdirs ()
+ public boolean mkdirs()
{
checkWrite();
- if (isDirectory ())
+ if (isDirectory())
return false;
return mkdirs (new File (path));
}
- private static synchronized String nextValue ()
+ private static synchronized String nextValue()
{
return Long.toString(counter++, Character.MAX_RADIX);
}
*
* @since 1.2
*/
- public static File createTempFile (String prefix, String suffix,
- File directory)
+ public static File createTempFile(String prefix, String suffix,
+ File directory)
throws IOException
{
// Grab the system temp directory if necessary
if (directory == null)
{
- String dirname = tmpdir;
- if (dirname == null)
- throw
- new IOException("Cannot determine system temporary directory");
+ String dirname = tmpdir;
+ if (dirname == null)
+ throw new IOException("Cannot determine system temporary directory");
- directory = new File(dirname);
- if (!directory.exists())
- throw new IOException("System temporary directory "
- + directory.getName() + " does not exist.");
- if (!directory.isDirectory())
- throw new IOException("System temporary directory "
- + directory.getName()
- + " is not really a directory.");
+ directory = new File(dirname);
+ if (!directory.exists())
+ throw new IOException("System temporary directory "
+ + directory.getName() + " does not exist.");
+ if (!directory.isDirectory())
+ throw new IOException("System temporary directory "
+ + directory.getName()
+ + " is not really a directory.");
}
- if (prefix.length () < 3)
- throw new IllegalArgumentException ("Prefix too short: " + prefix);
+ // Check if prefix is at least 3 characters long
+ if (prefix.length() < 3)
+ throw new IllegalArgumentException("Prefix too short: " + prefix);
+
+ // Set default value of suffix
if (suffix == null)
suffix = ".tmp";
// Truncation rules.
// `6' is the number of characters we generate.
- if (prefix.length () + 6 + suffix.length () > maxPathLen)
+ if (prefix.length() + 6 + suffix.length() > maxPathLen)
{
int suf_len = 0;
if (suffix.charAt(0) == '.')
suf_len = 4;
suffix = suffix.substring(0, suf_len);
- if (prefix.length () + 6 + suf_len > maxPathLen)
+ if (prefix.length() + 6 + suf_len > maxPathLen)
prefix = prefix.substring(0, maxPathLen - 6 - suf_len);
}
for (int i = 0; i < 100; ++i)
{
// This is ugly.
- String t = "ZZZZZZ" + nextValue ();
+ String t = "ZZZZZZ" + nextValue();
String l = prefix + t.substring(t.length() - 6) + suffix;
try
{
*
* @since 1.2
*/
- public boolean setReadOnly ()
+ public boolean setReadOnly()
{
+ // Do a security check before trying to do anything else.
checkWrite();
return performSetReadOnly();
}
*
* @since 1.2
*/
- public static File[] listRoots ()
+ public static File[] listRoots()
{
File[] roots = performListRoots();
{
try
{
- s.checkRead(roots[i].path);
+ s.checkRead (roots[i].path);
}
catch (SecurityException sx)
{
* this operation
* @exception IOException If an error occurs
*/
- public static File createTempFile (String prefix, String suffix)
+ public static File createTempFile(String prefix, String suffix)
throws IOException
{
- return createTempFile (prefix, suffix, null);
+ return createTempFile(prefix, suffix, null);
}
/**
*
* @since 1.2
*/
- public int compareTo(Object o)
+ public int compareTo(Object obj)
{
- File other = (File) o;
- return compareTo (other);
+ return compareTo((File) obj);
}
/*
* @exception SecurityException If write access is not allowed to the
* file by the <code>SecurityMananger</code>.
*/
- public synchronized boolean renameTo (File dest)
+ public synchronized boolean renameTo(File dest)
{
SecurityManager s = System.getSecurityManager();
String sname = getName();
String dname = dest.getName();
if (s != null)
{
- s.checkWrite(sname);
- s.checkWrite(dname);
+ s.checkWrite (sname);
+ s.checkWrite (dname);
}
return performRenameTo (dest);
}
*
* @since 1.2
*/
- public boolean setLastModified (long time)
+ public boolean setLastModified(long time)
{
+ if (time < 0)
+ throw new IllegalArgumentException("Negative modification time: " + time);
+
checkWrite();
return performSetLastModified(time);
}
- private void checkWrite ()
+ private void checkWrite()
{
// Check the SecurityManager
- SecurityManager s = System.getSecurityManager ();
+ SecurityManager s = System.getSecurityManager();
if (s != null)
- s.checkWrite (path);
+ s.checkWrite(path);
}
- private void checkRead ()
+ private void checkRead()
{
// Check the SecurityManager
- SecurityManager s = System.getSecurityManager ();
+ SecurityManager s = System.getSecurityManager();
if (s != null)
- s.checkRead (path);
+ s.checkRead(path);
}
/**
- * Add this File to the set of files to be deleted upon normal
- * termination.
- *
- * @since 1.2
- */
+ * Calling this method requests that the file represented by this object
+ * be deleted when the virtual machine exits. Note that this request cannot
+ * be cancelled. Also, it will only be carried out if the virtual machine
+ * exits normally.
+ *
+ * @exception SecurityException If deleting of the file is not allowed
+ *
+ * @since 1.2
+ */
// FIXME: This should use the ShutdownHook API once we implement that.
- public void deleteOnExit ()
+ public void deleteOnExit()
{
// Check the SecurityManager
- SecurityManager sm = System.getSecurityManager ();
+ SecurityManager sm = System.getSecurityManager();
if (sm != null)
- sm.checkDelete (getName ());
+ sm.checkDelete (getName());
FileDeleter.add (this);
}
- private void writeObject (ObjectOutputStream oos) throws IOException
+ private void writeObject(ObjectOutputStream oos) throws IOException
{
- oos.defaultWriteObject ();
- oos.writeChar (separatorChar);
+ oos.defaultWriteObject();
+ oos.writeChar(separatorChar);
}
- private void readObject (ObjectInputStream ois)
+ private void readObject(ObjectInputStream ois)
throws ClassNotFoundException, IOException
{
- ois.defaultReadObject ();
+ ois.defaultReadObject();
// If the file was from an OS with a different dir separator,
// fixup the path to use the separator on this OS.
- char oldSeparatorChar = ois.readChar ();
+ char oldSeparatorChar = ois.readChar();
if (oldSeparatorChar != separatorChar)
- path = path.replace (oldSeparatorChar, separatorChar);
+ path = path.replace(oldSeparatorChar, separatorChar);
}
+
} // class File