gcc/libjava/java/io/File.java

428 lines
10 KiB
Java
Raw Normal View History

1999-04-07 22:42:40 +08:00
// File.java - File name
/* Copyright (C) 1998, 1999, 2000 Free Software Foundation
1999-04-07 22:42:40 +08:00
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.io;
import java.util.*;
import gnu.gcj.runtime.FileDeleter;
1999-04-07 22:42:40 +08:00
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date September 24, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Complete to version 1.1; 1.2 functionality missing.
* A known bug: most calls to the security manager can generate
* IOException since we use the canonical path.
*/
public class File implements Serializable
{
public boolean canRead ()
{
return access (checkRead (), READ);
}
public boolean canWrite ()
{
SecurityManager s = System.getSecurityManager();
String p = safeCanonicalPath ();
// FIXME: it isn't entirely clear what to do if we can't find the
// canonical path.
if (p == null)
return false;
if (s != null)
s.checkWrite(p);
return access (p, WRITE);
}
private final native static boolean performDelete (String canon);
1999-04-07 22:42:40 +08:00
public boolean delete ()
{
SecurityManager s = System.getSecurityManager();
String p = safeCanonicalPath ();
// FIXME: what is right?
if (p == null)
return false;
if (s != null)
s.checkDelete(p);
return performDelete (p);
}
public boolean equals (Object obj)
{
if (! (obj instanceof File))
return false;
File other = (File) obj;
return path.compareTo(other.path) == 0;
}
public boolean exists ()
{
return access (checkRead (), EXISTS);
}
public File (String p)
{
if (p == null)
throw new NullPointerException ();
path = p;
}
public File (String dirPath, String name)
{
if (name == null)
throw new NullPointerException ();
if (dirPath != null && dirPath.length() > 0)
1999-04-07 22:42:40 +08:00
{
// Try to be smart about the number of separator characters.
if (dirPath.charAt(dirPath.length() - 1) == separatorChar)
path = dirPath + name;
else
path = dirPath + separatorChar + name;
}
else
path = name;
}
public File (File dir, String name)
{
this (dir == null ? null : dir.path, name);
}
public String getAbsolutePath ()
{
if (isAbsolute ())
return path;
return System.getProperty("user.dir") + separatorChar + path;
}
public native String getCanonicalPath () throws IOException;
public String getName ()
{
int last = path.lastIndexOf(separatorChar);
return path.substring(last + 1);
1999-04-07 22:42:40 +08:00
}
public String getParent ()
{
int last = path.lastIndexOf(separatorChar);
if (last == -1)
return null;
return path.substring(0, last);
}
public File getParentFile ()
{
String parent = getParent ();
return (parent == null ? null : new File (parent));
}
1999-04-07 22:42:40 +08:00
public String getPath ()
{
return path;
}
public int hashCode ()
{
// FIXME: test.
return path.hashCode();
}
public native boolean isAbsolute ();
public boolean isDirectory ()
{
return stat (checkRead (), DIRECTORY);
}
public boolean isFile ()
{
return stat (checkRead (), ISFILE);
}
public long lastModified ()
{
return attr (checkRead (), MODIFIED);
}
public long length ()
{
return attr (checkRead (), LENGTH);
}
private final native String[] performList (String canon,
FilenameFilter filter);
public String[] list (FilenameFilter filter)
{
return performList (checkRead (), filter);
}
public String[] list ()
{
return performList (checkRead (), null);
}
public String toString ()
{
return path;
}
private final native boolean performMkdir ();
public boolean mkdir ()
{
SecurityManager s = System.getSecurityManager();
if (s != null)
{
// NOTE: in theory we should use the canonical path. In
// practice, we can't compute the canonical path until we've
// made this completely. Lame.
s.checkWrite(path);
}
return performMkdir ();
}
private static boolean mkdirs (File x)
{
if (x.isDirectory())
return true;
String p = x.getPath();
String parent = x.getParent();
if (parent != null)
{
x.setPath(parent);
if (! mkdirs (x))
return false;
x.setPath(p);
}
1999-04-07 22:42:40 +08:00
return x.mkdir();
}
public boolean mkdirs ()
{
SecurityManager s = System.getSecurityManager();
if (s != null)
{
// NOTE: in theory we should use the canonical path. In
// practice, we can't compute the canonical path until we've
// made this completely. Lame.
s.checkWrite(path);
}
if (isDirectory ())
return false;
return mkdirs (new File (path));
}
private static synchronized String nextValue ()
{
return Long.toString(counter++, Character.MAX_RADIX);
}
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");
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);
if (suffix == null)
suffix = ".tmp";
// FIXME: filename length varies by architecture and filesystem.
int max_length = 255;
// Truncation rules.
// `6' is the number of characters we generate.
if (prefix.length () + 6 + suffix.length () > max_length)
{
int suf_len = 0;
if (suffix.charAt(0) == '.')
suf_len = 4;
suffix = suffix.substring(0, suf_len);
if (prefix.length () + 6 + suf_len > max_length)
prefix = prefix.substring(0, max_length - 6 - suf_len);
}
File f;
// How many times should we try? We choose 100.
for (int i = 0; i < 100; ++i)
{
// This is ugly.
String t = "ZZZZZZ" + nextValue ();
String l = prefix + t.substring(t.length() - 6) + suffix;
try
{
f = new File(directory, l);
if (f.exists())
continue;
else
{
String af = f.getAbsolutePath ();
// Check to see if we're allowed to write to it.
SecurityManager s = System.getSecurityManager();
if (s != null)
s.checkWrite (af);
// Now create the file.
FileDescriptor fd =
new FileDescriptor (af,
FileDescriptor.WRITE
| FileDescriptor.EXCL);
fd.close ();
return f;
}
}
catch (IOException _)
{
}
}
throw new IOException ("cannot create temporary file");
}
public static File createTempFile (String prefix, String suffix)
throws IOException
{
return createTempFile (prefix, suffix, null);
}
1999-04-07 22:42:40 +08:00
private final native boolean performRenameTo (File dest);
public boolean renameTo (File dest)
{
SecurityManager s = System.getSecurityManager();
if (s != null)
{
// FIXME: JCL doesn't specify which path to check. We check the
// source since we can canonicalize it.
s.checkWrite(safeCanonicalPath());
}
return performRenameTo (dest);
}
public static final String pathSeparator
= System.getProperty("path.separator");
public static final char pathSeparatorChar = pathSeparator.charAt(0);
public static final String separator = System.getProperty("file.separator");
public static final char separatorChar = separator.charAt(0);
private static final String tmpdir = System.getProperty("java.io.tmpdir");
1999-04-07 22:42:40 +08:00
// The path.
private String path;
// 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 ());
1999-04-07 22:42:40 +08:00
// mkdirs() uses this to avoid repeated allocations.
private final void setPath (String n)
{
path = n;
}
private final String checkRead ()
{
SecurityManager s = System.getSecurityManager();
String p = safeCanonicalPath ();
if (p == null)
return null;
if (s != null)
s.checkRead(p);
return p;
}
// Return canonical path, or null.
private final String safeCanonicalPath ()
{
String p = null;
try
{
p = getCanonicalPath ();
}
catch (IOException x)
{
// Nothing.
}
return p;
}
// Add this File to the set of files to be deleted upon normal
// termination.
public void deleteOnExit ()
{
SecurityManager sm = System.getSecurityManager ();
if (sm != null)
sm.checkDelete (getName ());
FileDeleter.add (this);
}
PropertyChangeEvent.java (serialVersionUID): Added. * java/beans/PropertyChangeEvent.java (serialVersionUID): Added. * java/beans/PropertyVetoException.java (serialVersionUID): Added. * java/io/File.java (writeObject): Added. (readObject): Added. (serialVersionUID): Added. * java/io/ObjectOutputStream.java (writeObject): Initialized fieldsAlreadyWritten before recursion rather than after. * java/io/ObjectStreamClass.java (serialVersionUID): Added. * java/io/OptionalDataException.java (serialVersionUID): Added. (OptionalDataException): Made package private. * java/io/SyncFailedException.java (SyncFailedException): Removed default constructor to match spec. * java/lang/Boolean.java (serialVersionUID): Added. * java/lang/Byte.java (serialVersionUID): Added. * java/lang/Character.java (serialVersionUID): Added. * java/lang/Double.java (serialVersionUID): Added. * java/lang/Float.java (serialVersionUID): Added. * java/lang/Integer.java (serialVersionUID): Added. * java/lang/Long.java (serialVersionUID): Added. * java/lang/Number.java (serialVersionUID): Added. * java/lang/Short.java (serialVersionUID): Added. * java/lang/String.java (serialVersionUID): Added. * java/lang/ThreadDeath.java (ThreadDeath): Removed constructor to match spec. * java/lang/reflect/InvocationTargetException.java (serialVersionUID): Added. * java/net/URL.java (handler): Made transient. (hashCode): Added field for serialization, per spec. and use cached value if available. (serialVersionUID): Added. (URL): Initialize hashCode. (set): Adjust hashCode. (readObject): New Method to initialize the protocol handler when deserializing. (writeObject): New method. * java/text/BreakIterator.java: Removed 'implements Serializable'. * java/text/Collator.java: Removed 'implements Serializable'. * java/util/GregorianCalendar.java (serialVersionUID): Added. * java/util/Properties.java (serialVersionUID): Added. * java/util/Random.java (serialVersionUID): Added. (seed): Made private. (nextNextGaussian): Made private. (haveNextNextGaussian): Made private. * java/util/Stack.java (serialVersionUID): Added. * java/util/TimeZone.java (serialVersionUID): Added. * java/util/Vector.java (serialVersionUID): Added. Serialization mods. From-SVN: r36272
2000-09-09 03:37:09 +08:00
private void writeObject (ObjectOutputStream oos) throws IOException
{
oos.defaultWriteObject ();
oos.writeChar (separatorChar);
}
private void readObject (ObjectInputStream ois)
throws ClassNotFoundException, IOException
{
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 ();
if (oldSeparatorChar != separatorChar)
path = path.replace (oldSeparatorChar, separatorChar);
}
1999-04-07 22:42:40 +08:00
// QUERY arguments to access function.
private final static int READ = 0;
private final static int WRITE = 1;
private final static int EXISTS = 2;
// QUERY arguments to stat function.
private final static int DIRECTORY = 0;
private final static int ISFILE = 1;
// QUERY arguments to attr function.
private final static int MODIFIED = 0;
private final static int LENGTH = 1;
private final native long attr (String p, int query);
private final native boolean access (String p, int query);
private final native boolean stat (String p, int query);
PropertyChangeEvent.java (serialVersionUID): Added. * java/beans/PropertyChangeEvent.java (serialVersionUID): Added. * java/beans/PropertyVetoException.java (serialVersionUID): Added. * java/io/File.java (writeObject): Added. (readObject): Added. (serialVersionUID): Added. * java/io/ObjectOutputStream.java (writeObject): Initialized fieldsAlreadyWritten before recursion rather than after. * java/io/ObjectStreamClass.java (serialVersionUID): Added. * java/io/OptionalDataException.java (serialVersionUID): Added. (OptionalDataException): Made package private. * java/io/SyncFailedException.java (SyncFailedException): Removed default constructor to match spec. * java/lang/Boolean.java (serialVersionUID): Added. * java/lang/Byte.java (serialVersionUID): Added. * java/lang/Character.java (serialVersionUID): Added. * java/lang/Double.java (serialVersionUID): Added. * java/lang/Float.java (serialVersionUID): Added. * java/lang/Integer.java (serialVersionUID): Added. * java/lang/Long.java (serialVersionUID): Added. * java/lang/Number.java (serialVersionUID): Added. * java/lang/Short.java (serialVersionUID): Added. * java/lang/String.java (serialVersionUID): Added. * java/lang/ThreadDeath.java (ThreadDeath): Removed constructor to match spec. * java/lang/reflect/InvocationTargetException.java (serialVersionUID): Added. * java/net/URL.java (handler): Made transient. (hashCode): Added field for serialization, per spec. and use cached value if available. (serialVersionUID): Added. (URL): Initialize hashCode. (set): Adjust hashCode. (readObject): New Method to initialize the protocol handler when deserializing. (writeObject): New method. * java/text/BreakIterator.java: Removed 'implements Serializable'. * java/text/Collator.java: Removed 'implements Serializable'. * java/util/GregorianCalendar.java (serialVersionUID): Added. * java/util/Properties.java (serialVersionUID): Added. * java/util/Random.java (serialVersionUID): Added. (seed): Made private. (nextNextGaussian): Made private. (haveNextNextGaussian): Made private. * java/util/Stack.java (serialVersionUID): Added. * java/util/TimeZone.java (serialVersionUID): Added. * java/util/Vector.java (serialVersionUID): Added. Serialization mods. From-SVN: r36272
2000-09-09 03:37:09 +08:00
private static final long serialVersionUID = 301077366599181567L;
1999-04-07 22:42:40 +08:00
}