You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by dk...@apache.org on 2010/09/14 19:22:17 UTC

svn commit: r997000 - in /cxf/branches/2.2.x-fixes: ./ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/

Author: dkulp
Date: Tue Sep 14 17:22:16 2010
New Revision: 997000

URL: http://svn.apache.org/viewvc?rev=997000&view=rev
Log:
Merged revisions 996207 via svnmerge from 
https://svn.apache.org/repos/asf/cxf/trunk

........
  r996207 | sergeyb | 2010-09-11 16:42:51 -0400 (Sat, 11 Sep 2010) | 1 line
  
  JAX-RS : fixing most of the UriBuilder tck related tests
........

Modified:
    cxf/branches/2.2.x-fixes/   (props changed)
    cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java
    cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java
    cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java

Propchange: cxf/branches/2.2.x-fixes/
------------------------------------------------------------------------------
Binary property 'svnmerge-integrated' - no diff available.

Modified: cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java?rev=997000&r1=996999&r2=997000&view=diff
==============================================================================
--- cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java (original)
+++ cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java Tue Sep 14 17:22:16 2010
@@ -82,62 +82,87 @@ public class UriBuilderImpl extends UriB
         thePath = substituteVarargs(pathTempl, values, 0);
         
         String theQuery = buildQuery(fromEncoded);
+        int queryTemplateVarsSize = 0;
         if (theQuery != null) {
             URITemplate queryTempl = new URITemplate(theQuery);
             int lengthDiff = values.length - pathTempl.getVariables().size(); 
             if (lengthDiff > 0) {
+                queryTemplateVarsSize = queryTempl.getVariables().size(); 
                 theQuery = substituteVarargs(queryTempl, values, values.length - lengthDiff);
             }
         }
         
+        String theFragment = fragment;
+        if (theFragment != null) {
+            URITemplate fragmentTempl = new URITemplate(theFragment);
+            int lengthDiff = values.length - pathTempl.getVariables().size() - queryTemplateVarsSize; 
+            if (lengthDiff > 0) {
+                theFragment = substituteVarargs(fragmentTempl, values, values.length - lengthDiff);
+            }
+        }
+        
         try {
-            return buildURI(fromEncoded, thePath, theQuery);
+            return buildURI(fromEncoded, thePath, theQuery, theFragment);
         } catch (URISyntaxException ex) {
             throw new UriBuilderException("URI can not be built", ex);
         }
     }
     
-    private URI buildURI(boolean fromEncoded, String thePath, String theQuery) throws URISyntaxException {
-        // TODO : do encodePartiallyEncoded only once here, do not do it inside buildPath()
-        // buildFromEncoded and buildFromEncodedMap - we'll need to be careful such that 
-        // path '/' separators are not encoded so probably we'll need to create PathSegments
-        // again if fromEncoded is set
+    private URI buildURI(boolean fromEncoded, String thePath, String theQuery, String theFragment) 
+        throws URISyntaxException {
         if (fromEncoded) {
-            StringBuilder b = new StringBuilder();
+            return buildURIFromEncoded(thePath, theQuery, theFragment);
+        } else if (!isSchemeOpaque()) {
+            if ((scheme != null || host != null || userInfo != null)
+                && thePath.length() != 0 && !thePath.startsWith("/")) {
+                thePath = "/" + thePath;
+            }
+            URI uri = new URI(scheme, userInfo, host, port, 
+                           thePath, theQuery, theFragment);
+            if (thePath.contains("%2F")) {
+                // TODO: the bogus case of segments containing encoded '/'
+                // Not sure if we have a cleaner solution though.
+                String realPath = uri.getRawPath().replace("%252F", "%2F");
+                uri = buildURIFromEncoded(realPath, uri.getRawQuery(), uri.getRawFragment());
+            }
+            return uri;
+        } else {
+            return new URI(scheme, schemeSpecificPart, theFragment);
+        }
+    }
+    
+    private URI buildURIFromEncoded(String thePath, String theQuery, String theFragment) 
+        throws URISyntaxException {
+        StringBuilder b = new StringBuilder();
+        if (scheme != null) {
             b.append(scheme).append(":");
-            if (!isSchemeOpaque()) {
+        }
+        if (!isSchemeOpaque()) {
+            if (scheme != null) {
                 b.append("//");
-                if (userInfo != null) {
-                    b.append(userInfo).append('@');
-                }
+            }
+            if (userInfo != null) {
+                b.append(userInfo).append('@');
+            }
+            if (host != null) {
                 b.append(host);
-                if (port != -1) {
-                    b.append(':').append(port);    
-                }
-                if (thePath != null && thePath.length() > 0) {
-                    b.append(thePath.startsWith("/") ? thePath : '/' + thePath);
-                }
-                if (theQuery != null && theQuery.length() != 0) {
-                    b.append('?').append(theQuery);
-                }
-            } else {
-                b.append(schemeSpecificPart);
             }
-            if (fragment != null) {
-                b.append('#').append(fragment);
+            if (port != -1) {
+                b.append(':').append(port);    
             }
-            return new URI(b.toString());
-        } else if (!isSchemeOpaque()) {
-            if ((scheme != null || host != null || userInfo != null)
-                && thePath.length() != 0 && !thePath.startsWith("/")) {
-                thePath = "/" + thePath;
+            if (thePath != null && thePath.length() > 0) {
+                b.append(thePath.startsWith("/") || b.length() == 0 ? thePath : '/' + thePath);
+            }
+            if (theQuery != null && theQuery.length() != 0) {
+                b.append('?').append(theQuery);
             }
-            
-            return new URI(scheme, userInfo, host, port, 
-                           thePath, theQuery, fragment);
         } else {
-            return new URI(scheme, schemeSpecificPart, fragment);
+            b.append(schemeSpecificPart);
         }
+        if (theFragment != null) {
+            b.append('#').append(theFragment);
+        }
+        return new URI(b.toString());
     }
     
     private boolean isSchemeOpaque() {
@@ -203,7 +228,9 @@ public class UriBuilderImpl extends UriB
                 theQuery = substituteMapped(theQuery, map);
             }
             
-            return buildURI(fromEncoded, thePath, theQuery);
+            String theFragment = fragment == null ? null : substituteMapped(fragment, map);
+            
+            return buildURI(fromEncoded, thePath, theQuery, theFragment);
         } catch (URISyntaxException ex) {
             throw new UriBuilderException("URI can not be built", ex);
         }
@@ -225,11 +252,31 @@ public class UriBuilderImpl extends UriB
     @Override
     public URI buildFromEncodedMap(Map<String, ? extends Object> map) throws IllegalArgumentException,
         UriBuilderException {
-        // see buildFromEncoded() comment
+        
         Map<String, String> decodedMap = new HashMap<String, String>(map.size());
         for (Map.Entry<String, ? extends Object> entry : map.entrySet()) {
-            decodedMap.put(entry.getKey(), 
-                           HttpUtils.encodePartiallyEncoded(entry.getValue().toString(), false));
+            if (entry.getValue() == null) {
+                throw new IllegalArgumentException("Value is null");
+            }
+            String theValue = entry.getValue().toString();
+            if (theValue.contains("/")) {
+                // protecting '/' from being encoded here assumes that a given value may constitute multiple
+                // path segments - very questionable especially given that queries and fragments may also 
+                // contain template vars - technically this can be covered by checking where a given template
+                // var is coming from and act accordingly. Confusing nonetheless.
+                StringBuilder buf = new StringBuilder();
+                String[] values = theValue.split("/");
+                for (int i = 0; i < values.length; i++) {
+                    buf.append(HttpUtils.encodePartiallyEncoded(values[i], false));
+                    if (i + 1 < values.length) {
+                        buf.append("/");
+                    }
+                }
+                decodedMap.put(entry.getKey(), buf.toString());
+            } else {
+                decodedMap.put(entry.getKey(), HttpUtils.encodePartiallyEncoded(theValue, false));
+            }
+            
         }
         return doBuildFromMap(decodedMap, true);
     }
@@ -324,7 +371,10 @@ public class UriBuilderImpl extends UriB
 
     @Override
     public UriBuilder path(String path) throws IllegalArgumentException {
-        
+        return doPath(path, true);
+    }
+
+    private UriBuilder doPath(String path, boolean checkSegments) {
         if (path == null) {
             throw new IllegalArgumentException("path is null");
         }
@@ -338,7 +388,14 @@ public class UriBuilderImpl extends UriB
         if (paths.isEmpty()) {
             leadingSlash = path.startsWith("/");
         }
-        List<PathSegment> segments = JAXRSUtils.getPathSegments(path, false, false);
+        
+        List<PathSegment> segments;
+        if (checkSegments) { 
+            segments = JAXRSUtils.getPathSegments(path, false, false);
+        } else {
+            segments = new ArrayList<PathSegment>();
+            segments.add(new PathSegmentImpl(path.replaceAll("/", "%2F"), false));
+        }
         if (!paths.isEmpty() && !matrix.isEmpty()) {
             PathSegment ps = paths.remove(paths.size() - 1);
             paths.add(replacePathSegment(ps));
@@ -350,7 +407,7 @@ public class UriBuilderImpl extends UriB
         }
         return this;
     }
-
+    
     @Override
     public UriBuilder port(int thePort) throws IllegalArgumentException {
         if (thePort < 0 && thePort != -1) {
@@ -398,11 +455,15 @@ public class UriBuilderImpl extends UriB
         if (uri == null) {
             throw new IllegalArgumentException("uri is null");
         }
-        scheme = uri.getScheme();
-        if (!uri.isOpaque()) {
+        String theScheme = uri.getScheme();
+        if (theScheme != null) {
+            scheme = theScheme;
+        }
+        String rawPath = uri.getRawPath();
+        if (!uri.isOpaque() 
+            && (theScheme != null || rawPath != null && rawPath.startsWith("/"))) {
             port = uri.getPort();
             host = uri.getHost();
-            String rawPath = uri.getRawPath();
             if (rawPath != null) {
                 setPathAndMatrix(uri.getRawPath());
             }
@@ -411,10 +472,14 @@ public class UriBuilderImpl extends UriB
                 query = JAXRSUtils.getStructuredParams(rawQuery, "&", false, false);
             }
             userInfo = uri.getUserInfo();
+            schemeSpecificPart = null;
         } else {
             schemeSpecificPart = uri.getSchemeSpecificPart();
         }
-        fragment = uri.getFragment();
+        String theFragment = uri.getFragment();
+        if (theFragment != null) {
+            fragment = theFragment;
+        }
     }
 
     private void setPathAndMatrix(String path) {
@@ -462,8 +527,8 @@ public class UriBuilderImpl extends UriB
 
     @Override
     public UriBuilder matrixParam(String name, Object... values) throws IllegalArgumentException {
-        if (name == null) {
-            throw new IllegalArgumentException("name is null");
+        if (name == null || values == null) {
+            throw new IllegalArgumentException("name or values is null");
         }
         List<String> list = matrix.get(name);
         if (list == null) {
@@ -476,8 +541,8 @@ public class UriBuilderImpl extends UriB
 
     @Override
     public UriBuilder queryParam(String name, Object... values) throws IllegalArgumentException {
-        if (name == null) {
-            throw new IllegalArgumentException("name is null");
+        if (name == null || values == null) {
+            throw new IllegalArgumentException("name or values is null");
         }
         List<String> list = query.get(name);
         if (list == null) {
@@ -543,7 +608,7 @@ public class UriBuilderImpl extends UriB
             throw new IllegalArgumentException("Segments should not be null");
         }
         for (String segment : segments) {
-            path(segment);
+            doPath(segment, false);
         }
         return this;
     }

Modified: cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java?rev=997000&r1=996999&r2=997000&view=diff
==============================================================================
--- cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java (original)
+++ cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java Tue Sep 14 17:22:16 2010
@@ -61,7 +61,7 @@ public final class HttpUtils {
     private static final Pattern ENCODE_PATTERN = Pattern.compile("%[0-9a-fA-F][0-9a-fA-F]");
     private static final String CHARSET_PARAMETER = "charset";
     // there are more of such characters, ex, '*' but '*' is not affected by UrlEncode
-    private static final String PATH_RESERVED_DELIMETERS = "=";
+    private static final String PATH_RESERVED_CHARACTERS = "=@";
     
     private HttpUtils() {
     }
@@ -86,10 +86,28 @@ public final class HttpUtils {
     }
     
     public static String pathEncode(String value) {
-        if (isReservedPathSequence(value)) {
-            return value;
+        
+        StringBuilder buffer = new StringBuilder();
+        StringBuilder bufferToEncode = new StringBuilder();
+        
+        for (int i = 0; i < value.length(); i++) {
+            char currentChar = value.charAt(i);
+            if (PATH_RESERVED_CHARACTERS.indexOf(currentChar) != -1) {
+                if (bufferToEncode.length() > 0) {
+                    buffer.append(urlEncode(bufferToEncode.toString()));
+                    bufferToEncode.setLength(0);
+                }    
+                buffer.append(currentChar);
+            } else {
+                bufferToEncode.append(currentChar);
+            }
         }
-        String result = urlEncode(value);
+        
+        if (bufferToEncode.length() > 0) {
+            buffer.append(urlEncode(bufferToEncode.toString()));
+        }
+        
+        String result = buffer.toString();
         // URLEncoder will encode '+' to %2B but will turn ' ' into '+'
         // We need to retain '+' and encode ' ' as %20
         if (result.indexOf('+') != -1) {
@@ -102,11 +120,7 @@ public final class HttpUtils {
         return result;
     }
     
-    private static boolean isReservedPathSequence(String sequence) {
-        // realistically, we'd probably need to check every character
-        return PATH_RESERVED_DELIMETERS.equals(sequence);
-    }
-    
+       
     /**
      * Encodes partially encoded string. Encode all values but those matching pattern 
      * "percent char followed by two hexadecimal digits".

Modified: cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java?rev=997000&r1=996999&r2=997000&view=diff
==============================================================================
--- cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java (original)
+++ cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java Tue Sep 14 17:22:16 2010
@@ -368,6 +368,92 @@ public class UriBuilderImplTest extends 
     }
 
     @Test
+    public void testBuildFromEncodedMapComplex() throws Exception {
+        Map<String, Object> maps = new HashMap<String, Object>();
+        maps.put("x", "x%20yz");
+        maps.put("y", "/path-absolute/%test1");
+        maps.put("z", "fred@example.com");
+        maps.put("w", "path-rootless/test2");
+
+        String expectedPath =
+                "path-rootless/test2/x%20yz//path-absolute/%25test1/fred@example.com/x%20yz";
+        
+        URI uri = UriBuilder.fromPath("").path("{w}/{x}/{y}/{z}/{x}")
+                            .buildFromEncodedMap(maps);
+        String rawPath = uri.getRawPath();
+        assertEquals(expectedPath, rawPath);    
+    }
+    
+    @Test
+    public void testBuildFromEncodedMapComplex2() throws Exception {
+        Map<String, Object> maps = new HashMap<String, Object>();
+        maps.put("x", "x%yz");
+        maps.put("y", "/path-absolute/test1");
+        maps.put("z", "fred@example.com");
+        maps.put("w", "path-rootless/test2");
+        maps.put("u", "extra");
+
+        String expectedPath =
+                "path-rootless/test2/x%25yz//path-absolute/test1/fred@example.com/x%25yz";
+        
+        URI uri = UriBuilder.fromPath("").path("{w}/{x}/{y}/{z}/{x}")
+                            .buildFromEncodedMap(maps);
+        String rawPath = uri.getRawPath();
+        assertEquals(expectedPath, rawPath);    
+    }
+    
+    @Test
+    public void testBuildFromEncodedMapMultipleTimes() throws Exception {
+        Map<String, Object> maps = new HashMap<String, Object>();
+        maps.put("x", "x%yz");
+        maps.put("y", "/path-absolute/test1");
+        maps.put("z", "fred@example.com");
+        maps.put("w", "path-rootless/test2");
+
+        Map<String, Object> maps1 = new HashMap<String, Object>();
+        maps1.put("x", "x%20yz");
+        maps1.put("y", "/path-absolute/test1");
+        maps1.put("z", "fred@example.com");
+        maps1.put("w", "path-rootless/test2");
+
+        Map<String, Object> maps2 = new HashMap<String, Object>();
+        maps2.put("x", "x%yz");
+        maps2.put("y", "/path-absolute/test1");
+        maps2.put("z", "fred@example.com");
+        maps2.put("w", "path-rootless/test2");
+        maps2.put("v", "xyz");
+
+        String expectedPath =
+                "path-rootless/test2/x%25yz//path-absolute/test1/fred@example.com/x%25yz";
+
+        String expectedPath1 =
+                "path-rootless/test2/x%20yz//path-absolute/test1/fred@example.com/x%20yz";
+
+        String expectedPath2 =
+                "path-rootless/test2/x%25yz//path-absolute/test1/fred@example.com/x%25yz";
+        
+        UriBuilder ub = UriBuilder.fromPath("").path("{w}/{x}/{y}/{z}/{x}"); 
+        
+        URI uri = ub.buildFromEncodedMap(maps);
+        assertEquals(expectedPath, uri.getRawPath());
+        
+        uri = ub.buildFromEncodedMap(maps1);
+        assertEquals(expectedPath1, uri.getRawPath());
+        
+        uri = ub.buildFromEncodedMap(maps2);
+        assertEquals(expectedPath2, uri.getRawPath());
+    }
+    
+    @Test(expected = IllegalArgumentException.class)
+    public void testBuildFromEncodedMapWithNullValue() throws Exception {
+        
+        Map<String, Object> maps = new HashMap<String, Object>();
+        maps.put("x", null);
+        maps.put("y", "bar");
+        UriBuilder.fromPath("").path("{x}/{y}").buildFromEncodedMap(maps);
+    }
+    
+    @Test
     public void testAddPath() throws Exception {
         URI uri = new URI("http://foo/bar");
         URI newUri = new UriBuilderImpl().uri(uri).path("baz").build();
@@ -477,6 +563,15 @@ public class UriBuilderImplTest extends 
     }
 
     @Test
+    public void testReplaceQueryWithNull2() {
+        String expected = "http://localhost:8080";
+
+        URI uri = UriBuilder.fromPath("http://localhost:8080")
+            .queryParam("name", "x=", "y?", "x y", "&").replaceQuery(null).build();
+        assertEquals(expected, uri.toString());        
+    }
+    
+    @Test
     public void testReplaceQueryEmpty() throws Exception {
         URI uri = new URI("http://foo/bar?p1=v1&p2=v2");
         URI newUri = new UriBuilderImpl(uri).replaceQuery("").build();
@@ -497,6 +592,15 @@ public class UriBuilderImplTest extends 
         assertEquals("URI is not built correctly", new URI("http://foo/bar?p1=nv1"), newUri);
     }
 
+    @Test
+    public void testReplaceQuery3() {
+        String expected = "http://localhost:8080?name1=xyz";
+
+        URI uri = UriBuilder.fromPath("http://localhost:8080")
+            .queryParam("name", "x=", "y?", "x y", "&").replaceQuery("name1=xyz").build();
+        assertEquals(expected, uri.toString());        
+    }
+    
     @Test(expected = IllegalArgumentException.class)
     public void testQueryParamNameNull() throws Exception {
         new UriBuilderImpl().queryParam(null, "baz");
@@ -506,6 +610,17 @@ public class UriBuilderImplTest extends 
     public void testQueryParamNullVal() throws Exception {
         new UriBuilderImpl().queryParam("foo", "bar", null, "baz");
     }
+    
+    @Test
+    @SuppressWarnings("all")
+    public void testNullQueryParamValues() {
+        try {
+            UriBuilder.fromPath("http://localhost:8080").queryParam("hello", null);
+            fail("Should be IllegalArgumentException");
+        } catch (IllegalArgumentException ex) {
+            //expected
+        }
+    }
 
     @Test
     public void testQueryParamSameNameAndVal() throws Exception {
@@ -741,8 +856,9 @@ public class UriBuilderImplTest extends 
         URI uri = UriBuilder.fromPath(path).build(value);
         assertEquals(expected, uri.toString());        
     }
+    
     @Test
-    public void testNullValue() {
+    public void testNullPathValue() {
         String value = null;
         String path = "{arg1}";
         try {
@@ -752,6 +868,7 @@ public class UriBuilderImplTest extends 
             //expected
         }
     }
+    
     @Test
     public void testFragment() {
         String expected = "test#abc";
@@ -759,18 +876,18 @@ public class UriBuilderImplTest extends 
         URI uri = UriBuilder.fromPath(path).fragment("abc").build();
         assertEquals(expected, uri.toString());        
     }
+    
     @Test
-    @Ignore
     public void testFragmentTemplate() {
         String expected = "abc#xyz";
         URI uri = UriBuilder
             .fromPath("{arg1}")
             .fragment("{arg2}")
-            .build("abc", "xyx");
+            .build("abc", "xyz");
         assertEquals(expected, uri.toString());        
     }
+    
     @Test
-    @Ignore
     public void testSegments() {
         String path1 = "ab";
         String[] path2 = {"a1", "x/y", "3b "};
@@ -779,8 +896,8 @@ public class UriBuilderImplTest extends 
         URI uri = UriBuilder.fromPath(path1).segment(path2).build();
         assertEquals(expected, uri.toString());        
     }
+    
     @Test
-    @Ignore
     public void testSegments2() {
         String path1 = "";
         String[] path2 = {"a1", "/", "3b "};
@@ -789,15 +906,8 @@ public class UriBuilderImplTest extends 
         URI uri = UriBuilder.fromPath(path1).segment(path2).build();
         assertEquals(expected, uri.toString());        
     }
-    @Test
-    @Ignore
-    public void testReplaceQuery3() {
-        String expected = "http://localhost:8080?name1=xyz";
-
-        URI uri = UriBuilder.fromPath("http://localhost:8080")
-            .queryParam("name", "x=", "y?", "x y", "&").replaceQuery("name1=xyz").build();
-        assertEquals(expected, uri.toString());        
-    }
+    
+    
     
     @Test
     public void testNullSegment() {
@@ -809,25 +919,6 @@ public class UriBuilderImplTest extends 
         }
     }
     
-    @Test
-    public void testNullQueryParam() {
-        try {
-            UriBuilder.fromPath("http://localhost:8080").queryParam("hello", (String)null);
-            fail("Should be IllegalArgumentException");
-        } catch (IllegalArgumentException ex) {
-            //expected
-        }
-    }
-
-    @Test
-    public void testReplaceQuery4() {
-        String expected = "http://localhost:8080";
-
-        URI uri = UriBuilder.fromPath("http://localhost:8080")
-            .queryParam("name", "x=", "y?", "x y", "&").replaceQuery(null).build();
-        assertEquals(expected, uri.toString());        
-    }
-    
     
     @Test
     public void testInvalidPort() {
@@ -914,9 +1005,115 @@ public class UriBuilderImplTest extends 
             .buildFromEncoded("a", "%25", "=", "%G0", "%", "23"); 
         assertEquals(expected, uri.toString());        
     }
+
+    @Test
+    public void testMultipleUriSchemes() throws Exception {
+        URI uri;
+
+        String[] urisOriginal = {
+            "ftp://ftp.is.co.za/rfc/rfc1808.txt",
+            "ftp://ftp.is.co.za/rfc/rfc1808.txt",
+            "mailto:java-net@java.sun.com",
+            "mailto:java-net@java.sun.com",
+            "news:comp.lang.java",
+            "news:comp.lang.java",
+            "urn:isbn:096139210x",
+            "http://www.ietf.org/rfc/rfc2396.txt",
+            "http://www.ietf.org/rfc/rfc2396.txt",
+            "ldap://[2001:db8::7]/c=GB?objectClass?one",
+            "ldap://[2001:db8::7]/c=GB?objectClass?one",
+            "tel:+1-816-555-1212",
+            "tel:+1-816-555-1212",
+            "telnet://192.0.2.16:80/",
+            "telnet://192.0.2.16:80/",
+            "foo://example.com:8042/over/there?name=ferret#nose",
+            "foo://example.com:8042/over/there?name=ferret#nose"
+        };
+
+        URI urisReplace[] = new URI[urisOriginal.length];
+
+        urisReplace[0] = new URI("http", "//ftp.is.co.za/rfc/rfc1808.txt",
+                null);
+        urisReplace[1] = new URI(null, "ftp.is.co.za",
+                "/test/rfc1808.txt", null, null);
+        urisReplace[2] = new URI("mailto", "java-net@java.sun.com", null);
+        urisReplace[3] = new URI(null, "testuser@sun.com", null);
+        urisReplace[4] = new URI("http", "//comp.lang.java", null);
+        urisReplace[5] = new URI(null, "news.lang.java", null);
+        urisReplace[6] = new URI("urn:isbn:096139210x");
+        urisReplace[7] = new URI(null, "//www.ietf.org/rfc/rfc2396.txt",
+                null);
+        urisReplace[8] = new URI(null, "www.ietf.org", "/rfc/rfc2396.txt", null,
+                null);
+        urisReplace[9] =
+                new URI("ldap", "//[2001:db8::7]/c=GB?objectClass?one", null);
+        urisReplace[10] =
+                new URI(null, "//[2001:db8::7]/c=GB?objectClass?one", null);
+        urisReplace[11] = new URI("tel", "+1-816-555-1212", null);
+        urisReplace[12] = new URI(null, "+1-866-555-1212", null);
+        urisReplace[13] = new URI("telnet", "//192.0.2.16:80/", null);
+        urisReplace[14] = new URI(null, "//192.0.2.16:81/", null);
+        urisReplace[15] =
+            new URI("http", "//example.com:8042/over/there?name=ferret",
+                null);
+        urisReplace[16] =
+                new URI(null, "//example.com:8042/over/there?name=ferret",
+                "mouth");
+        
+        String[] urisExpected = {
+            "http://ftp.is.co.za/rfc/rfc1808.txt",
+            "ftp://ftp.is.co.za/test/rfc1808.txt",
+            "mailto:java-net@java.sun.com",
+            "mailto:testuser@sun.com",
+            "http://comp.lang.java",
+            "news:news.lang.java",
+            "urn:isbn:096139210x",
+            "http://www.ietf.org/rfc/rfc2396.txt",
+            "http://www.ietf.org/rfc/rfc2396.txt",
+            "ldap://[2001:db8::7]/c=GB?objectClass?one",
+            "ldap://[2001:db8::7]/c=GB?objectClass?one",
+            "tel:+1-816-555-1212",
+            "tel:+1-866-555-1212",
+            "telnet://192.0.2.16:80/",
+            "telnet://192.0.2.16:81/",
+            "http://example.com:8042/over/there?name=ferret#nose",
+            "foo://example.com:8042/over/there?name=ferret#mouth"
+        };
+
+        for (int i = 0;  i < urisOriginal.length; i++) {
+            uri = UriBuilder.fromUri(new URI(urisOriginal[i])).uri(urisReplace[i]).
+                    build();
+            if (uri.toString().trim().compareToIgnoreCase(urisExpected[i]) != 0) {
+                fail("Problem replacing " + urisOriginal[i] + " with " + urisReplace[i]
+                     + ", index " + i);    
+            }
+        }        
+    }
+    
+    @Test
+    @Ignore("QueryParamTest5")
+    public void testEncodingQueryParamFromBuild() throws Exception {
+        String expectedValue =
+                "http://localhost:8080?name=x%3D&name=y?&name=x+y&name=%26";
+        URI uri = UriBuilder.fromPath("http://localhost:8080").queryParam("name",
+                    "x=", "y?", "x y", "&").build();
+        assertEquals(expectedValue, uri.toString());    
+    }
     
     @Test
-    public void testReplaceQuery5() {
+    @Ignore("ReplaceQueryParamTest3")
+    public void testReplaceParamAndEncodeQueryParamFromBuild() throws Exception {
+        String expectedValue =
+                "http://localhost:8080?name=x&name=y&name=y+x&name=x%25y&name=%20";
+        URI uri = UriBuilder.fromPath("http://localhost:8080").queryParam("name",
+                    "x=", "y?", "x y", "&").replaceQueryParam("name", "x", "y",
+                    "y x", "x%y", "%20").build();
+        assertEquals(expectedValue, uri.toString());
+    }
+
+    @Test
+    // ReplaceQuery3
+    public void testReplaceStringAndEncodeQueryParamFromBuild() {
         String expected = "http://localhost:8080?name1=x&name2=%20&name3=x+y&name4=23&name5=x%20y";
 
         URI uri = UriBuilder.fromPath("http://localhost:8080")
@@ -924,14 +1121,4 @@ public class UriBuilderImplTest extends 
             .replaceQuery("name1=x&name2=%20&name3=x+y&name4=23&name5=x y").build();
         assertEquals(expected, uri.toString());        
     }
-    
-    @Test
-    @Ignore
-    public void testQueryParam() {
-        String expected = "http://localhost:8080?name=x%3D&name=y?&name=x+y&name=%26";
-
-        URI uri =  UriBuilder.fromPath("http://localhost:8080")
-            .queryParam("name", "x=", "y?", "x y", "&").build();
-        assertEquals(expected, uri.toString());        
-    }
 }