[OLINGO-730] UriParser fix
This commit is contained in:
parent
4fd79b3c37
commit
9235cb2b05
|
@ -26,9 +26,9 @@ lexer grammar UriLexer;
|
||||||
QM : '?' -> pushMode(MODE_QUERY); //first query parameter
|
QM : '?' -> pushMode(MODE_QUERY); //first query parameter
|
||||||
AMP : '&' -> pushMode(MODE_QUERY); //more query parameters
|
AMP : '&' -> pushMode(MODE_QUERY); //more query parameters
|
||||||
STRING : '\'' -> more, pushMode(MODE_STRING); //reads up to next single '
|
STRING : '\'' -> more, pushMode(MODE_STRING); //reads up to next single '
|
||||||
QUOTATION_MARK : ('\u0022' | '%22') -> more, pushMode(MODE_JSON_STRING); //reads up to next unescaped "
|
QUOTATION_MARK : '\u0022' -> more, pushMode(MODE_JSON_STRING); //reads up to next unescaped "
|
||||||
SEARCH_INLINE : '$search' -> pushMode(MODE_SYSTEM_QUERY_SEARCH); //
|
SEARCH_INLINE : '$search' -> pushMode(MODE_SYSTEM_QUERY_SEARCH); //
|
||||||
FRAGMENT : '#' -> pushMode(MODE_FRAGMENT); //
|
FRAGMENT : '#' -> pushMode(MODE_FRAGMENT); //
|
||||||
|
|
||||||
GEOGRAPHY : G E O G R A P H Y SQUOTE -> pushMode(MODE_ODATA_GEO); //TODO make case insensitive
|
GEOGRAPHY : G E O G R A P H Y SQUOTE -> pushMode(MODE_ODATA_GEO); //TODO make case insensitive
|
||||||
GEOMETRY : G E O M E T R Y SQUOTE -> pushMode(MODE_ODATA_GEO);
|
GEOMETRY : G E O M E T R Y SQUOTE -> pushMode(MODE_ODATA_GEO);
|
||||||
|
@ -55,28 +55,28 @@ fragment Y : 'Y'|'y';
|
||||||
fragment Z : 'Z'|'z';
|
fragment Z : 'Z'|'z';
|
||||||
|
|
||||||
//special chars
|
//special chars
|
||||||
OPEN : '(' | '%28';
|
OPEN : '(';
|
||||||
CLOSE : ')' | '%29';
|
CLOSE : ')';
|
||||||
COMMA : ',' | '%2C';
|
COMMA : ',';
|
||||||
SLASH : '/';
|
SLASH : '/';
|
||||||
POINT : '.';
|
POINT : '.';
|
||||||
AT : '@';
|
AT : '@';
|
||||||
EQ : '=' ;
|
EQ : '=' ;
|
||||||
STAR : '*';
|
STAR : '*';
|
||||||
SEMI : ';' | '%3b';
|
SEMI : ';';
|
||||||
COLON : ':';
|
COLON : ':';
|
||||||
|
|
||||||
EQ_sq : '=' -> type(EQ);
|
EQ_sq : '=' -> type(EQ);
|
||||||
AMP_sq : '&' -> type(AMP), popMode;
|
AMP_sq : '&' -> type(AMP), popMode;
|
||||||
fragment WS : ( ' ' | '%09' | '%20' | '%09' );
|
fragment WS : ( ' ' | '\u0009' );
|
||||||
WSP : WS+;
|
WSP : WS+;
|
||||||
|
|
||||||
//JSON support
|
//JSON support
|
||||||
BEGIN_OBJECT : WS* ( '{' / '%7B' ) WS*;
|
BEGIN_OBJECT : WS* '{' WS*;
|
||||||
END_OBJECT : WS* ( '}' / '%7D' ) WS*;
|
END_OBJECT : WS* '}' WS*;
|
||||||
|
|
||||||
BEGIN_ARRAY : WS* ( '[' / '%5B' ) WS*;
|
BEGIN_ARRAY : WS* '[' WS*;
|
||||||
END_ARRAY : WS* ( ']' / '%5D' ) WS*;
|
END_ARRAY : WS* ']' WS*;
|
||||||
|
|
||||||
|
|
||||||
//alpha stuff
|
//alpha stuff
|
||||||
|
@ -132,7 +132,7 @@ BOOLEAN : T R U E | F A L S E;
|
||||||
PLUS : '+';
|
PLUS : '+';
|
||||||
|
|
||||||
MINUS : '-';
|
MINUS : '-';
|
||||||
SIGN : PLUS | '%2B' | '-';
|
SIGN : PLUS | '-';
|
||||||
INT : SIGN? DIGITS;
|
INT : SIGN? DIGITS;
|
||||||
DECIMAL : INT '.' DIGITS (('e'|'E') SIGN? DIGITS)?;
|
DECIMAL : INT '.' DIGITS (('e'|'E') SIGN? DIGITS)?;
|
||||||
NANINFINITY : 'NaN' | '-INF' | 'INF';
|
NANINFINITY : 'NaN' | '-INF' | 'INF';
|
||||||
|
@ -334,10 +334,10 @@ AND_sqc : 'AND' -> type(AND);
|
||||||
OR_sqc : 'OR' -> type(OR);
|
OR_sqc : 'OR' -> type(OR);
|
||||||
EQ_sqc : '=' -> type(EQ);
|
EQ_sqc : '=' -> type(EQ);
|
||||||
|
|
||||||
fragment WS_sqc : ( ' ' | '\u0009' | '%20' | '%09' );
|
fragment WS_sqc : ( ' ' | '\u0009');
|
||||||
WSP_sqc : WS_sqc+ -> type(WSP);
|
WSP_sqc : WS_sqc+ -> type(WSP);
|
||||||
|
|
||||||
QUOTATION_MARK_sqc : '\u0022' | '%22';
|
QUOTATION_MARK_sqc : '\u0022';
|
||||||
|
|
||||||
SEARCHWORD : ('a'..'z'|'A'..'Z')+;
|
SEARCHWORD : ('a'..'z'|'A'..'Z')+;
|
||||||
SEARCHPHRASE : QUOTATION_MARK_sqc ~["]* QUOTATION_MARK_sqc -> popMode;
|
SEARCHPHRASE : QUOTATION_MARK_sqc ~["]* QUOTATION_MARK_sqc -> popMode;
|
||||||
|
@ -356,7 +356,7 @@ mode MODE_JSON_STRING;
|
||||||
// Any """ characters inside a string are escaped with "\".
|
// Any """ characters inside a string are escaped with "\".
|
||||||
//;==============================================================================
|
//;==============================================================================
|
||||||
|
|
||||||
STRING_IN_JSON : ('\\"' | ~[\u0022] )* ('"' | '%22') -> popMode;
|
STRING_IN_JSON : ('\\"' | ~[\u0022] )* '"' -> popMode;
|
||||||
|
|
||||||
//;==============================================================================
|
//;==============================================================================
|
||||||
mode MODE_ODATA_GEO;
|
mode MODE_ODATA_GEO;
|
||||||
|
@ -379,21 +379,21 @@ fragment T_ : 't'|'T';
|
||||||
fragment U_ : 'u'|'U';
|
fragment U_ : 'u'|'U';
|
||||||
fragment Y_ : 'y'|'Y';
|
fragment Y_ : 'y'|'Y';
|
||||||
|
|
||||||
fragment SP_g : ' ';//'\u0020'; // a simple space
|
fragment SP_g : ' '; //'\u0020'; // a simple space
|
||||||
fragment WS_g : ( ' ' | '%20' | '%09' );
|
fragment WS_g : ( ' ' | '\u0009' );
|
||||||
|
|
||||||
OPEN_g : ('(' | '%28') -> type(OPEN);
|
OPEN_g : '(' -> type(OPEN);
|
||||||
CLOSE_g : (')' | '%29') -> type(CLOSE);
|
CLOSE_g : ')' -> type(CLOSE);
|
||||||
COMMA_g : (',' | '%2C') -> type(COMMA);
|
COMMA_g : ',' -> type(COMMA);
|
||||||
WSP_g : WS_g+ -> type(WSP);
|
WSP_g : WS_g+ -> type(WSP);
|
||||||
POINT_g : '.' -> type(POINT);
|
POINT_g : '.' -> type(POINT);
|
||||||
AT_g : '@' -> type(AT);
|
AT_g : '@' -> type(AT);
|
||||||
SEMI_g : (';' | '%3B') -> type(SEMI);
|
SEMI_g : ';' -> type(SEMI);
|
||||||
EQ_g : '=' -> type(EQ);
|
EQ_g : '=' -> type(EQ);
|
||||||
|
|
||||||
fragment DIGIT_g : '0'..'9';
|
fragment DIGIT_g : '0'..'9';
|
||||||
fragment DIGITS_g : DIGIT_g+;
|
fragment DIGITS_g : DIGIT_g+;
|
||||||
SIGN_g : ('+' | '%2B' |'-') -> type(SIGN);
|
SIGN_g : ('+' | '-') -> type(SIGN);
|
||||||
INT_g : SIGN_g? DIGITS_g -> type(INT);
|
INT_g : SIGN_g? DIGITS_g -> type(INT);
|
||||||
DECIMAL_g : 'SS' INT_g '.' DIGITS_g (('e'|'E') SIGN_g? DIGITS_g)? -> type(DECIMAL);
|
DECIMAL_g : 'SS' INT_g '.' DIGITS_g (('e'|'E') SIGN_g? DIGITS_g)? -> type(DECIMAL);
|
||||||
COLLECTION_g : C_ O_ L_ L_ E_ C_ T_ I_ O_ N_ -> type(COLLECTION);
|
COLLECTION_g : C_ O_ L_ L_ E_ C_ T_ I_ O_ N_ -> type(COLLECTION);
|
||||||
|
|
|
@ -457,6 +457,11 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
|
||||||
}
|
}
|
||||||
} else if (property instanceof EdmNavigationProperty) {
|
} else if (property instanceof EdmNavigationProperty) {
|
||||||
// create navigation property
|
// create navigation property
|
||||||
|
if(ctx.getParent() instanceof ExpandPathContext && ctx.vlNVO.size() > 0) {
|
||||||
|
throw wrap(new UriParserSemanticException("Navigation properties in expand system query options must not"
|
||||||
|
+ " be followed a an key", UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED));
|
||||||
|
}
|
||||||
|
|
||||||
UriResourceNavigationPropertyImpl navigationResource = new UriResourceNavigationPropertyImpl()
|
UriResourceNavigationPropertyImpl navigationResource = new UriResourceNavigationPropertyImpl()
|
||||||
.setNavigationProperty((EdmNavigationProperty) property);
|
.setNavigationProperty((EdmNavigationProperty) property);
|
||||||
context.contextUriInfo.addResourcePart(navigationResource);
|
context.contextUriInfo.addResourcePart(navigationResource);
|
||||||
|
@ -1215,7 +1220,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
|
||||||
// set tmp context
|
// set tmp context
|
||||||
context.contextExpandItemPath = expandItem;
|
context.contextExpandItemPath = expandItem;
|
||||||
context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.resource);
|
context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.resource);
|
||||||
|
|
||||||
super.visitExpandPath(ctx);
|
super.visitExpandPath(ctx);
|
||||||
|
|
||||||
EdmType startType = removeUriResourceStartingTypeFilterImpl(context.contextUriInfo);
|
EdmType startType = removeUriResourceStartingTypeFilterImpl(context.contextUriInfo);
|
||||||
|
@ -1769,6 +1774,11 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
|
||||||
if (ctx.vlNVO.size() > 0) {
|
if (ctx.vlNVO.size() > 0) {
|
||||||
// check for keyPredicates
|
// check for keyPredicates
|
||||||
if (pathInfoSegment instanceof UriResourceWithKeysImpl) {
|
if (pathInfoSegment instanceof UriResourceWithKeysImpl) {
|
||||||
|
if(ctx.vlNVO.size() > 1) {
|
||||||
|
throw wrap(new UriParserSemanticException("More than one key predicates found",
|
||||||
|
UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES));
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
List<UriParameterImpl> list = (List<UriParameterImpl>) ctx.vlNVO.get(0).accept(this);
|
List<UriParameterImpl> list = (List<UriParameterImpl>) ctx.vlNVO.get(0).accept(this);
|
||||||
((UriResourceWithKeysImpl) pathInfoSegment)
|
((UriResourceWithKeysImpl) pathInfoSegment)
|
||||||
|
|
|
@ -22,11 +22,6 @@ import java.io.UnsupportedEncodingException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.apache.olingo.commons.api.edm.Edm;
|
import org.apache.olingo.commons.api.edm.Edm;
|
||||||
import org.apache.olingo.commons.api.edm.EdmEntityContainer;
|
|
||||||
import org.apache.olingo.commons.api.edm.EdmEntitySet;
|
|
||||||
import org.apache.olingo.commons.api.edm.EdmEntityType;
|
|
||||||
import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
|
|
||||||
import org.apache.olingo.commons.api.edm.FullQualifiedName;
|
|
||||||
import org.apache.olingo.commons.api.http.HttpContentType;
|
import org.apache.olingo.commons.api.http.HttpContentType;
|
||||||
import org.apache.olingo.commons.core.Encoder;
|
import org.apache.olingo.commons.core.Encoder;
|
||||||
import org.apache.olingo.commons.core.edm.EdmProviderImpl;
|
import org.apache.olingo.commons.core.edm.EdmProviderImpl;
|
||||||
|
@ -51,7 +46,6 @@ import org.apache.olingo.server.tecsvc.provider.EnumTypeProvider;
|
||||||
import org.apache.olingo.server.tecsvc.provider.PropertyProvider;
|
import org.apache.olingo.server.tecsvc.provider.PropertyProvider;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.Mockito;
|
|
||||||
|
|
||||||
public class TestFullResourcePath {
|
public class TestFullResourcePath {
|
||||||
Edm edm = null;
|
Edm edm = null;
|
||||||
|
@ -5235,7 +5229,51 @@ public class TestFullResourcePath {
|
||||||
.goUpUriValidator()
|
.goUpUriValidator()
|
||||||
.isCustomParameter(0, "@A", "'2'");
|
.isCustomParameter(0, "@A", "'2'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected=UriParserException.class)
|
||||||
|
public void testDoublePercentDecoding() throws Exception {
|
||||||
|
testUri.run("ESAllPrim%252832767%29");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=UriParserException.class)
|
||||||
|
public void testMultipleKeysInResourcePath() throws Exception {
|
||||||
|
// See OLINGO-730
|
||||||
|
testUri.run("ESAllPrim(32767)(1)(2)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=UriParserException.class)
|
||||||
|
public void testSimpleKeyInExpandSystemQueryOption() throws Exception {
|
||||||
|
testUri.run("ESAllPrim(0)", "$expand=NavPropertyETTwoPrimMany(-365)($filter=PropertyString eq 'Test String1')");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=UriParserException.class)
|
||||||
|
public void testCompountKeyInExpandSystemQueryOption() throws Exception {
|
||||||
|
testUri.run("ESAllPrim(0)", "$expand=NavPropertyETTwoPrimMany(PropertyInt16=1,PropertyString=2)"
|
||||||
|
+ "($filter=PropertyString eq 'Test String1')");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=UriParserException.class)
|
||||||
|
public void testFilterSystemQueryOptionAnyWithKeyAny() throws Exception {
|
||||||
|
testUri.run("ESAllPrim", "$filter=NavPropertyETTwoPrimMany(1)"
|
||||||
|
+ "/any(d:d/PropertyInt16 eq 0)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=UriParserException.class)
|
||||||
|
public void testFilterSystemQueryOptionAnyWithKeyAll() throws Exception {
|
||||||
|
testUri.run("ESAllPrim", "$filter=NavPropertyETTwoPrimMany(1)"
|
||||||
|
+ "/all(d:d/PropertyInt16 eq 0)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNavigationPropertyWithCount() throws Exception {
|
||||||
|
testUri.run("ESKeyNav(1)/NavPropertyETTwoKeyNavMany/$count")
|
||||||
|
.goPath().at(0).isEntitySet("ESKeyNav").isKeyPredicate(0, "PropertyInt16", "1")
|
||||||
|
.at(1).isNavProperty("NavPropertyETTwoKeyNavMany", EntityTypeProvider.nameETTwoKeyNav, true)
|
||||||
|
.at(2).isCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ESKeyNav(1)/NavPropertyETTwoKeyNavMany/$count
|
||||||
|
|
||||||
public static String encode(final String decoded) throws UnsupportedEncodingException {
|
public static String encode(final String decoded) throws UnsupportedEncodingException {
|
||||||
return Encoder.encode(decoded);
|
return Encoder.encode(decoded);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue