A DESCRIPTION OF THE PROBLEM :
URI.getQuery() decodes the query string as documented, but query strings should never be decoded in that way because it loses the distinction between ampersands separating arguments and ampersands that are in argument values.
This means part of the javadoc is either incorrect or very misleading, where it says:
new URI(u.getScheme(),
u.getUserInfo(), u.getAuthority(),
u.getPath(), u.getQuery(),
u.getFragment())
.equals(u)
It says this only holds true if the URI "does not encode characters except those that must be quoted". You could say that when a query string argument value contains an ampersand character it must be encoded, but only because of the conventional syntax of query strings, which is not part of the URI specification.
For example:
URI u=new URI("http://localhost/?x=Q%26A&y=2");
URI u2=new URI(u.getScheme(),u.getUserInfo(),u.getHost(),u.getPort(),u.getPath(),u.getQuery(),u.getFragment());
The value of u2 is "http://localhost/?x=Q&A&y=2", which is not equal to u, and represents a completely different set of query string arguments.
The arguments in http://localhost/?x=Q%26A&y=2 are:
x=Q&A, y=2
The arguments in http://localhost/?x=Q&A&y=2 are:
x=Q, A, y=2
My suggestion is to completely deprecate the URI.getQuery() method in favour of the getRawQuery() method.
At the very least the javadoc of the getQuery() method should explain that is should never be used on query strings that follow the standard convention of separating arguments with ampersands.
---------- BEGIN SOURCE ----------
URI u=new URI("http://localhost/?x=Q%26A&y=2");
URI u2=new URI(u.getScheme(),u.getUserInfo(),u.getHost(),u.getPort(),u.getPath(),u.getQuery(),u.getFragment());
System.out.println(u.equals(u2)); // returns false, but any reasonable person reading the javadoc would expect true.
---------- END SOURCE ----------
FREQUENCY : always