Repository: olingo-odata2 Updated Branches: refs/heads/URIParser [created] 39e774ba4
Uri parser considers percent encoded resource paths with $batch, $value, $links, $value, $metadata Project: http://git-wip-us.apache.org/repos/asf/olingo-odata2/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata2/commit/39e774ba Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata2/tree/39e774ba Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata2/diff/39e774ba Branch: refs/heads/URIParser Commit: 39e774ba45e899ebbdf58493654b1464ea13ffd6 Parents: e26395f Author: Christian Holzer <[email protected]> Authored: Thu Apr 16 17:37:54 2015 +0200 Committer: Christian Holzer <[email protected]> Committed: Thu Apr 16 17:37:54 2015 +0200 ---------------------------------------------------------------------- .../olingo/odata2/core/uri/UriParserImpl.java | 29 +++---- .../olingo/odata2/core/uri/UriParserTest.java | 81 ++++++++++++++++++-- .../olingo/odata2/fit/basic/BasicBatchTest.java | 24 ++++++ .../ContentNegotiationDollarFormatTest.java | 23 ++++++ .../olingo/odata2/fit/basic/MetadataTest.java | 8 ++ 5 files changed, 146 insertions(+), 19 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/39e774ba/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriParserImpl.java ---------------------------------------------------------------------- diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriParserImpl.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriParserImpl.java index c58f7ae..d9ae0a5 100644 --- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriParserImpl.java +++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriParserImpl.java @@ -167,12 +167,13 @@ public class UriParserImpl extends UriParser { } else { currentPathSegment = pathSegments.remove(0); - - if ("$metadata".equals(currentPathSegment)) { + final String encodedPath = percentDecode(currentPathSegment); + + if ("$metadata".equals(encodedPath)) { ensureLastSegment(); uriResult.setUriType(UriType.URI8); - } else if ("$batch".equals(currentPathSegment)) { + } else if ("$batch".equals(encodedPath)) { ensureLastSegment(); uriResult.setUriType(UriType.URI9); @@ -245,12 +246,13 @@ public class UriParserImpl extends UriParser { private void handleNavigationPathOptions() throws UriSyntaxException, UriNotMatchingException, EdmException { currentPathSegment = pathSegments.remove(0); - + final String decodedPath = percentDecode(currentPathSegment); + checkCount(); if (uriResult.isCount()) { uriResult.setUriType(UriType.URI16); // Count of multiple entities is handled elsewhere - } else if ("$value".equals(currentPathSegment)) { + } else if ("$value".equals(decodedPath)) { if (uriResult.getTargetEntitySet().getEntityType().hasStream()) { ensureLastSegment(); uriResult.setUriType(UriType.URI17); @@ -259,7 +261,7 @@ public class UriParserImpl extends UriParser { throw new UriSyntaxException(UriSyntaxException.NOMEDIARESOURCE); } - } else if ("$links".equals(currentPathSegment)) { + } else if ("$links".equals(decodedPath)) { uriResult.setLinks(true); if (pathSegments.isEmpty()) { throw new UriSyntaxException(UriSyntaxException.MUSTNOTBELASTSEGMENT.addContent(currentPathSegment)); @@ -392,7 +394,7 @@ public class UriParserImpl extends UriParser { currentPathSegment = percentDecode(pathSegments.remove(0)); switch (type.getKind()) { case SIMPLE: - if ("$value".equals(currentPathSegment)) { + if ("$value".equals(percentDecode(currentPathSegment))) { ensureLastSegment(); uriResult.setValue(true); if (uriResult.getPropertyPath().size() == 1) { @@ -428,7 +430,7 @@ public class UriParserImpl extends UriParser { } private void checkCount() throws UriSyntaxException { - if ("$count".equals(currentPathSegment)) { + if ("$count".equals(percentDecode(currentPathSegment))) { if (pathSegments.isEmpty()) { uriResult.setCount(true); } else { @@ -520,7 +522,7 @@ public class UriParserImpl extends UriParser { if (!pathSegments.isEmpty()) { if (uriResult.getUriType() == UriType.URI14) { currentPathSegment = pathSegments.remove(0); - if ("$value".equals(currentPathSegment)) { + if ("$value".equals(percentDecode(currentPathSegment))) { uriResult.setValue(true); } else { throw new UriSyntaxException(UriSyntaxException.INVALIDSEGMENT.addContent(currentPathSegment)); @@ -532,15 +534,16 @@ public class UriParserImpl extends UriParser { private void distributeQueryParameters(final Map<String, List<String>> queryParameters) throws UriSyntaxException { for (final String queryOptionString : queryParameters.keySet()) { + final String decodedString = percentDecode(queryOptionString); final List<String> valueList = queryParameters.get(queryOptionString); if (valueList.size() >= 1) { String value = valueList.get(0); - - if (queryOptionString.startsWith("$")) { + + if (decodedString.startsWith("$")) { SystemQueryOption queryOption; try { - queryOption = SystemQueryOption.valueOf(queryOptionString); + queryOption = SystemQueryOption.valueOf(decodedString); } catch (IllegalArgumentException e) { throw new UriSyntaxException(UriSyntaxException.INVALIDSYSTEMQUERYOPTION.addContent(queryOptionString), e); } @@ -555,7 +558,7 @@ public class UriParserImpl extends UriParser { } } } else { - otherQueryParameters.put(queryOptionString, value); + otherQueryParameters.put(decodedString, value); } } else { throw new UriSyntaxException(UriSyntaxException.INVALIDNULLVALUE.addContent(queryOptionString)); http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/39e774ba/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/UriParserTest.java ---------------------------------------------------------------------- diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/UriParserTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/UriParserTest.java index 0c64844..d2b57d2 100644 --- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/UriParserTest.java +++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/UriParserTest.java @@ -130,7 +130,17 @@ public class UriParserTest extends BaseTest { assertEquals(1, pathSegments.size()); assertEquals("$metadata", pathSegments.get(0).getPath()); } - + + @Test + public void copyPathSegmentsTestEncoded() throws Exception { + List<PathSegment> pathSegments = new ArrayList<PathSegment>(); + pathSegments.add(new ODataPathSegmentImpl("$metadata", null)); + UriInfoImpl result = (UriInfoImpl) new UriParserImpl(edm).parse(pathSegments, + Collections.<String, String> emptyMap()); + assertNotNull(result); + assertEquals(UriType.URI8, result.getUriType()); + } + @Test public void parseNonsense() throws Exception { parseWrongUri("/bla", UriNotMatchingException.NOTFOUND); @@ -291,7 +301,19 @@ public class UriParserTest extends BaseTest { assertEquals("1", result.getKeyPredicates().get(0).getLiteral()); assertEquals("EmployeeId", result.getKeyPredicates().get(0).getProperty().getName()); } + + @Test + public void parseEmployeesEntityWithKeyCountEncoded() throws Exception { + UriInfoImpl result = parse("/Employees('1')/%24count"); + assertEquals("Employees", result.getTargetEntitySet().getName()); + assertEquals(UriType.URI16, result.getUriType()); + assertTrue(result.isCount()); + assertEquals(1, result.getKeyPredicates().size()); + assertEquals("1", result.getKeyPredicates().get(0).getLiteral()); + assertEquals("EmployeeId", result.getKeyPredicates().get(0).getProperty().getName()); + } + @Test public void parseEmployeesSimpleProperty() throws Exception { UriInfoImpl result = parse("/Employees('1')/EmployeeName"); @@ -310,7 +332,17 @@ public class UriParserTest extends BaseTest { assertEquals("EmployeeName", result.getPropertyPath().get(0).getName()); assertTrue(result.isValue()); } - + + @Test + public void parseEmployeesSimplePropertyValueEncoded() throws Exception { + UriInfoImpl result = parse("/Employees('1')/EmployeeName/%24value"); + assertNull(result.getEntityContainer().getName()); + assertEquals("Employees", result.getTargetEntitySet().getName()); + assertEquals(UriType.URI5, result.getUriType()); + assertEquals("EmployeeName", result.getPropertyPath().get(0).getName()); + assertTrue(result.isValue()); + } + @Test public void parseEmployeesComplexProperty() throws Exception { UriInfoImpl result = parse("/Employees('1')/Location"); @@ -403,7 +435,15 @@ public class UriParserTest extends BaseTest { assertTrue(result.isLinks()); assertEquals(UriType.URI7B, result.getUriType()); } - + + @Test + public void parseNavigationPropertyWithLinksManyEncoded() throws Exception { + UriInfoImpl result = parse("/Managers('1')/%24links/nm_Employees"); + assertEquals("Employees", result.getTargetEntitySet().getName()); + assertTrue(result.isLinks()); + assertEquals(UriType.URI7B, result.getUriType()); + } + @Test public void parseNavigationPropertyWithManagersCount() throws Exception { UriInfoImpl result = parse("/Employees('1')/ne_Manager/$count"); @@ -591,7 +631,12 @@ public class UriParserTest extends BaseTest { assertEquals("MaximalAge", result.getFunctionImport().getName()); assertTrue(result.isValue()); assertEquals(UriType.URI14, result.getUriType()); - + + result = parse("MaximalAge/%24value"); + assertEquals("MaximalAge", result.getFunctionImport().getName()); + assertTrue(result.isValue()); + assertEquals(UriType.URI14, result.getUriType()); + result = parse("MostCommonLocation"); assertEquals("MostCommonLocation", result.getFunctionImport().getName()); assertEquals(UriType.URI12, result.getUriType()); @@ -646,7 +691,16 @@ public class UriParserTest extends BaseTest { assertEquals("abc", result.getSkipToken()); assertEquals(2, result.getSkip().intValue()); assertEquals(1, result.getTop().intValue()); - + + result = parse("Employees?$format=json&%24inlinecount=allpages&%24skiptoken=abc&%24skip=2&$top=1"); + assertEquals("Employees", result.getTargetEntitySet().getName()); + assertEquals(UriType.URI1, result.getUriType()); + assertEquals("json", result.getFormat()); + assertEquals(InlineCount.ALLPAGES, result.getInlineCount()); + assertEquals("abc", result.getSkipToken()); + assertEquals(2, result.getSkip().intValue()); + assertEquals(1, result.getTop().intValue()); + result = parse("Employees?$format=atom&$inlinecount=none&$skip=0&$top=0"); assertEquals("Employees", result.getTargetEntitySet().getName()); assertEquals(UriType.URI1, result.getUriType()); @@ -824,7 +878,13 @@ public class UriParserTest extends BaseTest { assertEquals(UriType.URI1, result.getUriType()); assertEquals(1, result.getSelect().size()); assertEquals("EmployeeName", result.getSelect().get(0).getProperty().getName()); - + + result = parse("Employees?%24select=EmployeeName"); + assertEquals("Employees", result.getTargetEntitySet().getName()); + assertEquals(UriType.URI1, result.getUriType()); + assertEquals(1, result.getSelect().size()); + assertEquals("EmployeeName", result.getSelect().get(0).getProperty().getName()); + result = parse("Employees?$select=*"); assertEquals("Employees", result.getTargetEntitySet().getName()); assertEquals(UriType.URI1, result.getUriType()); @@ -910,6 +970,15 @@ public class UriParserTest extends BaseTest { assertEquals("Employees", result.getExpand().get(0).get(0).getTargetEntitySet().getName()); assertEquals(result.getTargetEntitySet().getEntityType().getProperty("nm_Employees"), result.getExpand().get(0) .get(0).getNavigationProperty()); + + result = parse("Managers('1')?%24expand=nm_Employees"); + assertEquals("Managers", result.getTargetEntitySet().getName()); + assertEquals(UriType.URI2, result.getUriType()); + assertEquals(1, result.getExpand().size()); + assertEquals(1, result.getExpand().get(0).size()); + assertEquals("Employees", result.getExpand().get(0).get(0).getTargetEntitySet().getName()); + assertEquals(result.getTargetEntitySet().getEntityType().getProperty("nm_Employees"), result.getExpand().get(0) + .get(0).getNavigationProperty()); } @Test http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/39e774ba/odata2-lib/odata-fit/src/test/java/org/apache/olingo/odata2/fit/basic/BasicBatchTest.java ---------------------------------------------------------------------- diff --git a/odata2-lib/odata-fit/src/test/java/org/apache/olingo/odata2/fit/basic/BasicBatchTest.java b/odata2-lib/odata-fit/src/test/java/org/apache/olingo/odata2/fit/basic/BasicBatchTest.java index b57e1e6..0dfec68 100644 --- a/odata2-lib/odata-fit/src/test/java/org/apache/olingo/odata2/fit/basic/BasicBatchTest.java +++ b/odata2-lib/odata-fit/src/test/java/org/apache/olingo/odata2/fit/basic/BasicBatchTest.java @@ -135,6 +135,30 @@ public class BasicBatchTest extends AbstractBasicTest { } @Test + public void testBatchUriEncoded() throws Exception { + final HttpPost post = new HttpPost(URI.create(getEndpoint().toString() + "%24batch")); + post.setHeader("Content-Type", "multipart/mixed;boundary=batch_98c1-8b13-36bb"); + HttpEntity entity = new StringEntity(REQUEST_PAYLOAD); + post.setEntity(entity); + HttpResponse response = getHttpClient().execute(post); + + assertNotNull(response); + assertEquals(202, response.getStatusLine().getStatusCode()); + assertEquals("HTTP/1.1", response.getProtocolVersion().toString()); + assertTrue(response.containsHeader("Content-Length")); + assertTrue(response.containsHeader("Content-Type")); + assertTrue(response.containsHeader("DataServiceVersion")); + assertTrue(response.getEntity().getContentType().getValue().matches(REG_EX)); + assertNotNull(response.getEntity().getContent()); + + String body = StringHelper.inputStreamToString(response.getEntity().getContent(), true); + assertTrue(body.contains("Content-Id: mimeHeaderContentId1")); + assertTrue(body.contains("Content-Id: requestHeaderContentId1")); + assertTrue(body.contains("Content-Id: mimeHeaderContentId2")); + assertTrue(body.contains("Content-Id: requestHeaderContentId2")); + } + + @Test public void testBatchInvalidContentTypeForPut() throws Exception { final HttpPost post = new HttpPost(URI.create(getEndpoint().toString() + "$batch")); post.setHeader("Content-Type", "multipart/mixed;boundary=batch_98c1-8b13-36bb"); http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/39e774ba/odata2-lib/odata-fit/src/test/java/org/apache/olingo/odata2/fit/basic/ContentNegotiationDollarFormatTest.java ---------------------------------------------------------------------- diff --git a/odata2-lib/odata-fit/src/test/java/org/apache/olingo/odata2/fit/basic/ContentNegotiationDollarFormatTest.java b/odata2-lib/odata-fit/src/test/java/org/apache/olingo/odata2/fit/basic/ContentNegotiationDollarFormatTest.java index 5831f82..f8aee5b 100644 --- a/odata2-lib/odata-fit/src/test/java/org/apache/olingo/odata2/fit/basic/ContentNegotiationDollarFormatTest.java +++ b/odata2-lib/odata-fit/src/test/java/org/apache/olingo/odata2/fit/basic/ContentNegotiationDollarFormatTest.java @@ -91,6 +91,18 @@ public class ContentNegotiationDollarFormatTest extends AbstractBasicTest { } @Test + public void atomFormatForServiceDocumentEncoded() throws Exception { + final HttpResponse response = executeGetRequest("?%24format=atom"); + + final String responseEntity = StringHelper.httpEntityToString(response.getEntity()); + assertEquals("Test passed.", responseEntity); + assertEquals(HttpStatusCodes.OK.getStatusCode(), response.getStatusLine().getStatusCode()); + + final Header header = response.getFirstHeader(HttpHeaders.CONTENT_TYPE); + assertEquals(HttpContentType.APPLICATION_ATOM_SVC_UTF8, header.getValue()); + } + + @Test public void formatCustom() throws Exception { final HttpResponse response = executeGetRequest("?$format=csv"); @@ -102,6 +114,17 @@ public class ContentNegotiationDollarFormatTest extends AbstractBasicTest { } @Test + public void formatCustomEncoded() throws Exception { + final HttpResponse response = executeGetRequest("?%24format=csv"); + + assertEquals(HttpStatusCodes.OK.getStatusCode(), response.getStatusLine().getStatusCode()); + + final Header header = response.getFirstHeader(HttpHeaders.CONTENT_TYPE); + assertNotNull(header); + assertEquals(CUSTOM_CONTENT_TYPE, header.getValue()); + } + + @Test public void formatNotAccepted() throws Exception { final HttpResponse response = executeGetRequest("?$format=csvOrSomethingElse"); http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/39e774ba/odata2-lib/odata-fit/src/test/java/org/apache/olingo/odata2/fit/basic/MetadataTest.java ---------------------------------------------------------------------- diff --git a/odata2-lib/odata-fit/src/test/java/org/apache/olingo/odata2/fit/basic/MetadataTest.java b/odata2-lib/odata-fit/src/test/java/org/apache/olingo/odata2/fit/basic/MetadataTest.java index 2168086..af71ed2 100644 --- a/odata2-lib/odata-fit/src/test/java/org/apache/olingo/odata2/fit/basic/MetadataTest.java +++ b/odata2-lib/odata-fit/src/test/java/org/apache/olingo/odata2/fit/basic/MetadataTest.java @@ -62,5 +62,13 @@ public class MetadataTest extends AbstractBasicTest { final String payload = StringHelper.inputStreamToString(response.getEntity().getContent()); assertEquals("metadata", payload); } + + @Test + public void readMetadataEncoded() throws ClientProtocolException, IOException, ODataException { + final HttpResponse response = executeGetRequest("%24metadata"); + assertEquals(HttpStatusCodes.OK.getStatusCode(), response.getStatusLine().getStatusCode()); + final String payload = StringHelper.inputStreamToString(response.getEntity().getContent()); + assertEquals("metadata", payload); + } }
