[kaffe] CVS kaffe (dalibor): Resynced with GNU Classpath: File fixes

Kaffe CVS cvs-commits at kaffe.org
Wed Aug 11 18:34:13 PDT 2004


PatchSet 5057 
Date: 2004/08/12 01:25:50
Author: dalibor
Branch: HEAD
Tag: (none) 
Log:
Resynced with GNU Classpath: File fixes

2004-08-11  Dalibor Topic  <robilad at kaffe.org>

        * libraries/javalib/java/io/File.java:
        Resynced with GNU Classpath. Cleaned up tests for Windows.

        2004-07-27  Jeroen Frijters  <jeroen at frijters.net>

        * java/io/File.java (dupSeparator): New field. (File(String)):
        Modified to use new normalizePath method. (normalizePath): New method
        merged from libgcj.
        (File(String,String)): Modified to use new normalizePath method.
        (File(File,String)): Modified to forward to File(String,String).
        (File(URI)): New constructor. (getAbsolutePath): Merged from libgcj.
        (getCanonicalPath): New implementation that forwards to VMFile.
        (getParent): Merged from libgcj. (isAbsolute): Merged from libgcj.
        (list(FilenameFilter)): Removed unnecessary path normalization.
        (toURL): Merged from libgcj. (mkdir): Removed unnecessary path
        normalization. (compareTo): Removed incorrect canonicalization.

Members: 
	ChangeLog:1.2615->1.2616 
	libraries/javalib/java/io/File.java:1.51->1.52 

Index: kaffe/ChangeLog
diff -u kaffe/ChangeLog:1.2615 kaffe/ChangeLog:1.2616
--- kaffe/ChangeLog:1.2615	Wed Aug 11 15:24:05 2004
+++ kaffe/ChangeLog	Thu Aug 12 01:25:50 2004
@@ -1,5 +1,24 @@
 2004-08-11  Dalibor Topic  <robilad at kaffe.org>
 
+	* libraries/javalib/java/io/File.java:
+	Resynced with GNU Classpath. Cleaned up tests for Windows.
+
+	2004-07-27  Jeroen Frijters  <jeroen at frijters.net>
+
+        * java/io/File.java (dupSeparator): New field. (File(String)):
+        Modified to use new normalizePath method. (normalizePath): New method
+        merged from libgcj.
+        (File(String,String)): Modified to use new normalizePath method.
+        (File(File,String)): Modified to forward to File(String,String).
+        (File(URI)): New constructor. (getAbsolutePath): Merged from libgcj.
+        (getCanonicalPath): New implementation that forwards to VMFile.
+        (getParent): Merged from libgcj. (isAbsolute): Merged from libgcj.
+        (list(FilenameFilter)): Removed unnecessary path normalization.
+        (toURL): Merged from libgcj. (mkdir): Removed unnecessary path
+        normalization. (compareTo): Removed incorrect canonicalization.
+
+2004-08-11  Dalibor Topic  <robilad at kaffe.org>
+
 	* libraries/clib/awt/classpath-gtk/gtk-peer/gthread-jni.c:
 	Resynced with GNU Classpath.
 
Index: kaffe/libraries/javalib/java/io/File.java
diff -u kaffe/libraries/javalib/java/io/File.java:1.51 kaffe/libraries/javalib/java/io/File.java:1.52
--- kaffe/libraries/javalib/java/io/File.java:1.51	Mon Jul 26 21:13:55 2004
+++ kaffe/libraries/javalib/java/io/File.java	Thu Aug 12 01:25:54 2004
@@ -39,8 +39,6 @@
 
 package java.io;
 
-import gnu.java.io.PlatformHelper;
-
 import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URISyntaxException;
@@ -70,6 +68,7 @@
    * 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
@@ -156,7 +155,7 @@
              accept '/' as separator. In that case the following code
              will fail.
           */
-          String filename = (separatorChar!='\\')?"test-dir-write":"tst";
+          String filename = (!ON_WINDOWS)?"test-dir-write":"tst";
   	  File test = createTempFile(filename, null, this);
   	  return (test != null && test.delete());
         }
@@ -251,37 +250,83 @@
 
   /**
    * This method initializes a new <code>File</code> object to represent
-   * a file with the specified URI.
-   *
-   * @param uri The URI of the file
-   * @author Ito Kazumitsu
-   */
-  public File(URI uri)
-  {
-    this.path = uri.getPath();
-    if (this.path == null)
-      {
-	throw new IllegalArgumentException();
-      }
-  }
-
-  /**
-   * This method initializes a new <code>File</code> object to represent
    * a file with the specified path.
    *
    * @param name The path name of the file
    */
   public File(String name)
   {
-    path = name;
+    path = normalizePath (name);
+  }
+ 
+  // Remove duplicate and redundant separator characters.
+  private String normalizePath(String p)
+  {
+    // On Windows, convert any '/' to '\'.  This appears to be the same logic
+    // that Sun's Win32 Java performs.
+    if (ON_WINDOWS)
+      {
+        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();
+
+    // Special case: permit Windows UNC path prefix.
+    if (dupSeparator.equals("\\\\") && dupIndex == 0)
+      dupIndex = p.indexOf(dupSeparator, 1);
 
-    // Per the spec
-    if (path == null)
-      throw new NullPointerException("File name is null");
-
-    while (!PlatformHelper.isRootDirectory(path)
-  	 && PlatformHelper.endWithSeparator(path))
-        path = PlatformHelper.removeTailSeparator(path);
+    if (dupIndex == -1)
+      {
+        // Ignore trailing separator (though on Windows "a:\", for
+        // example, is a valid and minimal path).
+        if (plen > 1 && p.charAt (plen - 1) == separatorChar)
+	  {
+	    if (! (ON_WINDOWS && plen == 3 && p.charAt (1) == ':'))
+	      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 (except special cases
+    // like "a:\" on Windows).
+    int end;
+    if (plen > 1 && p.charAt (plen - 1) == separatorChar)
+    {
+      if (ON_WINDOWS && plen == 3 && p.charAt (1) == ':')
+        end = plen;
+      else
+        end = plen - 1;
+    }
+    else
+      end = plen;
+    newpath.append(p.substring(last, end));
+    
+    return newpath.toString();
   }
  
   /**
@@ -296,7 +341,26 @@
    */
   public File(String dirPath, String name)
   {
-    this (dirPath == null ? (File) null : new File(dirPath), name);
+    if (name == null)
+      throw new NullPointerException();
+    if (dirPath != null) {
+      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 {
+	/* if the dirPath is empty, use a system dependant
+	 * default prefix.
+	 */
+	path = normalizePath(separatorChar + name);
+      }
+    }
+    else
+      path = normalizePath(name);
   }
 
   /**
@@ -311,23 +375,24 @@
    */
   public File(File directory, String name)
   {
-    if (name == null)
-      throw new NullPointerException("filename is null");
+    this (directory == null ? null : directory.path, name);
+  }
 
-    String dirpath;
-    
-    if (directory == null)
-      dirpath = "";
-    else if (directory.getPath() == "")
-      dirpath = "/";
-    else
-      dirpath = directory.getPath();
+  /**
+   * 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 (PlatformHelper.isRootDirectory(dirpath)
-	|| dirpath.equals(""))
-      path = dirpath + name;
-    else
-      path = dirpath + separator + name;
+    if (!uri.getScheme().equals("file"))
+	throw new IllegalArgumentException("invalid uri protocol");
+
+    path = normalizePath(uri.getPath());
   }
 
   /**
@@ -343,15 +408,43 @@
   {
     if (isAbsolute())
       return path;
-    
-    String dir = System.getProperty("user.dir");
-    if (dir == null)
-      return path;
-
-    if (PlatformHelper.endWithSeparator(dir))
-      return dir + path;
-
-    return dir + separator + path;
+    else if (ON_WINDOWS 
+             && 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
+        // the current working directory to it.
+        return System.getProperty ("user.dir").substring (0, 2) + path;
+      }
+    else if (ON_WINDOWS 
+             && path.length() > 1 && path.charAt (1) == ':'
+             && ((path.charAt (0) >= 'a' && path.charAt (0) <= 'z')
+                 || (path.charAt (0) >= 'A' && path.charAt (0) <= 'Z')))
+      {
+        // On Windows, a process has a current working directory for
+        // each drive and a path like "G:foo\bar" would mean the 
+        // absolute path "G:\wombat\foo\bar" if "\wombat" is the 
+        // working directory on the G drive.
+        String drvDir = null;
+        try
+          {
+            drvDir = new File (path.substring (0, 2)).getCanonicalPath();
+          }
+        catch (IOException e)
+          {
+            drvDir = path.substring (0, 2) + "\\";
+          }
+        
+        // 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());
+        else
+          return drvDir;
+      }
+    else
+      return System.getProperty ("user.dir") + separatorChar + path;
   }
 
   /**
@@ -382,8 +475,19 @@
    */
   public String getCanonicalPath() throws IOException
   {
-    String abspath = getAbsolutePath();
-    return PlatformHelper.toCanonicalForm(abspath);
+    // On Windows, getAbsolutePath might end up calling us, so we
+    // have to special case that call to avoid infinite recursion.
+    if (ON_WINDOWS && path.length() == 2 &&
+	((path.charAt(0) >= 'a' && path.charAt(0) <= 'z') ||
+	 (path.charAt(0) >= 'A' && path.charAt(0) <= 'Z')) &&
+	path.charAt(1) == ':')
+    {
+	return VMFile.toCanonicalForm(path);
+    }
+    // Call getAbsolutePath first to make sure that we do the
+    // current directory handling, because the native code
+    // may have a different idea of the current directory.
+    return VMFile.toCanonicalForm(getAbsolutePath());
   }
 
   /**
@@ -423,16 +527,56 @@
    */
   public String getParent()
   {
-    if (PlatformHelper.isRootDirectory(path))
-      return null;
+    String prefix = null;
+    int nameSeqIndex = 0;
 
-    String par_path = path;
+    // The "prefix", if present, is the leading "/" on UNIX and 
+    // either the drive specifier (e.g. "C:") or the leading "\\"
+    // of a UNC network path on Windows.
+    if (separatorChar == '/' && path.charAt (0) == '/')
+      {
+        prefix = "/";
+        nameSeqIndex = 1;
+      }
+    else if (ON_WINDOWS && path.length() > 1)
+      {
+        if ((path.charAt (0) == '\\' && path.charAt (1) == '\\')
+            || (((path.charAt (0) >= 'a' && path.charAt (0) <= 'z')
+                 || (path.charAt (0) >= 'A' && path.charAt (0) <= 'Z'))
+                && path.charAt (1) == ':'))
+          {
+            prefix = path.substring (0, 2);
+            nameSeqIndex = 2;
+          }
+      }
 
-    int pos = PlatformHelper.lastIndexOfSeparator(par_path);
-    if (pos == -1)
-      return null;
+    // 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())
+      {
+        String nameSeq = path.substring (nameSeqIndex, path.length());
+        int last = nameSeq.lastIndexOf (separatorChar);
+        if (last == -1)
+          return prefix;
+        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.
+          return null;
+        else if (last == 0)
+          last++;
 
-    return par_path.substring(0, pos);
+        if (prefix != null)
+          return prefix + nameSeq.substring (0, last);
+        else
+          return nameSeq.substring (0, last);
+      }
+    else
+      // Sun's JRE 1.4 returns null if the prefix is the only 
+      // component of the path - so "/" gives null on UNIX and 
+      // "C:", "\\", etc. return null on Windows.
+      return null;
   }
 
   /**
@@ -488,7 +632,15 @@
    */
   public boolean isAbsolute()
   {
-    return PlatformHelper.beginWithRootPathPrefix(path) > 0;
+    if (ON_WINDOWS)
+	return path.startsWith(dupSeparator) || 
+	    (path.length() > 2 && 
+	     ((path.charAt(0) >= 'a' && path.charAt(0) <= 'z') ||
+	      (path.charAt(0) >= 'A' && path.charAt(0) <= 'Z')) &&
+	     path.charAt(1) == ':' &&
+	     path.charAt(2) == '\\');
+    else
+	return path.startsWith(separator);
   }
 
   /**
@@ -603,14 +755,11 @@
   {
     checkRead();
 
-    // Get the list of files
-    String list_path = PlatformHelper.removeTailSeparator(path);
-    File dir = new File(list_path);
-
-    if (! dir.exists() || ! dir.isDirectory())
+    if (!exists() || !isDirectory())
       return null;
     
-    String files[] = VMFile.list(list_path);
+    // Get the list of files
+    String files[] = VMFile.list(path);
     
     // Check if an error occured in listInternal().
     if (files == null)
@@ -793,7 +942,10 @@
     String abspath = getAbsolutePath();
 
     if (isDirectory())
-      abspath = abspath + separator;
+      abspath = abspath + separatorChar;
+
+    if (ON_WINDOWS)
+      abspath = separatorChar + abspath;
         
     try
       {
@@ -821,14 +973,17 @@
    */
   public URL toURL() throws MalformedURLException
   {
-    String abspath = getAbsolutePath();
-
-    if (isDirectory())
-      abspath = abspath + separator;
-
-    return new URL("file", "", abspath.replace(separatorChar, '/'));
+    // 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 (ON_WINDOWS)
+      return new URL ("file:/" + getAbsolutePath().replace ('\\', '/')
+		      + (isDirectory() ? "/" : ""));
+    else
+      return new URL ("file:" + getAbsolutePath()
+		      + (isDirectory() ? "/" : ""));
   }
 
+
   /**
    * This method creates a directory for the path represented by this object.
    *
@@ -840,7 +995,7 @@
   public boolean mkdir()
   {
     checkWrite();
-    return VMFile.mkdir(PlatformHelper.removeTailSeparator(path));
+    return VMFile.mkdir(path);
   }
 
   /**
@@ -938,7 +1093,7 @@
        will fail.
     */
     File file;
-    if (separatorChar!='\\')
+    if (!ON_WINDOWS)
       {      
         // probably a non-DOS-filesystem, use long names
         do
@@ -1070,26 +1225,10 @@
    */
   public int compareTo(File other)
   {
-    String p1, p2;
-    
-    try
-      {  
-        p1 = getCanonicalPath();
-        p2 = other.getCanonicalPath();
-      }
-    catch(IOException e)
-      {
-        // FIXME: What do we do here?  The spec requires the canonical path.
-        // Even if we don't call the method, we must replicate the functionality
-        // which per the spec can fail.  What happens in that situation?
-        // I just assume the files are equal!
-        return 0;
-      }
-    
     if (VMFile.caseSensitive)
-      return p1.compareTo(p2);
+      return path.compareTo (other.path);
     else
-      return p1.compareToIgnoreCase(p2);
+      return path.compareToIgnoreCase (other.path);
   }
 
   /**
@@ -1219,6 +1358,11 @@
     if (oldSeparatorChar != separatorChar)
       path = path.replace(oldSeparatorChar, separatorChar);
   }
-  
+
+  /**
+   * Used to determine whether we are running under Windows.
+   */
+  private static final boolean ON_WINDOWS = separatorChar =='\\';
+
 } // class File
 



More information about the kaffe mailing list