You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wink.apache.org by jr...@apache.org on 2010/02/16 17:33:13 UTC

svn commit: r910582 - in /incubator/wink/trunk: wink-common/src/main/java/org/apache/wink/common/internal/ wink-common/src/main/java/org/apache/wink/common/internal/uri/ wink-common/src/test/java/org/apache/wink/common/internal/ wink-common/src/test/ja...

Author: jramos
Date: Tue Feb 16 16:33:12 2010
New Revision: 910582

URL: http://svn.apache.org/viewvc?rev=910582&view=rev
Log:
Add debugging to UriBuilderImpl and make fixes in UriBuilder and UriEncoder to conform to the JSR311 1.0 javadoc.

Added:
    incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/UriBuilderTest.java
Modified:
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/UriBuilderImpl.java
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/uri/UriEncoder.java
    incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/UriBuilderImplTest.java
    incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/uri/UriEncoderTest.java

Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/UriBuilderImpl.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/UriBuilderImpl.java?rev=910582&r1=910581&r2=910582&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/UriBuilderImpl.java (original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/UriBuilderImpl.java Tue Feb 16 16:33:12 2010
@@ -24,6 +24,7 @@
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -38,9 +39,13 @@
 import org.apache.wink.common.internal.uri.UriEncoder;
 import org.apache.wink.common.internal.uritemplate.JaxRsUriTemplateProcessor;
 import org.apache.wink.common.internal.utils.UriHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class UriBuilderImpl extends UriBuilder implements Cloneable {
 
+    private static final Logger            logger = LoggerFactory.getLogger(UriBuilderImpl.class);
+
     private String                         scheme;
     private String                         userInfo;
     private String                         host;
@@ -49,30 +54,37 @@
     private List<PathSegment>              segments;
     private MultivaluedMap<String, String> query;
     private String                         schemeSpecificPart;
+    private boolean                        isFirstCall;
 
     public UriBuilderImpl() {
         reset();
+        isFirstCall = true;
     }
 
     public void reset() {
+        logger.debug("Entered reset"); //$NON-NLS-1$
         scheme = null;
         resetSchemeSpecificPart();
         query = null;
         fragment = null;
+        logger.debug("Exit reset"); //$NON-NLS-1$
     }
 
     private void resetSchemeSpecificPart() {
+        logger.debug("Entered resetSchemeSpecificPart"); //$NON-NLS-1$
         schemeSpecificPart = null;
         userInfo = null;
         host = null;
         port = -1;
         segments = null;
+        logger.debug("Exit resetSchemeSpecificPart"); //$NON-NLS-1$
     }
 
     private List<PathSegment> getPathSegments() {
         if (segments == null) {
             segments = new ArrayList<PathSegment>();
         }
+        logger.debug("getPathSegments returning {}", segments); //$NON-NLS-1$
         return segments;
     }
 
@@ -80,36 +92,45 @@
         if (query == null) {
             query = new MultivaluedMapImpl<String, String>();
         }
+        logger.debug("getQuery returning {}", query); //$NON-NLS-1$
         return query;
     }
 
     private String constructPathString() {
         if (segments == null) {
+            logger.debug("constructPathString() returning null because null segments"); //$NON-NLS-1$
             return null;
         }
 
         StringBuilder path = new StringBuilder();
         for (PathSegment segment : segments) {
             String segmentStr = segment.toString();
-            path.append("/");
+            path.append("/"); //$NON-NLS-1$
             path.append(segmentStr);
+            logger.debug("appending {} from path segment to path", segmentStr); //$NON-NLS-1$
         }
 
-        return path.toString();
+        String str = path.toString();
+        logger.debug("constructPathString() returning {}", str); //$NON-NLS-1$
+        return str;
     }
 
     private String constructQueryString() {
         if (query == null) {
+            logger.debug("constructQueryString returning null beause null"); //$NON-NLS-1$
             return null;
         }
         if (query.size() == 0) {
-            return "";
+            logger.debug("constructQueryString returning empty string because string size is 0"); //$NON-NLS-1$
+            return ""; //$NON-NLS-1$
         }
-        String queryStr = "?" + MultivaluedMapImpl.toString(query, "&");
+        String queryStr = "?" + MultivaluedMapImpl.toString(query, "&"); //$NON-NLS-1$ //$NON-NLS-2$
+        logger.debug("constructQueryString returning {}", queryStr); //$NON-NLS-1$
         return queryStr;
     }
 
     private Set<String> getVariableNamesList() {
+        logger.debug("getVariableNamesList() entry"); //$NON-NLS-1$
         String constructedPath = constructPathString();
         String constructedQuery = constructQueryString();
         String uriStr =
@@ -121,11 +142,17 @@
                                   constructedQuery,
                                   fragment);
         JaxRsUriTemplateProcessor uriTemplate = new JaxRsUriTemplateProcessor(uriStr);
-        return uriTemplate.getVariableNames();
+        Set<String> ret = uriTemplate.getVariableNames();
+        logger.debug("getVariableNamesList() returning {}", ret); //$NON-NLS-1$
+        return ret;
     }
 
     private URI buildInternal(Map<String, ? extends Object> values)
         throws IllegalArgumentException, UriBuilderException {
+        if (logger.isDebugEnabled()) {
+            logger.debug("buildInternal({}, {}) entry", values //$NON-NLS-1$
+                );
+        }
         StringBuilder out = new StringBuilder();
         buildScheme(values, out);
         buildAuthority(values, out);
@@ -134,6 +161,7 @@
         buildFragment(values, out);
         String uriString = out.toString();
         try {
+            logger.debug("buildInternal() exit", uriString); //$NON-NLS-1$
             return new URI(uriString);
         } catch (URISyntaxException e) {
             throw new UriBuilderException(e);
@@ -141,20 +169,25 @@
     }
 
     private void buildScheme(Map<String, ? extends Object> values, StringBuilder out) {
+        logger.debug("buildScheme({}, {}) entry", values, out); //$NON-NLS-1$
         if (scheme == null) {
+            logger.debug("buildScheme() is null so returning"); //$NON-NLS-1$
             return;
         }
         JaxRsUriTemplateProcessor.expand(scheme,
                                          MultivaluedMapImpl.toMultivaluedMapString(values),
                                          out);
         out.append(':');
+        logger.debug("buildScheme() exit changed out to {}", out); //$NON-NLS-1$
     }
 
     private void buildAuthority(Map<String, ? extends Object> values, StringBuilder out) {
+        logger.debug("buildAuthority({}, {}) entry", values, out); //$NON-NLS-1$
         if (userInfo == null && host == null && port == -1) {
+            logger.debug("buildAuthority() is null so returning"); //$NON-NLS-1$
             return;
         }
-        out.append("//");
+        out.append("//"); //$NON-NLS-1$
         if (userInfo != null) {
             String eUserInfo =
                 JaxRsUriTemplateProcessor.expand(userInfo, MultivaluedMapImpl
@@ -171,10 +204,16 @@
             out.append(':');
             out.append(port);
         }
+        logger.debug("buildAuthority() exit changed out to {}", out); //$NON-NLS-1$
     }
 
     private void buildPath(Map<String, ? extends Object> values, StringBuilder out) {
+        if (logger.isDebugEnabled()) {
+            logger.debug("buildPath({}, {}) entry", new Object[] {values, out, //$NON-NLS-1$
+            });
+        }
         if (segments == null || segments.size() == 0) {
+            logger.debug("buildPath() segments is null or empty so returning"); //$NON-NLS-1$
             return;
         }
 
@@ -185,7 +224,15 @@
             String eSegmentPath =
                 JaxRsUriTemplateProcessor.expand(segmentPath, MultivaluedMapImpl
                     .toMultivaluedMapString(values));
-            eSegmentPath = UriEncoder.encodePathSegment(eSegmentPath, true);
+            // note that even though we're encoding inside a loop over segments,
+            // we're treating the path string (eSegmentPath) as just a path (so
+            // "/" will not be encoded).
+
+            // this allows the "values" map to contain values with "/" which
+            // should not be encoded (since "/" is an unreserved character in
+            // paths but not path segments). for real path segments specified by
+            // the segments() method, the "/" is encoded in that method
+            eSegmentPath = UriEncoder.encodePath(eSegmentPath, true);
 
             // we output the path separator if:
             // 1. if we already have some uri built and the last character is
@@ -222,10 +269,17 @@
                 }
             }
         }
+        if (logger.isDebugEnabled()) {
+            logger.debug("buildPath() exit changes out to {} ", out); //$NON-NLS-1$
+        }
     }
 
     private void buildQuery(Map<String, ? extends Object> values, StringBuilder out) {
+        if (logger.isDebugEnabled()) {
+            logger.debug("buildQuery({}, {}) entry", values, out); //$NON-NLS-1$
+        }
         if (query == null || query.size() == 0) {
+            logger.debug("buildQuery() exit - query is null"); //$NON-NLS-1$
             return;
         }
         char delim = '?';
@@ -252,9 +306,11 @@
                 delim = '&';
             }
         }
+        logger.debug("buildQuery() exit - changes out to {}", out); //$NON-NLS-1$
     }
 
     private void buildFragment(Map<String, ? extends Object> values, StringBuilder out) {
+        logger.debug("buildFragment({}, {})", values, out); //$NON-NLS-1$
         if (fragment == null) {
             return;
         }
@@ -264,6 +320,7 @@
         eFragment = UriEncoder.encodeFragment(eFragment, true);
         out.append('#');
         out.append(eFragment);
+        logger.debug("buildFragment() exit - changes out to {}", out); //$NON-NLS-1$
     }
 
     @Override
@@ -279,18 +336,25 @@
 
     private URI build(boolean escapePercent, Object... values) throws IllegalArgumentException,
         UriBuilderException {
-
+        if (logger.isDebugEnabled()) {
+            logger.debug("build({}, {}) enFtry", Boolean.valueOf(escapePercent), Arrays //$NON-NLS-1$
+                .asList(values));
+        }
         if (schemeSpecificPart != null) {
             try {
                 // uri templates will be automatically encoded
-                return new URI(scheme, schemeSpecificPart, fragment);
+                URI uri = new URI(scheme, schemeSpecificPart, fragment);
+                if (logger.isDebugEnabled()) {
+                    logger.debug("build() returning {}", uri.toString()); //$NON-NLS-1$
+                }
+                return uri;
             } catch (URISyntaxException e) {
                 throw new IllegalArgumentException("schemeSpecificPart is invalid", e);
             }
         }
 
         Set<String> names = getVariableNamesList();
-        if (names.size() > values.length) {
+        if (values == null || names.size() > values.length) {
             throw new IllegalArgumentException("missing variable values");
         }
         Map<String, Object> valuesMap = new HashMap<String, Object>();
@@ -306,9 +370,15 @@
                     value = escapePercent(value);
                 }
                 valuesMap.put(name, value);
+                logger.debug("name: {} has value : {}", name, value); //$NON-NLS-1$
             }
             ++i;
         }
+        for (; i < values.length; ++i) {
+            if (values[i] == null) {
+                throw new IllegalArgumentException();
+            }
+        }
         return buildInternal(valuesMap);
     }
 
@@ -326,10 +396,14 @@
 
     private URI buildFromMap(boolean escapePercent, Map<String, ? extends Object> values)
         throws IllegalArgumentException, UriBuilderException {
+        if (logger.isDebugEnabled()) {
+            logger.debug("buildFromMap({}, {})", Boolean.valueOf(escapePercent), values); //$NON-NLS-1$
+        }
         Set<String> names = getVariableNamesList();
-        if (names.size() > values.size()) {
+        if (values == null || (names.size() > values.size())) {
             throw new IllegalArgumentException("missing variable values");
         }
+        logger.debug("names are {}", names); //$NON-NLS-1$
         Map<String, Object> valuesMap = new HashMap<String, Object>();
         for (String name : names) {
             Object value = values.get(name);
@@ -343,26 +417,31 @@
                     valueToPut = escapePercent(valueToPut);
                 }
                 valuesMap.put(name, valueToPut);
+                logger.debug("name {} set to value {}", name, valueToPut); //$NON-NLS-1$
             }
         }
         return buildInternal(valuesMap);
     }
 
     private String escapePercent(String string) {
+        logger.debug("escapePercent({}) entry", string); //$NON-NLS-1$
         StringBuilder out = new StringBuilder(string.length());
         for (int i = 0; i < string.length(); ++i) {
             char c = string.charAt(i);
             if (c == '%') {
-                out.append("%25");
+                out.append("%25"); //$NON-NLS-1$
             } else {
                 out.append(c);
             }
         }
-        return out.toString();
+        String ret = out.toString();
+        logger.debug("escapePercent() return {}", ret); //$NON-NLS-1$
+        return ret;
     }
 
     @Override
     public UriBuilder clone() {
+        logger.debug("clone() entry"); //$NON-NLS-1$
         UriBuilderImpl uriBuilder = new UriBuilderImpl();
         uriBuilder.scheme(this.scheme);
         uriBuilder.userInfo(this.userInfo);
@@ -371,44 +450,58 @@
         uriBuilder.fragment(this.fragment);
         uriBuilder.segments(this.segments);
         uriBuilder.query(this.query);
+        logger.debug("clone() exit"); //$NON-NLS-1$
         return this;
     }
 
     private void query(MultivaluedMap<String, String> query) {
+        logger.debug("query({}) entry", query); //$NON-NLS-1$
         if (query == null) {
+            logger.debug("query exit"); //$NON-NLS-1$
             return;
         }
         this.query = ((MultivaluedMapImpl<String, String>)query).clone();
+        logger.debug("query exit"); //$NON-NLS-1$
     }
 
     private void segments(List<PathSegment> pathSegments) {
+        logger.debug("segments({}) entry", pathSegments); //$NON-NLS-1$
         if (pathSegments == null) {
+            logger.debug("segments() exit"); //$NON-NLS-1$
             return;
         }
         this.segments = new ArrayList<PathSegment>();
         for (PathSegment segment : pathSegments) {
             this.segments.add(((PathSegmentImpl)segment).clone());
         }
+        logger.debug("segments() exit"); //$NON-NLS-1$
     }
 
     @Override
     public UriBuilder fragment(String fragment) {
+        logger.debug("fragment({}) entry", fragment); //$NON-NLS-1$
         this.fragment = fragment;
+        logger.debug("fragment() exit"); //$NON-NLS-1$
         return this;
     }
 
     @Override
     public UriBuilder host(String host) throws IllegalArgumentException {
-        // null unsets the host so don't check that
+        logger.debug("host({}) entry", host); //$NON-NLS-1$
         if ("".equals(host)) {
             throw new IllegalArgumentException();
         }
         this.host = host;
+        logger.debug("host() exit"); //$NON-NLS-1$
         return this;
     }
 
     @Override
     public UriBuilder matrixParam(String name, Object... values) throws IllegalArgumentException {
+        if (logger.isDebugEnabled()) {
+            logger.debug("matrixParam({}, {}) entry", name, (values == null) ? null : Arrays //$NON-NLS-1$
+                .asList(values));
+        }
         if (name == null) {
             throw new IllegalArgumentException("name is null");
         }
@@ -418,29 +511,55 @@
         PathSegmentImpl lastSegment = getLastPathSegment();
         for (Object value : values) {
             lastSegment.getMatrixParameters().add(name, value.toString());
+            if (logger.isDebugEnabled()) {
+                logger.debug("lastSegment add({}, {})", name, value.toString()); //$NON-NLS-1$
+            }
         }
+        logger.debug("matrixParam exit"); //$NON-NLS-1$
         return this;
     }
 
     private PathSegmentImpl getLastPathSegment() {
+        logger.debug("getLastPathSegment() entry"); //$NON-NLS-1$
         List<PathSegment> pathSegments = getPathSegments();
+        logger.debug("getPathSegments() is {}", pathSegments); //$NON-NLS-1$
         PathSegmentImpl lastSegment = null;
         int lastSegmentIndex = pathSegments.size() - 1;
         if (lastSegmentIndex >= 0) {
             lastSegment = (PathSegmentImpl)pathSegments.get(lastSegmentIndex);
         } else {
-            lastSegment = new PathSegmentImpl("");
+            lastSegment = new PathSegmentImpl(""); //$NON-NLS-1$
             pathSegments.add(lastSegment);
         }
+        logger.debug("getLastPathSegment() returning {}", lastSegment); //$NON-NLS-1$
         return lastSegment;
     }
 
     @Override
     public UriBuilder path(String path) throws IllegalArgumentException {
+        logger.debug("path({}) entry", path); //$NON-NLS-1$
         if (path == null) {
             throw new IllegalArgumentException("path is null");
         }
-        List<PathSegment> list = UriHelper.parsePath(path);
+        if ("".equals(path)) {
+            // do nothing if there is an empty path
+            return this;
+        }
+
+        // strip off the authority prefix if present
+        String _path = path;
+        if (path.startsWith("//")) {
+            if (path.length() > 2) {
+                _path = path.substring(2);
+                getPathSegments().add(new PathSegmentImpl("/"));
+            } else {
+                logger.debug("path() exit"); //$NON-NLS-1$
+                return this;
+            }
+        }
+
+        List<PathSegment> list = UriHelper.parsePath(_path);
+        logger.debug("path is {}", list); //$NON-NLS-1$
         for (PathSegment segment : list) {
             segment(segment.getPath());
             MultivaluedMap<String, String> matrixParameters = segment.getMatrixParameters();
@@ -448,26 +567,32 @@
                 matrixParam(matrix, matrixParameters.get(matrix).toArray());
             }
         }
+        logger.debug("path() exit"); //$NON-NLS-1$
         return this;
     }
 
     @SuppressWarnings("unchecked")
     @Override
     public UriBuilder path(Class resource) throws IllegalArgumentException {
+        logger.debug("path({}) entry", resource); //$NON-NLS-1$
         if (resource == null) {
             throw new IllegalArgumentException("resource is null");
         }
+        isFirstCall = false;
         Path pathAnnotation = ((Class<?>)resource).getAnnotation(Path.class);
         if (pathAnnotation == null) {
             throw new IllegalArgumentException("resource is not annotated with Path");
         }
         String path = pathAnnotation.value();
+        logger.debug("path annotation value is {}", path); //$NON-NLS-1$
         path(path);
+        logger.debug("path() exit"); //$NON-NLS-1$
         return this;
     }
 
     @Override
     public UriBuilder path(Method method) throws IllegalArgumentException {
+        logger.debug("path({}) entry", method); //$NON-NLS-1$
         if (method == null) {
             throw new IllegalArgumentException("method is null");
         }
@@ -476,13 +601,16 @@
             throw new IllegalArgumentException("method is not annotated with Path");
         }
         String path = pathAnnotation.value();
+        logger.debug("path method annotation is {}", path); //$NON-NLS-1$
         path(path);
+        logger.debug("path() exit"); //$NON-NLS-1$
         return this;
     }
 
     @SuppressWarnings("unchecked")
     @Override
     public UriBuilder path(Class resource, String method) throws IllegalArgumentException {
+        logger.debug("path({}, {}) entry", resource, method); //$NON-NLS-1$
         if (resource == null) {
             throw new IllegalArgumentException("resource is null");
         }
@@ -508,21 +636,29 @@
             throw new IllegalArgumentException("no method with Path annotation exists");
         }
         path(foundMethod);
+        logger.debug("path() exit"); //$NON-NLS-1$
         return this;
     }
 
     @Override
     public UriBuilder port(int port) throws IllegalArgumentException {
-        // -1 unsets the port so don't worry about that
+        if (logger.isDebugEnabled()) {
+            logger.debug("port({}) entry", port); //$NON-NLS-1$
+        }
         if (port < -1) {
             throw new IllegalArgumentException();
         }
         this.port = port;
+        logger.debug("port() exit"); //$NON-NLS-1$
         return this;
     }
 
     @Override
     public UriBuilder queryParam(String name, Object... values) throws IllegalArgumentException {
+        if (logger.isDebugEnabled()) {
+            logger.debug("queryParam({}, {}) entry", name, (values == null) ? null : Arrays //$NON-NLS-1$
+                .asList(values));
+        }
         if (name == null) {
             throw new IllegalArgumentException("name is null");
         }
@@ -530,38 +666,46 @@
             throw new IllegalArgumentException("values is null");
         }
         MultivaluedMap<String, String> query = getQuery();
+        logger.debug("query map is {}", query); //$NON-NLS-1$
         for (Object value : values) {
+            if (value == null) {
+                throw new IllegalArgumentException(); //$NON-NLS-1$ //$NON-NLS-2$
+            }
             query.add(name, value != null ? value.toString() : null);
         }
+        logger.debug("queryParam() exit"); //$NON-NLS-1$
         return this;
     }
 
     @Override
     public UriBuilder replaceMatrix(String matrix) throws IllegalArgumentException {
+        logger.debug("replaceMatrix({}) entry", matrix); //$NON-NLS-1$
         // clear all matrix parameters from existing last segment
         PathSegmentImpl lastPathSegment = getLastPathSegment();
         lastPathSegment.clearAllMatrixParameters();
 
         // use a temporary PathSegmentImpl to parse the matrix parameters
-        PathSegmentImpl tmpPathSegment = new PathSegmentImpl("", matrix);
+        PathSegmentImpl tmpPathSegment = new PathSegmentImpl("", matrix); //$NON-NLS-1$
         MultivaluedMap<String, String> matrixParameters = tmpPathSegment.getMatrixParameters();
         for (String param : matrixParameters.keySet()) {
             List<String> matrixValues = matrixParameters.get(param);
             // add the matrix parameter and its values
             matrixParam(param, matrixValues.toArray());
         }
+        logger.debug("replaceMatrix() exit"); //$NON-NLS-1$
         return this;
     }
 
     @Override
     public UriBuilder replaceMatrixParam(String name, Object... values)
         throws IllegalArgumentException {
+        if (logger.isDebugEnabled()) {
+            logger.debug("replaceMatrixParam({}, {})", name, (values == null) ? null : Arrays //$NON-NLS-1$
+                .asList(values));
+        }
         if (name == null) {
             throw new IllegalArgumentException("name is null");
         }
-        if (values == null) {
-            throw new IllegalArgumentException("values is null");
-        }
         PathSegmentImpl lastPathSegment = getLastPathSegment();
         if (values == null || values.length == 0) {
             lastPathSegment.clearMatrixParameter(name);
@@ -572,36 +716,87 @@
             }
             matrixParam(name, values);
         }
+        logger.debug("replaceMatrixParam() exit"); //$NON-NLS-1$
         return this;
     }
 
     @Override
     public UriBuilder replacePath(String path) {
+        logger.debug("replacePath({}) entry", path); //$NON-NLS-1$
+        if (isFirstCall) {
+            if (path == null) {
+                throw new IllegalArgumentException("path is null"); //$NON-NLS-1$ //$NON-NLS-2$
+            }
+            isFirstCall = false;
+        }
         if (path == null) {
-            throw new IllegalArgumentException("path is null");
+            logger.debug("path is null. resetting");
+            reset();
+            logger.debug("replacePath() exit");
+            return this;
         }
         getPathSegments().clear();
-        if (path != null) {
+        if (path.indexOf(":") != -1) {
+            // we need to parse this as scheme:scheme-specific-part#fragment for
+            // a hierarchical URI
+            // if a non-valid URI is passed in, the path is parsed as normal
+            String[] segments = path.split(":", 2);
+            if (segments.length == 2 && segments[0].length() > 0) {
+                String scheme = segments[0];
+                segments = segments[1].split("#", 2);
+                if (segments[0].length() > 0) {
+                    String schemeSpecificPart = segments[0];
+                    String fragment = null;
+                    if (segments.length == 2)
+                        fragment = segments[1];
+                    scheme(scheme);
+                    schemeSpecificPart(schemeSpecificPart);
+                    fragment(fragment);
+                    logger.debug("replacePath() exit");
+                    return this;
+                }
+            }
+        }
+        if (path != null && !"".equals(path)) {
             path(path);
         }
+        logger.debug("replacePath() exit"); //$NON-NLS-1$
         return this;
     }
 
     @Override
     public UriBuilder replaceQuery(String query) throws IllegalArgumentException {
+        logger.debug("replaceQuery({}) entry", query); //$NON-NLS-1$
         getQuery().clear();
         if (query != null) {
+            query = query.replaceAll(" ", "%20");
             MultivaluedMap<String, String> queries = UriHelper.parseQuery(query);
+            // should values be URL encoded or query encoded?
+
+            logger.debug("queries after parsing: {}", queries); //$NON-NLS-1$
+            MultivaluedMap<String, String> queryValues = getQuery();
             for (String name : queries.keySet()) {
-                queryParam(name, queries.get(name).toArray());
+                List<String> values = queries.get(name);
+                for (String v : values) {
+                    if (v == null) {
+                        queryValues.add(name, null);
+                    } else {
+                        queryParam(name, v);
+                    }
+                }
             }
         }
+        logger.debug("replaceQuery() exit"); //$NON-NLS-1$
         return this;
     }
 
     @Override
     public UriBuilder replaceQueryParam(String name, Object... values)
         throws IllegalArgumentException {
+        if (logger.isDebugEnabled()) {
+            logger.debug("replaceQueryParam({}, {}) entry", name, (values == null) ? null : Arrays //$NON-NLS-1$
+                .asList(values));
+        }
         if (name == null) {
             throw new IllegalArgumentException("name is null");
         }
@@ -611,22 +806,26 @@
         if (values != null) {
             queryParam(name, values);
         }
+        logger.debug("replaceQueryParam() exit"); //$NON-NLS-1$
         return this;
     }
 
     @Override
     public UriBuilder scheme(String scheme) throws IllegalArgumentException {
+        logger.debug("scheme({}) entry", scheme); //$NON-NLS-1$
         this.scheme = scheme;
+        logger.debug("scheme() exit"); //$NON-NLS-1$
         return this;
     }
 
     @Override
     public UriBuilder schemeSpecificPart(String ssp) throws IllegalArgumentException {
+        logger.debug("schemeSpecificPart({}) entry", ssp); //$NON-NLS-1$
         if (ssp == null) {
             throw new IllegalArgumentException("schemeSpecificPart is null");
         }
 
-        if (!ssp.startsWith("/")) {
+        if (!ssp.startsWith("/")) { //$NON-NLS-1$
             // An opaque URI is an absolute URI whose scheme-specific part does
             // not begin with a slash character ('/').
             // Opaque URIs are not subject to further parsing.
@@ -657,11 +856,15 @@
         if (uri.getRawPath() != null) {
             path(UriEncoder.decodeString(uri.getRawPath()));
         }
+        logger.debug("schemeSpecificPart() exit"); //$NON-NLS-1$
         return this;
     }
 
     @Override
     public UriBuilder segment(String... segments) throws IllegalArgumentException {
+        if (logger.isDebugEnabled()) {
+            logger.debug("segment({}) entry", (segments == null) ? null : Arrays.asList(segments)); //$NON-NLS-1$
+        }
         if (segments == null) {
             throw new IllegalArgumentException("segments is null");
         }
@@ -671,49 +874,67 @@
             if (segments[i] == null) {
                 throw new IllegalArgumentException("segment at index " + i + " is null");
             }
-            pathSegments.add(new PathSegmentImpl(segments[i]));
+            if (segments[i].contains("/")) {
+                String segValue = segments[i].replace("/", "%2F");
+                pathSegments.add(new PathSegmentImpl(segValue));
+            } else {
+                pathSegments.add(new PathSegmentImpl(segments[i]));
+            }
         }
+        logger.debug("segment() exit"); //$NON-NLS-1$
         return this;
     }
 
     @Override
     public UriBuilder userInfo(String ui) {
+        logger.debug("userInfo({}) entry", ui); //$NON-NLS-1$
         userInfo = ui;
+        logger.debug("userInfo() exit"); //$NON-NLS-1$
         return this;
     }
 
     @Override
     public UriBuilder uri(URI uri) throws IllegalArgumentException {
+        logger.debug("Entering uri({})", uri); //$NON-NLS-1$
         if (uri == null) {
             throw new IllegalArgumentException("uri is null");
         }
 
-        reset();
+        isFirstCall = false;
 
         if (uri.getScheme() != null) {
+            logger.debug("Constructing scheme"); //$NON-NLS-1$
             scheme(uri.getScheme());
         }
         if (uri.getRawUserInfo() != null) {
+            logger.debug("Constructing userInfo"); //$NON-NLS-1$
             userInfo(uri.getRawUserInfo());
         }
         if (uri.getHost() != null) {
+            logger.debug("Constructing host"); //$NON-NLS-1$
             host(uri.getHost());
         }
         if (uri.getPort() != -1) {
+            logger.debug("Constructing port"); //$NON-NLS-1$
             port(uri.getPort());
         }
         if (uri.getRawPath() != null) {
+            logger.debug("Constructing rawPath"); //$NON-NLS-1$
             path(uri.getRawPath());
         }
         if (uri.getRawQuery() != null) {
+            logger.debug("Constructing rawQuery"); //$NON-NLS-1$
             replaceQuery(uri.getRawQuery());
         }
         if (uri.getRawFragment() != null) {
+            logger.debug("Constructing fragment"); //$NON-NLS-1$
             fragment(uri.getRawFragment());
         }
         if (uri.getSchemeSpecificPart() != null) {
+            logger.debug("Constructing schemeSpecificPart"); //$NON-NLS-1$
             schemeSpecificPart(uri.getSchemeSpecificPart());
         }
+        logger.debug("uri() exit"); //$NON-NLS-1$
         return this;
     }
 

Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/uri/UriEncoder.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/uri/UriEncoder.java?rev=910582&r1=910581&r2=910582&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/uri/UriEncoder.java (original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/uri/UriEncoder.java Tue Feb 16 16:33:12 2010
@@ -261,7 +261,45 @@
      * @return encoded query parameter string
      */
     public static String encodeQueryParam(String queryParam, boolean relax) {
-        return encode(queryParam, relax, queryParamChars);
+        boolean[] unreserved = queryParamChars;
+        String string = queryParam;
+
+        if (queryParam == null) {
+            return null;
+        }
+
+        if (!needsEncoding(queryParam, false, unreserved)) {
+            return string;
+        }
+
+        // Encode to UTF-8
+        ByteBuffer buffer = CHARSET_UTF_8.encode(string);
+        // Prepare string buffer
+        StringBuilder sb = new StringBuilder(buffer.remaining());
+        // Now encode the characters
+        while (buffer.hasRemaining()) {
+            int c = buffer.get();
+
+            if ((c == '%') && relax && (buffer.remaining() >= 2)) {
+                int position = buffer.position();
+                if (isHex(buffer.get(position)) && isHex(buffer.get(position + 1))) {
+                    sb.append((char)c);
+                    continue;
+                }
+            }
+
+            if ((c >= ' ' && unreserved[c])) {
+                sb.append((char)c);
+            } else if ((c == ' ')) {
+                sb.append('+');
+            } else {
+                sb.append('%');
+                sb.append(hexDigits[(c & 0xf0) >> 4]);
+                sb.append(hexDigits[c & 0xf]);
+            }
+        }
+
+        return sb.toString();
     }
 
     /**
@@ -361,7 +399,7 @@
                 }
             }
 
-            if (c >= ' ' && unreserved[c]) {
+            if ((c >= ' ' && unreserved[c])) {
                 sb.append((char)c);
             } else {
                 sb.append('%');

Modified: incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/UriBuilderImplTest.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/UriBuilderImplTest.java?rev=910582&r1=910581&r2=910582&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/UriBuilderImplTest.java (original)
+++ incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/UriBuilderImplTest.java Tue Feb 16 16:33:12 2010
@@ -20,6 +20,7 @@
 
 package org.apache.wink.common.internal;
 
+import java.lang.reflect.Method;
 import java.net.URI;
 import java.util.HashMap;
 import java.util.Map;
@@ -151,7 +152,7 @@
         builder = new UriBuilderImpl();
         builder.segment("path1").segment("{var1}");
         uri = builder.build("/s1,s2");
-        assertEquals("path1/%2Fs1,s2", uri.toString());
+        assertEquals("path1//s1,s2", uri.toString());
 
         builder.replacePath("/r1/{v1}");
         uri = builder.build("r2");
@@ -277,7 +278,7 @@
         assertEquals("//localhost:8080/some/path/pathEx/a+b/a+bc%2Bd#frag", uriString);
     }
 
-    public void testUri() {
+    public void testUri() throws Exception {
         UriBuilder builder = new UriBuilderImpl();
         builder.scheme("http").host("localhost").port(80).segment("path1", "path2");
         builder.matrixParam("mat1", "{var1}", "v2");
@@ -286,6 +287,58 @@
         builder.uri(uri);
         String uriStr = builder.build().toString();
         assertEquals("http://iamlegend@remotehost:90/path3;mat2=v1/path4#this%20fragment", uriStr);
+
+        UriBuilder uriBuilder =
+            UriBuilder.fromUri(new URI("ftp://ftp.ftpsite.site/files/file.txt"));
+        uriBuilder = uriBuilder.uri(new URI("//%2F%2Fftp.ftpsite.site/files/file.txt"));
+        assertEquals("ftp://ftp.ftpsite.site/files/file.txt", uriBuilder.build().toString());
+
+        uriBuilder = UriBuilder.fromUri(new URI("ftp.ftpsite.site/files/file.txt"));
+        uriBuilder = uriBuilder.scheme("ftp");
+        uriBuilder = uriBuilder.uri(new URI("//%2F%2Fftp.ftpsite.site/files/file.txt"));
+        assertEquals("ftp://ftp.ftpsite.site/files/file.txt", uriBuilder.build().toString());
+
+        uriBuilder = UriBuilder.fromUri(new URI("mailto:ibmuser@ibm.com"));
+        uriBuilder = uriBuilder.uri(new URI("ibmuser@ibm.com"));
+        assertEquals("mailto:ibmuser@ibm.com", uriBuilder.build().toString());
+
+        uriBuilder = UriBuilder.fromUri(new URI("ibmuser@ibm.com"));
+        uriBuilder.scheme("mailto");
+        uriBuilder = uriBuilder.uri(new URI("ibmuser@ibm.com"));
+        assertEquals("mailto:ibmuser@ibm.com", uriBuilder.build().toString());
+
+        uriBuilder = UriBuilder.fromUri(new URI("news:ibm.com"));
+        uriBuilder = uriBuilder.uri(new URI("http://ibm.com"));
+        assertEquals("http://ibm.com", uriBuilder.build().toString());
+
+        uriBuilder = UriBuilder.fromUri(new URI("news:ibm.com"));
+        uriBuilder = uriBuilder.uri(new URI("us.ibm.com"));
+        assertEquals("news:us.ibm.com", uriBuilder.build().toString());
+
+        uriBuilder = UriBuilder.fromUri(new URI("http://ww.httpsite.site/files/file.txt"));
+        uriBuilder = uriBuilder.uri(new URI("//www.httpsite.site/files/file.txt"));
+        assertEquals("http://www.httpsite.site/files/file.txt", uriBuilder.build().toString());
+
+        uriBuilder = UriBuilder.fromUri(new URI("http://www.httpsite.site/files/file.txt"));
+        uriBuilder = uriBuilder.uri(new URI("//%2F%2Fwww.httpsite.site/files/file.txt"));
+        assertEquals("http://www.httpsite.site/files/file.txt", uriBuilder.build().toString());
+
+        uriBuilder = UriBuilder.fromUri(new URI("tel:+1-234-567-8901"));
+        uriBuilder = uriBuilder.uri(new URI("+1-234-567-8901"));
+        assertEquals("tel:+1-234-567-8901", uriBuilder.build().toString());
+
+        uriBuilder = UriBuilder.fromUri(new URI("telnet://192.168.0.1/"));
+        uriBuilder = uriBuilder.uri(new URI("//192.168.0.2/"));
+        assertEquals("telnet://192.168.0.2/", uriBuilder.build().toString());
+
+        uriBuilder = UriBuilder.fromUri(new URI("foo://localhost:8080/com/ibm?name=myname#first"));
+        uriBuilder = uriBuilder.uri(new URI("http://localhost:8080/com/ibm?name=myname#first"));
+        assertEquals("http://localhost:8080/com/ibm?name=myname#first", uriBuilder.build()
+            .toString());
+
+        uriBuilder = UriBuilder.fromUri(new URI("foo://localhost:8080/com/ibm?name=myname#first"));
+        uriBuilder = uriBuilder.uri(new URI("//localhost:8080/com/ibm?name=myname#last"));
+        assertEquals("foo://localhost:8080/com/ibm?name=myname#last", uriBuilder.build().toString());
     }
 
     public void testClone() {
@@ -301,47 +354,199 @@
         assertEquals(uri1, uri2);
     }
 
-    public void testFromUri() {
+    public void testFromUri() throws Exception {
 
         String[] urisArray =
             {"ftp://ftp.is.co.za/rfc/rfc1808.txt", "http://www.ietf.org/rfc/rfc2396.txt",
-                "ldap://[2001:db8::7]/c=GB?objectClass?one", "mailto:John.Doe@example.com",
+                "ldap://[2001:db8::7]/c=GB?objectClass?one=two", "mailto:John.Doe@example.com",
                 "news:comp.infosystems.www.servers.unix", "tel:+1-816-555-1212",
                 "telnet://192.0.2.16:80/", "urn:oasis:names:specification:docbook:dtd:xml:4.1.2"};
 
         for (String uris : urisArray) {
             URI uri = UriBuilder.fromUri(uris).build();
-            assertTrue(uri.toString().equals(uris));
+            assertTrue(uri.toString(), uri.toString().equals(uris));
+        }
+
+        for (String uris : urisArray) {
+            URI uri = UriBuilder.fromUri(new URI(uris)).build();
+            assertTrue(uri.toString(), uri.toString().equals(uris));
         }
     }
 
-    public void testInvalidPort() {
-        UriBuilder builder = UriBuilder.fromUri("http://localhost/");
+    /**
+     * Tests that only '%' are encoded when calling from build...Encoded
+     * methods.
+     */
+    public void testBuildEncoded() {
+        UriBuilder uriBuilder = UriBuilder.fromPath("{a}");
+        Map<String, String> values = new HashMap<String, String>();
+        values.put("a", "/%test%/");
+        assertEquals("/%25test%25/", uriBuilder.buildFromEncodedMap(values).toASCIIString());
+
+        uriBuilder = UriBuilder.fromPath("{a}");
+        assertEquals("/%25test%25/", uriBuilder.buildFromMap(values).toASCIIString());
+
+        uriBuilder = UriBuilder.fromPath("{a}");
+        assertEquals("/%25test%25/", uriBuilder.buildFromEncoded("/%test%/").toASCIIString());
+
+        uriBuilder = UriBuilder.fromPath("{a}");
+        assertEquals("/%25test%25/", uriBuilder.build("/%test%/").toASCIIString());
+    }
+
+    public void testRootless() {
+        UriBuilder uriBuilder = UriBuilder.fromPath("");
+        uriBuilder.path("{w}");
+        Map<String, String> values = new HashMap<String, String>();
+        values.put("w", "somerootlesspath");
+        URI uri = uriBuilder.buildFromEncodedMap(values);
+        assertEquals("somerootlesspath", uri.toASCIIString());
+
+        uriBuilder = UriBuilder.fromPath("{w}");
+        values = new HashMap<String, String>();
+        values.put("w", "somerootlesspath");
+        uri = uriBuilder.buildFromEncodedMap(values);
+        assertEquals("somerootlesspath", uri.toASCIIString());
+    }
+
+    public void testQueryIllegal() {
+        UriBuilder uriBuilder = UriBuilder.fromPath("");
         try {
-            builder.port(-2);
+            uriBuilder.queryParam("a", null);
+            fail();
         } catch (IllegalArgumentException e) {
-            /* expected */
+            // expected
         }
-        builder.port(1);
-        builder.port(-1);
-        URI uri = builder.build();
-        assertEquals("http://localhost/", uri.toASCIIString());
+
+        uriBuilder = UriBuilder.fromPath("");
+        try {
+            uriBuilder.queryParam("a", "abcd", null);
+            fail();
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    public void testURIPath() throws Exception {
+        UriBuilder uriBuilder = UriBuilder.fromPath("http://localhost");
+        uriBuilder.path("/{v}");
+        URI uri = uriBuilder.buildFromEncoded("a");
+        assertEquals(uri.toString(), "http://localhost/a");
     }
 
-    public void testInvalidHost() {
-        UriBuilder builder = UriBuilder.fromUri("http://localhost/");
-        builder.host("abcd");
+    public void testBuildWithPathValues() {
+        /*
+         * by the docs of UriBuilder build() a "/" character in a path is
+         * unreserved in a regular path. it should only be encoded when called
+         * via a segment.
+         */
+        UriBuilder uriBuilder = UriBuilder.fromPath("{w}");
+        Map<String, Object> values = new HashMap<String, Object>();
+        values.put("w", "pathwithslash/test2");
+
+        URI uri = uriBuilder.buildFromMap(values);
+        assertEquals("pathwithslash/test2", uri.toString());
+    }
+
+    public void testBuildWithEmptyString() {
+        URI uri =
+            UriBuilder.fromPath("http://localhost:8080").path("/{a}/{b}/{c}")
+                .buildFromEncoded("xy", " ", "%");
+
+        assertEquals("http://localhost:8080/xy/%20/%25", uri.toString());
+    }
+
+    public void testNullReplacePath() {
+        UriBuilder uriBuilder = UriBuilder.fromPath("/path").replacePath(null);
+        assertEquals("", uriBuilder.build().toString());
+    }
+
+    public void testNullHost() {
+        UriBuilder uriBuilder = UriBuilder.fromPath("/path");
+        uriBuilder = uriBuilder.host("localhost");
+        assertEquals("//localhost/path", uriBuilder.build().toString());
+
+        uriBuilder = uriBuilder.host(null);
+        assertEquals("/path", uriBuilder.build().toString());
+    }
+
+    public void testBuildWithQueryParam() {
+        URI uri = UriBuilder.fromPath("http://localhost:8080").queryParam("a", "b").build();
+        // note the missing "/"
+        assertEquals("http://localhost:8080?a=b", uri.toString());
+    }
+
+    public void testBuildWithSpaceInValue() {
+        URI uri = UriBuilder.fromPath("http://localhost:8080").queryParam("a", "b c").build();
+        assertEquals("http://localhost:8080?a=b+c", uri.toString());
+
+        String name = "abcd";
+        uri =
+            UriBuilder.fromPath("http://localhost:8080").replaceQuery("key=value1 value2").build();
+        assertEquals("http://localhost:8080?key=value1%20value2", uri.toString());
+    }
+
+    public void testNullPathCall() throws SecurityException, NoSuchMethodException {
         try {
-            builder.host("");
+            UriBuilder.fromPath(null);
+            fail();
         } catch (IllegalArgumentException e) {
-            /* expected */
+            // expected
         }
-        URI uri = builder.build();
-        assertEquals("http://abcd/", uri.toASCIIString());
-       
-        builder = UriBuilder.fromUri("http://localhost");
-        builder.host(null);
-        uri = builder.build();
-        assertEquals("http:/", uri.toASCIIString());
+
+        // these should work
+        UriBuilder.fromPath("/blah").replacePath("hello");
+        UriBuilder.fromPath("/blah").replacePath(null);
+
+        try {
+            UriBuilder.fromPath("/test").path((String)null);
+            fail();
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            UriBuilder.fromPath("/test").path((Class)null);
+            fail();
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            UriBuilder.fromPath("/test").path(UriBuilderImplTest.class);
+            fail();
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            Method m = UriBuilderImplTest.class.getMethod("testNullPathCall", (Class<?>[])null);
+            UriBuilder.fromPath("/test").path(m);
+            fail();
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            Method m = UriBuilderImplTest.class.getMethod("testNullPathCall", (Class<?>[])null);
+            UriBuilder.fromPath("/test").path(UriBuilderImplTest.class, "testNullPathCall");
+            fail();
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            Method m = UriBuilderImplTest.class.getMethod("testNullPathCall", (Class<?>[])null);
+            UriBuilder.fromPath("/test").path(m);
+            fail();
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    public void testQueryParamWithEmptyValue() {
+        assertEquals("http://localhost/?something", UriBuilder
+            .fromUri("http://localhost/?something").build().toString());
+        assertEquals("http://localhost?something", UriBuilder.fromUri("http://localhost?something")
+            .build().toString());
     }
 }

Modified: incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/uri/UriEncoderTest.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/uri/UriEncoderTest.java?rev=910582&r1=910581&r2=910582&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/uri/UriEncoderTest.java (original)
+++ incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/uri/UriEncoderTest.java Tue Feb 16 16:33:12 2010
@@ -72,9 +72,9 @@
     }
 
     public void testEncodeQueryParam() {
-        assertEquals("abcxyzABCXYZ0189-._~!$%26'()*+,;%3D:/?%23%5B%5D@%7B%7D%20%50", UriEncoder
+        assertEquals("abcxyzABCXYZ0189-._~!$%26'()*+,;%3D:/?%23%5B%5D@%7B%7D+%50", UriEncoder
             .encodeQueryParam(TEST_STRING, true));
-        assertEquals("abcxyzABCXYZ0189-._~!$%26'()*+,;%3D:/?%23%5B%5D@%7B%7D%20%2550", UriEncoder
+        assertEquals("abcxyzABCXYZ0189-._~!$%26'()*+,;%3D:/?%23%5B%5D@%7B%7D+%2550", UriEncoder
             .encodeQueryParam(TEST_STRING, false));
     }
 

Added: incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/UriBuilderTest.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/UriBuilderTest.java?rev=910582&view=auto
==============================================================================
--- incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/UriBuilderTest.java (added)
+++ incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/UriBuilderTest.java Tue Feb 16 16:33:12 2010
@@ -0,0 +1,193 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *  
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *  
+ *******************************************************************************/
+
+package org.apache.wink.server.internal;
+
+import java.net.URI;
+import java.util.Collections;
+import java.util.Map;
+
+import javax.ws.rs.core.UriBuilder;
+
+import junit.framework.TestCase;
+
+public class UriBuilderTest extends TestCase {
+
+    /**
+     * Tests instances where {@link UriBuilder#build(Object...)} should throw an
+     * IllegalArgumentException.
+     * 
+     * @throws Exception
+     */
+    public void testIllegalArgumentExceptionFromBuild() throws Exception {
+        URI uri = UriBuilder.fromUri("http://www.example.com").build();
+        assertEquals(uri.toASCIIString(), "http://www.example.com");
+
+        uri = UriBuilder.fromUri("http://www.example.com/").path("{arg1}").build("someValue");
+        assertEquals(uri.toASCIIString(), "http://www.example.com/someValue");
+
+        uri =
+            UriBuilder.fromUri("http://www.example.com/").path("{arg1}").build("someValue",
+                                                                               "otherValue");
+        assertEquals(uri.toASCIIString(), "http://www.example.com/someValue");
+
+        try {
+            UriBuilder.fromUri("http://www.example.com/").path("{arg1}").build();
+            fail("Expected illegal argument exception");
+        } catch (IllegalArgumentException e) {
+            /* good catch */
+        }
+
+        try {
+            UriBuilder.fromUri("http://www.example.com/").path("{arg1}").build((Object)null);
+            fail("Expected illegal argument exception");
+        } catch (IllegalArgumentException e) {
+            /* good catch */
+        }
+
+        try {
+            UriBuilder.fromUri("http://www.example.com/").build((Object)null);
+            fail("Expected illegal argument exception");
+        } catch (IllegalArgumentException e) {
+            /* good catch */
+        }
+
+        try {
+            UriBuilder.fromUri("http://www.example.com/").path("{arg1}").build("value",
+                                                                               (Object)null);
+            fail("Expected illegal argument exception");
+        } catch (IllegalArgumentException e) {
+            /* good catch */
+        }
+
+        uri = UriBuilder.fromPath("somePath").build();
+        assertEquals(uri.toASCIIString(), "somePath");
+
+        uri = UriBuilder.fromPath("somePath/{arg1}").build("value");
+        assertEquals(uri.toASCIIString(), "somePath/value");
+
+        uri = UriBuilder.fromPath("somePath/{arg1}").build("value", "otherValue");
+        assertEquals(uri.toASCIIString(), "somePath/value");
+
+        try {
+            UriBuilder.fromPath("somePath/{arg1}").build();
+            fail("Expected illegal argument exception");
+        } catch (IllegalArgumentException e) {
+            /* good catch */
+        }
+
+        try {
+            UriBuilder.fromPath("somePath/{arg1}").build((Object)null);
+            fail("Expected illegal argument exception");
+        } catch (IllegalArgumentException e) {
+            /* good catch */
+        }
+
+        try {
+            UriBuilder.fromPath("somePath/").build((Object)null);
+            fail("Expected illegal argument exception");
+        } catch (IllegalArgumentException e) {
+            /* good catch */
+        }
+
+        try {
+            UriBuilder.fromPath("somePath/{arg1}").build("value", (Object)null);
+            fail("Expected illegal argument exception");
+        } catch (IllegalArgumentException e) {
+            /* good catch */
+        }
+    }
+
+    /**
+     * Tests instances where {@link UriBuilder#buildFromEncodedMap(Map)} should
+     * throw an IllegalArgumentException.
+     * 
+     * @throws Exception
+     */
+    public void testBuiltFromEncoded() throws Exception {
+        Map<String, String> valueMap = Collections.singletonMap("arg1", "Hello");
+        URI uri = UriBuilder.fromUri("http://www.example.com").buildFromEncodedMap(valueMap);
+        assertEquals(uri.toASCIIString(), "http://www.example.com");
+
+        uri =
+            UriBuilder.fromUri("http://www.example.com").path("{arg1}")
+                .buildFromEncodedMap(valueMap);
+        assertEquals(uri.toASCIIString(), "http://www.example.com/Hello");
+
+        valueMap = Collections.singletonMap("arg1", null);
+
+        try {
+            uri =
+                UriBuilder.fromUri("http://www.example.com").path("{arg1}")
+                    .buildFromEncodedMap(valueMap);
+            fail("Expected illegal argument exception");
+        } catch (IllegalArgumentException e) {
+            /* good catch */
+        }
+
+        try {
+            uri =
+                UriBuilder.fromUri("http://www.example.com").path("{arg1}")
+                    .buildFromEncodedMap(null);
+            fail("Expected illegal argument exception");
+        } catch (IllegalArgumentException e) {
+            /* good catch */
+        }
+    }
+
+    public void testIllegalHostnameReplacement() throws Exception {
+        try {
+            UriBuilder.fromUri("http://www.ibm.com/").host("").build();
+            fail("Expected illegal argument exception");
+        } catch (IllegalArgumentException e) {
+            /* good catch */
+        }
+
+        /* this is valid */
+        URI uri = UriBuilder.fromUri("http://www.ibm.com/").build();
+        assertEquals("www.ibm.com", uri.getHost());
+
+        uri = UriBuilder.fromUri("http://www.ibm.com/").host(null).build();
+        assertEquals(null, uri.getHost());
+    }
+
+    public void testIllegalPortReplacement() throws Exception {
+        try {
+            UriBuilder.fromUri("http://www.ibm.com:9080/").port(-100).build();
+            fail("Expected illegal argument exception");
+        } catch (IllegalArgumentException e) {
+            /* good catch */
+        }
+
+        /* this is valid */
+        URI uri = UriBuilder.fromUri("http://www.ibm.com/").port(9080).build();
+        assertEquals(9080, uri.getPort());
+
+        uri = UriBuilder.fromUri("http://www.ibm.com:9080/").build();
+        assertEquals(9080, uri.getPort());
+
+        uri = UriBuilder.fromUri("http://www.ibm.com/").port(-1).build();
+        assertEquals(-1, uri.getPort());
+
+        uri = UriBuilder.fromUri("http://www.ibm.com:9080/").port(-1).build();
+        assertEquals(-1, uri.getPort());
+
+    }
+}