Repository: olingo-odata4
Updated Branches:
  refs/heads/master 081a38001 -> 7715006ea


Content-Type is mandatory in POST/PUT/PATCH requests

Change-Id: Icbd3455241b0618339d2418214441e4ab59602c8

Signed-off-by: Michael Bolz <[email protected]>


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

Branch: refs/heads/master
Commit: 30d67c71f5b138577d5f499c900db34ba6177720
Parents: 081a380
Author: Klaus Straubinger <[email protected]>
Authored: Fri Sep 11 08:45:05 2015 +0200
Committer: Michael Bolz <[email protected]>
Committed: Fri Sep 11 09:14:06 2015 +0200

----------------------------------------------------------------------
 .../olingo/server/core/ODataDispatcher.java     | 47 ++++++++++++--------
 .../server/core/ODataExceptionHelper.java       |  3 +-
 .../server/core/ODataHandlerException.java      |  2 +
 .../server-core-exceptions-i18n.properties      |  1 +
 .../processor/TechnicalEntityProcessor.java     |  7 ---
 .../TechnicalPrimitiveComplexProcessor.java     |  1 -
 .../tecsvc/processor/TechnicalProcessor.java    |  2 +-
 .../olingo/server/core/ODataHandlerTest.java    |  9 ++++
 8 files changed, 43 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/30d67c71/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataDispatcher.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataDispatcher.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataDispatcher.java
index 459c1ae..90ec8c2 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataDispatcher.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataDispatcher.java
@@ -206,10 +206,9 @@ public class ODataDispatcher {
       // Only bound actions can have ETag control for the binding parameter.
       validatePreconditions(request, false);
     }
+    final ContentType requestFormat = 
getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE),
+        RepresentationType.ACTION_PARAMETERS, false);
     final EdmReturnType returnType = action.getReturnType();
-    final ContentType requestFormat = 
ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
-    checkContentTypeSupport(requestFormat, 
RepresentationType.ACTION_PARAMETERS);
-
     if (returnType == null) {
       handler.selectProcessor(ActionVoidProcessor.class)
           .processActionVoid(request, response, uriInfo, requestFormat);
@@ -277,8 +276,8 @@ public class ODataDispatcher {
           .readReferenceCollection(request, response, uriInfo, responseFormat);
 
     } else if (isCollection && httpMethod == HttpMethod.POST) {
-      final ContentType requestFormat = 
ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
-      checkContentTypeSupport(requestFormat, RepresentationType.REFERENCE);
+      final ContentType requestFormat = 
getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE),
+          RepresentationType.REFERENCE, true);
       handler.selectProcessor(ReferenceProcessor.class)
           .createReference(request, response, uriInfo, requestFormat);
 
@@ -288,8 +287,8 @@ public class ODataDispatcher {
       handler.selectProcessor(ReferenceProcessor.class).readReference(request, 
response, uriInfo, responseFormat);
 
     } else if (!isCollection && (httpMethod == HttpMethod.PUT || httpMethod == 
HttpMethod.PATCH)) {
-      final ContentType requestFormat = 
ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
-      checkContentTypeSupport(requestFormat, RepresentationType.REFERENCE);
+      final ContentType requestFormat = 
getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE),
+          RepresentationType.REFERENCE, true);
       handler.selectProcessor(ReferenceProcessor.class)
           .updateReference(request, response, uriInfo, requestFormat);
 
@@ -327,8 +326,8 @@ public class ODataDispatcher {
             .readPrimitiveValue(request, response, uriInfo, 
requestedContentType);
       } else if (method == HttpMethod.PUT && resource instanceof 
UriResourceProperty) {
         validatePreconditions(request, false);
-        final ContentType requestFormat = 
ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
-        checkContentTypeSupport(requestFormat, valueRepresentationType);
+        final ContentType requestFormat = 
getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE),
+            valueRepresentationType, true);
         final ContentType responseFormat = 
ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
             request, handler.getCustomContentTypeSupport(), 
valueRepresentationType);
         handler.selectProcessor(PrimitiveValueProcessor.class)
@@ -382,8 +381,8 @@ public class ODataDispatcher {
       }
     } else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) {
       validatePreconditions(request, false);
-      final ContentType requestFormat = 
ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
-      checkContentTypeSupport(requestFormat, complexRepresentationType);
+      final ContentType requestFormat = 
getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE),
+          complexRepresentationType, true);
       final ContentType responseFormat = 
ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
           request, handler.getCustomContentTypeSupport(), 
complexRepresentationType);
       if (isCollection) {
@@ -425,8 +424,8 @@ public class ODataDispatcher {
       }
     } else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) {
       validatePreconditions(request, false);
-      final ContentType requestFormat = 
ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
-      checkContentTypeSupport(requestFormat, representationType);
+      final ContentType requestFormat = 
getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE),
+          representationType, true);
       final ContentType responseFormat = 
ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
           request, handler.getCustomContentTypeSupport(), representationType);
       if (isCollection) {
@@ -481,14 +480,15 @@ public class ODataDispatcher {
         handler.selectProcessor(EntityCollectionProcessor.class)
             .readEntityCollection(request, response, uriInfo, 
requestedContentType);
       } else if (method == HttpMethod.POST) {
-        final ContentType requestFormat = 
ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
         final ContentType responseFormat = 
ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
             request, handler.getCustomContentTypeSupport(), 
RepresentationType.ENTITY);
         if (isMedia) {
+          final ContentType requestFormat = 
ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
           handler.selectProcessor(MediaEntityProcessor.class)
               .createMediaEntity(request, response, uriInfo, requestFormat, 
responseFormat);
         } else {
-          checkContentTypeSupport(requestFormat, RepresentationType.ENTITY);
+          final ContentType requestFormat = 
getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE),
+              RepresentationType.ENTITY, true);
           handler.selectProcessor(EntityProcessor.class)
               .createEntity(request, response, uriInfo, requestFormat, 
responseFormat);
         }
@@ -504,8 +504,8 @@ public class ODataDispatcher {
             .readEntity(request, response, uriInfo, requestedContentType);
       } else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) {
         validatePreconditions(request, false);
-        final ContentType requestFormat = 
ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
-        checkContentTypeSupport(requestFormat, RepresentationType.ENTITY);
+        final ContentType requestFormat = 
getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE),
+            RepresentationType.ENTITY, true);
         final ContentType responseFormat = 
ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
             request, handler.getCustomContentTypeSupport(), 
RepresentationType.ENTITY);
         handler.selectProcessor(EntityProcessor.class)
@@ -542,9 +542,18 @@ public class ODataDispatcher {
     }
   }
 
-  private void checkContentTypeSupport(final ContentType requestFormat, final 
RepresentationType representationType)
+  private ContentType getSupportedContentType(final String contentTypeHeader,
+      final RepresentationType representationType, final boolean mustNotBeNull)
       throws ODataHandlerException, ContentNegotiatorException {
-    ContentNegotiator.checkSupport(requestFormat, 
handler.getCustomContentTypeSupport(), representationType);
+    if (contentTypeHeader == null) {
+      if (mustNotBeNull) {
+        throw new ODataHandlerException(contentTypeHeader, 
ODataHandlerException.MessageKeys.MISSING_CONTENT_TYPE);
+      }
+      return null;
+    }
+    final ContentType contentType = ContentType.parse(contentTypeHeader);
+    ContentNegotiator.checkSupport(contentType, 
handler.getCustomContentTypeSupport(), representationType);
+    return contentType;
   }
 
   private boolean isMedia(final UriResource pathSegment) {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/30d67c71/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataExceptionHelper.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataExceptionHelper.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataExceptionHelper.java
index 830867b..cc03922 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataExceptionHelper.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataExceptionHelper.java
@@ -90,7 +90,8 @@ public class ODataExceptionHelper {
       
serverError.setStatusCode(HttpStatusCode.NOT_IMPLEMENTED.getStatusCode());
     } else if 
(ODataHandlerException.MessageKeys.ODATA_VERSION_NOT_SUPPORTED.equals(e.getMessageKey())
         || 
ODataHandlerException.MessageKeys.INVALID_HTTP_METHOD.equals(e.getMessageKey())
-        || 
ODataHandlerException.MessageKeys.AMBIGUOUS_XHTTP_METHOD.equals(e.getMessageKey()))
 {
+        || 
ODataHandlerException.MessageKeys.AMBIGUOUS_XHTTP_METHOD.equals(e.getMessageKey())
+        || 
ODataHandlerException.MessageKeys.MISSING_CONTENT_TYPE.equals(e.getMessageKey()))
 {
       serverError.setStatusCode(HttpStatusCode.BAD_REQUEST.getStatusCode());
     } else if 
(ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED.equals(e.getMessageKey()))
 {
       
serverError.setStatusCode(HttpStatusCode.METHOD_NOT_ALLOWED.getStatusCode());

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/30d67c71/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerException.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerException.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerException.java
index 62adf19..03c4f9f 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerException.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerException.java
@@ -35,6 +35,8 @@ public class ODataHandlerException extends 
ODataLibraryException {
     PROCESSOR_NOT_IMPLEMENTED,
     /** no parameter */
     FUNCTIONALITY_NOT_IMPLEMENTED,
+    /** no parameter */
+    MISSING_CONTENT_TYPE,
     /** parameter: content type */
     UNSUPPORTED_CONTENT_TYPE,
     /** parameter: version */

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/30d67c71/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties 
b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
index f6440fb..a2b92ca 100644
--- a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
+++ b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
@@ -24,6 +24,7 @@ ODataHandlerException.HTTP_METHOD_NOT_ALLOWED=HTTP method 
'%1$s' not allowed for
 ODataHandlerException.PROCESSOR_NOT_IMPLEMENTED=No processor for interface 
'%1$s' registered.
 ODataHandlerException.FUNCTIONALITY_NOT_IMPLEMENTED=The requested 
functionality has not been implemented (yet).
 ODataHandlerException.ODATA_VERSION_NOT_SUPPORTED=OData version '%1$s' is not 
supported.
+ODataHandlerException.MISSING_CONTENT_TYPE=The Content-Type HTTP header must 
be specified for this request.
 ODataHandlerException.UNSUPPORTED_CONTENT_TYPE=The content type '%1$s' is not 
supported for this request.
 
 UriParserSyntaxException.MUST_BE_LAST_SEGMENT=The segment '%1$s' must be the 
last segment.

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/30d67c71/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
----------------------------------------------------------------------
diff --git 
a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
 
b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
index 315623f..d0285c8 100644
--- 
a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
+++ 
b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
@@ -146,7 +146,6 @@ public class TechnicalEntityProcessor extends 
TechnicalProcessor
     }
     checkRequestFormat(requestFormat);
 
-    //
     if 
(odata.createPreferences(request.getHeaders(HttpHeader.PREFER)).hasRespondAsync())
 {
       TechnicalAsyncService asyncService = TechnicalAsyncService.getInstance();
       TechnicalEntityProcessor processor = new 
TechnicalEntityProcessor(dataProvider, serviceMetadata);
@@ -154,12 +153,9 @@ public class TechnicalEntityProcessor extends 
TechnicalProcessor
       AsyncProcessor<EntityProcessor> asyncProcessor = 
asyncService.register(processor, EntityProcessor.class);
       asyncProcessor.prepareFor().createEntity(request, response, uriInfo, 
requestFormat, responseFormat);
       String location = asyncProcessor.processAsync();
-      //
       TechnicalAsyncService.acceptedResponse(response, location);
-      //
       return;
     }
-    //
 
     final UriResourceEntitySet resourceEntitySet = (UriResourceEntitySet) 
uriInfo.getUriResourceParts().get(0);
     final EdmEntitySet edmEntitySet = resourceEntitySet.getEntitySet();
@@ -227,7 +223,6 @@ public class TechnicalEntityProcessor extends 
TechnicalProcessor
     odata.createETagHelper().checkChangePreconditions(entity.getETag(),
         request.getHeaders(HttpHeader.IF_MATCH),
         request.getHeaders(HttpHeader.IF_NONE_MATCH));
-    checkRequestFormat(requestFormat);
     final ODataDeserializer deserializer = 
odata.createDeserializer(requestFormat);
     final Entity changedEntity = deserializer.entity(request.getBody(), 
edmEntitySet.getEntityType()).getEntity();
 
@@ -592,8 +587,6 @@ public class TechnicalEntityProcessor extends 
TechnicalProcessor
   private ContextURL getContextUrl(String rawODataPath, final EdmEntitySet 
entitySet, final EdmEntityType entityType,
       final boolean isSingleEntity, final ExpandOption expand, final 
SelectOption select)
       throws ODataLibraryException {
-    //
-    //
     Builder builder = ContextURL.with().oDataPath(rawODataPath);
     builder = entitySet == null ?
         isSingleEntity ? builder.type(entityType) : 
builder.asCollection().type(entityType) :

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/30d67c71/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java
----------------------------------------------------------------------
diff --git 
a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java
 
b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java
index cf4b38e..e6a8e90 100644
--- 
a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java
+++ 
b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java
@@ -287,7 +287,6 @@ public class TechnicalPrimitiveComplexProcessor extends 
TechnicalProcessor
 
     Property property = getPropertyData(entity, path);
 
-    checkRequestFormat(requestFormat);
     if (representationType == RepresentationType.VALUE) {
       final FixedFormatDeserializer deserializer = 
odata.createFixedFormatDeserializer();
       final Object value = edmProperty.getType() == 
odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Binary) ?

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/30d67c71/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
----------------------------------------------------------------------
diff --git 
a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
 
b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
index af82eed..f61f30a 100644
--- 
a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
+++ 
b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
@@ -73,7 +73,7 @@ public abstract class TechnicalProcessor implements Processor 
{
     EdmEntitySet entitySet = null;
     final List<UriResource> resourcePaths = uriInfo.getUriResourceParts();
 
-    // First must be entity set or function import.
+    // First must be an entity, an entity collection, a function import, or an 
action import.
     blockTypeFilters(resourcePaths.get(0));
     if (resourcePaths.get(0) instanceof UriResourceEntitySet) {
       entitySet = ((UriResourceEntitySet) resourcePaths.get(0)).getEntitySet();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/30d67c71/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
----------------------------------------------------------------------
diff --git 
a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
 
b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
index b6c6a81..031d32b 100644
--- 
a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
+++ 
b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
@@ -688,6 +688,15 @@ public class ODataHandlerTest {
   }
 
   @Test
+  public void noRequestContentType() throws Exception {
+    EntityProcessor processor = mock(EntityProcessor.class);
+    final ODataResponse response = dispatch(HttpMethod.POST, "ESAllPrim", null,
+        HttpHeader.CONTENT_TYPE, null, processor);
+    verifyZeroInteractions(processor);
+    assertEquals(HttpStatusCode.BAD_REQUEST.getStatusCode(), 
response.getStatusCode());
+  }
+
+  @Test
   public void unsupportedRequestContentType() throws Exception {
     EntityProcessor processor = mock(EntityProcessor.class);
     ErrorProcessor errorProcessor = mock(ErrorProcessor.class);

Reply via email to