[OLINGO-206] http method validation

This commit is contained in:
Stephan Klevenz 2014-03-25 14:34:10 +01:00
parent 3bfc3893f0
commit 9a980e88e2
2 changed files with 135 additions and 61 deletions

View File

@ -59,10 +59,22 @@ public class UriValidator {
/* propertyPrimitiveCollectionCount 18 */ { false, false, false, false, false, false, false, false, false, false, false, false }, /* propertyPrimitiveCollectionCount 18 */ { false, false, false, false, false, false, false, false, false, false, false, false },
/* propertyPrimitiveValue 19 */ { false, true , false, false, false, false, false, false, false, false, false, false }, /* propertyPrimitiveValue 19 */ { false, true , false, false, false, false, false, false, false, false, false, false },
}; };
private boolean[][] decisionMatrixForHttpMethod =
{
/* 0-FILTER 1-FORMAT 2-EXPAND 3-ID 4-COUNT 5-ORDERBY 6-SEARCH 7-SELECT 8-SKIP 9-SKIPTOKEN 10-LEVELS 11-TOP */
/* GET 0 */ { true , true , true , true, true , true , true , true , true , true , true , true },
/* POST 0 */ { true , false , true , false, false , true , false , true , false , false , true , false },
/* PUT 0 */ { false , false , false , false, false , false , false , false , false , false , false , false },
/* DELETE 0 */ { false , false , false , false, false , false, false , false, false , false , false, false },
/* PATCH 0 */ { false , false , false , false, false , false , false , false , false , false , false , false },
/* MERGE 0 */ { false , false , false , false, false , false , false , false , false , false , false , false },
};
//CHECKSTYLE:ON //CHECKSTYLE:ON
//@formatter:on //@formatter:on
private enum RowIndex { private enum RowIndexForUriType {
all(0), all(0),
batch(1), batch(1),
crossjoin(2), crossjoin(2),
@ -86,7 +98,7 @@ public class UriValidator {
private int idx; private int idx;
RowIndex(int i) { RowIndexForUriType(int i) {
idx = i; idx = i;
} }
@ -121,8 +133,29 @@ public class UriValidator {
} }
public void validate(final UriInfo uriInfo, final Edm edm) throws UriValidationException { private enum RowIndexForHttpMethod {
GET(0),
POST(1),
PUT(2),
DELETE(3),
MERGE(4),
PATCH(5);
private int idx;
RowIndexForHttpMethod(int i) {
idx = i;
}
public int getIndex() {
return idx;
}
}
public void validate(final UriInfo uriInfo, final Edm edm, String httpMethod) throws UriValidationException {
validateForHttpMethod(uriInfo, httpMethod);
validateQueryOptions(uriInfo, edm); validateQueryOptions(uriInfo, edm);
validateKeyPredicateTypes(uriInfo, edm); validateKeyPredicateTypes(uriInfo, edm);
@ -174,30 +207,30 @@ public class UriValidator {
return idx; return idx;
} }
private RowIndex rowIndex(final UriInfo uriInfo, Edm edm) throws UriValidationException { private RowIndexForUriType rowIndexForUriType(final UriInfo uriInfo, Edm edm) throws UriValidationException {
RowIndex idx; RowIndexForUriType idx;
switch (uriInfo.getKind()) { switch (uriInfo.getKind()) {
case all: case all:
idx = RowIndex.all; idx = RowIndexForUriType.all;
break; break;
case batch: case batch:
idx = RowIndex.batch; idx = RowIndexForUriType.batch;
break; break;
case crossjoin: case crossjoin:
idx = RowIndex.crossjoin; idx = RowIndexForUriType.crossjoin;
break; break;
case entityId: case entityId:
idx = RowIndex.entityId; idx = RowIndexForUriType.entityId;
break; break;
case metadata: case metadata:
idx = RowIndex.metadata; idx = RowIndexForUriType.metadata;
break; break;
case resource: case resource:
idx = rowIndexForResourceKind(uriInfo, edm); idx = rowIndexForResourceKind(uriInfo, edm);
break; break;
case service: case service:
idx = RowIndex.service; idx = RowIndexForUriType.service;
break; break;
default: default:
throw new ODataRuntimeException("Unsupported uriInfo kind: " + uriInfo.getKind()); throw new ODataRuntimeException("Unsupported uriInfo kind: " + uriInfo.getKind());
@ -206,8 +239,8 @@ public class UriValidator {
return idx; return idx;
} }
private RowIndex rowIndexForResourceKind(UriInfo uriInfo, Edm edm) throws UriValidationException { private RowIndexForUriType rowIndexForResourceKind(UriInfo uriInfo, Edm edm) throws UriValidationException {
RowIndex idx; RowIndexForUriType idx;
int lastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 1; int lastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 1;
UriResource lastPathSegment = uriInfo.getUriResourceParts().get(lastPathSegmentIndex); UriResource lastPathSegment = uriInfo.getUriResourceParts().get(lastPathSegmentIndex);
@ -229,7 +262,9 @@ public class UriValidator {
idx = rowIndexForFunction(lastPathSegment); idx = rowIndexForFunction(lastPathSegment);
break; break;
case navigationProperty: case navigationProperty:
idx = ((UriResourceNavigation) lastPathSegment).isCollection() ? RowIndex.entitySet : RowIndex.entity; idx =
((UriResourceNavigation) lastPathSegment).isCollection() ? RowIndexForUriType.entitySet
: RowIndexForUriType.entity;
break; break;
case primitiveProperty: case primitiveProperty:
idx = rowIndexForPrimitiveProperty(lastPathSegment); idx = rowIndexForPrimitiveProperty(lastPathSegment);
@ -238,10 +273,10 @@ public class UriValidator {
idx = rowIndexForRef(uriInfo, lastPathSegment); idx = rowIndexForRef(uriInfo, lastPathSegment);
break; break;
case root: case root:
idx = RowIndex.service; idx = RowIndexForUriType.service;
break; break;
case singleton: case singleton:
idx = RowIndex.entity; idx = RowIndexForUriType.entity;
break; break;
case value: case value:
idx = rowIndexForValue(uriInfo); idx = rowIndexForValue(uriInfo);
@ -253,16 +288,16 @@ public class UriValidator {
return idx; return idx;
} }
private RowIndex rowIndexForValue(UriInfo uriInfo) throws UriValidationException { private RowIndexForUriType rowIndexForValue(UriInfo uriInfo) throws UriValidationException {
RowIndex idx; RowIndexForUriType idx;
int secondLastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 2; int secondLastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 2;
UriResource secondLastPathSegment = uriInfo.getUriResourceParts().get(secondLastPathSegmentIndex); UriResource secondLastPathSegment = uriInfo.getUriResourceParts().get(secondLastPathSegmentIndex);
switch (secondLastPathSegment.getKind()) { switch (secondLastPathSegment.getKind()) {
case primitiveProperty: case primitiveProperty:
idx = RowIndex.propertyPrimitiveValue; idx = RowIndexForUriType.propertyPrimitiveValue;
break; break;
case entitySet: case entitySet:
idx = RowIndex.mediaStream; idx = RowIndexForUriType.mediaStream;
break; break;
default: default:
throw new UriValidationException("Unexpected kind in path segment before $value: " throw new UriValidationException("Unexpected kind in path segment before $value: "
@ -272,14 +307,16 @@ public class UriValidator {
return idx; return idx;
} }
private RowIndex rowIndexForRef(UriInfo uriInfo, UriResource lastPathSegment) private RowIndexForUriType rowIndexForRef(UriInfo uriInfo, UriResource lastPathSegment)
throws UriValidationException { throws UriValidationException {
RowIndex idx; RowIndexForUriType idx;
int secondLastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 2; int secondLastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 2;
UriResource secondLastPathSegment = uriInfo.getUriResourceParts().get(secondLastPathSegmentIndex); UriResource secondLastPathSegment = uriInfo.getUriResourceParts().get(secondLastPathSegmentIndex);
if (secondLastPathSegment instanceof UriResourcePartTyped) { if (secondLastPathSegment instanceof UriResourcePartTyped) {
idx = ((UriResourcePartTyped) secondLastPathSegment).isCollection() ? RowIndex.references : RowIndex.reference; idx =
((UriResourcePartTyped) secondLastPathSegment).isCollection() ? RowIndexForUriType.references
: RowIndexForUriType.reference;
} else { } else {
throw new UriValidationException("secondLastPathSegment not a class of UriResourcePartTyped: " throw new UriValidationException("secondLastPathSegment not a class of UriResourcePartTyped: "
+ lastPathSegment.getClass()); + lastPathSegment.getClass());
@ -288,13 +325,13 @@ public class UriValidator {
return idx; return idx;
} }
private RowIndex rowIndexForPrimitiveProperty(UriResource lastPathSegment) private RowIndexForUriType rowIndexForPrimitiveProperty(UriResource lastPathSegment)
throws UriValidationException { throws UriValidationException {
RowIndex idx; RowIndexForUriType idx;
if (lastPathSegment instanceof UriResourcePartTyped) { if (lastPathSegment instanceof UriResourcePartTyped) {
idx = idx =
((UriResourcePartTyped) lastPathSegment).isCollection() ? RowIndex.propertyPrimitiveCollection ((UriResourcePartTyped) lastPathSegment).isCollection() ? RowIndexForUriType.propertyPrimitiveCollection
: RowIndex.propertyPrimitive; : RowIndexForUriType.propertyPrimitive;
} else { } else {
throw new UriValidationException("lastPathSegment not a class of UriResourcePartTyped: " throw new UriValidationException("lastPathSegment not a class of UriResourcePartTyped: "
+ lastPathSegment.getClass()); + lastPathSegment.getClass());
@ -302,23 +339,23 @@ public class UriValidator {
return idx; return idx;
} }
private RowIndex rowIndexForFunction(UriResource lastPathSegment) throws UriValidationException { private RowIndexForUriType rowIndexForFunction(UriResource lastPathSegment) throws UriValidationException {
RowIndex idx; RowIndexForUriType idx;
UriResourceFunction urf = (UriResourceFunction) lastPathSegment; UriResourceFunction urf = (UriResourceFunction) lastPathSegment;
EdmReturnType rt = urf.getFunction().getReturnType(); EdmReturnType rt = urf.getFunction().getReturnType();
switch (rt.getType().getKind()) { switch (rt.getType().getKind()) {
case ENTITY: case ENTITY:
if (((EdmEntityType) rt.getType()).hasStream()) { if (((EdmEntityType) rt.getType()).hasStream()) {
idx = RowIndex.mediaStream; idx = RowIndexForUriType.mediaStream;
} else { } else {
idx = rt.isCollection() ? RowIndex.entitySet : RowIndex.entity; idx = rt.isCollection() ? RowIndexForUriType.entitySet : RowIndexForUriType.entity;
} }
break; break;
case PRIMITIVE: case PRIMITIVE:
idx = rt.isCollection() ? RowIndex.propertyPrimitiveCollection : RowIndex.propertyPrimitive; idx = rt.isCollection() ? RowIndexForUriType.propertyPrimitiveCollection : RowIndexForUriType.propertyPrimitive;
break; break;
case COMPLEX: case COMPLEX:
idx = rt.isCollection() ? RowIndex.propertyComplexCollection : RowIndex.propertyComplex; idx = rt.isCollection() ? RowIndexForUriType.propertyComplexCollection : RowIndexForUriType.propertyComplex;
break; break;
default: default:
throw new UriValidationException("Unsupported function return type: " + rt.getType().getKind()); throw new UriValidationException("Unsupported function return type: " + rt.getType().getKind());
@ -327,23 +364,12 @@ public class UriValidator {
return idx; return idx;
} }
private RowIndex rowIndexForEntitySet(UriResource lastPathSegment) throws UriValidationException { private RowIndexForUriType rowIndexForEntitySet(UriResource lastPathSegment) throws UriValidationException {
RowIndex idx; RowIndexForUriType idx;
if (lastPathSegment instanceof UriResourcePartTyped) {
idx = ((UriResourcePartTyped) lastPathSegment).isCollection() ? RowIndex.entitySet : RowIndex.entity;
} else {
throw new UriValidationException("lastPathSegment not a class of UriResourcePartTyped: "
+ lastPathSegment.getClass());
}
return idx;
}
private RowIndex rowIndexForComplexProperty(UriResource lastPathSegment) throws UriValidationException {
RowIndex idx;
if (lastPathSegment instanceof UriResourcePartTyped) { if (lastPathSegment instanceof UriResourcePartTyped) {
idx = idx =
((UriResourcePartTyped) lastPathSegment).isCollection() ? RowIndex.propertyComplexCollection ((UriResourcePartTyped) lastPathSegment).isCollection() ? RowIndexForUriType.entitySet
: RowIndex.propertyComplex; : RowIndexForUriType.entity;
} else { } else {
throw new UriValidationException("lastPathSegment not a class of UriResourcePartTyped: " throw new UriValidationException("lastPathSegment not a class of UriResourcePartTyped: "
+ lastPathSegment.getClass()); + lastPathSegment.getClass());
@ -351,23 +377,36 @@ public class UriValidator {
return idx; return idx;
} }
private RowIndex rowIndexForAction(UriResource lastPathSegment) throws UriValidationException { private RowIndexForUriType rowIndexForComplexProperty(UriResource lastPathSegment) throws UriValidationException {
RowIndex idx; RowIndexForUriType idx;
if (lastPathSegment instanceof UriResourcePartTyped) {
idx =
((UriResourcePartTyped) lastPathSegment).isCollection() ? RowIndexForUriType.propertyComplexCollection
: RowIndexForUriType.propertyComplex;
} else {
throw new UriValidationException("lastPathSegment not a class of UriResourcePartTyped: "
+ lastPathSegment.getClass());
}
return idx;
}
private RowIndexForUriType rowIndexForAction(UriResource lastPathSegment) throws UriValidationException {
RowIndexForUriType idx;
UriResourceAction ura = (UriResourceAction) lastPathSegment; UriResourceAction ura = (UriResourceAction) lastPathSegment;
EdmReturnType rt = ura.getAction().getReturnType(); EdmReturnType rt = ura.getAction().getReturnType();
switch (rt.getType().getKind()) { switch (rt.getType().getKind()) {
case ENTITY: case ENTITY:
if (((EdmEntityType) rt.getType()).hasStream()) { if (((EdmEntityType) rt.getType()).hasStream()) {
idx = RowIndex.mediaStream; idx = RowIndexForUriType.mediaStream;
} else { } else {
idx = rt.isCollection() ? RowIndex.entitySet : RowIndex.entity; idx = rt.isCollection() ? RowIndexForUriType.entitySet : RowIndexForUriType.entity;
} }
break; break;
case PRIMITIVE: case PRIMITIVE:
idx = rt.isCollection() ? RowIndex.propertyPrimitiveCollection : RowIndex.propertyPrimitive; idx = rt.isCollection() ? RowIndexForUriType.propertyPrimitiveCollection : RowIndexForUriType.propertyPrimitive;
break; break;
case COMPLEX: case COMPLEX:
idx = rt.isCollection() ? RowIndex.propertyComplexCollection : RowIndex.propertyComplex; idx = rt.isCollection() ? RowIndexForUriType.propertyComplexCollection : RowIndexForUriType.propertyComplex;
break; break;
default: default:
throw new UriValidationException("Unsupported action return type: " + rt.getType().getKind()); throw new UriValidationException("Unsupported action return type: " + rt.getType().getKind());
@ -376,21 +415,21 @@ public class UriValidator {
return idx; return idx;
} }
private RowIndex rowIndexForCount(UriInfo uriInfo, UriResource lastPathSegment) private RowIndexForUriType rowIndexForCount(UriInfo uriInfo, UriResource lastPathSegment)
throws UriValidationException { throws UriValidationException {
RowIndex idx; RowIndexForUriType idx;
int secondLastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 2; int secondLastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 2;
UriResource secondLastPathSegment = uriInfo.getUriResourceParts().get(secondLastPathSegmentIndex); UriResource secondLastPathSegment = uriInfo.getUriResourceParts().get(secondLastPathSegmentIndex);
switch (secondLastPathSegment.getKind()) { switch (secondLastPathSegment.getKind()) {
case entitySet: case entitySet:
idx = RowIndex.entitySetCount; idx = RowIndexForUriType.entitySetCount;
break; break;
case complexProperty: case complexProperty:
idx = RowIndex.propertyComplexCollectionCount; idx = RowIndexForUriType.propertyComplexCollectionCount;
break; break;
case primitiveProperty: case primitiveProperty:
idx = RowIndex.propertyPrimitiveCollectionCount; idx = RowIndexForUriType.propertyPrimitiveCollectionCount;
break; break;
default: default:
throw new UriValidationException("Illegal path part kind: " + lastPathSegment.getKind()); throw new UriValidationException("Illegal path part kind: " + lastPathSegment.getKind());
@ -401,7 +440,7 @@ public class UriValidator {
private void validateQueryOptions(final UriInfo uriInfo, Edm edm) throws UriValidationException { private void validateQueryOptions(final UriInfo uriInfo, Edm edm) throws UriValidationException {
try { try {
RowIndex row = rowIndex(uriInfo, edm); RowIndexForUriType row = rowIndexForUriType(uriInfo, edm);
for (SystemQueryOption option : uriInfo.getSystemQueryOptions()) { for (SystemQueryOption option : uriInfo.getSystemQueryOptions()) {
ColumnIndex col = colIndex(option.getKind()); ColumnIndex col = colIndex(option.getKind());
@ -418,6 +457,41 @@ public class UriValidator {
} }
private void validateForHttpMethod(UriInfo uriInfo, String httpMethod) throws UriValidationException {
RowIndexForHttpMethod row = rowIndexForHttpMethod(httpMethod);
for (SystemQueryOption option : uriInfo.getSystemQueryOptions()) {
ColumnIndex col = colIndex(option.getKind());
if (!decisionMatrixForHttpMethod[row.getIndex()][col.getIndex()]) {
throw new UriValidationException("System query option " + option.getName() + " not allowed for method "
+ httpMethod);
}
}
}
private RowIndexForHttpMethod rowIndexForHttpMethod(String httpMethod) throws UriValidationException {
RowIndexForHttpMethod idx;
if ("GET".equalsIgnoreCase(httpMethod)) {
idx = RowIndexForHttpMethod.GET;
} else if ("POST".equalsIgnoreCase(httpMethod)) {
idx = RowIndexForHttpMethod.POST;
} else if ("PUT".equalsIgnoreCase(httpMethod)) {
idx = RowIndexForHttpMethod.PUT;
} else if ("DELETE".equalsIgnoreCase(httpMethod)) {
idx = RowIndexForHttpMethod.DELETE;
} else if ("PATCH".equalsIgnoreCase(httpMethod)) {
idx = RowIndexForHttpMethod.PATCH;
} else if ("MERGE".equalsIgnoreCase(httpMethod)) {
idx = RowIndexForHttpMethod.MERGE;
} else {
throw new UriValidationException("HTTP method not supported: " + httpMethod);
}
return idx;
}
private void validateKeyPredicateTypes(final UriInfo uriInfo, final Edm edm) throws UriValidationException {} private void validateKeyPredicateTypes(final UriInfo uriInfo, final Edm edm) throws UriValidationException {}
} }

View File

@ -322,6 +322,6 @@ public class UriEdmValidatorTest {
UriValidator validator = new UriValidator(); UriValidator validator = new UriValidator();
System.out.print("URI: " + uri); System.out.print("URI: " + uri);
validator.validate(uriInfo, edm); validator.validate(uriInfo, edm, "GET");
} }
} }