Repository: olingo-odata4 Updated Branches: refs/heads/master 74a2da7d5 -> 4a51d1642
OLINGO-1046: allowing bad white space where OData specificationa allows during the URL parsing Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/2751c130 Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/2751c130 Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/2751c130 Branch: refs/heads/master Commit: 2751c130e24506ccd1ba5da14b7eeef1863a0fc3 Parents: 7e262c8 Author: Ramesh Reddy <[email protected]> Authored: Thu Apr 20 11:07:26 2017 -0500 Committer: Ramesh Reddy <[email protected]> Committed: Thu Apr 20 11:07:26 2017 -0500 ---------------------------------------------------------------------- .../server/core/uri/parser/ExpandParser.java | 1 + .../core/uri/parser/ExpressionParser.java | 41 +++++++++++++++++++- .../server/core/uri/parser/ParserHelper.java | 4 ++ .../server/core/uri/parser/SearchParser.java | 2 + .../server/core/uri/parser/UriTokenizer.java | 2 +- .../core/uri/parser/ExpressionParserTest.java | 10 +++++ 6 files changed, 58 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2751c130/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java index 53a14d7..60e858d 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java @@ -251,6 +251,7 @@ public class ExpandParser { } else if (tokenizer.next(TokenKind.SEARCH)) { ParserHelper.requireNext(tokenizer, TokenKind.EQ); + ParserHelper.bws(tokenizer); systemQueryOption = new SearchParser().parse(tokenizer); } else if (!forRef && !forCount && tokenizer.next(TokenKind.SELECT)) { http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2751c130/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java index 7a34095..29ef5cb 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java @@ -254,12 +254,15 @@ public class ExpressionParser { // The TokenKind 'IsOfMethod' consumes also the opening parenthesis. // The first parameter could be an expression or a type literal. List<Expression> parameters = new ArrayList<Expression>(); + ParserHelper.bws(tokenizer); parameters.add(parseExpression()); if (!(parameters.get(0) instanceof TypeLiteral)) { // The first parameter is not a type literal, so there must be a second parameter. + ParserHelper.bws(tokenizer); ParserHelper.requireNext(tokenizer, TokenKind.COMMA); + ParserHelper.bws(tokenizer); parameters.add(parseExpression()); - + ParserHelper.bws(tokenizer); // The second parameter must be a type literal. if (!(parameters.get(1) instanceof TypeLiteral)) { throw new UriParserSemanticException("Type literal expected.", @@ -335,7 +338,9 @@ public class ExpressionParser { private Expression parseExprValue() throws UriParserException, UriValidationException { if (tokenizer.next(TokenKind.OPEN)) { + ParserHelper.bws(tokenizer); final Expression expression = parseExpression(); + ParserHelper.bws(tokenizer); ParserHelper.requireNext(tokenizer, TokenKind.CLOSE); return expression; } @@ -441,6 +446,7 @@ public class ExpressionParser { case NOW: case MAXDATETIME: case MINDATETIME: + ParserHelper.bws(tokenizer); break; // Must have one parameter. @@ -448,7 +454,9 @@ public class ExpressionParser { case TOLOWER: case TOUPPER: case TRIM: + ParserHelper.bws(tokenizer); final Expression stringParameter = parseExpression(); + ParserHelper.bws(tokenizer); checkType(stringParameter, EdmPrimitiveTypeKind.String); checkNoCollection(stringParameter); parameters.add(stringParameter); @@ -456,7 +464,9 @@ public class ExpressionParser { case YEAR: case MONTH: case DAY: + ParserHelper.bws(tokenizer); final Expression dateParameter = parseExpression(); + ParserHelper.bws(tokenizer); checkType(dateParameter, EdmPrimitiveTypeKind.Date, EdmPrimitiveTypeKind.DateTimeOffset); checkNoCollection(dateParameter); parameters.add(dateParameter); @@ -465,7 +475,9 @@ public class ExpressionParser { case MINUTE: case SECOND: case FRACTIONALSECONDS: + ParserHelper.bws(tokenizer); final Expression timeParameter = parseExpression(); + ParserHelper.bws(tokenizer); checkType(timeParameter, EdmPrimitiveTypeKind.TimeOfDay, EdmPrimitiveTypeKind.DateTimeOffset); checkNoCollection(timeParameter); parameters.add(timeParameter); @@ -473,13 +485,17 @@ public class ExpressionParser { case DATE: case TIME: case TOTALOFFSETMINUTES: + ParserHelper.bws(tokenizer); final Expression dateTimeParameter = parseExpression(); + ParserHelper.bws(tokenizer); checkType(dateTimeParameter, EdmPrimitiveTypeKind.DateTimeOffset); checkNoCollection(dateTimeParameter); parameters.add(dateTimeParameter); break; case TOTALSECONDS: + ParserHelper.bws(tokenizer); final Expression durationParameter = parseExpression(); + ParserHelper.bws(tokenizer); checkType(durationParameter, EdmPrimitiveTypeKind.Duration); checkNoCollection(durationParameter); parameters.add(durationParameter); @@ -487,14 +503,18 @@ public class ExpressionParser { case ROUND: case FLOOR: case CEILING: + ParserHelper.bws(tokenizer); final Expression decimalParameter = parseExpression(); + ParserHelper.bws(tokenizer); checkType(decimalParameter, EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, EdmPrimitiveTypeKind.Double); checkNoCollection(decimalParameter); parameters.add(decimalParameter); break; case GEOLENGTH: + ParserHelper.bws(tokenizer); final Expression geoParameter = parseExpression(); + ParserHelper.bws(tokenizer); checkType(geoParameter, EdmPrimitiveTypeKind.GeographyLineString, EdmPrimitiveTypeKind.GeometryLineString); checkNoCollection(geoParameter); @@ -507,35 +527,47 @@ public class ExpressionParser { case STARTSWITH: case INDEXOF: case CONCAT: + ParserHelper.bws(tokenizer); final Expression stringParameter1 = parseExpression(); checkType(stringParameter1, EdmPrimitiveTypeKind.String); checkNoCollection(stringParameter1); parameters.add(stringParameter1); + ParserHelper.bws(tokenizer); ParserHelper.requireNext(tokenizer, TokenKind.COMMA); + ParserHelper.bws(tokenizer); final Expression stringParameter2 = parseExpression(); + ParserHelper.bws(tokenizer); checkType(stringParameter2, EdmPrimitiveTypeKind.String); checkNoCollection(stringParameter2); parameters.add(stringParameter2); break; case GEODISTANCE: + ParserHelper.bws(tokenizer); final Expression geoParameter1 = parseExpression(); checkType(geoParameter1, EdmPrimitiveTypeKind.GeographyPoint, EdmPrimitiveTypeKind.GeometryPoint); checkNoCollection(geoParameter1); parameters.add(geoParameter1); + ParserHelper.bws(tokenizer); ParserHelper.requireNext(tokenizer, TokenKind.COMMA); + ParserHelper.bws(tokenizer); final Expression geoParameter2 = parseExpression(); + ParserHelper.bws(tokenizer); checkType(geoParameter2, EdmPrimitiveTypeKind.GeographyPoint, EdmPrimitiveTypeKind.GeometryPoint); checkNoCollection(geoParameter2); parameters.add(geoParameter2); break; case GEOINTERSECTS: + ParserHelper.bws(tokenizer); final Expression geoPointParameter = parseExpression(); checkType(geoPointParameter, EdmPrimitiveTypeKind.GeographyPoint, EdmPrimitiveTypeKind.GeometryPoint); checkNoCollection(geoPointParameter); parameters.add(geoPointParameter); + ParserHelper.bws(tokenizer); ParserHelper.requireNext(tokenizer, TokenKind.COMMA); + ParserHelper.bws(tokenizer); final Expression geoPolygonParameter = parseExpression(); + ParserHelper.bws(tokenizer); checkType(geoPolygonParameter, EdmPrimitiveTypeKind.GeographyPolygon, EdmPrimitiveTypeKind.GeometryPolygon); checkNoCollection(geoPolygonParameter); @@ -544,16 +576,23 @@ public class ExpressionParser { // Can have two or three parameters. case SUBSTRING: + ParserHelper.bws(tokenizer); final Expression parameterFirst = parseExpression(); checkType(parameterFirst, EdmPrimitiveTypeKind.String); checkNoCollection(parameterFirst); parameters.add(parameterFirst); + ParserHelper.bws(tokenizer); ParserHelper.requireNext(tokenizer, TokenKind.COMMA); + ParserHelper.bws(tokenizer); final Expression parameterSecond = parseExpression(); + ParserHelper.bws(tokenizer); checkIntegerType(parameterSecond); parameters.add(parameterSecond); + ParserHelper.bws(tokenizer); if (tokenizer.next(TokenKind.COMMA)) { + ParserHelper.bws(tokenizer); final Expression parameterThird = parseExpression(); + ParserHelper.bws(tokenizer); checkIntegerType(parameterThird); parameters.add(parameterThird); } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2751c130/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java index 498ba18..edaabae 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java @@ -108,6 +108,10 @@ public class ParserHelper { requireNext(tokenizer, TokenKind.EOF); } + protected static boolean bws(UriTokenizer tokenizer) { + return tokenizer.nextWhitespace(); + } + protected static TokenKind next(UriTokenizer tokenizer, final TokenKind... kinds) { for (final TokenKind kind : kinds) { if (tokenizer.next(kind)) { http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2751c130/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SearchParser.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SearchParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SearchParser.java index 8d046a5..2a6800e 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SearchParser.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SearchParser.java @@ -71,7 +71,9 @@ public class SearchParser { private SearchExpression processTerm(UriTokenizer tokenizer) throws SearchParserException { if (tokenizer.next(TokenKind.OPEN)) { + ParserHelper.bws(tokenizer); final SearchExpression expr = processExprOr(tokenizer); + ParserHelper.bws(tokenizer); if (!tokenizer.next(TokenKind.CLOSE)) { throw new SearchParserException("Missing close parenthesis after open parenthesis.", SearchParserException.MessageKeys.MISSING_CLOSE); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2751c130/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java index 6654df9..37d49ca 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java @@ -801,7 +801,7 @@ public class UriTokenizer { * otherwise leaves the index unchanged. * @return whether whitespace characters have been found at the current index */ - private boolean nextWhitespace() { + boolean nextWhitespace() { int count = 0; while (nextCharacter(' ') || nextCharacter('\t')) { count++; http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2751c130/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java index 1fce7b5..5646a4e 100644 --- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java +++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java @@ -149,6 +149,10 @@ public class ExpressionParserTest { expression = parseExpression("-(5 add 5)"); assertEquals("{MINUS {5 ADD 5}}", expression.toString()); + + expression = parseExpression("-( 5 add 5\t)"); + assertEquals("{MINUS {5 ADD 5}}", expression.toString()); + } @Test @@ -191,6 +195,8 @@ public class ExpressionParserTest { wrongExpression("trim()"); wrongExpression("trim(1)"); wrongExpression("ceiling('1.2')"); + + assertEquals("{trim ['abc']}", parseExpression("trim( 'abc' )").toString()); } @Test @@ -209,6 +215,8 @@ public class ExpressionParserTest { wrongExpression("concat('a')"); wrongExpression("endswith('a',1)"); + + assertEquals("{concat ['a', 'b']}", parseExpression("concat( 'a' ,\t'b' )").toString()); } @Test @@ -227,6 +235,8 @@ public class ExpressionParserTest { wrongExpression("substring(1,2)"); wrongExpression("cast(1,2)"); wrongExpression("isof(Edm.Int16,2)"); + + assertEquals("{cast [42, Edm.SByte]}", parseExpression("cast( 42\t, Edm.SByte )").toString()); } private void parseMethod(TokenKind kind, String... parameters) throws UriParserException, UriValidationException {
