[kaffe] CVS kaffe (dalibor): Resynced with GNU Classpath: Fixes for URI

Kaffe CVS Kaffe Mailing List <kaffe@kaffe.org>
Sun Mar 21 13:40:03 2004


PatchSet 4553 
Date: 2004/03/21 21:26:11
Author: dalibor
Branch: HEAD
Tag: (none) 
Log:
Resynced with GNU Classpath: Fixes for URI

2004-03-21  Dalibor Topic <robilad@kaffe.org>

        Resynced with GNU Classpath.

        2004-03-20  Jeroen Frijters  <jeroen@frijters.net>

        * java/net/URI.java (parseURI): Added unquoting.
        (unquote): New method.
        (quoteAuthority): Implemented.
        (quote(String,String)): New method.
        (quotePath): Implemented.
        (getRawSchemeSpecificPart): Return new rawSchemeSpecificPart field.
        (getSchemeSpecificPart): Removed FIXME comment.
        (getRawAuthority): Return new rawAuthority field.
        (getAuthority): Removed FIXME comment.
        (getRawUserInfo): Return new rawUserInfo field.
        (getUserInfo): Removed FIXME comment.
        (getRawPath): Return new rawPath field.
        (getPath): Removed FIXME comment.
        (getRawQuery): Return new rawQuery field.
        (getQuery): Removed FIXME comment.
        (getRawFragment): Return new rawFragment field.
        (getFragment): Removed FIXME comment.

Members: 
	ChangeLog:1.2131->1.2132 
	libraries/javalib/java/net/URI.java:1.5->1.6 

Index: kaffe/ChangeLog
diff -u kaffe/ChangeLog:1.2131 kaffe/ChangeLog:1.2132
--- kaffe/ChangeLog:1.2131	Sun Mar 21 20:29:59 2004
+++ kaffe/ChangeLog	Sun Mar 21 21:26:11 2004
@@ -2,6 +2,30 @@
 
 	Resynced with GNU Classpath.
 
+	2004-03-20  Jeroen Frijters  <jeroen@frijters.net>
+
+        * java/net/URI.java (parseURI): Added unquoting.
+        (unquote): New method.
+        (quoteAuthority): Implemented.
+        (quote(String,String)): New method.
+        (quotePath): Implemented.
+        (getRawSchemeSpecificPart): Return new rawSchemeSpecificPart field.
+        (getSchemeSpecificPart): Removed FIXME comment.
+        (getRawAuthority): Return new rawAuthority field.
+        (getAuthority): Removed FIXME comment.
+        (getRawUserInfo): Return new rawUserInfo field.
+        (getUserInfo): Removed FIXME comment.
+        (getRawPath): Return new rawPath field.
+        (getPath): Removed FIXME comment.
+        (getRawQuery): Return new rawQuery field.
+        (getQuery): Removed FIXME comment.
+        (getRawFragment): Return new rawFragment field.
+        (getFragment): Removed FIXME comment.
+
+2004-03-21  Dalibor Topic <robilad@kaffe.org>
+
+	Resynced with GNU Classpath.
+
 	2004-03-20  Michael Koch  <konqueror@gmx.de>
 
         * java/net/InetAddress.java: Reformated.
Index: kaffe/libraries/javalib/java/net/URI.java
diff -u kaffe/libraries/javalib/java/net/URI.java:1.5 kaffe/libraries/javalib/java/net/URI.java:1.6
--- kaffe/libraries/javalib/java/net/URI.java:1.5	Thu Mar 11 15:33:17 2004
+++ kaffe/libraries/javalib/java/net/URI.java	Sun Mar 21 21:26:15 2004
@@ -1,5 +1,5 @@
 /* URI.java - An URI class
-   Copyright (C) 2002 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -45,7 +45,9 @@
 import java.util.regex.Pattern;
 
 /**
- * @author Michael Koch <konqueror@gmx.de>
+ * @author Ito Kazumitsu (ito.kazumitsu@hitachi-cable.co.jp)
+ * @author Dalibor Topic (robilad@kaffe.org)
+ * @author Michael Koch (konqueror@gmx.de)
  * @since 1.4
  */
 public final class URI
@@ -63,6 +65,21 @@
     "^(([^:/?#]+):)?((//([^/?#]*))?([^?#]*)(\\?([^#]*))?)?(#(.*))?";
 
   /**
+   * Valid characters (taken from rfc2396)
+   */
+  private static final String RFC2396_DIGIT = "0123456789";
+  private static final String RFC2396_LOWALPHA = "abcdefghijklmnopqrstuvwxyz";
+  private static final String RFC2396_UPALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+  private static final String RFC2396_ALPHA = RFC2396_LOWALPHA + RFC2396_UPALPHA;
+  private static final String RFC2396_ALPHANUM = RFC2396_DIGIT + RFC2396_ALPHA;
+  private static final String RFC2396_MARK = "-_.!~*'()";
+  private static final String RFC2396_UNRESERVED = RFC2396_ALPHANUM + RFC2396_MARK;
+  private static final String RFC2396_REG_NAME = RFC2396_UNRESERVED + "$,;:@&=+";
+  private static final String RFC2396_PCHAR = RFC2396_UNRESERVED + ":@&=+$,";
+  private static final String RFC2396_SEGMENT = RFC2396_PCHAR + ";";
+  private static final String RFC2396_PATH_SEGMENTS = RFC2396_SEGMENT + "/";
+
+  /**
    * Index of scheme component in parsed URI.
    */
   private static final int SCHEME_GROUP = 2;
@@ -92,15 +109,21 @@
    */
   private static final int FRAGMENT_GROUP = 10;
 
-  String string;  
   private String scheme;
+  private String rawSchemeSpecificPart;
   private String schemeSpecificPart;
+  private String rawAuthority;
   private String authority;
+  private String rawUserInfo;
   private String userInfo;
+  private String rawHost;
   private String host;
   private int port;
+  private String rawPath;
   private String path;
+  private String rawQuery;
   private String query;
+  private String rawFragment;
   private String fragment;
 
   private void readObject (ObjectInputStream is)
@@ -130,16 +153,65 @@
   {
     Pattern pattern = Pattern.compile(URI_REGEXP);
     Matcher matcher = pattern.matcher(str);
-    if (matcher.matches()) {
-      scheme = getURIGroup(matcher, SCHEME_GROUP);
-      schemeSpecificPart = getURIGroup(matcher, SCHEME_SPEC_PART_GROUP); 
-      authority = getURIGroup(matcher, AUTHORITY_GROUP);
-      path = getURIGroup(matcher, PATH_GROUP);
-      query = getURIGroup(matcher, QUERY_GROUP);
-      fragment = getURIGroup(matcher, FRAGMENT_GROUP);
+    if (matcher.matches())
+      {
+	scheme = getURIGroup(matcher, SCHEME_GROUP);
+	rawSchemeSpecificPart = getURIGroup(matcher, SCHEME_SPEC_PART_GROUP); 
+	rawAuthority = getURIGroup(matcher, AUTHORITY_GROUP);
+	rawPath = getURIGroup(matcher, PATH_GROUP);
+	rawQuery = getURIGroup(matcher, QUERY_GROUP);
+	rawFragment = getURIGroup(matcher, FRAGMENT_GROUP);
+      }
+    else
+      throw new URISyntaxException(str,
+				   "doesn't match URI regular expression");
+    // We must eagerly unquote the parts, because this is the only time
+    // we may throw an exception.
+    schemeSpecificPart = unquote(rawSchemeSpecificPart);
+    authority = unquote(rawAuthority);
+    path = unquote(rawPath);
+    query = unquote(rawQuery);
+    fragment = unquote(rawFragment);
+  }
+
+  /**
+   * Unquote "%" + hex quotes characters
+   *
+   * @param str The string to unquote or null.
+   *
+   * @return The unquoted string or null if str was null.
+   *
+   * @exception URISyntaxException If the given string contains invalid
+   * escape sequences.
+   */
+  private static String unquote (String str)
+    throws URISyntaxException
+  {
+    if (str == null)
+      return null;
+    byte[] buf = new byte[str.length()];
+    int pos = 0;
+    for (int i = 0; i < str.length(); i++) {
+      char c = str.charAt(i);
+      if (c > 127)
+	  throw new URISyntaxException(str, "Invalid character");
+      if (c == '%') {
+        if (i + 2 >= str.length())
+	  throw new URISyntaxException(str, "Invalid quoted character");
+	String hex = "0123456789ABCDEF";
+        int hi = hex.indexOf(str.charAt(++i));
+        int lo = hex.indexOf(str.charAt(++i));
+        if (lo < 0 || hi < 0)
+	  throw new URISyntaxException(str, "Invalid quoted character");
+	buf[pos++] = (byte)(hi * 16 + lo);
+      } else {
+	buf[pos++] = (byte)c;
+      }
     }
-    else {
-      throw new URISyntaxException(str, "doesn't match URI regular expression");
+    try {
+      return new String(buf, 0, pos, "utf-8");
+    } catch (java.io.UnsupportedEncodingException x2) {
+      throw (Error)new InternalError().initCause(x2);
     }
   }
 
@@ -171,8 +243,52 @@
    * @return The quoted string.
    */
   private static String quoteAuthority (String str) {
-    // FIXME: unimplemented.
-    return str;
+    // Technically, we should be using RFC2396_AUTHORITY, but
+    // it contains no additional characters.
+    return quote(str, RFC2396_REG_NAME);
+  }
+
+  /**
+   * Quote characters in str that are not part of legalCharacters.
+   *
+   * Replace illegal characters by encoding their UTF-8
+   * representation as "%" + hex code for each resulting
+   * UTF-8 character.
+   *
+   * @param str The string to quote
+   * @param legalCharacters The set of legal characters
+   * 
+   * @return The quoted string.
+   */
+  private static String quote (String str, String legalCharacters)
+  {
+    StringBuffer sb = new StringBuffer(str.length());
+    for (int i = 0; i < str.length(); i++) {
+      char c = str.charAt(i);
+      if (legalCharacters.indexOf(c) == -1) {
+	String hex = "0123456789ABCDEF";
+	if (c <= 127) {
+	  sb.append('%')
+	    .append(hex.charAt(c / 16))
+	    .append(hex.charAt(c % 16));
+	} else {
+	  try {
+	    // this is far from optimal, but it works
+	    byte[] utf8 = str.substring(i, i + 1).getBytes("utf-8");
+	    for (int j = 0; j < utf8.length; j++) {
+		sb.append('%')
+		.append(hex.charAt((utf8[j] & 0xff) / 16))
+		.append(hex.charAt((utf8[j] & 0xff) % 16));
+	    }
+	  } catch (java.io.UnsupportedEncodingException x) {
+	    throw (Error)new InternalError().initCause(x);
+	  }
+	}
+      } else {
+	sb.append(c);
+      }
+    }
+    return sb.toString();
   }
 
   /**
@@ -203,8 +319,9 @@
    * @return The quoted string.
    */
   private static String quotePath (String str) {
-    // FIXME: unimplemented.
-    return str;
+    // Technically, we should be using RFC2396_PATH, but
+    // it contains no additional characters.
+    return quote(str, RFC2396_PATH_SEGMENTS);
   }
 
   /**
@@ -254,8 +371,7 @@
 	     String path, String query, String fragment)
     throws URISyntaxException
   {
-    this(""
-	 + (scheme == null ? "" : scheme + ":" )
+    this((scheme == null ? "" : scheme + ":" )
 	 + (userInfo == null && host == null && port == -1 ? "" : "//")
 	 + (userInfo == null ? "" : quoteUserInfo(userInfo) + "@")
 	 + (host == null ? "" : quoteHost(host))
@@ -263,7 +379,7 @@
 	 + (path == null ? "" : quotePath(path))
 	 + (query == null ? "" : "?" + quote(query))
 	 + (fragment == null ? "" : "#" + quote(fragment)));
-
+    
     parseServerAuthority();
   }
 
@@ -282,8 +398,7 @@
 	     String fragment)
     throws URISyntaxException
   {
-    this(""
-	 + (scheme == null ? "" : scheme + ":")
+    this((scheme == null ? "" : scheme + ":")
 	 + (authority == null ? "" : "//" + quoteAuthority(authority))
 	 + (path == null ? "" : quotePath(path))
 	 + (query == null ? "" : "?" + quote(query))
@@ -318,8 +433,7 @@
   public URI (String scheme, String ssp, String fragment)
     throws URISyntaxException
   {
-    this(""
-	 + (scheme == null ? "" : scheme + ":")
+    this((scheme == null ? "" : scheme + ":")
 	 + (ssp == null ? "" : quote(ssp))
 	 + (fragment == null ? "" : "#" + quote(fragment)));
   }
@@ -334,13 +448,15 @@
    */
   public static URI create (String str)
   {
-    try {
-      return new URI(str);
-    }
-    catch(URISyntaxException e) {
-      throw (IllegalArgumentException)
-	new IllegalArgumentException().initCause(e);
-    }
+    try
+      {
+	return new URI(str);
+      }
+    catch(URISyntaxException e)
+      {
+	throw (IllegalArgumentException)
+	  new IllegalArgumentException().initCause(e);
+      }
   }
 
   /**
@@ -368,14 +484,18 @@
    *
    * @param uri The URI to resolve against this URI
    *
-   * @return The resulting URI
+   * @return The resulting URI, or null when it couldn't be resolved
+   * for some reason.
    *
    * @exception NullPointerException If uri is null
    */
   public URI resolve (URI uri)
   { 
-    if (uri.isAbsolute()) return uri;
-    if (uri.isOpaque()) return uri;
+    if (uri.isAbsolute())
+      return uri;
+    if (uri.isOpaque())
+      return uri;
+
     String scheme = uri.getScheme();
     String schemeSpecificPart = uri.getSchemeSpecificPart();
     String authority = uri.getAuthority();
@@ -383,35 +503,38 @@
     String query = uri.getQuery();
     String fragment = uri.getFragment();
 
-    try {
+    try
+      {
         if (fragment != null &&
             path != null && path.equals("") &&
-            scheme == null && authority == null && query == null) {
-
-            return new URI(this.scheme, this.schemeSpecificPart, fragment);
+            scheme == null && authority == null && query == null)
+	  return new URI(this.scheme, this.schemeSpecificPart, fragment);
 
-        }
-
-        if (authority == null) {
+        if (authority == null)
+	  {
             authority = this.authority;
-            if (path == null) path = "";
-            if (!(path.startsWith("/"))) {
+            if (path == null)
+	      path = "";
+            if (!(path.startsWith("/")))
+	      {
                 StringBuffer basepath = new StringBuffer(this.path);
                 int i = this.path.lastIndexOf('/');
-                if (i >= 0) {
-                    basepath.delete(i+1, basepath.length());
-                }
+
+                if (i >= 0)
+		  basepath.delete(i+1, basepath.length());
+
                 basepath.append(path);
                 path = basepath.toString();
-                //  We must normalize the path here.
+                //  FIXME We must normalize the path here.
                 //  Normalization process omitted.
-            }
-        }
+	      }
+	  }
         return new URI(this.scheme, authority, path, query, fragment);
-    }
-    catch (URISyntaxException e) {
+      }
+    catch (URISyntaxException e)
+      {
         return null;
-    }
+      }
   }
 
   /**
@@ -455,9 +578,9 @@
   public URL toURL ()
     throws IllegalArgumentException, MalformedURLException
   {
-    if (isAbsolute()) {
-        return new URL(this.toString());
-    }
+    if (isAbsolute())
+      return new URL(this.toString());
+
     throw new IllegalArgumentException("not absolute");
   }
 
@@ -482,8 +605,7 @@
    */
   public boolean isOpaque ()
   {
-    return ((scheme != null) &&
-           !(schemeSpecificPart.startsWith("/")));
+    return ((scheme != null) && !(schemeSpecificPart.startsWith("/")));
   }
 
   /**
@@ -492,7 +614,7 @@
    */
   public String getRawSchemeSpecificPart ()
   {
-    return schemeSpecificPart;
+    return rawSchemeSpecificPart;
   }
 
   /**
@@ -500,7 +622,6 @@
    */
   public String getSchemeSpecificPart ()
   {
-    // FIXME: unimplemented.
     return schemeSpecificPart;
   }
 
@@ -509,7 +630,7 @@
    */
   public String getRawAuthority ()
   {
-    return authority;
+    return rawAuthority;
   }
 
   /**
@@ -517,7 +638,6 @@
    */
   public String getAuthority ()
   {
-    // FIXME: unimplemented.
     return authority;
   }
 
@@ -526,7 +646,7 @@
    */
   public String getRawUserInfo ()
   {
-    return userInfo;
+    return rawUserInfo;
   }
 
   /**
@@ -534,7 +654,6 @@
    */
   public String getUserInfo ()
   {
-    // FIXME: unimplemented.
     return userInfo;
   }
 
@@ -559,7 +678,7 @@
    */
   public String getRawPath ()
   {
-    return path;
+    return rawPath;
   }
 
   /**
@@ -567,7 +686,6 @@
    */
   public String getPath ()
   {
-    // FIXME: unimplemented.
     return path;
   }
 
@@ -576,7 +694,7 @@
    */
   public String getRawQuery ()
   {
-    return query;
+    return rawQuery;
   }
 
   /**
@@ -584,7 +702,6 @@
    */
   public String getQuery ()
   {
-    // FIXME: unimplemented.
     return query;
   }
 
@@ -593,7 +710,7 @@
    */
   public String getRawFragment ()
   {
-    return fragment;
+    return rawFragment;
   }
 
   /**
@@ -601,7 +718,6 @@
    */
   public String getFragment ()
   {
-    // FIXME: unimplemented.
     return fragment;
   }
 
@@ -641,8 +757,7 @@
    */
   public String toString ()
   {
-    return ""
-      + (getScheme() == null ? "" : getScheme() + ":")
+    return (getScheme() == null ? "" : getScheme() + ":")
       + (getRawAuthority() == null ? "" : "//" + getRawAuthority())
       + (getRawPath() == null ? "" : getRawPath())
       + (getRawQuery() == null ? "" : "?" + getRawQuery())