mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			581 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			581 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Java
		
	
	
	
| // File.java - File name
 | |
| 
 | |
| /* Copyright (C) 1998, 1999, 2000, 2001  Free Software Foundation
 | |
| 
 | |
|    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 java.net.*;
 | |
| import gnu.gcj.runtime.FileDeleter;
 | |
| 
 | |
| /**
 | |
|  * @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.3.
 | |
|  */
 | |
| 
 | |
| public class File implements Serializable, Comparable
 | |
| {
 | |
|   public boolean canRead ()
 | |
|   {
 | |
|     checkRead();
 | |
|     return _access (READ);
 | |
|   }
 | |
| 
 | |
|   public boolean canWrite ()
 | |
|   {
 | |
|     checkWrite();
 | |
|     return _access (WRITE);
 | |
|   }
 | |
|   
 | |
|   private native boolean performCreate() throws IOException;
 | |
| 
 | |
|   /** @since 1.2 */
 | |
|   public boolean createNewFile() throws IOException
 | |
|   {
 | |
|     checkWrite();
 | |
|     return performCreate();
 | |
|   }
 | |
|   
 | |
|   private native boolean performDelete ();
 | |
|   public boolean delete ()
 | |
|   {
 | |
|     SecurityManager s = System.getSecurityManager();
 | |
|     String name = path;
 | |
|     if (s != null)
 | |
|       s.checkDelete(path);
 | |
|     return performDelete ();
 | |
|   }
 | |
| 
 | |
|   public boolean equals (Object obj)
 | |
|   {
 | |
|     if (! (obj instanceof File))
 | |
|       return false;
 | |
|     File other = (File) obj;
 | |
|     if (caseSensitive)
 | |
|       return (path.equals(other.path));
 | |
|     else
 | |
|       return (path.equalsIgnoreCase(other.path));      
 | |
|   }
 | |
| 
 | |
|   public boolean exists ()
 | |
|   {
 | |
|     checkRead();
 | |
|     return _access (EXISTS);
 | |
|   }
 | |
| 
 | |
|   public File (String p)
 | |
|   {
 | |
|     path = normalizePath(p);
 | |
|   }
 | |
| 
 | |
|   // Remove duplicate and redundant separator characters.
 | |
|   private String normalizePath(String p)
 | |
|   {
 | |
|     int dupIndex = p.indexOf(dupSeparator);
 | |
|     int plen = p.length();
 | |
| 
 | |
|     // Special case: permit Windows UNC path prefix.
 | |
|     if (dupSeparator.equals("\\\\") && dupIndex == 0)
 | |
|       dupIndex = p.indexOf(dupSeparator, 1);
 | |
| 
 | |
|     if (dupIndex == -1)
 | |
|       {
 | |
|         // Ignore trailing separator.
 | |
|         if (plen > 1 && p.charAt(plen - 1) == separatorChar)
 | |
| 	  return p.substring(0, plen - 1);
 | |
| 	else
 | |
| 	  return p;
 | |
|       }
 | |
|     
 | |
|     StringBuffer newpath = new StringBuffer(plen);
 | |
|     int last = 0;
 | |
|     while (dupIndex != -1)
 | |
|       {
 | |
|         newpath.append(p.substring(last, dupIndex));
 | |
| 	// Ignore the duplicate path characters.
 | |
| 	while (p.charAt(dupIndex) == separatorChar)
 | |
| 	  {
 | |
| 	    dupIndex++;
 | |
| 	    if (dupIndex == plen)
 | |
| 	      return newpath.toString();
 | |
| 	  }
 | |
| 	newpath.append(separatorChar);
 | |
| 	last = dupIndex;
 | |
| 	dupIndex = p.indexOf(dupSeparator, last);
 | |
|       }
 | |
|     
 | |
|     // Again, ignore possible trailing separator.
 | |
|     int end;
 | |
|     if (plen > 1 && p.charAt(plen - 1) == separatorChar)
 | |
|       end = plen - 1;
 | |
|     else
 | |
|       end = plen;
 | |
|     newpath.append(p.substring(last, end));
 | |
|     
 | |
|     return newpath.toString();
 | |
|   }
 | |
|   
 | |
|   public File (String dirPath, String name)
 | |
|   {
 | |
|     if (name == null)
 | |
|       throw new NullPointerException ();
 | |
|     if (dirPath != null && 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(name);
 | |
|   }
 | |
| 
 | |
|   public File (File dir, String name)
 | |
|   {
 | |
|     this (dir == null ? null : dir.path, name);
 | |
|   }
 | |
| 
 | |
|   // FIXME  ???
 | |
|   public String getAbsolutePath ()
 | |
|   {
 | |
|     if (isAbsolute ())
 | |
|       return path;
 | |
|     return System.getProperty("user.dir") + separatorChar + path;
 | |
|   }
 | |
| 
 | |
|   /** @since 1.2 */
 | |
|   public File getAbsoluteFile ()
 | |
|   {
 | |
|     return new File (getAbsolutePath());
 | |
|   }
 | |
| 
 | |
|   public native String getCanonicalPath () throws IOException;
 | |
| 
 | |
|   /** @since 1.2 */
 | |
|   public File getCanonicalFile () throws IOException
 | |
|   {
 | |
|     return new File (getCanonicalPath());
 | |
|   }
 | |
| 
 | |
|   public String getName ()
 | |
|   {
 | |
|     int last = path.lastIndexOf(separatorChar);
 | |
|     return path.substring(last + 1);
 | |
|   }
 | |
| 
 | |
|   public String getParent ()
 | |
|   {
 | |
|     int last = path.lastIndexOf(separatorChar);
 | |
|     if (last == -1)
 | |
|       return null;
 | |
|     // FIXME: POSIX assumption.
 | |
|     if (last == 0 && path.charAt (0) == '/')
 | |
|       ++last;
 | |
|     return path.substring(0, last);
 | |
|   }
 | |
| 
 | |
|   /** @since 1.2 */
 | |
|   public File getParentFile ()
 | |
|   {
 | |
|     String parent = getParent ();
 | |
|     return (parent == null ? null : new File (parent));
 | |
|   }
 | |
| 
 | |
|   public String getPath ()
 | |
|   {
 | |
|     return path;
 | |
|   }
 | |
| 
 | |
|   public int hashCode ()
 | |
|   {
 | |
|     if (caseSensitive)
 | |
|       return (path.hashCode() ^ 1234321);
 | |
|     else
 | |
|       return (path.toLowerCase().hashCode() ^ 1234321);
 | |
|   }
 | |
| 
 | |
|   public native boolean isAbsolute ();
 | |
| 
 | |
|   public boolean isDirectory ()
 | |
|   {
 | |
|     checkRead();
 | |
|     return _stat (DIRECTORY);
 | |
|   }
 | |
| 
 | |
|   public boolean isFile ()
 | |
|   {
 | |
|     checkRead();
 | |
|     return _stat (ISFILE);
 | |
|   }
 | |
| 
 | |
|   /** @since 1.2 */
 | |
|   public boolean isHidden()
 | |
|   {
 | |
|     checkRead();
 | |
|     return _stat (ISHIDDEN);
 | |
|   }
 | |
| 
 | |
|   public long lastModified ()
 | |
|   {
 | |
|     checkRead();
 | |
|     return attr (MODIFIED);
 | |
|   }
 | |
| 
 | |
|   public long length ()
 | |
|   {
 | |
|     checkRead();
 | |
|     return attr (LENGTH);
 | |
|   }
 | |
|     
 | |
|   private final native Object[] performList (FilenameFilter filter,
 | |
| 					     FileFilter fileFilter,
 | |
| 					     Class result_type);
 | |
| 
 | |
|   public String[] list (FilenameFilter filter)
 | |
|   {
 | |
|     checkRead();
 | |
|     return (String[]) performList (filter, null, String.class);
 | |
|   }
 | |
| 
 | |
|   public String[] list ()
 | |
|   {
 | |
|     checkRead();
 | |
|     return (String[]) performList (null, null, String.class);
 | |
|   }
 | |
| 
 | |
|   /** @since 1.2 */
 | |
|   public File[] listFiles()
 | |
|   {
 | |
|     checkRead();
 | |
|     return (File[]) performList (null, null, File.class);
 | |
|   }
 | |
|   
 | |
|   /** @since 1.2 */
 | |
|   public File[] listFiles(FilenameFilter filter)
 | |
|   {
 | |
|     checkRead();
 | |
|     return (File[]) performList (filter, null, File.class);
 | |
|   }
 | |
|   
 | |
|   /** @since 1.2 */
 | |
|   public File[] listFiles(FileFilter filter)
 | |
|   {
 | |
|     checkRead();
 | |
|     return (File[]) performList (null, filter, File.class);
 | |
|   }
 | |
| 
 | |
|   public String toString ()
 | |
|   {
 | |
|     return path;
 | |
|   }
 | |
| 
 | |
|   public URL toURL () throws MalformedURLException
 | |
|   {
 | |
|     return new URL ("file://" + getAbsolutePath ()
 | |
| 		    + (isDirectory() ? "/" : ""));
 | |
|   }
 | |
| 
 | |
|   private final native boolean performMkdir ();
 | |
| 
 | |
|   public boolean mkdir ()
 | |
|   {
 | |
|     checkWrite();
 | |
|     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.path = parent;
 | |
| 	if (! mkdirs (x))
 | |
| 	  return false;
 | |
| 	x.path = p;
 | |
|       }
 | |
|     return x.mkdir();
 | |
|   }
 | |
| 
 | |
|   public boolean mkdirs ()
 | |
|   {
 | |
|     checkWrite();
 | |
|     if (isDirectory ())
 | |
|       return false;
 | |
|     return mkdirs (new File (path));
 | |
|   }
 | |
| 
 | |
|   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)
 | |
|     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";
 | |
| 
 | |
|     // Truncation rules.
 | |
|     // `6' is the number of characters we generate.
 | |
|     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)
 | |
| 	  prefix = prefix.substring(0, maxPathLen - 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.createNewFile())
 | |
| 	      return f;
 | |
| 	  }
 | |
| 	catch (IOException ignored)
 | |
| 	  {
 | |
| 	  }
 | |
|       }
 | |
| 
 | |
|     throw new IOException ("cannot create temporary file");
 | |
|   }
 | |
| 
 | |
|   private native boolean performSetReadOnly();
 | |
| 
 | |
|   /** @since 1.2 */
 | |
|   public boolean setReadOnly()
 | |
|   {
 | |
|     checkWrite();
 | |
|     return performSetReadOnly();
 | |
|   }
 | |
| 
 | |
|   private static native File[] performListRoots();
 | |
| 
 | |
|   /** @since 1.2 */
 | |
|   public static File[] listRoots()
 | |
|   {
 | |
|     File[] roots = performListRoots();
 | |
|     
 | |
|     SecurityManager s = System.getSecurityManager();
 | |
|     if (s != null)
 | |
|       {
 | |
| 	// Only return roots to which the security manager permits read access.
 | |
| 	int count = roots.length;
 | |
| 	for (int i = 0; i < roots.length; i++)
 | |
| 	  {
 | |
| 	    try
 | |
| 	      {
 | |
|         	s.checkRead(roots[i].path);		
 | |
| 	      }
 | |
| 	    catch (SecurityException sx)
 | |
| 	      {
 | |
| 	        roots[i] = null;
 | |
| 		count--;
 | |
| 	      }
 | |
| 	  }
 | |
| 	if (count != roots.length)
 | |
| 	  {
 | |
| 	    File[] newRoots = new File[count];
 | |
| 	    int k = 0;
 | |
| 	    for (int i=0; i < roots.length; i++)
 | |
| 	      {
 | |
| 	        if (roots[i] != null)
 | |
| 		  newRoots[k++] = roots[i];
 | |
| 	      }
 | |
| 	    roots = newRoots;
 | |
| 	  }
 | |
|       }
 | |
|     return roots;
 | |
|   }
 | |
| 
 | |
|   public static File createTempFile (String prefix, String suffix)
 | |
|     throws IOException
 | |
|   {
 | |
|     return createTempFile (prefix, suffix, null);
 | |
|   }
 | |
| 
 | |
|   /** @since 1.2 */
 | |
|   public int compareTo(File other)
 | |
|   {
 | |
|     if (caseSensitive)
 | |
|       return path.compareTo (other.path);
 | |
|     else
 | |
|       return path.compareToIgnoreCase (other.path);
 | |
|   }
 | |
| 
 | |
|   /** @since 1.2 */
 | |
|   public int compareTo(Object o)
 | |
|   {
 | |
|     File other = (File) o;
 | |
|     return compareTo (other);
 | |
|   }
 | |
| 
 | |
|   private native boolean performRenameTo (File dest);
 | |
|   public boolean renameTo (File dest)
 | |
|   {
 | |
|     SecurityManager s = System.getSecurityManager();
 | |
|     String sname = getName();
 | |
|     String dname = dest.getName();
 | |
|     if (s != null)
 | |
|       {
 | |
| 	s.checkWrite(sname);
 | |
| 	s.checkWrite(dname);
 | |
|       }
 | |
|     return performRenameTo (dest);
 | |
|   }
 | |
| 
 | |
|   private native boolean performSetLastModified(long time);
 | |
|   
 | |
|   /** @since 1.2 */
 | |
|   public boolean setLastModified(long time)
 | |
|   {
 | |
|     checkWrite();
 | |
|     return performSetLastModified(time);
 | |
|   }
 | |
| 
 | |
|   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);
 | |
| 
 | |
|   static final String tmpdir = System.getProperty("java.io.tmpdir");
 | |
|   static int maxPathLen;
 | |
|   static boolean caseSensitive;
 | |
|   static String dupSeparator = separator + separator;
 | |
|   
 | |
|   static
 | |
|   {
 | |
|     init_native();
 | |
|   }
 | |
|   
 | |
|   // Native function called at class initialization. This should should
 | |
|   // set the maxPathLen and caseSensitive variables.
 | |
|   private static native void init_native();
 | |
| 
 | |
|   // 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 ());
 | |
| 
 | |
|   private void checkWrite ()
 | |
|   {
 | |
|     SecurityManager s = System.getSecurityManager();
 | |
|     if (s != null)
 | |
|       s.checkWrite(path);
 | |
|   }
 | |
| 
 | |
|   private void checkRead ()
 | |
|   {
 | |
|     SecurityManager s = System.getSecurityManager();
 | |
|     if (s != null)
 | |
|       s.checkRead(path);
 | |
|   }
 | |
| 
 | |
|   /** 
 | |
|     * Add this File to the set of files to be deleted upon normal
 | |
|     * termination.
 | |
|     *
 | |
|     * @since 1.2 
 | |
|     */
 | |
|   // FIXME: This should use the ShutdownHook API once we implement that.
 | |
|   public void deleteOnExit ()
 | |
|   {
 | |
|     SecurityManager sm = System.getSecurityManager ();
 | |
|     if (sm != null)
 | |
|       sm.checkDelete (getName ());
 | |
| 
 | |
|     FileDeleter.add (this);
 | |
|   }
 | |
| 
 | |
|   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);
 | |
|   }
 | |
| 
 | |
|   // 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;
 | |
|   private final static int ISHIDDEN = 2;
 | |
| 
 | |
|   // QUERY arguments to attr function.
 | |
|   private final static int MODIFIED = 0;
 | |
|   private final static int LENGTH = 1;
 | |
|   
 | |
|   private final native long attr (int query);
 | |
|   // On OSF1 V5.0, `stat' is a macro.  It is easiest to use the name
 | |
|   // `_stat' instead.  We do the same thing for `_access' just in
 | |
|   // case.
 | |
|   private final native boolean _access (int query);
 | |
|   private final native boolean _stat (int query);
 | |
| 
 | |
|   private static final long serialVersionUID = 301077366599181567L;
 | |
| }
 |