Patch: File.toURL() and URLStreamHandler.parseURL() fixes

Ranjit Mathew rmathew@hotmail.com
Sun Feb 23 16:25:00 GMT 2003


Hi,

    As promised earlier, this is a fuller patch for the URL
parsing problems in libgcj w.r.t. Win32. 

In the process, I found a problem with File.isAbsolute( ) 
which affected the generated URLs on Win32 - on Win32, a 
path is not absolute even if it starts with a '\' as the
drive specifier needs to be prefixed. For example, "\temp"
could mean either "c:\temp" or "d:\temp" or whatever, 
depending on the current working directory of the user.
This is also consistent with Sun's JDK.

I have made File.toURL( ) more consistent with the URLs
emitted by Sun's JDK - the URLs are like "file:/c:/foo/bar.txt"
on Win32 and "file:/foo/bar.txt" on UNIX. (Tested with
Sun's JDK 1.3.1 on Solaris 2.6 and JDK 1.4.1 on Win98.)

Finally, according to the JDK docs, if a relative path
is used with a context URL, it should be canonicalised - check 
the JDK 1.4.1 docs for URL( URL context, String spec).

After this patch, the output of GCJ matches that of
Sun's JDK for a large number of cases, at least on 
Win98 and with Sun's JDK 1.4.1.

It also solves the original problem reported by Erik
about loading and reading a property file using
getResourceAsStream( ) of the system ClassLoader.

Ranjit.


Index: ChangeLog
from  Ranjit Mathew  <rmathew@hotmail.com>

	* java/io/File (getAbsolutePath): Prefix drive specifier on
	Windows for paths starting with a '\'.
	(toURL): Make URL more consistent with what Sun's JDK returns.

	* java/io/natFileWin32.cc (java::io::File::isAbsolute): Return
	true only if the path is a UNC network path or it starts with a
	drive specifier.

	* java/net/URLStreamHandler.java (parseURL): Correct minor typo.
	Be prepared to handle either '/' or '\\' in the file path for
	Windows if using the "file" protocol.
	Canonicalise the file path if using a relative path in the given
	context and the "file" protocol.

Index: java/io/File.java
===================================================================
--- java/io/File.java	2003-02-23 16:35:53.000000000 +0530
+++ java/io/File.java	2003-02-23 20:49:49.000000000 +0530
@@ -1,5 +1,5 @@
 // File.java - File name
 
-/* Copyright (C) 1998, 1999, 2000, 2001  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2003  Free Software Foundation, Inc.
 
    This file is part of libgcj.
@@ -159,5 +159,14 @@
     if (isAbsolute ())
       return path;
-    return System.getProperty("user.dir") + separatorChar + path;
+    else if (separatorChar == '\\' 
+             && 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
+      return System.getProperty ("user.dir") + separatorChar + path;
   }
 
@@ -290,6 +299,12 @@
   public URL toURL () throws MalformedURLException
   {
-    return new URL ("file://" + getAbsolutePath ()
-		    + (isDirectory() ? "/" : ""));
+    // 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 ('\\', '/')
+		      + (isDirectory() ? "/" : ""));
+    else
+      return new URL ("file:" + getAbsolutePath ()
+		      + (isDirectory() ? "/" : ""));
   }
 
Index: java/io/natFileWin32.cc
===================================================================
--- java/io/natFileWin32.cc	2003-02-23 20:06:26.000000000 +0530
+++ java/io/natFileWin32.cc	2003-02-23 20:49:20.000000000 +0530
@@ -120,7 +120,12 @@
 java::io::File::isAbsolute (void)
 {
-  if (path->length() > 0
-      && (path->charAt(0) == '/' || path->charAt(0) == '\\'))
+  // See if the path represents a Windows UNC network path.
+  if (path->length () > 1
+      && (path->charAt (0) == '\\') && (path->charAt (1) == '\\'))
     return true;
+
+  // Note that the path is not an absolute path even if it starts with
+  // a '/' or a '\' because it lacks a drive specifier.
+
   if (path->length() < 3)
     return false;
Index: java/net/URLStreamHandler.java
===================================================================
--- java/net/URLStreamHandler.java	2003-02-19 00:33:08.000000000 +0530
+++ java/net/URLStreamHandler.java	2003-02-23 21:19:27.000000000 +0530
@@ -1,4 +1,4 @@
 /* URLStreamHandler.java -- Abstract superclass for all protocol handlers
-   Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
@@ -40,4 +40,5 @@
 
 import java.io.IOException;
+import java.io.File;
 
 /*
@@ -113,5 +114,5 @@
    * syntax should override this method.  The lone exception is that if
    * the protocol name set in the URL is "file", this method will accept
-   * a an empty hostname (i.e., "file:///"), which is legal for that protocol
+   * an empty hostname (i.e., "file:///"), which is legal for that protocol
    *
    * @param url The URL object in which to store the results
@@ -177,6 +178,30 @@
       {
 	// Context is available, but only override it if there is a new file.
-	file = file.substring(0, file.lastIndexOf('/'))
-		+ '/' + spec.substring(start, end);
+        char sepChar = '/';
+        int lastSlash = file.lastIndexOf (sepChar);
+        if (lastSlash < 0 && File.separatorChar != sepChar
+            && url.getProtocol ().equals ("file"))
+          {
+            // On Windows, even '\' is allowed in a "file" URL.
+            sepChar = File.separatorChar;
+            lastSlash = file.lastIndexOf (sepChar);
+          }
+        
+        file = file.substring(0, lastSlash)
+                + sepChar + spec.substring (start, end);
+
+        if (url.getProtocol ().equals ("file"))
+          {
+            // For "file" URLs constructed relative to a context, we
+            // need to canonicalise the file path.
+            try
+              {
+                file = new File (file).getCanonicalPath ();
+              }
+            catch (IOException e)
+              {
+              }
+          }
+
 	ref = null;
       }



More information about the Java-patches mailing list