Repository: olingo-odata4
Updated Branches:
  refs/heads/master 34f082560 -> d19afa013


[OLINGO-350] Status code handling and refactoring


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

Branch: refs/heads/master
Commit: 5c0b34a92d67f7f4f3846a1bdd2ad76e70cd0f6b
Parents: 34f0825
Author: Christian Amend <[email protected]>
Authored: Fri Aug 1 16:20:55 2014 +0200
Committer: Christian Amend <[email protected]>
Committed: Wed Aug 6 17:10:15 2014 +0200

----------------------------------------------------------------------
 .../server/api/ODataTranslatedException.java    |   6 -
 .../api/processor/CollectionProcessor.java      |  40 -------
 .../server/api/processor/DefaultProcessor.java  |   4 +-
 .../processor/EntityCollectionProcessor.java    |  40 +++++++
 .../src/main/resources/i18n.properties          |   7 +-
 .../olingo/server/core/ContentNegotiator.java   |  35 +++---
 .../server/core/ContentNegotiatorException.java |  45 +++++++
 .../apache/olingo/server/core/ODataHandler.java | 120 +++++++++++--------
 .../server/core/ContentNegotiatorTest.java      |  41 +++----
 .../server/core/ODataHttpHandlerImplTest.java   |   6 -
 .../tecsvc/processor/TechnicalProcessor.java    |   4 +-
 .../olingo/server/core/ODataHandlerTest.java    |  49 ++++++++
 12 files changed, 249 insertions(+), 148 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5c0b34a9/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataTranslatedException.java
----------------------------------------------------------------------
diff --git 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataTranslatedException.java
 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataTranslatedException.java
index b703f93..1dbb810 100644
--- 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataTranslatedException.java
+++ 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataTranslatedException.java
@@ -45,12 +45,6 @@ public class ODataTranslatedException extends ODataException 
{
     PROCESSOR_NOT_IMPLEMENTED,
     FUNCTIONALITY_NOT_IMPLEMENTED,
     ODATA_VERSION_NOT_SUPPORTED,
-    /** parameters: HTTP header name, HTTP header value */
-    WRONG_CHARSET_IN_HEADER,
-    /** parameter: list of content-type ranges */
-    UNSUPPORTED_CONTENT_TYPES,
-    /** parameter: content type */
-    UNSUPPORTED_CONTENT_TYPE
   }
 
   private MessageKey messageKey;

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5c0b34a9/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/CollectionProcessor.java
----------------------------------------------------------------------
diff --git 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/CollectionProcessor.java
 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/CollectionProcessor.java
deleted file mode 100644
index d61734c..0000000
--- 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/CollectionProcessor.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.olingo.server.api.processor;
-
-import org.apache.olingo.commons.api.format.ContentType;
-import org.apache.olingo.server.api.ODataRequest;
-import org.apache.olingo.server.api.ODataResponse;
-import org.apache.olingo.server.api.uri.UriInfo;
-
-/**
- * Processor interface for handling collections of entities (collections, 
EntitySets or feeds).
- */
-public interface CollectionProcessor extends Processor {
-
-  /**
-   * Read entities data from persistency and puts serialized content and 
status into the response.
-   *  @param request - OData request object containing raw http information.
-   *  @param response - OData response object for collecting response data
-   *  @param uriInfo - information of a parsed OData uri
-   *  @param requestedContentType - requested content type after content 
negotiation
-   */
-  void readCollection(ODataRequest request, ODataResponse response, UriInfo 
uriInfo, ContentType requestedContentType);
-
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5c0b34a9/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/DefaultProcessor.java
----------------------------------------------------------------------
diff --git 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/DefaultProcessor.java
 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/DefaultProcessor.java
index 028bf6b..359136b 100644
--- 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/DefaultProcessor.java
+++ 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/DefaultProcessor.java
@@ -87,7 +87,9 @@ public class DefaultProcessor implements MetadataProcessor, 
ServiceDocumentProce
     } catch (Exception e) {
       // This should never happen but to be sure we have this catch here to 
prevent sending a stacktrace to a client.
       String responseContent =
-          "An unexpected exception occoured during error processing with 
message: \"" + e.getMessage() + "\"";
+          "{\"error\":{\"code\":null,\"message\":\"An unexpected exception 
occoured during " +
+              "error processing with message: "
+              + e.getMessage() + "\"}}";
       response.setContent(new 
ByteArrayInputStream(responseContent.getBytes()));
       
response.setStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode());
       response.setHeader(HttpHeader.CONTENT_TYPE, 
ContentType.APPLICATION_JSON.toContentTypeString());

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5c0b34a9/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityCollectionProcessor.java
----------------------------------------------------------------------
diff --git 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityCollectionProcessor.java
 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityCollectionProcessor.java
new file mode 100644
index 0000000..0e58c96
--- /dev/null
+++ 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityCollectionProcessor.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.server.api.processor;
+
+import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.server.api.ODataRequest;
+import org.apache.olingo.server.api.ODataResponse;
+import org.apache.olingo.server.api.uri.UriInfo;
+
+/**
+ * Processor interface for handling collections of entities (collections, 
EntitySets or feeds).
+ */
+public interface EntityCollectionProcessor extends Processor {
+
+  /**
+   * Read entities data from persistency and puts serialized content and 
status into the response.
+   *  @param request - OData request object containing raw http information.
+   *  @param response - OData response object for collecting response data
+   *  @param uriInfo - information of a parsed OData uri
+   *  @param requestedContentType - requested content type after content 
negotiation
+   */
+  void readCollection(ODataRequest request, ODataResponse response, UriInfo 
uriInfo, ContentType requestedContentType);
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5c0b34a9/lib/server-api/src/main/resources/i18n.properties
----------------------------------------------------------------------
diff --git a/lib/server-api/src/main/resources/i18n.properties 
b/lib/server-api/src/main/resources/i18n.properties
index 3efb829..7a7fbe9 100644
--- a/lib/server-api/src/main/resources/i18n.properties
+++ b/lib/server-api/src/main/resources/i18n.properties
@@ -23,9 +23,10 @@ ODataTranslatedException.HTTP_METHOD_NOT_IMPLEMENTED=Invalid 
HTTP method given:
 ODataTranslatedException.PROCESSOR_NOT_IMPLEMENTED=No processor for interface 
'%1$s' registered.
 ODataTranslatedException.FUNCTIONALITY_NOT_IMPLEMENTED=The requested 
functionality has not been implemented (yet).
 ODataTranslatedException.ODATA_VERSION_NOT_SUPPORTED=OData version '%1$s' is 
not supported.
-ODataTranslatedException.WRONG_CHARSET_IN_HEADER=The HTTP header '%1$s' with 
value '%2$s' contains an invalid character-set specification.
-ODataTranslatedException.UNSUPPORTED_CONTENT_TYPES=The content-type range 
'%1$s' is not supported.
-ODataTranslatedException.UNSUPPORTED_CONTENT_TYPE=The content type '%1$s' is 
not supported.
+ContentNegotiatorException.WRONG_CHARSET_IN_HEADER=The HTTP header '%1$s' with 
value '%2$s' contains an invalid character-set specification.
+ContentNegotiatorException.UNSUPPORTED_CONTENT_TYPES=The content-type range 
'%1$s' is not supported.
+ContentNegotiatorException.UNSUPPORTED_CONTENT_TYPE=The content type '%1$s' is 
not supported.
+ContentNegotiatorException.UNSUPPORTED_FORMAT_OPTION=The $format option '%1$s' 
is not supported.
 
 ODataSerializerException.NOT_IMPLEMENTED=The requested serialization method 
has not been implemented yet.
 ODataSerializerException.UNSUPPORTED_FORMAT=The format '%1$s' is not supported.

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5c0b34a9/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiator.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiator.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiator.java
index 2bdadd8..e762464 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiator.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiator.java
@@ -18,28 +18,23 @@
  */
 package org.apache.olingo.server.core;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
 import org.apache.olingo.commons.api.format.AcceptType;
 import org.apache.olingo.commons.api.format.ContentType;
 import org.apache.olingo.commons.api.format.ODataFormat;
 import org.apache.olingo.commons.api.http.HttpHeader;
 import org.apache.olingo.server.api.ODataRequest;
-import org.apache.olingo.server.api.ODataTranslatedException;
 import 
org.apache.olingo.server.api.processor.CustomContentTypeSupportProcessor;
 import org.apache.olingo.server.api.processor.FormatContentTypeMapping;
 import org.apache.olingo.server.api.processor.MetadataProcessor;
 import org.apache.olingo.server.api.processor.Processor;
 import org.apache.olingo.server.api.uri.queryoption.FormatOption;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.List;
 
 public class ContentNegotiator {
 
-  private final static Logger LOG = 
LoggerFactory.getLogger(ContentNegotiator.class);
-
   private ContentNegotiator() {}
 
   private static List<FormatContentTypeMapping>
@@ -71,7 +66,7 @@ public class ContentNegotiator {
   }
 
   public static ContentType doContentNegotiation(final FormatOption 
formatOption, final ODataRequest request,
-      final Processor processor, final Class<? extends Processor> 
processorClass) throws ODataTranslatedException {
+      final Processor processor, final Class<? extends Processor> 
processorClass) throws ContentNegotiatorException {
     ContentType requestedContentType = null;
 
     List<FormatContentTypeMapping> supportedContentTypes = 
getSupportedContentTypes(processor, processorClass);
@@ -81,7 +76,6 @@ public class ContentNegotiator {
     boolean supported = false;
 
     if (formatOption != null) {
-
       if ("json".equalsIgnoreCase(formatOption.getText().trim())) {
         requestedContentType = 
ODataFormat.JSON.getContentType(ODataServiceVersion.V40);
         for (FormatContentTypeMapping entry : supportedContentTypes) {
@@ -107,6 +101,10 @@ public class ContentNegotiator {
           }
         }
       }
+      if (!supported) {
+        throw new ContentNegotiatorException("Unsupported $format = " + 
formatOption.getText(),
+            ContentNegotiatorException.MessageKeys.UNSUPPORTED_FORMAT_OPTION, 
formatOption.getText());
+      }
     } else if (acceptHeaderValue != null) {
       List<AcceptType> acceptedContentTypes = 
AcceptType.create(acceptHeaderValue);
 
@@ -119,8 +117,8 @@ public class ContentNegotiator {
             if ("utf8".equalsIgnoreCase(value) || 
"utf-8".equalsIgnoreCase(value)) {
               ct = ContentType.create(ct, ContentType.PARAMETER_CHARSET_UTF8);
             } else {
-              throw new ODataTranslatedException("charset in accept header not 
supported: " + acceptHeaderValue,
-                  
ODataTranslatedException.MessageKeys.WRONG_CHARSET_IN_HEADER, 
HttpHeader.ACCEPT, acceptHeaderValue);
+              throw new ContentNegotiatorException("charset in accept header 
not supported: " + acceptHeaderValue,
+                  
ContentNegotiatorException.MessageKeys.WRONG_CHARSET_IN_HEADER, 
HttpHeader.ACCEPT, acceptHeaderValue);
             }
           }
 
@@ -135,13 +133,12 @@ public class ContentNegotiator {
         }
       }
 
-      if (requestedContentType == null) {
-        throw new ODataTranslatedException(
+      if (!supported) {
+        throw new ContentNegotiatorException(
             "unsupported accept content type: " + acceptedContentTypes + " != 
" + supportedContentTypes,
-            ODataTranslatedException.MessageKeys.UNSUPPORTED_CONTENT_TYPES, 
acceptedContentTypes.toString());
+            ContentNegotiatorException.MessageKeys.UNSUPPORTED_CONTENT_TYPES, 
acceptedContentTypes.toString());
       }
     } else {
-
       if (processorClass == MetadataProcessor.class) {
         requestedContentType = ContentType.APPLICATION_XML;
       } else {
@@ -157,13 +154,11 @@ public class ContentNegotiator {
     }
 
     if (!supported) {
-      throw new ODataTranslatedException(
+      throw new ContentNegotiatorException(
           "unsupported accept content type: " + requestedContentType + " != " 
+ supportedContentTypes,
-          ODataTranslatedException.MessageKeys.UNSUPPORTED_CONTENT_TYPE, 
requestedContentType.toContentTypeString());
+          ContentNegotiatorException.MessageKeys.UNSUPPORTED_CONTENT_TYPE, 
requestedContentType.toContentTypeString());
     }
 
-    LOG.debug("requested content type: " + requestedContentType);
-
     return requestedContentType;
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5c0b34a9/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiatorException.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiatorException.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiatorException.java
new file mode 100644
index 0000000..6e0d823
--- /dev/null
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiatorException.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.server.core;
+
+import org.apache.olingo.server.api.ODataTranslatedException;
+
+public class ContentNegotiatorException extends ODataTranslatedException {
+  private static final long serialVersionUID = -8112658467394158700L;
+
+  public static enum MessageKeys implements MessageKey {
+    /** parameters: HTTP header name, HTTP header value */
+    WRONG_CHARSET_IN_HEADER,
+    /** parameter: list of content-type ranges */
+    UNSUPPORTED_CONTENT_TYPES,
+    /** parameter: content type */
+    UNSUPPORTED_CONTENT_TYPE,
+    /** parameter: format string */
+    UNSUPPORTED_FORMAT_OPTION
+  }
+
+  public ContentNegotiatorException(String developmentMessage, MessageKey 
messageKey, String... parameters) {
+    super(developmentMessage, messageKey, parameters);
+  }
+
+  public ContentNegotiatorException(String developmentMessage, Throwable 
cause, MessageKey messageKey,
+      String... parameters) {
+    super(developmentMessage, cause, messageKey, parameters);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5c0b34a9/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
index 9c6bf3e..f364a22 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
@@ -22,7 +22,6 @@ import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
 
-import org.apache.olingo.commons.api.ODataRuntimeException;
 import org.apache.olingo.commons.api.edm.Edm;
 import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
 import org.apache.olingo.commons.api.format.ContentType;
@@ -36,7 +35,7 @@ import org.apache.olingo.server.api.ODataRequest;
 import org.apache.olingo.server.api.ODataResponse;
 import org.apache.olingo.server.api.ODataServerError;
 import org.apache.olingo.server.api.ODataTranslatedException;
-import org.apache.olingo.server.api.processor.CollectionProcessor;
+import org.apache.olingo.server.api.processor.EntityCollectionProcessor;
 import org.apache.olingo.server.api.processor.DefaultProcessor;
 import org.apache.olingo.server.api.processor.EntityProcessor;
 import org.apache.olingo.server.api.processor.ExceptionProcessor;
@@ -48,6 +47,8 @@ import org.apache.olingo.server.api.uri.UriResource;
 import org.apache.olingo.server.api.uri.UriResourceNavigation;
 import org.apache.olingo.server.api.uri.UriResourcePartTyped;
 import org.apache.olingo.server.core.uri.parser.Parser;
+import org.apache.olingo.server.core.uri.parser.UriParserException;
+import org.apache.olingo.server.core.uri.validator.UriValidationException;
 import org.apache.olingo.server.core.uri.validator.UriValidator;
 
 public class ODataHandler {
@@ -69,46 +70,17 @@ public class ODataHandler {
     ContentType requestedContentType = null;
     ODataResponse response = new ODataResponse();
     try {
-      validateODataVersion(request, response);
 
-      Parser parser = new Parser();
-      String odUri =
-          request.getRawODataPath() + (request.getRawQueryPath() == null ? "" 
: "?" + request.getRawQueryPath());
-      UriInfo uriInfo = parser.parseUri(odUri, edm);
+      processInternal(request, requestedContentType, response);
 
-      UriValidator validator = new UriValidator();
-      validator.validate(uriInfo, request.getMethod());
+    } catch (UriParserException e) {
 
-      switch (uriInfo.getKind()) {
-      case metadata:
-        MetadataProcessor mp = selectProcessor(MetadataProcessor.class, 
response);
-
-        requestedContentType =
-            ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), 
request, mp, MetadataProcessor.class);
-
-        mp.readMetadata(request, response, uriInfo, requestedContentType);
-        break;
-      case service:
-        if ("".equals(request.getRawODataPath())) {
-          RedirectProcessor rdp = selectProcessor(RedirectProcessor.class, 
response);
-          rdp.redirect(request, response);
-        } else {
-          ServiceDocumentProcessor sdp = 
selectProcessor(ServiceDocumentProcessor.class, response);
-
-          requestedContentType =
-              
ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, sdp,
-                  ServiceDocumentProcessor.class);
-
-          sdp.readServiceDocument(request, response, uriInfo, 
requestedContentType);
-        }
-        break;
-      case resource:
-        handleResourceDispatching(request, response, uriInfo);
-        break;
-      default:
-        throw new ODataTranslatedException("not implemented",
-            
ODataTranslatedException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
-      }
+    } catch (ContentNegotiatorException e) {
+      Locale requestedLocale = null;
+      ODataServerError serverError =
+          ODataExceptionHelper.createServerErrorObject(e, 
HttpStatusCode.NOT_ACCEPTABLE.getStatusCode(),
+              requestedLocale);
+      handleException(request, response, serverError, requestedContentType);
     } catch (ODataTranslatedException e) {
       Locale requestedLocale = null;
       ODataServerError serverError =
@@ -124,6 +96,53 @@ public class ODataHandler {
     return response;
   }
 
+  private void processInternal(final ODataRequest request, ContentType 
requestedContentType,
+      final ODataResponse response)
+      throws ODataTranslatedException, UriParserException, 
UriValidationException, ContentNegotiatorException,
+      ODataApplicationException {
+    validateODataVersion(request, response);
+
+    Parser parser = new Parser();
+    String odUri =
+        request.getRawODataPath() + (request.getRawQueryPath() == null ? "" : 
"?" + request.getRawQueryPath());
+    UriInfo uriInfo = parser.parseUri(odUri, edm);
+
+    UriValidator validator = new UriValidator();
+    validator.validate(uriInfo, request.getMethod());
+
+    switch (uriInfo.getKind()) {
+    case metadata:
+      MetadataProcessor mp = selectProcessor(MetadataProcessor.class, 
response);
+
+      requestedContentType =
+          ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), 
request, mp, MetadataProcessor.class);
+
+      mp.readMetadata(request, response, uriInfo, requestedContentType);
+      break;
+    case service:
+      if ("".equals(request.getRawODataPath())) {
+        RedirectProcessor rdp = selectProcessor(RedirectProcessor.class, 
response);
+        rdp.redirect(request, response);
+      } else {
+        ServiceDocumentProcessor sdp = 
selectProcessor(ServiceDocumentProcessor.class, response);
+
+        requestedContentType =
+            ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), 
request, sdp,
+                ServiceDocumentProcessor.class);
+
+        sdp.readServiceDocument(request, response, uriInfo, 
requestedContentType);
+      }
+      break;
+    case resource:
+      handleResourceDispatching(request, response, uriInfo);
+      break;
+    default:
+      response.setStatusCode(HttpStatusCode.NOT_IMPLEMENTED.getStatusCode());
+      throw new ODataTranslatedException("not implemented",
+          ODataTranslatedException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
+    }
+  }
+
   private void handleException(ODataRequest request, ODataResponse response, 
ODataServerError serverError,
       ContentType requestedContentType) {
     ExceptionProcessor exceptionProcessor;
@@ -132,10 +151,10 @@ public class ODataHandler {
     } catch (ODataTranslatedException e) {
       exceptionProcessor = new DefaultProcessor();
     }
-      if (requestedContentType == null) {
-        requestedContentType = 
ODataFormat.JSON.getContentType(ODataServiceVersion.V40);
-      }
-      exceptionProcessor.processException(request, response, serverError, 
requestedContentType);
+    if (requestedContentType == null) {
+      requestedContentType = 
ODataFormat.JSON.getContentType(ODataServiceVersion.V40);
+    }
+    exceptionProcessor.processException(request, response, serverError, 
requestedContentType);
   }
 
   private void handleResourceDispatching(final ODataRequest request, final 
ODataResponse response,
@@ -148,13 +167,15 @@ public class ODataHandler {
     case entitySet:
       if (((UriResourcePartTyped) lastPathSegment).isCollection()) {
         if (request.getMethod().equals(HttpMethod.GET)) {
-          CollectionProcessor cp = selectProcessor(CollectionProcessor.class, 
response);
+          EntityCollectionProcessor cp = 
selectProcessor(EntityCollectionProcessor.class, response);
 
           requestedContentType =
-              
ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, cp, 
CollectionProcessor.class);
+              
ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, cp,
+                  EntityCollectionProcessor.class);
 
           cp.readCollection(request, response, uriInfo, requestedContentType);
         } else {
+          
response.setStatusCode(HttpStatusCode.NOT_IMPLEMENTED.getStatusCode());
           throw new ODataTranslatedException("not implemented",
               
ODataTranslatedException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
         }
@@ -167,6 +188,7 @@ public class ODataHandler {
 
           ep.readEntity(request, response, uriInfo, requestedContentType);
         } else {
+          
response.setStatusCode(HttpStatusCode.NOT_IMPLEMENTED.getStatusCode());
           throw new ODataTranslatedException("not implemented",
               
ODataTranslatedException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
         }
@@ -175,13 +197,15 @@ public class ODataHandler {
     case navigationProperty:
       if (((UriResourceNavigation) lastPathSegment).isCollection()) {
         if (request.getMethod().equals(HttpMethod.GET)) {
-          CollectionProcessor cp = selectProcessor(CollectionProcessor.class, 
response);
+          EntityCollectionProcessor cp = 
selectProcessor(EntityCollectionProcessor.class, response);
 
           requestedContentType =
-              
ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, cp, 
CollectionProcessor.class);
+              
ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, cp,
+                  EntityCollectionProcessor.class);
 
           cp.readCollection(request, response, uriInfo, requestedContentType);
         } else {
+          
response.setStatusCode(HttpStatusCode.NOT_IMPLEMENTED.getStatusCode());
           throw new ODataTranslatedException("not implemented",
               
ODataTranslatedException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
         }
@@ -194,12 +218,14 @@ public class ODataHandler {
 
           ep.readEntity(request, response, uriInfo, requestedContentType);
         } else {
+          
response.setStatusCode(HttpStatusCode.NOT_IMPLEMENTED.getStatusCode());
           throw new ODataTranslatedException("not implemented",
               
ODataTranslatedException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
         }
       }
       break;
     default:
+      response.setStatusCode(HttpStatusCode.NOT_IMPLEMENTED.getStatusCode());
       throw new ODataTranslatedException("not implemented",
           ODataTranslatedException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
     }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5c0b34a9/lib/server-core/src/test/java/org/apache/olingo/server/core/ContentNegotiatorTest.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/test/java/org/apache/olingo/server/core/ContentNegotiatorTest.java
 
b/lib/server-core/src/test/java/org/apache/olingo/server/core/ContentNegotiatorTest.java
index ca78ba0..f858aa0 100644
--- 
a/lib/server-core/src/test/java/org/apache/olingo/server/core/ContentNegotiatorTest.java
+++ 
b/lib/server-core/src/test/java/org/apache/olingo/server/core/ContentNegotiatorTest.java
@@ -18,6 +18,17 @@
  */
 package org.apache.olingo.server.core;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
 import org.apache.olingo.commons.api.edm.Edm;
 import org.apache.olingo.commons.api.format.ContentType;
 import org.apache.olingo.commons.api.http.HttpHeader;
@@ -25,8 +36,7 @@ import org.apache.olingo.commons.api.http.HttpMethod;
 import org.apache.olingo.server.api.OData;
 import org.apache.olingo.server.api.ODataRequest;
 import org.apache.olingo.server.api.ODataResponse;
-import org.apache.olingo.server.api.ODataTranslatedException;
-import org.apache.olingo.server.api.processor.CollectionProcessor;
+import org.apache.olingo.server.api.processor.EntityCollectionProcessor;
 import 
org.apache.olingo.server.api.processor.CustomContentTypeSupportProcessor;
 import org.apache.olingo.server.api.processor.FormatContentTypeMapping;
 import org.apache.olingo.server.api.processor.MetadataProcessor;
@@ -35,19 +45,6 @@ import 
org.apache.olingo.server.api.processor.ServiceDocumentProcessor;
 import org.apache.olingo.server.api.uri.UriInfo;
 import org.apache.olingo.server.api.uri.queryoption.FormatOption;
 import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 
 public class ContentNegotiatorTest {
 
@@ -103,8 +100,6 @@ public class ContentNegotiatorTest {
   //CHECKSTYLE:ON
   //@formatter:on
 
-  private final static Logger LOG = 
LoggerFactory.getLogger(ContentNegotiatorTest.class);
-
   @Test
   public void testServiceDocumentSingleCase() throws Exception {
     String[] useCase = { ACCEPT_CASE_MIN_UTF8, null, ACCEPT_CASE_MIN_UTF8, 
null, null };
@@ -139,17 +134,17 @@ public class ContentNegotiatorTest {
       try {
         testContentNegotiation(useCase, MetadataProcessor.class);
         fail("Exeption expected!");
-      } catch (Exception e) {
+      } catch (ContentNegotiatorException e) {
 
+      }catch (Exception e) {
+        e.printStackTrace();
+        fail("Wrong Exception: " + e.getClass().getName());
       }
     }
   }
 
   public void testContentNegotiation(final String[] useCase, final Class<? 
extends Processor> processorClass)
-      throws ODataTranslatedException {
-
-    LOG.debug(Arrays.asList(useCase).toString());
-
+      throws Exception {
     ODataRequest request = new ODataRequest();
     request.setMethod(HttpMethod.GET);
     request.setRawODataPath("/" + (useCase[1] == null ? "" : "?$format=" + 
useCase[1]));
@@ -194,7 +189,7 @@ public class ContentNegotiatorTest {
   }
 
   private class ProcessorStub implements ServiceDocumentProcessor, 
MetadataProcessor,
-      CollectionProcessor,
+      EntityCollectionProcessor,
       CustomContentTypeSupportProcessor {
 
     List<FormatContentTypeMapping> customMapping;

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5c0b34a9/lib/server-core/src/test/java/org/apache/olingo/server/core/ODataHttpHandlerImplTest.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/test/java/org/apache/olingo/server/core/ODataHttpHandlerImplTest.java
 
b/lib/server-core/src/test/java/org/apache/olingo/server/core/ODataHttpHandlerImplTest.java
index 03fc0ea..a81af68 100644
--- 
a/lib/server-core/src/test/java/org/apache/olingo/server/core/ODataHttpHandlerImplTest.java
+++ 
b/lib/server-core/src/test/java/org/apache/olingo/server/core/ODataHttpHandlerImplTest.java
@@ -29,13 +29,9 @@ import org.apache.olingo.commons.api.http.HttpMethod;
 import org.apache.olingo.server.api.ODataRequest;
 import org.apache.olingo.server.api.ODataTranslatedException;
 import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 public class ODataHttpHandlerImplTest {
 
-  private final Logger LOG = 
LoggerFactory.getLogger(ODataHttpHandlerImplTest.class);
-
   @Test
   public void extractMethod() throws Exception {
     String[][] mm = {
@@ -149,8 +145,6 @@ public class ODataHttpHandlerImplTest {
       String requestUri = p[1] + p[2] + p[3] + p[4];
       String queryString = p[5].isEmpty() ? null : p[5];
 
-      LOG.debug(requestUrl + (queryString == null ? "" : "?" + queryString));
-
       when(hr.getRequestURL()).thenReturn(new StringBuffer(requestUrl));
       when(hr.getRequestURI()).thenReturn(requestUri);
       when(hr.getQueryString()).thenReturn(queryString);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5c0b34a9/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 d079dd0..3ea7b1e 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
@@ -31,7 +31,7 @@ import org.apache.olingo.server.api.OData;
 import org.apache.olingo.server.api.ODataRequest;
 import org.apache.olingo.server.api.ODataResponse;
 import org.apache.olingo.server.api.ODataTranslatedException;
-import org.apache.olingo.server.api.processor.CollectionProcessor;
+import org.apache.olingo.server.api.processor.EntityCollectionProcessor;
 import org.apache.olingo.server.api.processor.EntityProcessor;
 import org.apache.olingo.server.api.serializer.ODataSerializer;
 import org.apache.olingo.server.api.uri.UriInfo;
@@ -42,7 +42,7 @@ import org.apache.olingo.server.tecsvc.data.DataProvider;
 
 import java.util.List;
 
-public class TechnicalProcessor implements CollectionProcessor, 
EntityProcessor {
+public class TechnicalProcessor implements EntityCollectionProcessor, 
EntityProcessor {
 
   private OData odata;
   private Edm edm;

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5c0b34a9/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 efd0e65..5eaff89 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
@@ -21,22 +21,28 @@ package org.apache.olingo.server.core;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
 
 import java.util.Arrays;
+import java.util.Locale;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.olingo.commons.api.edm.Edm;
 import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
+import org.apache.olingo.commons.api.format.ContentType;
 import org.apache.olingo.commons.api.http.HttpContentType;
 import org.apache.olingo.commons.api.http.HttpHeader;
 import org.apache.olingo.commons.api.http.HttpMethod;
 import org.apache.olingo.commons.api.http.HttpStatusCode;
 import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.ODataApplicationException;
 import org.apache.olingo.server.api.ODataRequest;
 import org.apache.olingo.server.api.ODataResponse;
 import org.apache.olingo.server.api.processor.MetadataProcessor;
 import org.apache.olingo.server.api.processor.ServiceDocumentProcessor;
+import org.apache.olingo.server.api.uri.UriInfo;
 import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
 import org.junit.Before;
 import org.junit.Test;
@@ -187,4 +193,47 @@ public class ODataHandlerTest {
     assertEquals(400, response.getStatusCode());
   }
 
+  @Test
+  public void testContentNegotiationSupported() {
+    ODataRequest request = new ODataRequest();
+
+    request.setMethod(HttpMethod.GET);
+    request.setRawODataPath("$metadata");
+    request.setRawQueryPath("$format=xml");
+
+    ODataResponse response = handler.process(request);
+    assertNotNull(response);
+    assertEquals(200, response.getStatusCode());
+  }
+
+  @Test
+  public void testContentNegotiationNotSupported() {
+    ODataRequest request = new ODataRequest();
+
+    request.setMethod(HttpMethod.GET);
+    request.setRawODataPath("$metadata");
+    request.setRawQueryPath("$format=notSupported");
+
+    ODataResponse response = handler.process(request);
+    assertNotNull(response);
+    assertEquals(406, response.getStatusCode());
+  }
+
+  @Test
+  public void testWithApplicationExceptionInProcessor() throws Exception {
+    ODataRequest request = new ODataRequest();
+
+    request.setMethod(HttpMethod.GET);
+    request.setRawODataPath("$metadata");
+
+    MetadataProcessor metadataProcessor = mock(MetadataProcessor.class);
+    doThrow(new ODataApplicationException("msg", 412, 
Locale.ENGLISH)).when(metadataProcessor).readMetadata(
+        any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), 
any(ContentType.class));
+
+    handler.register(metadataProcessor);
+
+    ODataResponse response = handler.process(request);
+    assertNotNull(response);
+    assertEquals(412, response.getStatusCode());
+  }
 }

Reply via email to