You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by mi...@apache.org on 2013/09/04 11:00:07 UTC

git commit: Fix for incorrect Accept handling in case

Updated Branches:
  refs/heads/master 7bbc14ed9 -> 33834d2be


Fix for incorrect Accept handling in  case


Project: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/commit/33834d2b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/tree/33834d2b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/diff/33834d2b

Branch: refs/heads/master
Commit: 33834d2be75a3b2ebe552217d07e0dd0980be547
Parents: 7bbc14e
Author: Michael Bolz <mi...@apache.org>
Authored: Wed Sep 4 10:57:59 2013 +0200
Committer: Michael Bolz <mi...@apache.org>
Committed: Wed Sep 4 10:57:59 2013 +0200

----------------------------------------------------------------------
 .../olingo/odata2/core/ContentNegotiator.java   | 13 ++-
 .../olingo/odata2/core/ODataRequestHandler.java | 26 +++++-
 .../core/ODataRequestHandlerValidationTest.java | 93 +++++++++++++++++++-
 3 files changed, 128 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/33834d2b/odata-core/src/main/java/org/apache/olingo/odata2/core/ContentNegotiator.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ContentNegotiator.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ContentNegotiator.java
index f9767c3..02bbd23 100644
--- a/odata-core/src/main/java/org/apache/olingo/odata2/core/ContentNegotiator.java
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ContentNegotiator.java
@@ -26,6 +26,7 @@ import java.util.Set;
 import org.apache.olingo.odata2.api.exception.ODataBadRequestException;
 import org.apache.olingo.odata2.api.exception.ODataException;
 import org.apache.olingo.odata2.api.exception.ODataNotAcceptableException;
+import org.apache.olingo.odata2.api.uri.UriInfo;
 import org.apache.olingo.odata2.core.commons.ContentType;
 import org.apache.olingo.odata2.core.commons.ContentType.ODataFormat;
 import org.apache.olingo.odata2.core.uri.UriInfoImpl;
@@ -39,7 +40,17 @@ public class ContentNegotiator {
   private static final String URI_INFO_FORMAT_ATOM = "atom";
   private static final String URI_INFO_FORMAT_XML = "xml";
   static final String DEFAULT_CHARSET = "utf-8";
-
+  
+  /**
+   * Do the content negotiation based on requested content type (in <code>acceptHeaderContentTypes</code> list) 
+   * and supported content types (in <code>supportedContentTypes</code> list).
+   * 
+   * @param uriInfo additional uri informations especially <code>$format</code> 
+   * @param acceptHeaderContentTypes list of requested content types
+   * @param supportedContentTypes list of supported content types
+   * @return best fitting content type or <code>NULL</code> if content type is not set and for given {@link UriInfo} is ignored
+   * @throws ODataException if no supported content type was found
+   */
   public String doContentNegotiation(final UriInfoImpl uriInfo, final List<String> acceptHeaderContentTypes, final List<String> supportedContentTypes) throws ODataException {
     ContentType contentType;
     if (uriInfo.getFormat() == null) {

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/33834d2b/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataRequestHandler.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataRequestHandler.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataRequestHandler.java
index 56b0fab..b61c6c2 100644
--- a/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataRequestHandler.java
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataRequestHandler.java
@@ -100,19 +100,19 @@ public class ODataRequestHandler {
       context.stopRuntimeMeasurement(timingHandle2);
 
       final ODataHttpMethod method = request.getMethod();
-      final UriType uriType = uriInfo.getUriType();
       validateMethodAndUri(method, uriInfo);
 
       if (method == ODataHttpMethod.POST || method == ODataHttpMethod.PUT || method == ODataHttpMethod.PATCH || method == ODataHttpMethod.MERGE) {
         checkRequestContentType(uriInfo, request.getContentType());
       }
 
-      final String acceptContentType = new ContentNegotiator().doContentNegotiation(uriInfo, request.getAcceptHeaders(), getSupportedContentTypes(uriInfo));
+      final String acceptContentType = doContentNegotiation(request, uriInfo);
 
       timingHandle2 = context.startRuntimeMeasurement("Dispatcher", "dispatch");
       odataResponse = dispatcher.dispatch(method, uriInfo, request.getBody(), request.getContentType(), acceptContentType);
       context.stopRuntimeMeasurement(timingHandle2);
 
+      final UriType uriType = uriInfo.getUriType();
       final String location = (method == ODataHttpMethod.POST && (uriType == UriType.URI1 || uriType == UriType.URI6B)) ? odataResponse.getIdLiteral() : null;
       final HttpStatusCodes s = odataResponse.getStatus() == null ? method == ODataHttpMethod.POST ? uriType == UriType.URI9 ? HttpStatusCodes.OK : uriType == UriType.URI7B ? HttpStatusCodes.NO_CONTENT : HttpStatusCodes.CREATED : method == ODataHttpMethod.PUT || method == ODataHttpMethod.PATCH || method == ODataHttpMethod.MERGE || method == ODataHttpMethod.DELETE ? HttpStatusCodes.NO_CONTENT : HttpStatusCodes.OK : odataResponse.getStatus();
 
@@ -133,6 +133,23 @@ public class ODataRequestHandler {
     return debugValue == null ? odataResponse : new ODataDebugResponseWrapper(context, odataResponse, uriInfo, exception, debugValue).wrapResponse();
   }
 
+  /**
+   * Do the content negotiation based on requested content type (in HTTP accept header) and from {@link ODataService}
+   * supported content types (via {@link ODataService#getSupportedContentTypes(Class)}).
+   * 
+   * @param request with requested content type
+   * @param uriInfo additional uri informations
+   * @return best fitting content type or <code>NULL</code> if content type is not set and for given {@link UriInfo} is ignored
+   * @throws ODataException if no supported content type was found
+   */
+  private String doContentNegotiation(final ODataRequest request, UriInfoImpl uriInfo) throws ODataException {
+    if(uriInfo.isCount() || uriInfo.isValue()) {
+      return request.getRequestHeaderValue("Accept");
+    } else {
+      return new ContentNegotiator().doContentNegotiation(uriInfo, request.getAcceptHeaders(), getSupportedContentTypes(uriInfo));
+    }
+  }
+
   private String getServerDataServiceVersion() throws ODataException {
     return service.getVersion() == null ? ODataServiceVersion.V20 : service.getVersion();
   }
@@ -220,6 +237,11 @@ public class ODataRequestHandler {
     case URI17:
       if (method != ODataHttpMethod.GET && method != ODataHttpMethod.PUT && method != ODataHttpMethod.DELETE) {
         throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      } else {
+        if(uriInfo.getFormat() != null) {
+//          throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+          throw new ODataBadRequestException(ODataBadRequestException.INVALID_SYNTAX);
+        }
       }
       break;
 

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/33834d2b/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataRequestHandlerValidationTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataRequestHandlerValidationTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataRequestHandlerValidationTest.java
index fe39c76..279bdd3 100644
--- a/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataRequestHandlerValidationTest.java
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataRequestHandlerValidationTest.java
@@ -218,6 +218,7 @@ public class ODataRequestHandlerValidationTest extends BaseTest {
       final ODataHttpMethod method,
       final List<String> pathSegments,
       final Map<String, String> queryParameters,
+      final List<String> acceptHeaders,
       final String requestContentType) throws ODataException {
     ODataRequest request = mock(ODataRequest.class);
     when(request.getMethod()).thenReturn(method);
@@ -233,8 +234,20 @@ public class ODataRequestHandlerValidationTest extends BaseTest {
     when(request.getQueryParameters())
         .thenReturn(queryParameters == null ? new HashMap<String, String>() : queryParameters);
     when(request.getContentType()).thenReturn(requestContentType);
+    when(request.getAcceptHeaders()).thenReturn(acceptHeaders);
     return request;
   }
+  
+  private ODataRequest mockODataRequest(
+      final ODataHttpMethod method,
+      final List<String> pathSegments,
+      final Map<String, String> queryParameters,
+      final String requestContentType) throws ODataException {
+
+    List<String> acceptHeaders = new ArrayList<String>(0);
+    return mockODataRequest(method, pathSegments, queryParameters, acceptHeaders, requestContentType);
+  }
+
 
   private ODataService mockODataService(final ODataServiceFactory serviceFactory) throws ODataException {
     ODataService service = DispatcherTest.getMockService();
@@ -312,6 +325,36 @@ public class ODataRequestHandlerValidationTest extends BaseTest {
         response.getStatus());
   }
 
+  private void executeAndValidateGetRequest(
+      final List<String> pathSegments,
+      final Map<String, String> queryParameters,
+      final List<String> acceptHeaders,
+      final HttpStatusCodes expectedStatusCode) throws ODataException {
+
+    executeAndValidateRequest(ODataHttpMethod.GET, pathSegments, queryParameters, acceptHeaders, null, expectedStatusCode);
+  }
+
+  private void executeAndValidateRequest(final ODataHttpMethod method,
+      final List<String> pathSegments,
+      final Map<String, String> queryParameters,
+      final List<String> acceptHeaders,
+      final String requestContentType,
+      final HttpStatusCodes expectedStatusCode) throws ODataException {
+
+    ODataServiceFactory serviceFactory = mock(ODataServiceFactory.class);
+    final ODataService service = mockODataService(serviceFactory);
+    when(serviceFactory.createService(any(ODataContext.class))).thenReturn(service);
+
+    final ODataRequest request = mockODataRequest(method, pathSegments, queryParameters, acceptHeaders, requestContentType);
+    final ODataContextImpl context = new ODataContextImpl(request, serviceFactory);
+
+    final ODataResponse response = new ODataRequestHandler(serviceFactory, service, context).handle(request);
+    assertNotNull(response);
+    assertEquals(expectedStatusCode == null ? HttpStatusCodes.PAYMENT_REQUIRED : expectedStatusCode,
+        response.getStatus());
+  }
+
+  
   private void checkValueContentType(final ODataHttpMethod method, final UriType uriType, final String requestContentType) throws Exception {
     executeAndValidateRequest(method, createPathSegments(uriType, false, true), null, requestContentType, null);
   }
@@ -498,7 +541,15 @@ public class ODataRequestHandlerValidationTest extends BaseTest {
     wrongOptions(ODataHttpMethod.POST, UriType.URI7B, false, false, false, false, false, false, true, false, false);
 
     wrongOptions(ODataHttpMethod.PUT, UriType.URI17, false, true, false, false, false, false, false, false, false);
-    wrongOptions(ODataHttpMethod.DELETE, UriType.URI17, true, false, false, false, false, false, false, false, false);
+    executeAndValidateRequest(ODataHttpMethod.PUT, createPathSegments(UriType.URI17, false, false), 
+        createOptions(true, false, false, false, false, false, false, false, false), 
+        null, HttpStatusCodes.BAD_REQUEST);
+    
+    executeAndValidateRequest(ODataHttpMethod.DELETE, createPathSegments(UriType.URI17, false, false), 
+        createOptions(true, false, false, false, false, false, false, false, false), 
+        null, HttpStatusCodes.BAD_REQUEST);
+//    wrongOptions(ODataHttpMethod.DELETE, UriType.URI17, true, false, false, false, false, false, false, false, false);
+
     wrongOptions(ODataHttpMethod.DELETE, UriType.URI17, false, true, false, false, false, false, false, false, false);
   }
 
@@ -547,6 +598,46 @@ public class ODataRequestHandlerValidationTest extends BaseTest {
     wrongNavigationPath(ODataHttpMethod.DELETE, UriType.URI17, HttpStatusCodes.BAD_REQUEST);
   }
 
+  
+  @Test
+  public void requestAcceptHeader() throws Exception {
+    executeAndValidateGetRequest(createPathSegments(UriType.URI1, false, false), null, 
+        Arrays.asList(HttpContentType.APPLICATION_JSON), null);
+    executeAndValidateGetRequest(createPathSegments(UriType.URI2, false, false), null, 
+        Arrays.asList(HttpContentType.APPLICATION_JSON), null);
+    executeAndValidateGetRequest(createPathSegments(UriType.URI3, false, false), null, 
+        Arrays.asList(HttpContentType.APPLICATION_JSON), null);
+    executeAndValidateGetRequest(createPathSegments(UriType.URI4, false, false), null, 
+        Arrays.asList(HttpContentType.APPLICATION_JSON), null);
+    executeAndValidateGetRequest(createPathSegments(UriType.URI5, false, false), null, 
+        Arrays.asList(HttpContentType.APPLICATION_JSON), null);
+    executeAndValidateGetRequest(createPathSegments(UriType.URI6A, false, false), null, 
+        Arrays.asList(HttpContentType.APPLICATION_JSON), null);
+    executeAndValidateGetRequest(createPathSegments(UriType.URI6B, false, false), null, 
+        Arrays.asList(HttpContentType.APPLICATION_JSON), null);
+    executeAndValidateGetRequest(createPathSegments(UriType.URI7A, false, false), null, 
+        Arrays.asList(HttpContentType.APPLICATION_JSON), null);
+    executeAndValidateGetRequest(createPathSegments(UriType.URI7B, false, false), null, 
+        Arrays.asList(HttpContentType.APPLICATION_JSON), null);
+    executeAndValidateGetRequest(createPathSegments(UriType.URI8, false, false), null, 
+        Arrays.asList(HttpContentType.APPLICATION_XML), null);
+    // in discussion, hence currently not implemented (see ODataRequestHandler#doContentNegotiation(...))
+//    executeAndValidateGetRequest(createPathSegments(UriType.URI8, false, false), null, 
+//        Arrays.asList(HttpContentType.TEXT_PLAIN), null);
+    executeAndValidateGetRequest(createPathSegments(UriType.URI9, false, false), null, 
+        Arrays.asList(HttpContentType.APPLICATION_XML), HttpStatusCodes.METHOD_NOT_ALLOWED);
+    executeAndValidateGetRequest(createPathSegments(UriType.URI15, false, false), null, 
+        Arrays.asList(HttpContentType.TEXT_PLAIN), null);
+    executeAndValidateGetRequest(createPathSegments(UriType.URI16, false, false), null, 
+        Arrays.asList(HttpContentType.TEXT_PLAIN), null);
+    executeAndValidateGetRequest(createPathSegments(UriType.URI17, false, true), null, 
+        Arrays.asList(HttpContentType.APPLICATION_OCTET_STREAM), null);
+    executeAndValidateGetRequest(createPathSegments(UriType.URI50A, false, false), null, 
+        Arrays.asList(HttpContentType.APPLICATION_XML), null);
+    executeAndValidateGetRequest(createPathSegments(UriType.URI50B, false, false), null, 
+        Arrays.asList(HttpContentType.APPLICATION_XML), null);
+  }
+  
   @Test
   public void requestContentType() throws Exception {
     executeAndValidateRequest(ODataHttpMethod.PUT, createPathSegments(UriType.URI2, false, false), null, HttpContentType.APPLICATION_XML, null);