OLINGO-1046: allowing bad white space where OData specificationa allows during the URL parsing
This commit is contained in:
parent
7e262c8d07
commit
2751c130e2
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue