Author: sergeyb
Date: Thu May 9 11:27:10 2013
New Revision: 1480593
URL: http://svn.apache.org/r1480593
Log:
[CXF-5007] UriBuilder updates to get some edge-case tests passing
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java?rev=1480593&r1=1480592&r2=1480593&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java
Thu May 9 11:27:10 2013
@@ -51,6 +51,7 @@ public class UriBuilderImpl extends UriB
private int port = -1;
private String host;
private List<PathSegment> paths = new ArrayList<PathSegment>();
+ private boolean originalPathEmpty;
private boolean leadingSlash;
private String fragment;
private String schemeSpecificPart;
@@ -159,7 +160,7 @@ public class UriBuilderImpl extends UriB
return buildURIFromEncoded(thePath, theQuery, theFragment);
} else if (!isSchemeOpaque()) {
if ((scheme != null || host != null || userInfo != null)
- && thePath.length() != 0 && !thePath.startsWith("/")) {
+ && thePath.length() != 0 && !(thePath.startsWith("/") ||
thePath.startsWith(";"))) {
thePath = "/" + thePath;
}
try {
@@ -205,7 +206,8 @@ public class UriBuilderImpl extends UriB
b.append(':').append(port);
}
if (thePath != null && thePath.length() > 0) {
- b.append(thePath.startsWith("/") || b.length() == 0 ? thePath
: '/' + thePath);
+ b.append(thePath.startsWith("/") || b.length() == 0 ||
originalPathEmpty
+ ? thePath : '/' + thePath);
}
if (theQuery != null && theQuery.length() != 0) {
b.append('?').append(theQuery);
@@ -289,24 +291,27 @@ public class UriBuilderImpl extends UriB
? Collections.<String>emptySet() : new HashSet<String>();
for (String var : uniqueVars) {
- boolean isPathEncVar = !isQuery &&
alreadyResolvedTsPathEnc.containsKey(var);
+ boolean resolvedPathVarHasToBeEncoded = !isQuery &&
alreadyResolvedTsPathEnc.containsKey(var);
+ boolean varValueHasToBeEncoded = resolvedPathVarHasToBeEncoded ||
alreadyResolvedTs.containsKey(var);
- boolean isVarEncoded = isPathEncVar ||
alreadyResolvedTs.containsKey(var) ? false : true;
- Map<String, Object> resolved = isVarEncoded ? alreadyResolvedTsEnc
- : isPathEncVar ? alreadyResolvedTsPathEnc : alreadyResolvedTs;
+ Map<String, Object> resolved = !varValueHasToBeEncoded ?
alreadyResolvedTsEnc
+ : resolvedPathVarHasToBeEncoded ? alreadyResolvedTsPathEnc :
alreadyResolvedTs;
Object oval = resolved.isEmpty() ? null : resolved.remove(var);
+ boolean valueFromEncodedMap = false;
if (oval == null) {
if (allowUnresolved) {
continue;
}
oval = values[idx++];
- }
+ } else {
+ valueFromEncodedMap = resolved == alreadyResolvedTsEnc;
+ }
if (oval == null) {
throw new IllegalArgumentException("No object for " + var);
}
String value = oval.toString();
- if (fromEncoded) {
+ if (fromEncoded || valueFromEncodedMap) {
value = HttpUtils.encodePartiallyEncoded(value, isQuery);
} else {
value = isQuery ? HttpUtils.queryEncode(value) :
HttpUtils.pathEncode(value);
@@ -314,7 +319,8 @@ public class UriBuilderImpl extends UriB
varValueMap.put(var, value);
- if (!isQuery && (isPathEncVar || encodePathSlash)) {
+ if (!isQuery && (resolvedPathVarHasToBeEncoded
+ || encodePathSlash && !varValueHasToBeEncoded)) {
pathEncodeVars.add(var);
}
@@ -418,6 +424,7 @@ public class UriBuilderImpl extends UriB
builder.matrix = new MetadataMap<String, String>(matrix);
builder.schemeSpecificPart = schemeSpecificPart;
builder.leadingSlash = leadingSlash;
+ builder.originalPathEmpty = originalPathEmpty;
return builder;
}
@@ -504,7 +511,30 @@ public class UriBuilderImpl extends UriB
throw new IllegalArgumentException("path is null");
}
if (isAbsoluteUriPath(path)) {
- uri(URI.create(path));
+ try {
+ URI uri = URI.create(path);
+ this.originalPathEmpty = StringUtils.isEmpty(uri.getPath());
+ uri(uri);
+ } catch (IllegalArgumentException ex) {
+ String pathEncoded = HttpUtils.pathEncode(path);
+ // Bad hack to bypass the TCK usage of bogus URI with empty
paths containing matrix parameters,
+ // which even URI class chokes upon; cheaper to do the
following than try to challenge,
+ // given that URI RFC mentions the possibility of empty paths,
though no word on the possibility of
+ // such empty paths having matrix parameters...
+ int schemeIndex = pathEncoded.indexOf("//");
+ if (schemeIndex != -1) {
+ int pathComponentStart = pathEncoded.indexOf("/",
schemeIndex + 2);
+ if (pathComponentStart == -1) {
+ this.originalPathEmpty = true;
+ pathComponentStart = pathEncoded.indexOf(";");
+ if (pathComponentStart != -1) {
+ pathEncoded = pathEncoded.substring(0,
pathComponentStart)
+ + "/" +
pathEncoded.substring(pathComponentStart);
+ }
+ }
+ }
+ setUriParts(URI.create(pathEncoded));
+ }
return this;
}
@@ -589,7 +619,7 @@ public class UriBuilderImpl extends UriB
port = uri.getPort();
host = uri.getHost();
if (rawPath != null) {
- setPathAndMatrix(uri.getRawPath());
+ setPathAndMatrix(rawPath);
}
String rawQuery = uri.getRawQuery();
if (rawQuery != null) {
@@ -607,7 +637,7 @@ public class UriBuilderImpl extends UriB
}
private void setPathAndMatrix(String path) {
- leadingSlash = path.startsWith("/");
+ leadingSlash = !originalPathEmpty && path.startsWith("/");
paths = JAXRSUtils.getPathSegments(path, false, false);
if (!paths.isEmpty()) {
matrix = paths.get(paths.size() - 1).getMatrixParameters();
@@ -673,7 +703,8 @@ public class UriBuilderImpl extends UriB
@Override
public UriBuilder replaceMatrix(String matrixValues) throws
IllegalArgumentException {
- this.matrix = JAXRSUtils.getStructuredParams(matrixValues, ";", true,
false);
+ String encodedMatrixValues = matrixValues != null ?
HttpUtils.pathEncode(matrixValues) : null;
+ this.matrix = JAXRSUtils.getStructuredParams(encodedMatrixValues, ";",
true, false);
return this;
}
@@ -837,6 +868,9 @@ public class UriBuilderImpl extends UriB
public UriBuilder uri(String uriTemplate) throws IllegalArgumentException {
+ if (StringUtils.isEmpty(uriTemplate)) {
+ throw new IllegalArgumentException();
+ }
try {
return uri(URI.create(uriTemplate));
} catch (Exception ex) {
Modified:
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java?rev=1480593&r1=1480592&r2=1480593&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java
Thu May 9 11:27:10 2013
@@ -158,6 +158,26 @@ public class UriBuilderImplTest extends
}
@Test
+ public void testResolveTemplateFromEncodedMap() {
+ String expected =
+
"path-rootless%2Ftest2/x%25yz/%2Fpath-absolute%2F%2525test1/[email protected]/x%25yz";
+
+ Map<String, Object> map = new HashMap<String, Object>();
+ map.put("v", new StringBuilder("path-rootless%2Ftest2"));
+ map.put("w", new StringBuilder("x%yz"));
+ map.put("x", new Object() {
+ public String toString() {
+ return "%2Fpath-absolute%2F%2525test1";
+ }
+ });
+ map.put("y", "[email protected]");
+ UriBuilder builder =
UriBuilder.fromPath("").path("{v}/{w}/{x}/{y}/{w}");
+ builder = builder.resolveTemplatesFromEncoded(map);
+ URI uri = builder.build();
+ assertEquals(expected, uri.getRawPath());
+ }
+
+ @Test
public void testResolveTemplateFromMap() {
URI uri;
uri = UriBuilder.fromPath("/{a}/{b}").resolveTemplate("a", "1")
@@ -166,6 +186,62 @@ public class UriBuilderImplTest extends
}
@Test
+ public void testResolveTemplateFromMap2() {
+ String expected =
+
"path-rootless%2Ftest2/x%25yz/%2Fpath-absolute%2F%2525test1/[email protected]/x%25yz";
+
+ Map<String, Object> map = new HashMap<String, Object>();
+ map.put("x", new StringBuilder("x%yz"));
+ map.put("y", new StringBuffer("/path-absolute/%25test1"));
+ map.put("z", new Object() {
+ public String toString() {
+ return "[email protected]";
+ }
+ });
+ map.put("w", "path-rootless/test2");
+ UriBuilder builder =
UriBuilder.fromPath("").path("{w}/{x}/{y}/{z}/{x}");
+ URI uri = builder.resolveTemplates(map).build();
+
+ assertEquals(expected, uri.getRawPath());
+ }
+
+ @Test
+ public void testResolveTemplatesMapBooleanSlashEncoded() throws Exception {
+ String expected =
+
"path-rootless%2Ftest2/x%25yz/%2Fpath-absolute%2F%2525test1/[email protected]/x%25yz";
+ Map<String, Object> map = new HashMap<String, Object>();
+ map.put("x", new StringBuilder("x%yz"));
+ map.put("y", new StringBuffer("/path-absolute/%25test1"));
+ map.put("z", new Object() {
+ public String toString() {
+ return "[email protected]";
+ }
+ });
+ map.put("w", "path-rootless/test2");
+ UriBuilder builder =
UriBuilder.fromPath("").path("{w}/{x}/{y}/{z}/{x}");
+ URI uri = builder.resolveTemplates(map, true).build();
+ assertEquals(expected, uri.getRawPath());
+ }
+
+ @Test
+ public void testResolveTemplatesMapBooleanSlashNotEncoded() throws
Exception {
+ String expected =
+
"path-rootless/test2/x%25yz//path-absolute/test1/[email protected]/x%25yz";
+ Map<String, Object> map = new HashMap<String, Object>();
+ map.put("x", new StringBuilder("x%yz"));
+ map.put("y", new StringBuffer("/path-absolute/test1"));
+ map.put("z", new Object() {
+ public String toString() {
+ return "[email protected]";
+ }
+ });
+ map.put("w", "path-rootless/test2");
+ UriBuilder builder =
UriBuilder.fromPath("").path("{w}/{x}/{y}/{z}/{x}");
+ URI uri = builder.resolveTemplates(map, false).build();
+ assertEquals(expected, uri.getRawPath());
+ }
+
+ @Test
public void testQueryParamWithTemplateValues() {
URI uri;
uri = UriBuilder.fromPath("/index.jsp").queryParam("a",
"{a}").queryParam("b", "{b}")
@@ -387,6 +463,37 @@ public class UriBuilderImplTest extends
}
@Test
+ public void replaceMatrixParamWithEmptyPathTest() throws Exception {
+ String name = "name";
+ String expected =
"http://localhost:8080;name=x;name=y;name=y%20x;name=x%25y;name=%20";
+
+ URI uri =
UriBuilder.fromPath("http://localhost:8080;name=x=;name=y?;name=x y;name=&")
+ .replaceMatrixParam(name, "x", "y", "y x", "x%y", "%20")
+ .build();
+ assertEquals(expected, uri.toString());
+ }
+
+ @Test
+ public void replaceMatrixWithEmptyPathTest() throws Exception {
+ String expected =
"http://localhost:8080;name=x;name=y;name=y%20x;name=x%25y;name=%20";
+ String value = "name=x;name=y;name=y x;name=x%y;name= ";
+
+ URI uri =
UriBuilder.fromPath("http://localhost:8080;name=x=;name=y?;name=x y;name=&")
+ .replaceMatrix(value).build();
+ assertEquals(expected, uri.toString());
+ }
+
+ @Test
+ public void testAddMatrixToEmptyPath() throws Exception {
+ String name = "name";
+ String expected = "http://localhost:8080;name=x;name=y";
+
+ URI uri =
UriBuilder.fromPath("http://localhost:8080").matrixParam(name, "x", "y")
+ .build();
+ assertEquals(expected, uri.toString());
+ }
+
+ @Test
public void testSchemeSpecificPart() throws Exception {
URI uri = new URI("http://bar");
URI newUri = new
UriBuilderImpl(uri).scheme("https").schemeSpecificPart("//localhost:8080/foo/bar")
@@ -1126,6 +1233,18 @@ public class UriBuilderImplTest extends
URI uri = UriBuilder.fromPath(path1).path(path2).build(new
Object[]{"x/y"}, false);
assertEquals(uri.toString(), expected);
}
+
+ @Test
+ public void testInvalidUriReplacement() throws Exception {
+ UriBuilder builder = UriBuilder.fromUri(new
URI("news:comp.lang.java"));
+ try {
+ builder.uri("").build();
+ fail("IAE exception is expected");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
@Test
public void testNullSegment() {