[OLINGO-206] http method validation

Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/9a980e88
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/9a980e88
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/9a980e88

Branch: refs/heads/master
Commit: 9a980e88e2bfcd7a53e03ee5600843088e11f5f6
Parents: 3bfc389
Author: Stephan Klevenz <[email protected]>
Authored: Tue Mar 25 14:34:10 2014 +0100
Committer: Stephan Klevenz <[email protected]>
Committed: Tue Mar 25 14:34:10 2014 +0100

----------------------------------------------------------------------
 .../server/core/uri/validator/UriValidator.java | 178 +++++++++++++------
 .../core/uri/validator/UriEdmValidatorTest.java |   2 +-
 2 files changed, 127 insertions(+), 53 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9a980e88/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
index f5b785b..a8f1790 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
@@ -59,10 +59,22 @@ public class UriValidator {
           /* 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 },                    
       };
+
+  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
   //@formatter:on
 
-  private enum RowIndex {
+  private enum RowIndexForUriType {
     all(0),
     batch(1),
     crossjoin(2),
@@ -86,7 +98,7 @@ public class UriValidator {
 
     private int idx;
 
-    RowIndex(int i) {
+    RowIndexForUriType(int 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);
     validateKeyPredicateTypes(uriInfo, edm);
 
@@ -174,30 +207,30 @@ public class UriValidator {
     return idx;
   }
 
-  private RowIndex rowIndex(final UriInfo uriInfo, Edm edm) throws 
UriValidationException {
-    RowIndex idx;
+  private RowIndexForUriType rowIndexForUriType(final UriInfo uriInfo, Edm 
edm) throws UriValidationException {
+    RowIndexForUriType idx;
 
     switch (uriInfo.getKind()) {
     case all:
-      idx = RowIndex.all;
+      idx = RowIndexForUriType.all;
       break;
     case batch:
-      idx = RowIndex.batch;
+      idx = RowIndexForUriType.batch;
       break;
     case crossjoin:
-      idx = RowIndex.crossjoin;
+      idx = RowIndexForUriType.crossjoin;
       break;
     case entityId:
-      idx = RowIndex.entityId;
+      idx = RowIndexForUriType.entityId;
       break;
     case metadata:
-      idx = RowIndex.metadata;
+      idx = RowIndexForUriType.metadata;
       break;
     case resource:
       idx = rowIndexForResourceKind(uriInfo, edm);
       break;
     case service:
-      idx = RowIndex.service;
+      idx = RowIndexForUriType.service;
       break;
     default:
       throw new ODataRuntimeException("Unsupported uriInfo kind: " + 
uriInfo.getKind());
@@ -206,8 +239,8 @@ public class UriValidator {
     return idx;
   }
 
-  private RowIndex rowIndexForResourceKind(UriInfo uriInfo, Edm edm) throws 
UriValidationException {
-    RowIndex idx;
+  private RowIndexForUriType rowIndexForResourceKind(UriInfo uriInfo, Edm edm) 
throws UriValidationException {
+    RowIndexForUriType idx;
 
     int lastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 1;
     UriResource lastPathSegment = 
uriInfo.getUriResourceParts().get(lastPathSegmentIndex);
@@ -229,7 +262,9 @@ public class UriValidator {
       idx = rowIndexForFunction(lastPathSegment);
       break;
     case navigationProperty:
-      idx = ((UriResourceNavigation) lastPathSegment).isCollection() ? 
RowIndex.entitySet : RowIndex.entity;
+      idx =
+          ((UriResourceNavigation) lastPathSegment).isCollection() ? 
RowIndexForUriType.entitySet
+              : RowIndexForUriType.entity;
       break;
     case primitiveProperty:
       idx = rowIndexForPrimitiveProperty(lastPathSegment);
@@ -238,10 +273,10 @@ public class UriValidator {
       idx = rowIndexForRef(uriInfo, lastPathSegment);
       break;
     case root:
-      idx = RowIndex.service;
+      idx = RowIndexForUriType.service;
       break;
     case singleton:
-      idx = RowIndex.entity;
+      idx = RowIndexForUriType.entity;
       break;
     case value:
       idx = rowIndexForValue(uriInfo);
@@ -253,16 +288,16 @@ public class UriValidator {
     return idx;
   }
 
-  private RowIndex rowIndexForValue(UriInfo uriInfo) throws 
UriValidationException {
-    RowIndex idx;
+  private RowIndexForUriType rowIndexForValue(UriInfo uriInfo) throws 
UriValidationException {
+    RowIndexForUriType idx;
     int secondLastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 2;
     UriResource secondLastPathSegment = 
uriInfo.getUriResourceParts().get(secondLastPathSegmentIndex);
     switch (secondLastPathSegment.getKind()) {
     case primitiveProperty:
-      idx = RowIndex.propertyPrimitiveValue;
+      idx = RowIndexForUriType.propertyPrimitiveValue;
       break;
     case entitySet:
-      idx = RowIndex.mediaStream;
+      idx = RowIndexForUriType.mediaStream;
       break;
     default:
       throw new UriValidationException("Unexpected kind in path segment before 
$value: "
@@ -272,14 +307,16 @@ public class UriValidator {
     return idx;
   }
 
-  private RowIndex rowIndexForRef(UriInfo uriInfo, UriResource lastPathSegment)
+  private RowIndexForUriType rowIndexForRef(UriInfo uriInfo, UriResource 
lastPathSegment)
       throws UriValidationException {
-    RowIndex idx;
+    RowIndexForUriType idx;
     int secondLastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 2;
     UriResource secondLastPathSegment = 
uriInfo.getUriResourceParts().get(secondLastPathSegmentIndex);
 
     if (secondLastPathSegment instanceof UriResourcePartTyped) {
-      idx = ((UriResourcePartTyped) secondLastPathSegment).isCollection() ? 
RowIndex.references : RowIndex.reference;
+      idx =
+          ((UriResourcePartTyped) secondLastPathSegment).isCollection() ? 
RowIndexForUriType.references
+              : RowIndexForUriType.reference;
     } else {
       throw new UriValidationException("secondLastPathSegment not a class of 
UriResourcePartTyped: "
           + lastPathSegment.getClass());
@@ -288,13 +325,13 @@ public class UriValidator {
     return idx;
   }
 
-  private RowIndex rowIndexForPrimitiveProperty(UriResource lastPathSegment)
+  private RowIndexForUriType rowIndexForPrimitiveProperty(UriResource 
lastPathSegment)
       throws UriValidationException {
-    RowIndex idx;
+    RowIndexForUriType idx;
     if (lastPathSegment instanceof UriResourcePartTyped) {
       idx =
-          ((UriResourcePartTyped) lastPathSegment).isCollection() ? 
RowIndex.propertyPrimitiveCollection
-              : RowIndex.propertyPrimitive;
+          ((UriResourcePartTyped) lastPathSegment).isCollection() ? 
RowIndexForUriType.propertyPrimitiveCollection
+              : RowIndexForUriType.propertyPrimitive;
     } else {
       throw new UriValidationException("lastPathSegment not a class of 
UriResourcePartTyped: "
           + lastPathSegment.getClass());
@@ -302,23 +339,23 @@ public class UriValidator {
     return idx;
   }
 
-  private RowIndex rowIndexForFunction(UriResource lastPathSegment) throws 
UriValidationException {
-    RowIndex idx;
+  private RowIndexForUriType rowIndexForFunction(UriResource lastPathSegment) 
throws UriValidationException {
+    RowIndexForUriType idx;
     UriResourceFunction urf = (UriResourceFunction) lastPathSegment;
     EdmReturnType rt = urf.getFunction().getReturnType();
     switch (rt.getType().getKind()) {
     case ENTITY:
       if (((EdmEntityType) rt.getType()).hasStream()) {
-        idx = RowIndex.mediaStream;
+        idx = RowIndexForUriType.mediaStream;
       } else {
-        idx = rt.isCollection() ? RowIndex.entitySet : RowIndex.entity;
+        idx = rt.isCollection() ? RowIndexForUriType.entitySet : 
RowIndexForUriType.entity;
       }
       break;
     case PRIMITIVE:
-      idx = rt.isCollection() ? RowIndex.propertyPrimitiveCollection : 
RowIndex.propertyPrimitive;
+      idx = rt.isCollection() ? RowIndexForUriType.propertyPrimitiveCollection 
: RowIndexForUriType.propertyPrimitive;
       break;
     case COMPLEX:
-      idx = rt.isCollection() ? RowIndex.propertyComplexCollection : 
RowIndex.propertyComplex;
+      idx = rt.isCollection() ? RowIndexForUriType.propertyComplexCollection : 
RowIndexForUriType.propertyComplex;
       break;
     default:
       throw new UriValidationException("Unsupported function return type: " + 
rt.getType().getKind());
@@ -327,10 +364,12 @@ public class UriValidator {
     return idx;
   }
 
-  private RowIndex rowIndexForEntitySet(UriResource lastPathSegment) throws 
UriValidationException {
-    RowIndex idx;
+  private RowIndexForUriType rowIndexForEntitySet(UriResource lastPathSegment) 
throws UriValidationException {
+    RowIndexForUriType idx;
     if (lastPathSegment instanceof UriResourcePartTyped) {
-      idx = ((UriResourcePartTyped) lastPathSegment).isCollection() ? 
RowIndex.entitySet : RowIndex.entity;
+      idx =
+          ((UriResourcePartTyped) lastPathSegment).isCollection() ? 
RowIndexForUriType.entitySet
+              : RowIndexForUriType.entity;
     } else {
       throw new UriValidationException("lastPathSegment not a class of 
UriResourcePartTyped: "
           + lastPathSegment.getClass());
@@ -338,12 +377,12 @@ public class UriValidator {
     return idx;
   }
 
-  private RowIndex rowIndexForComplexProperty(UriResource lastPathSegment) 
throws UriValidationException {
-    RowIndex idx;
+  private RowIndexForUriType rowIndexForComplexProperty(UriResource 
lastPathSegment) throws UriValidationException {
+    RowIndexForUriType idx;
     if (lastPathSegment instanceof UriResourcePartTyped) {
       idx =
-          ((UriResourcePartTyped) lastPathSegment).isCollection() ? 
RowIndex.propertyComplexCollection
-              : RowIndex.propertyComplex;
+          ((UriResourcePartTyped) lastPathSegment).isCollection() ? 
RowIndexForUriType.propertyComplexCollection
+              : RowIndexForUriType.propertyComplex;
     } else {
       throw new UriValidationException("lastPathSegment not a class of 
UriResourcePartTyped: "
           + lastPathSegment.getClass());
@@ -351,23 +390,23 @@ public class UriValidator {
     return idx;
   }
 
-  private RowIndex rowIndexForAction(UriResource lastPathSegment) throws 
UriValidationException {
-    RowIndex idx;
+  private RowIndexForUriType rowIndexForAction(UriResource lastPathSegment) 
throws UriValidationException {
+    RowIndexForUriType idx;
     UriResourceAction ura = (UriResourceAction) lastPathSegment;
     EdmReturnType rt = ura.getAction().getReturnType();
     switch (rt.getType().getKind()) {
     case ENTITY:
       if (((EdmEntityType) rt.getType()).hasStream()) {
-        idx = RowIndex.mediaStream;
+        idx = RowIndexForUriType.mediaStream;
       } else {
-        idx = rt.isCollection() ? RowIndex.entitySet : RowIndex.entity;
+        idx = rt.isCollection() ? RowIndexForUriType.entitySet : 
RowIndexForUriType.entity;
       }
       break;
     case PRIMITIVE:
-      idx = rt.isCollection() ? RowIndex.propertyPrimitiveCollection : 
RowIndex.propertyPrimitive;
+      idx = rt.isCollection() ? RowIndexForUriType.propertyPrimitiveCollection 
: RowIndexForUriType.propertyPrimitive;
       break;
     case COMPLEX:
-      idx = rt.isCollection() ? RowIndex.propertyComplexCollection : 
RowIndex.propertyComplex;
+      idx = rt.isCollection() ? RowIndexForUriType.propertyComplexCollection : 
RowIndexForUriType.propertyComplex;
       break;
     default:
       throw new UriValidationException("Unsupported action return type: " + 
rt.getType().getKind());
@@ -376,21 +415,21 @@ public class UriValidator {
     return idx;
   }
 
-  private RowIndex rowIndexForCount(UriInfo uriInfo, UriResource 
lastPathSegment)
+  private RowIndexForUriType rowIndexForCount(UriInfo uriInfo, UriResource 
lastPathSegment)
       throws UriValidationException {
 
-    RowIndex idx;
+    RowIndexForUriType idx;
     int secondLastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 2;
     UriResource secondLastPathSegment = 
uriInfo.getUriResourceParts().get(secondLastPathSegmentIndex);
     switch (secondLastPathSegment.getKind()) {
     case entitySet:
-      idx = RowIndex.entitySetCount;
+      idx = RowIndexForUriType.entitySetCount;
       break;
     case complexProperty:
-      idx = RowIndex.propertyComplexCollectionCount;
+      idx = RowIndexForUriType.propertyComplexCollectionCount;
       break;
     case primitiveProperty:
-      idx = RowIndex.propertyPrimitiveCollectionCount;
+      idx = RowIndexForUriType.propertyPrimitiveCollectionCount;
       break;
     default:
       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 {
     try {
-      RowIndex row = rowIndex(uriInfo, edm);
+      RowIndexForUriType row = rowIndexForUriType(uriInfo, edm);
 
       for (SystemQueryOption option : uriInfo.getSystemQueryOptions()) {
         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 {}
 
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9a980e88/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/validator/UriEdmValidatorTest.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/validator/UriEdmValidatorTest.java
 
b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/validator/UriEdmValidatorTest.java
index 9ec844c..a76cee5 100644
--- 
a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/validator/UriEdmValidatorTest.java
+++ 
b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/validator/UriEdmValidatorTest.java
@@ -322,6 +322,6 @@ public class UriEdmValidatorTest {
     UriValidator validator = new UriValidator();
 
     System.out.print("URI: " + uri);
-    validator.validate(uriInfo, edm);
+    validator.validate(uriInfo, edm, "GET");
   }
 }

Reply via email to