Return-Path: X-Original-To: apmail-cxf-commits-archive@www.apache.org Delivered-To: apmail-cxf-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id B2549F08E for ; Thu, 9 May 2013 11:27:42 +0000 (UTC) Received: (qmail 69560 invoked by uid 500); 9 May 2013 11:27:42 -0000 Delivered-To: apmail-cxf-commits-archive@cxf.apache.org Received: (qmail 69328 invoked by uid 500); 9 May 2013 11:27:37 -0000 Mailing-List: contact commits-help@cxf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cxf.apache.org Delivered-To: mailing list commits@cxf.apache.org Received: (qmail 69297 invoked by uid 99); 9 May 2013 11:27:36 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 09 May 2013 11:27:36 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 09 May 2013 11:27:32 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id BD23E23888D2; Thu, 9 May 2013 11:27:10 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1480593 - in /cxf/trunk/rt/frontend/jaxrs/src: main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java Date: Thu, 09 May 2013 11:27:10 -0000 To: commits@cxf.apache.org From: sergeyb@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20130509112710.BD23E23888D2@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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 paths = new ArrayList(); + 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.emptySet() : new HashSet(); 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 resolved = isVarEncoded ? alreadyResolvedTsEnc - : isPathEncVar ? alreadyResolvedTsPathEnc : alreadyResolvedTs; + Map 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(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/fred@example.com/x%25yz"; + + Map map = new HashMap(); + 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", "fred@example.com"); + 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/fred@example.com/x%25yz"; + + Map map = new HashMap(); + map.put("x", new StringBuilder("x%yz")); + map.put("y", new StringBuffer("/path-absolute/%25test1")); + map.put("z", new Object() { + public String toString() { + return "fred@example.com"; + } + }); + 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/fred@example.com/x%25yz"; + Map map = new HashMap(); + map.put("x", new StringBuilder("x%yz")); + map.put("y", new StringBuffer("/path-absolute/%25test1")); + map.put("z", new Object() { + public String toString() { + return "fred@example.com"; + } + }); + 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/fred@example.com/x%25yz"; + Map map = new HashMap(); + map.put("x", new StringBuilder("x%yz")); + map.put("y", new StringBuffer("/path-absolute/test1")); + map.put("z", new Object() { + public String toString() { + return "fred@example.com"; + } + }); + 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() {