# HG changeset patch # User khazra # Date 1358463002 28800 # Node ID b0055428d83520b33fdb52d4e8718e9ba15d0818 # Parent 570508dfed48ea2cb539eab1e88cd736f9d9d5dc 7171415: java.net.URI.equals/hashCode not consistent for some URIs Summary: Rewrite URI.hashCode() to consider encoded characters, also reviewed by vitalyd@gmail.com, schlosna@gmail.com Reviewed-by: chegar diff -r 570508dfed48 -r b0055428d835 jdk/src/share/classes/java/net/URI.java --- a/jdk/src/share/classes/java/net/URI.java Thu Jan 17 12:49:33 2013 -0800 +++ b/jdk/src/share/classes/java/net/URI.java Thu Jan 17 14:50:02 2013 -0800 @@ -1694,6 +1694,13 @@ return c; } + // US-ASCII only + private static int toUpper(char c) { + if ((c >= 'a') && (c <= 'z')) + return c - ('a' - 'A'); + return c; + } + private static boolean equal(String s, String t) { if (s == t) return true; if ((s != null) && (t != null)) { @@ -1744,7 +1751,26 @@ private static int hash(int hash, String s) { if (s == null) return hash; - return hash * 127 + s.hashCode(); + return s.indexOf('%') < 0 ? hash * 127 + s.hashCode() + : normalizedHash(hash, s); + } + + + private static int normalizedHash(int hash, String s) { + int h = 0; + for (int index = 0; index < s.length(); index++) { + char ch = s.charAt(index); + h = 31 * h + ch; + if (ch == '%') { + /* + * Process the next two encoded characters + */ + for (int i = index + 1; i < index + 3; i++) + h = 31 * h + toUpper(s.charAt(i)); + index += 2; + } + } + return hash * 127 + h; } // US-ASCII only diff -r 570508dfed48 -r b0055428d835 jdk/test/java/net/URI/Test.java --- a/jdk/test/java/net/URI/Test.java Thu Jan 17 12:49:33 2013 -0800 +++ b/jdk/test/java/net/URI/Test.java Thu Jan 17 14:50:02 2013 -0800 @@ -24,6 +24,7 @@ /* @test * @summary Unit test for java.net.URI * @bug 4464135 4505046 4503239 4438319 4991359 4866303 7023363 7041800 + * 7171415 * @author Mark Reinhold */ @@ -1337,7 +1338,7 @@ } - static void eq0(Comparable u, Comparable v) throws URISyntaxException { + static void eq0(URI u, URI v) throws URISyntaxException { testCount++; if (!u.equals(v)) throw new RuntimeException("Not equal: " + u + " " + v); @@ -1352,7 +1353,7 @@ + " [" + Integer.toHexString(uh) + "]"); } - static void cmp0(Comparable u, Comparable v, boolean same) + static void cmp0(URI u, URI v, boolean same) throws URISyntaxException { int c = u.compareTo(v); @@ -1361,18 +1362,18 @@ + " " + c); } - static void eq(Comparable u, Comparable v) throws URISyntaxException { + static void eq(URI u, URI v) throws URISyntaxException { eq0(u, v); cmp0(u, v, true); } - static void eqeq(Comparable u, Comparable v) { + static void eqeq(URI u, URI v) { testCount++; if (u != v) throw new RuntimeException("Not ==: " + u + " " + v); } - static void ne0(Comparable u, Comparable v) throws URISyntaxException { + static void ne0(URI u, URI v) throws URISyntaxException { testCount++; if (u.equals(v)) throw new RuntimeException("Equal: " + u + " " + v); @@ -1383,17 +1384,17 @@ + "]"); } - static void ne(Comparable u, Comparable v) throws URISyntaxException { + static void ne(URI u, URI v) throws URISyntaxException { ne0(u, v); cmp0(u, v, false); } - static void lt(Comparable u, Comparable v) throws URISyntaxException { + static void lt(URI u, URI v) throws URISyntaxException { ne0(u, v); int c = u.compareTo(v); if (c >= 0) { - show((URI)u); - show((URI)v); + show(u); + show(v); throw new RuntimeException("Not less than: " + u + " " + v + " " + c); } @@ -1404,7 +1405,7 @@ lt(new URI(s), new URI(t)); } - static void gt(Comparable u, Comparable v) throws URISyntaxException { + static void gt(URI u, URI v) throws URISyntaxException { lt(v, u); } @@ -1430,6 +1431,8 @@ lt(s, new URI("http://jag:cafebabe@java.sun.com:94/b/c/d?q#g")); eq(new URI("http://host/a%00bcd"), new URI("http://host/a%00bcd")); ne(new URI("http://host/a%00bcd"), new URI("http://host/aZ00bcd")); + eq0(new URI("http://host/abc%e2def%C3ghi"), + new URI("http://host/abc%E2def%c3ghi")); lt("p", "s:p"); lt("s:p", "T:p"); @@ -1465,7 +1468,7 @@ ObjectInputStream oi = new ObjectInputStream(bi); try { Object o = oi.readObject(); - eq(u, (Comparable)o); + eq(u, (URI)o); } catch (ClassNotFoundException x) { x.printStackTrace(); throw new RuntimeException(x.toString());