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 2015/06/27 11:48:28 UTC

[1/4] olingo-odata2 git commit: [OLINGO-710] FixGetCallbackGeneric

Repository: olingo-odata2
Updated Branches:
  refs/heads/master 5fc3ed2a1 -> 438f7a95e


[OLINGO-710] FixGetCallbackGeneric


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

Branch: refs/heads/master
Commit: 5f81a5c4c2c79a26619528ed9587de27bf27b7e7
Parents: 5fc3ed2
Author: mibo <mi...@mirb.de>
Authored: Sun Jun 21 16:46:36 2015 +0200
Committer: mibo <mi...@mirb.de>
Committed: Sun Jun 21 16:46:36 2015 +0200

----------------------------------------------------------------------
 .../annotation/processor/ref/AnnotationRefServiceFactory.java      | 2 +-
 .../olingo/odata2/jpa/processor/api/ODataJPAServiceFactory.java    | 2 +-
 .../java/org/apache/olingo/odata2/api/ODataServiceFactory.java     | 2 +-
 .../org/apache/olingo/odata2/core/ODataExceptionWrapperTest.java   | 2 +-
 .../odata2/core/rest/ODataServiceFactoryWithCallbackImpl.java      | 2 +-
 .../org/apache/olingo/odata2/fit/misc/ODataApplicationFactory.java | 2 +-
 .../apache/olingo/odata2/ref/processor/ScenarioServiceFactory.java | 2 +-
 .../olingo/odata2/testutil/fit/DebugCallbackFactoryFlase.java      | 2 +-
 .../olingo/odata2/testutil/fit/DebugCallbackFactoryTrue.java       | 2 +-
 .../apache/olingo/odata2/testutil/fit/FitStaticServiceFactory.java | 2 +-
 .../src/main/java/processor/AnnotationSampleServiceFactory.java    | 2 +-
 11 files changed, 11 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/5f81a5c4/odata2-annotation-processor/annotation-processor-ref/src/main/java/org/apache/olingo/odata2/annotation/processor/ref/AnnotationRefServiceFactory.java
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-ref/src/main/java/org/apache/olingo/odata2/annotation/processor/ref/AnnotationRefServiceFactory.java b/odata2-annotation-processor/annotation-processor-ref/src/main/java/org/apache/olingo/odata2/annotation/processor/ref/AnnotationRefServiceFactory.java
index 9130a19..a7cc61d 100644
--- a/odata2-annotation-processor/annotation-processor-ref/src/main/java/org/apache/olingo/odata2/annotation/processor/ref/AnnotationRefServiceFactory.java
+++ b/odata2-annotation-processor/annotation-processor-ref/src/main/java/org/apache/olingo/odata2/annotation/processor/ref/AnnotationRefServiceFactory.java
@@ -77,7 +77,7 @@ public class AnnotationRefServiceFactory extends ODataServiceFactory {
 
   @SuppressWarnings("unchecked")
   @Override
-  public <T extends ODataCallback> T getCallback(final Class<? extends ODataCallback> callbackInterface) {
+  public <T extends ODataCallback> T getCallback(final Class<T> callbackInterface) {
     return (T) (callbackInterface.isAssignableFrom(ScenarioErrorCallback.class)
         ? new ScenarioErrorCallback() : callbackInterface.isAssignableFrom(ODataDebugCallback.class)
             ? new ScenarioDebugCallback() : super.getCallback(callbackInterface));

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/5f81a5c4/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPAServiceFactory.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPAServiceFactory.java b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPAServiceFactory.java
index bb982b8..5566ada 100644
--- a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPAServiceFactory.java
+++ b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPAServiceFactory.java
@@ -159,7 +159,7 @@ public abstract class ODataJPAServiceFactory extends ODataServiceFactory {
 
   @SuppressWarnings("unchecked")
   @Override
-  public <T extends ODataCallback> T getCallback(final Class<? extends ODataCallback> callbackInterface) {
+  public <T extends ODataCallback> T getCallback(final Class<T> callbackInterface) {
     if (setDetailErrors == true) {
       if (callbackInterface.isAssignableFrom(ODataErrorCallback.class)) {
         return (T) new ODataJPAErrorCallback();

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/5f81a5c4/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataServiceFactory.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataServiceFactory.java b/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataServiceFactory.java
index 7b6f7a3..681b70d 100644
--- a/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataServiceFactory.java
+++ b/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataServiceFactory.java
@@ -70,7 +70,7 @@ public abstract class ODataServiceFactory {
    * @param callbackInterface a interface type to query for implementation
    * @return a callback implementation for this interface or null
    */
-  public <T extends ODataCallback> T getCallback(final Class<? extends ODataCallback> callbackInterface) {
+  public <T extends ODataCallback> T getCallback(final Class<T> callbackInterface) {
     return null;
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/5f81a5c4/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataExceptionWrapperTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataExceptionWrapperTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataExceptionWrapperTest.java
index a2fe86c..98c6b26 100644
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataExceptionWrapperTest.java
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataExceptionWrapperTest.java
@@ -118,7 +118,7 @@ public class ODataExceptionWrapperTest extends BaseTest {
 
     @SuppressWarnings("unchecked")
     @Override
-    public <T extends ODataCallback> T getCallback(final Class<? extends ODataCallback> callbackInterface) {
+    public <T extends ODataCallback> T getCallback(final Class<T> callbackInterface) {
       if (callbackInterface == ODataErrorCallback.class) {
         if (errorCallback == null) {
           return (T) new ODataErrorHandlerCallbackImpl();

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/5f81a5c4/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/rest/ODataServiceFactoryWithCallbackImpl.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/rest/ODataServiceFactoryWithCallbackImpl.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/rest/ODataServiceFactoryWithCallbackImpl.java
index c210de6..0d24da4 100644
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/rest/ODataServiceFactoryWithCallbackImpl.java
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/rest/ODataServiceFactoryWithCallbackImpl.java
@@ -38,7 +38,7 @@ public class ODataServiceFactoryWithCallbackImpl extends ODataServiceFactory {
 
   @SuppressWarnings("unchecked")
   @Override
-  public <T extends ODataCallback> T getCallback(final Class<? extends ODataCallback> callbackInterface) {
+  public <T extends ODataCallback> T getCallback(final Class<T> callbackInterface) {
     T callback = null;
 
     if (callbackInterface == ODataErrorCallback.class) {

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/5f81a5c4/odata2-lib/odata-fit/src/test/java/org/apache/olingo/odata2/fit/misc/ODataApplicationFactory.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-fit/src/test/java/org/apache/olingo/odata2/fit/misc/ODataApplicationFactory.java b/odata2-lib/odata-fit/src/test/java/org/apache/olingo/odata2/fit/misc/ODataApplicationFactory.java
index e28aad2..7577cc8 100644
--- a/odata2-lib/odata-fit/src/test/java/org/apache/olingo/odata2/fit/misc/ODataApplicationFactory.java
+++ b/odata2-lib/odata-fit/src/test/java/org/apache/olingo/odata2/fit/misc/ODataApplicationFactory.java
@@ -33,7 +33,7 @@ public class ODataApplicationFactory extends ODataServiceFactory {
   }
 
   @Override
-  public <T extends ODataCallback> T getCallback(final Class<? extends ODataCallback> callbackInterface) {
+  public <T extends ODataCallback> T getCallback(final Class<T> callbackInterface) {
     return new ScenarioServiceFactory().getCallback(callbackInterface);
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/5f81a5c4/odata2-lib/odata-ref/src/main/java/org/apache/olingo/odata2/ref/processor/ScenarioServiceFactory.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-ref/src/main/java/org/apache/olingo/odata2/ref/processor/ScenarioServiceFactory.java b/odata2-lib/odata-ref/src/main/java/org/apache/olingo/odata2/ref/processor/ScenarioServiceFactory.java
index d3075da..add23f9 100644
--- a/odata2-lib/odata-ref/src/main/java/org/apache/olingo/odata2/ref/processor/ScenarioServiceFactory.java
+++ b/odata2-lib/odata-ref/src/main/java/org/apache/olingo/odata2/ref/processor/ScenarioServiceFactory.java
@@ -44,7 +44,7 @@ public class ScenarioServiceFactory extends ODataServiceFactory {
 
   @SuppressWarnings("unchecked")
   @Override
-  public <T extends ODataCallback> T getCallback(final Class<? extends ODataCallback> callbackInterface) {
+  public <T extends ODataCallback> T getCallback(final Class<T> callbackInterface) {
     return (T) (callbackInterface.isAssignableFrom(ScenarioErrorCallback.class) ?
         new ScenarioErrorCallback() : callbackInterface.isAssignableFrom(ODataDebugCallback.class) ?
             new ScenarioDebugCallback() : super.getCallback(callbackInterface));

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/5f81a5c4/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/fit/DebugCallbackFactoryFlase.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/fit/DebugCallbackFactoryFlase.java b/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/fit/DebugCallbackFactoryFlase.java
index 9e7cdc6..fc71390 100644
--- a/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/fit/DebugCallbackFactoryFlase.java
+++ b/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/fit/DebugCallbackFactoryFlase.java
@@ -25,7 +25,7 @@ public class DebugCallbackFactoryFlase extends FitStaticServiceFactory {
 
   @SuppressWarnings("unchecked")
   @Override
-  public <T extends ODataCallback> T getCallback(final Class<? extends ODataCallback> callbackInterface) {
+  public <T extends ODataCallback> T getCallback(final Class<T> callbackInterface) {
     if (callbackInterface.isAssignableFrom(FitErrorCallback.class)) {
       return (T) new FitErrorCallback();
     } else if (callbackInterface.isAssignableFrom(ODataDebugCallback.class)) {

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/5f81a5c4/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/fit/DebugCallbackFactoryTrue.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/fit/DebugCallbackFactoryTrue.java b/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/fit/DebugCallbackFactoryTrue.java
index 66f483d..ba7248b 100644
--- a/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/fit/DebugCallbackFactoryTrue.java
+++ b/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/fit/DebugCallbackFactoryTrue.java
@@ -25,7 +25,7 @@ public class DebugCallbackFactoryTrue extends FitStaticServiceFactory {
 
   @SuppressWarnings("unchecked")
   @Override
-  public <T extends ODataCallback> T getCallback(final Class<? extends ODataCallback> callbackInterface) {
+  public <T extends ODataCallback> T getCallback(final Class<T> callbackInterface) {
     if (callbackInterface.isAssignableFrom(FitErrorCallback.class)) {
       return (T) new FitErrorCallback();
     } else if (callbackInterface.isAssignableFrom(ODataDebugCallback.class)) {

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/5f81a5c4/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/fit/FitStaticServiceFactory.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/fit/FitStaticServiceFactory.java b/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/fit/FitStaticServiceFactory.java
index 0a86faf..fd8a9ea 100644
--- a/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/fit/FitStaticServiceFactory.java
+++ b/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/fit/FitStaticServiceFactory.java
@@ -40,7 +40,7 @@ public class FitStaticServiceFactory extends ODataServiceFactory {
 
   @SuppressWarnings("unchecked")
   @Override
-  public <T extends ODataCallback> T getCallback(final Class<? extends ODataCallback> callbackInterface) {
+  public <T extends ODataCallback> T getCallback(final Class<T> callbackInterface) {
     if (callbackInterface.isAssignableFrom(FitErrorCallback.class)) {
       return (T) new FitErrorCallback();
     }

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/5f81a5c4/odata2-sample/cars-annotation-archetype/src/main/resources/archetype-resources/src/main/java/processor/AnnotationSampleServiceFactory.java
----------------------------------------------------------------------
diff --git a/odata2-sample/cars-annotation-archetype/src/main/resources/archetype-resources/src/main/java/processor/AnnotationSampleServiceFactory.java b/odata2-sample/cars-annotation-archetype/src/main/resources/archetype-resources/src/main/java/processor/AnnotationSampleServiceFactory.java
index fc8ebb2..c244bf6 100644
--- a/odata2-sample/cars-annotation-archetype/src/main/resources/archetype-resources/src/main/java/processor/AnnotationSampleServiceFactory.java
+++ b/odata2-sample/cars-annotation-archetype/src/main/resources/archetype-resources/src/main/java/processor/AnnotationSampleServiceFactory.java
@@ -69,7 +69,7 @@ public class AnnotationSampleServiceFactory extends ODataServiceFactory {
 
   @SuppressWarnings("unchecked")
   @Override
-  public <T extends ODataCallback> T getCallback(final Class<? extends ODataCallback> callbackInterface) {
+  public <T extends ODataCallback> T getCallback(final Class<T> callbackInterface) {
     return (T) (callbackInterface.isAssignableFrom(ScenarioErrorCallback.class)
             ? new ScenarioErrorCallback() : callbackInterface.isAssignableFrom(ODataDebugCallback.class)
             ? new ScenarioDebugCallback() : super.getCallback(callbackInterface));


[4/4] olingo-odata2 git commit: Merge branch 'OLINGO-709-InjectODataServiceFactory'

Posted by mi...@apache.org.
Merge branch 'OLINGO-709-InjectODataServiceFactory'


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

Branch: refs/heads/master
Commit: 438f7a95e6209aafb763d3790f260efd6067d0d7
Parents: 5f81a5c ac22319
Author: mibo <mi...@mirb.de>
Authored: Sat Jun 27 11:45:03 2015 +0200
Committer: mibo <mi...@mirb.de>
Committed: Sat Jun 27 11:45:03 2015 +0200

----------------------------------------------------------------------
 .../olingo/odata2/api/ODataServiceFactory.java  |   5 +
 .../odata2/core/servlet/ODataServlet.java       | 112 +++++++++++++------
 .../olingo/odata2/core/servlet/RestUtil.java    |   5 +-
 .../odata2/core/servlet/ODataServletTest.java   |  54 +++++----
 4 files changed, 120 insertions(+), 56 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/438f7a95/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataServiceFactory.java
----------------------------------------------------------------------


[3/4] olingo-odata2 git commit: [OLINGO-709] Merged abstract with concrete ODataServlet

Posted by mi...@apache.org.
[OLINGO-709] Merged abstract with concrete ODataServlet


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

Branch: refs/heads/master
Commit: ac22319687de5c2da1f58e3667612803fd6ffd2a
Parents: f1ca1a2
Author: Michael Bolz <mi...@sap.com>
Authored: Tue Jun 23 13:39:09 2015 +0200
Committer: Michael Bolz <mi...@sap.com>
Committed: Tue Jun 23 13:39:09 2015 +0200

----------------------------------------------------------------------
 .../core/servlet/AbstractODataServlet.java      | 350 -------------------
 .../odata2/core/servlet/ODataServlet.java       | 321 ++++++++++++++++-
 .../core/servlet/AbstractODataServletTest.java  | 280 ---------------
 .../odata2/core/servlet/ODataServletTest.java   |   8 +-
 4 files changed, 322 insertions(+), 637 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/ac223196/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/AbstractODataServlet.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/AbstractODataServlet.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/AbstractODataServlet.java
deleted file mode 100644
index 2fc6972..0000000
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/AbstractODataServlet.java
+++ /dev/null
@@ -1,350 +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.odata2.core.servlet;
-
-import org.apache.olingo.odata2.api.ODataService;
-import org.apache.olingo.odata2.api.ODataServiceFactory;
-import org.apache.olingo.odata2.api.commons.HttpHeaders;
-import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
-import org.apache.olingo.odata2.api.commons.ODataHttpMethod;
-import org.apache.olingo.odata2.api.exception.MessageReference;
-import org.apache.olingo.odata2.api.exception.ODataBadRequestException;
-import org.apache.olingo.odata2.api.exception.ODataHttpException;
-import org.apache.olingo.odata2.api.exception.ODataInternalServerErrorException;
-import org.apache.olingo.odata2.api.exception.ODataMethodNotAllowedException;
-import org.apache.olingo.odata2.api.exception.ODataNotAcceptableException;
-import org.apache.olingo.odata2.api.exception.ODataNotImplementedException;
-import org.apache.olingo.odata2.api.processor.ODataContext;
-import org.apache.olingo.odata2.api.processor.ODataRequest;
-import org.apache.olingo.odata2.api.processor.ODataResponse;
-import org.apache.olingo.odata2.core.ODataContextImpl;
-import org.apache.olingo.odata2.core.ODataRequestHandler;
-import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
-
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.InputStream;
-
-public abstract class AbstractODataServlet extends HttpServlet {
-
-  private static final String HTTP_METHOD_OPTIONS = "OPTIONS";
-  private static final String HTTP_METHOD_HEAD = "HEAD";
-
-  /**
-   * 
-   */
-  private static final long serialVersionUID = 1L;
-
-  /**
-   * Get the service factory instance which is used for creation of the
-   * <code>ODataService</code> which handles the processing of the request.
-   *
-   * @param request the http request which is processed as an OData request
-   * @return an instance of an ODataServiceFactory
-   */
-  protected abstract ODataServiceFactory getServiceFactory(HttpServletRequest request);
-
-  @Override
-  protected void service(final HttpServletRequest req, final HttpServletResponse resp) throws IOException {
-    // We have to create the Service Factory here because otherwise we do not have access to the error callback
-    ODataServiceFactory serviceFactory = getServiceFactory(req);
-    if(serviceFactory == null) {
-      throw new ODataRuntimeException("Unable to get Service Factory. Check either '" +
-          ODataServiceFactory.FACTORY_LABEL + "' or '" + ODataServiceFactory.FACTORY_INSTANCE_LABEL + "' config.");
-    }
-
-    String xHttpMethod = req.getHeader("X-HTTP-Method");
-    String xHttpMethodOverride = req.getHeader("X-HTTP-Method-Override");
-    if (xHttpMethod != null && xHttpMethodOverride != null) {
-      if (!xHttpMethod.equalsIgnoreCase(xHttpMethodOverride)) {
-        ODataExceptionWrapper wrapper = new ODataExceptionWrapper(req, serviceFactory);
-        createResponse(resp, wrapper.wrapInExceptionResponse(
-            new ODataBadRequestException(ODataBadRequestException.AMBIGUOUS_XMETHOD)));
-      }
-    }
-
-    if (req.getPathInfo() != null) {
-      handle(req, resp, xHttpMethod, xHttpMethodOverride, serviceFactory);
-    } else {
-      handleRedirect(req, resp, serviceFactory);
-    }
-  }
-
-
-  protected void handle(final HttpServletRequest req, final HttpServletResponse resp, final String xHttpMethod,
-      final String xHttpMethodOverride, ODataServiceFactory serviceFactory) throws IOException {
-    String method = req.getMethod();
-    if (ODataHttpMethod.GET.name().equals(method)) {
-      handleRequest(req, ODataHttpMethod.GET, resp, serviceFactory);
-    } else if (ODataHttpMethod.POST.name().equals(method)) {
-      if (xHttpMethod == null && xHttpMethodOverride == null) {
-        handleRequest(req, ODataHttpMethod.POST, resp, serviceFactory);
-      } else if (xHttpMethod == null) {
-        /* tunneling */
-        boolean methodHandled = handleHttpTunneling(req, resp, xHttpMethodOverride, serviceFactory);
-        if (!methodHandled) {
-          createMethodNotAllowedResponse(req, ODataHttpException.COMMON, resp, serviceFactory);
-        }
-      } else {
-        /* tunneling */
-        boolean methodHandled = handleHttpTunneling(req, resp, xHttpMethod, serviceFactory);
-        if (!methodHandled) {
-          createNotImplementedResponse(req, ODataNotImplementedException.TUNNELING, resp, serviceFactory);
-        }
-      }
-
-    } else if (ODataHttpMethod.PUT.name().equals(method)) {
-      handleRequest(req, ODataHttpMethod.PUT, resp, serviceFactory);
-    } else if (ODataHttpMethod.DELETE.name().equals(method)) {
-      handleRequest(req, ODataHttpMethod.DELETE, resp, serviceFactory);
-    } else if (ODataHttpMethod.PATCH.name().equals(method)) {
-      handleRequest(req, ODataHttpMethod.PATCH, resp, serviceFactory);
-    } else if (ODataHttpMethod.MERGE.name().equals(method)) {
-      handleRequest(req, ODataHttpMethod.MERGE, resp, serviceFactory);
-    } else if (HTTP_METHOD_HEAD.equals(method) || HTTP_METHOD_OPTIONS.equals(method)) {
-      createNotImplementedResponse(req, ODataNotImplementedException.COMMON, resp, serviceFactory);
-    } else {
-      createNotImplementedResponse(req, ODataHttpException.COMMON, resp, serviceFactory);
-    }
-  }
-
-  private boolean handleHttpTunneling(final HttpServletRequest req, final HttpServletResponse resp,
-      final String xHttpMethod, ODataServiceFactory serviceFactory) throws IOException {
-    if (ODataHttpMethod.MERGE.name().equals(xHttpMethod)) {
-      handleRequest(req, ODataHttpMethod.MERGE, resp, serviceFactory);
-    } else if (ODataHttpMethod.PATCH.name().equals(xHttpMethod)) {
-      handleRequest(req, ODataHttpMethod.PATCH, resp, serviceFactory);
-    } else if (ODataHttpMethod.DELETE.name().equals(xHttpMethod)) {
-      handleRequest(req, ODataHttpMethod.DELETE, resp, serviceFactory);
-    } else if (ODataHttpMethod.PUT.name().equals(xHttpMethod)) {
-      handleRequest(req, ODataHttpMethod.PUT, resp, serviceFactory);
-    } else if (ODataHttpMethod.GET.name().equals(xHttpMethod)) {
-      handleRequest(req, ODataHttpMethod.GET, resp, serviceFactory);
-    } else if (ODataHttpMethod.POST.name().equals(xHttpMethod)) {
-      handleRequest(req, ODataHttpMethod.POST, resp, serviceFactory);
-    } else if (HTTP_METHOD_HEAD.equals(xHttpMethod) || HTTP_METHOD_OPTIONS.equals(xHttpMethod)) {
-      createNotImplementedResponse(req, ODataNotImplementedException.COMMON, resp, serviceFactory);
-    } else {
-      createNotImplementedResponse(req, ODataNotImplementedException.COMMON, resp, serviceFactory);
-    }
-    return true;
-  }
-
-  private void
-      handleRequest(final HttpServletRequest req, final ODataHttpMethod method, final HttpServletResponse resp,
-          ODataServiceFactory serviceFactory)
-          throws IOException {
-    try {
-      final String pathSplitAsString = getInitParameter(ODataServiceFactory.PATH_SPLIT_LABEL);
-      int pathSplit = 0;
-      if (pathSplitAsString != null) {
-        pathSplit = Integer.parseInt(pathSplitAsString);
-      }
-      if (req.getHeader(HttpHeaders.ACCEPT) != null && req.getHeader(HttpHeaders.ACCEPT).isEmpty()) {
-        createNotAcceptableResponse(req, ODataNotAcceptableException.COMMON, resp, serviceFactory);
-      }
-      ODataRequest odataRequest = ODataRequest.method(method)
-          .contentType(RestUtil.extractRequestContentType(req.getContentType()).toContentTypeString())
-          .acceptHeaders(RestUtil.extractAcceptHeaders(req.getHeader(HttpHeaders.ACCEPT)))
-          .acceptableLanguages(RestUtil.extractAcceptableLanguage(req.getHeader(HttpHeaders.ACCEPT_LANGUAGE)))
-          .pathInfo(RestUtil.buildODataPathInfo(req, pathSplit))
-          .allQueryParameters(RestUtil.extractAllQueryParameters(req.getQueryString()))
-          .requestHeaders(RestUtil.extractHeaders(req))
-          .body(req.getInputStream())
-          .build();
-
-      ODataContextImpl context = new ODataContextImpl(odataRequest, serviceFactory);
-      context.setParameter(ODataContext.HTTP_SERVLET_REQUEST_OBJECT, req);
-
-      ODataService service = serviceFactory.createService(context);
-      if (service == null) {
-        createServiceUnavailableResponse(req, ODataInternalServerErrorException.NOSERVICE, resp, serviceFactory);
-      } else {
-        context.setService(service);
-        service.getProcessor().setContext(context);
-
-        ODataRequestHandler requestHandler = new ODataRequestHandler(serviceFactory, service, context);
-        final ODataResponse odataResponse = requestHandler.handle(odataRequest);
-        createResponse(resp, odataResponse);
-      }
-    } catch (Exception e) {
-      ODataExceptionWrapper wrapper = new ODataExceptionWrapper(req, serviceFactory);
-      createResponse(resp, wrapper.wrapInExceptionResponse(e));
-    }
-  }
-
-  protected void handleRedirect(final HttpServletRequest req, final HttpServletResponse resp,
-                                ODataServiceFactory serviceFactory) throws IOException {
-    String method = req.getMethod();
-    if (ODataHttpMethod.GET.name().equals(method) ||
-        ODataHttpMethod.POST.name().equals(method) ||
-        ODataHttpMethod.PUT.name().equals(method) ||
-        ODataHttpMethod.DELETE.name().equals(method) ||
-        ODataHttpMethod.PATCH.name().equals(method) ||
-        ODataHttpMethod.MERGE.name().equals(method) ||
-        HTTP_METHOD_HEAD.equals(method) ||
-        HTTP_METHOD_OPTIONS.equals(method)) {
-      ODataResponse odataResponse = ODataResponse.status(HttpStatusCodes.TEMPORARY_REDIRECT)
-          .header(HttpHeaders.LOCATION, createLocation(req))
-          .build();
-      createResponse(resp, odataResponse);
-    } else {
-      createNotImplementedResponse(req, ODataHttpException.COMMON, resp, serviceFactory);
-    }
-
-  }
-
-  private String createLocation(final HttpServletRequest req) {
-    StringBuilder location = new StringBuilder();
-    String contextPath = req.getContextPath();
-    if (contextPath != null) {
-      location.append(contextPath);
-    }
-    String servletPath = req.getServletPath();
-    if (servletPath != null) {
-      location.append(servletPath);
-    }
-    location.append("/");
-    return location.toString();
-  }
-
-  protected void createResponse(final HttpServletResponse resp, final ODataResponse response) throws IOException {
-    resp.setStatus(response.getStatus().getStatusCode());
-    resp.setContentType(response.getContentHeader());
-    for (String headerName : response.getHeaderNames()) {
-      resp.setHeader(headerName, response.getHeader(headerName));
-    }
-
-    Object entity = response.getEntity();
-    if (entity != null) {
-      ServletOutputStream out = resp.getOutputStream();
-      int curByte;
-      int contentLength = 0;
-
-      if (entity instanceof InputStream) {
-        while ((curByte = ((InputStream) entity).read()) != -1) {
-          contentLength++;
-          out.write((char) curByte);
-        }
-        ((InputStream) entity).close();
-      } else if (entity instanceof String) {
-        String body = (String) entity;
-        final byte[] entityBytes = body.getBytes("utf-8");
-        out.write(entityBytes);
-        contentLength = entityBytes.length;
-      }
-
-      if (response.getHeader(HttpHeaders.CONTENT_LENGTH) != null) {
-        // Override content length
-        try {
-          contentLength = Integer.parseInt(response.getHeader(HttpHeaders.CONTENT_LENGTH));
-        } catch (NumberFormatException e) {
-          // Ignore
-        }
-      }
-
-      resp.setContentLength(contentLength);
-      out.flush();
-      out.close();
-    }
-  }
-
-  private void createNotImplementedResponse(final HttpServletRequest req, final MessageReference messageReference,
-      final HttpServletResponse resp, ODataServiceFactory serviceFactory) throws IOException {
-    // RFC 2616, 5.1.1: "An origin server SHOULD return the status code [...]
-    // 501 (Not Implemented) if the method is unrecognized [...] by the origin server."
-    ODataExceptionWrapper exceptionWrapper = new ODataExceptionWrapper(req, serviceFactory);
-    ODataResponse response =
-        exceptionWrapper.wrapInExceptionResponse(new ODataNotImplementedException(messageReference));
-//    resp.setStatus(HttpStatusCodes.NOT_IMPLEMENTED.getStatusCode());
-    createResponse(resp, response);
-  }
-
-  private void createMethodNotAllowedResponse(final HttpServletRequest req, final MessageReference messageReference,
-      final HttpServletResponse resp, ODataServiceFactory serviceFactory) throws IOException {
-    ODataExceptionWrapper exceptionWrapper = new ODataExceptionWrapper(req, serviceFactory);
-    ODataResponse response =
-        exceptionWrapper.wrapInExceptionResponse(new ODataMethodNotAllowedException(messageReference));
-    createResponse(resp, response);
-  }
-
-  private void createNotAcceptableResponse(final HttpServletRequest req, final MessageReference messageReference,
-      final HttpServletResponse resp, ODataServiceFactory serviceFactory) throws IOException {
-    ODataExceptionWrapper exceptionWrapper = new ODataExceptionWrapper(req, serviceFactory);
-    ODataResponse response =
-        exceptionWrapper.wrapInExceptionResponse(new ODataNotAcceptableException(messageReference));
-    createResponse(resp, response);
-  }
-
-  private void createServiceUnavailableResponse(HttpServletRequest req, MessageReference messageReference,
-      HttpServletResponse resp, ODataServiceFactory serviceFactory) throws IOException {
-    ODataExceptionWrapper exceptionWrapper = new ODataExceptionWrapper(req, serviceFactory);
-    ODataResponse response =
-        exceptionWrapper.wrapInExceptionResponse(new ODataInternalServerErrorException(messageReference));
-    createResponse(resp, response);
-  }
-
-  /**
-   * Create an instance of a ODataServiceFactory via factory class
-   * from servlet init parameter ODataServiceFactory.FACTORY_LABEL
-   * and ODataServiceFactory.FACTORY_CLASSLOADER_LABEL (if set).
-   *
-   * @see ODataServiceFactory#FACTORY_LABEL
-   * @see ODataServiceFactory#FACTORY_CLASSLOADER_LABEL
-   *
-   * @param req http servlet request
-   * @return instance of a ODataServiceFactory
-   */
-  protected ODataServiceFactory createODataServiceFactory(HttpServletRequest req)
-      throws InstantiationException, IllegalAccessException, ClassNotFoundException {
-    final String factoryClassName = getInitParameter(ODataServiceFactory.FACTORY_LABEL);
-    if(factoryClassName == null) {
-      return null;
-    }
-
-    ClassLoader cl = (ClassLoader) req.getAttribute(ODataServiceFactory.FACTORY_CLASSLOADER_LABEL);
-    if (cl == null) {
-      return (ODataServiceFactory) Class.forName(factoryClassName).newInstance();
-    } else {
-      return (ODataServiceFactory) Class.forName(factoryClassName, true, cl).newInstance();
-    }
-  }
-
-  /**
-   * Get an instance of a ODataServiceFactory from request attribute
-   * ODataServiceFactory.FACTORY_INSTANCE_LABEL
-   *
-   * @see ODataServiceFactory#FACTORY_INSTANCE_LABEL
-   *
-   * @param req http servlet request
-   * @return instance of a ODataServiceFactory
-   */
-  protected ODataServiceFactory getServiceFactoryInstance(HttpServletRequest req) {
-    Object factory = req.getAttribute(ODataServiceFactory.FACTORY_INSTANCE_LABEL);
-    if(factory == null) {
-      return null;
-    } else if(factory instanceof ODataServiceFactory) {
-      return (ODataServiceFactory) factory;
-    }
-    throw new ODataRuntimeException("Invalid service factory instance of type " + factory.getClass());
-  }
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/ac223196/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/ODataServlet.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/ODataServlet.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/ODataServlet.java
index d3e95e8..1aaf9d8 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/ODataServlet.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/ODataServlet.java
@@ -18,21 +18,78 @@
  ******************************************************************************/
 package org.apache.olingo.odata2.core.servlet;
 
+import org.apache.olingo.odata2.api.ODataService;
 import org.apache.olingo.odata2.api.ODataServiceFactory;
+import org.apache.olingo.odata2.api.commons.HttpHeaders;
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.api.commons.ODataHttpMethod;
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.api.exception.ODataBadRequestException;
+import org.apache.olingo.odata2.api.exception.ODataHttpException;
+import org.apache.olingo.odata2.api.exception.ODataInternalServerErrorException;
+import org.apache.olingo.odata2.api.exception.ODataMethodNotAllowedException;
+import org.apache.olingo.odata2.api.exception.ODataNotAcceptableException;
+import org.apache.olingo.odata2.api.exception.ODataNotImplementedException;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.processor.ODataRequest;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.core.ODataContextImpl;
+import org.apache.olingo.odata2.core.ODataRequestHandler;
 import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
 
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
 
-public final class ODataServlet extends AbstractODataServlet {
+public class ODataServlet extends HttpServlet {
 
+  private static final String HTTP_METHOD_OPTIONS = "OPTIONS";
+  private static final String HTTP_METHOD_HEAD = "HEAD";
+
+  /**
+   * 
+   */
   private static final long serialVersionUID = 1L;
 
+  @Override
+  protected void service(final HttpServletRequest req, final HttpServletResponse resp) throws IOException {
+    // We have to create the Service Factory here because otherwise we do not have access to the error callback
+    ODataServiceFactory serviceFactory = getServiceFactory(req);
+    if(serviceFactory == null) {
+      throw new ODataRuntimeException("Unable to get Service Factory. Check either '" +
+          ODataServiceFactory.FACTORY_LABEL + "' or '" + ODataServiceFactory.FACTORY_INSTANCE_LABEL + "' config.");
+    }
+
+    String xHttpMethod = req.getHeader("X-HTTP-Method");
+    String xHttpMethodOverride = req.getHeader("X-HTTP-Method-Override");
+    if (xHttpMethod != null && xHttpMethodOverride != null) {
+      if (!xHttpMethod.equalsIgnoreCase(xHttpMethodOverride)) {
+        ODataExceptionWrapper wrapper = new ODataExceptionWrapper(req, serviceFactory);
+        createResponse(resp, wrapper.wrapInExceptionResponse(
+            new ODataBadRequestException(ODataBadRequestException.AMBIGUOUS_XMETHOD)));
+      }
+    }
+
+    if (req.getPathInfo() != null) {
+      handle(req, resp, xHttpMethod, xHttpMethodOverride, serviceFactory);
+    } else {
+      handleRedirect(req, resp, serviceFactory);
+    }
+  }
+
   /**
-   * @{inherit}
+   * Get the service factory instance which is used for creation of the
+   * <code>ODataService</code> which handles the processing of the request.
+   *
+   * @param request the http request which is processed as an OData request
+   * @return an instance of an ODataServiceFactory
    */
   protected ODataServiceFactory getServiceFactory(HttpServletRequest request) {
     try {
-      ODataServiceFactory factoryInstance = getServiceFactoryInstance(request);
+      ODataServiceFactory factoryInstance = getODataServiceFactoryInstance(request);
       if(factoryInstance == null) {
         return createODataServiceFactory(request);
       }
@@ -42,4 +99,262 @@ public final class ODataServlet extends AbstractODataServlet {
       throw new ODataRuntimeException(e);
     }
   }
+
+  protected void handle(final HttpServletRequest req, final HttpServletResponse resp, final String xHttpMethod,
+      final String xHttpMethodOverride, ODataServiceFactory serviceFactory) throws IOException {
+    String method = req.getMethod();
+    if (ODataHttpMethod.GET.name().equals(method)) {
+      handleRequest(req, ODataHttpMethod.GET, resp, serviceFactory);
+    } else if (ODataHttpMethod.POST.name().equals(method)) {
+      if (xHttpMethod == null && xHttpMethodOverride == null) {
+        handleRequest(req, ODataHttpMethod.POST, resp, serviceFactory);
+      } else if (xHttpMethod == null) {
+        /* tunneling */
+        boolean methodHandled = handleHttpTunneling(req, resp, xHttpMethodOverride, serviceFactory);
+        if (!methodHandled) {
+          createMethodNotAllowedResponse(req, ODataHttpException.COMMON, resp, serviceFactory);
+        }
+      } else {
+        /* tunneling */
+        boolean methodHandled = handleHttpTunneling(req, resp, xHttpMethod, serviceFactory);
+        if (!methodHandled) {
+          createNotImplementedResponse(req, ODataNotImplementedException.TUNNELING, resp, serviceFactory);
+        }
+      }
+
+    } else if (ODataHttpMethod.PUT.name().equals(method)) {
+      handleRequest(req, ODataHttpMethod.PUT, resp, serviceFactory);
+    } else if (ODataHttpMethod.DELETE.name().equals(method)) {
+      handleRequest(req, ODataHttpMethod.DELETE, resp, serviceFactory);
+    } else if (ODataHttpMethod.PATCH.name().equals(method)) {
+      handleRequest(req, ODataHttpMethod.PATCH, resp, serviceFactory);
+    } else if (ODataHttpMethod.MERGE.name().equals(method)) {
+      handleRequest(req, ODataHttpMethod.MERGE, resp, serviceFactory);
+    } else if (HTTP_METHOD_HEAD.equals(method) || HTTP_METHOD_OPTIONS.equals(method)) {
+      createNotImplementedResponse(req, ODataNotImplementedException.COMMON, resp, serviceFactory);
+    } else {
+      createNotImplementedResponse(req, ODataHttpException.COMMON, resp, serviceFactory);
+    }
+  }
+
+  private boolean handleHttpTunneling(final HttpServletRequest req, final HttpServletResponse resp,
+      final String xHttpMethod, ODataServiceFactory serviceFactory) throws IOException {
+    if (ODataHttpMethod.MERGE.name().equals(xHttpMethod)) {
+      handleRequest(req, ODataHttpMethod.MERGE, resp, serviceFactory);
+    } else if (ODataHttpMethod.PATCH.name().equals(xHttpMethod)) {
+      handleRequest(req, ODataHttpMethod.PATCH, resp, serviceFactory);
+    } else if (ODataHttpMethod.DELETE.name().equals(xHttpMethod)) {
+      handleRequest(req, ODataHttpMethod.DELETE, resp, serviceFactory);
+    } else if (ODataHttpMethod.PUT.name().equals(xHttpMethod)) {
+      handleRequest(req, ODataHttpMethod.PUT, resp, serviceFactory);
+    } else if (ODataHttpMethod.GET.name().equals(xHttpMethod)) {
+      handleRequest(req, ODataHttpMethod.GET, resp, serviceFactory);
+    } else if (ODataHttpMethod.POST.name().equals(xHttpMethod)) {
+      handleRequest(req, ODataHttpMethod.POST, resp, serviceFactory);
+    } else if (HTTP_METHOD_HEAD.equals(xHttpMethod) || HTTP_METHOD_OPTIONS.equals(xHttpMethod)) {
+      createNotImplementedResponse(req, ODataNotImplementedException.COMMON, resp, serviceFactory);
+    } else {
+      createNotImplementedResponse(req, ODataNotImplementedException.COMMON, resp, serviceFactory);
+    }
+    return true;
+  }
+
+  private void
+      handleRequest(final HttpServletRequest req, final ODataHttpMethod method, final HttpServletResponse resp,
+          ODataServiceFactory serviceFactory)
+          throws IOException {
+    try {
+      final String pathSplitAsString = getInitParameter(ODataServiceFactory.PATH_SPLIT_LABEL);
+      int pathSplit = 0;
+      if (pathSplitAsString != null) {
+        pathSplit = Integer.parseInt(pathSplitAsString);
+      }
+      if (req.getHeader(HttpHeaders.ACCEPT) != null && req.getHeader(HttpHeaders.ACCEPT).isEmpty()) {
+        createNotAcceptableResponse(req, ODataNotAcceptableException.COMMON, resp, serviceFactory);
+      }
+      ODataRequest odataRequest = ODataRequest.method(method)
+          .contentType(RestUtil.extractRequestContentType(req.getContentType()).toContentTypeString())
+          .acceptHeaders(RestUtil.extractAcceptHeaders(req.getHeader(HttpHeaders.ACCEPT)))
+          .acceptableLanguages(RestUtil.extractAcceptableLanguage(req.getHeader(HttpHeaders.ACCEPT_LANGUAGE)))
+          .pathInfo(RestUtil.buildODataPathInfo(req, pathSplit))
+          .allQueryParameters(RestUtil.extractAllQueryParameters(req.getQueryString()))
+          .requestHeaders(RestUtil.extractHeaders(req))
+          .body(req.getInputStream())
+          .build();
+
+      ODataContextImpl context = new ODataContextImpl(odataRequest, serviceFactory);
+      context.setParameter(ODataContext.HTTP_SERVLET_REQUEST_OBJECT, req);
+
+      ODataService service = serviceFactory.createService(context);
+      if (service == null) {
+        createServiceUnavailableResponse(req, ODataInternalServerErrorException.NOSERVICE, resp, serviceFactory);
+      } else {
+        context.setService(service);
+        service.getProcessor().setContext(context);
+
+        ODataRequestHandler requestHandler = new ODataRequestHandler(serviceFactory, service, context);
+        final ODataResponse odataResponse = requestHandler.handle(odataRequest);
+        createResponse(resp, odataResponse);
+      }
+    } catch (Exception e) {
+      ODataExceptionWrapper wrapper = new ODataExceptionWrapper(req, serviceFactory);
+      createResponse(resp, wrapper.wrapInExceptionResponse(e));
+    }
+  }
+
+  protected void handleRedirect(final HttpServletRequest req, final HttpServletResponse resp,
+                                ODataServiceFactory serviceFactory) throws IOException {
+    String method = req.getMethod();
+    if (ODataHttpMethod.GET.name().equals(method) ||
+        ODataHttpMethod.POST.name().equals(method) ||
+        ODataHttpMethod.PUT.name().equals(method) ||
+        ODataHttpMethod.DELETE.name().equals(method) ||
+        ODataHttpMethod.PATCH.name().equals(method) ||
+        ODataHttpMethod.MERGE.name().equals(method) ||
+        HTTP_METHOD_HEAD.equals(method) ||
+        HTTP_METHOD_OPTIONS.equals(method)) {
+      ODataResponse odataResponse = ODataResponse.status(HttpStatusCodes.TEMPORARY_REDIRECT)
+          .header(HttpHeaders.LOCATION, createLocation(req))
+          .build();
+      createResponse(resp, odataResponse);
+    } else {
+      createNotImplementedResponse(req, ODataHttpException.COMMON, resp, serviceFactory);
+    }
+
+  }
+
+  private String createLocation(final HttpServletRequest req) {
+    StringBuilder location = new StringBuilder();
+    String contextPath = req.getContextPath();
+    if (contextPath != null) {
+      location.append(contextPath);
+    }
+    String servletPath = req.getServletPath();
+    if (servletPath != null) {
+      location.append(servletPath);
+    }
+    location.append("/");
+    return location.toString();
+  }
+
+  protected void createResponse(final HttpServletResponse resp, final ODataResponse response) throws IOException {
+    resp.setStatus(response.getStatus().getStatusCode());
+    resp.setContentType(response.getContentHeader());
+    for (String headerName : response.getHeaderNames()) {
+      resp.setHeader(headerName, response.getHeader(headerName));
+    }
+
+    Object entity = response.getEntity();
+    if (entity != null) {
+      ServletOutputStream out = resp.getOutputStream();
+      int curByte;
+      int contentLength = 0;
+
+      if (entity instanceof InputStream) {
+        while ((curByte = ((InputStream) entity).read()) != -1) {
+          contentLength++;
+          out.write((char) curByte);
+        }
+        ((InputStream) entity).close();
+      } else if (entity instanceof String) {
+        String body = (String) entity;
+        final byte[] entityBytes = body.getBytes("utf-8");
+        out.write(entityBytes);
+        contentLength = entityBytes.length;
+      }
+
+      if (response.getHeader(HttpHeaders.CONTENT_LENGTH) != null) {
+        // Override content length
+        try {
+          contentLength = Integer.parseInt(response.getHeader(HttpHeaders.CONTENT_LENGTH));
+        } catch (NumberFormatException e) {
+          // Ignore
+        }
+      }
+
+      resp.setContentLength(contentLength);
+      out.flush();
+      out.close();
+    }
+  }
+
+  private void createNotImplementedResponse(final HttpServletRequest req, final MessageReference messageReference,
+      final HttpServletResponse resp, ODataServiceFactory serviceFactory) throws IOException {
+    // RFC 2616, 5.1.1: "An origin server SHOULD return the status code [...]
+    // 501 (Not Implemented) if the method is unrecognized [...] by the origin server."
+    ODataExceptionWrapper exceptionWrapper = new ODataExceptionWrapper(req, serviceFactory);
+    ODataResponse response =
+        exceptionWrapper.wrapInExceptionResponse(new ODataNotImplementedException(messageReference));
+//    resp.setStatus(HttpStatusCodes.NOT_IMPLEMENTED.getStatusCode());
+    createResponse(resp, response);
+  }
+
+  private void createMethodNotAllowedResponse(final HttpServletRequest req, final MessageReference messageReference,
+      final HttpServletResponse resp, ODataServiceFactory serviceFactory) throws IOException {
+    ODataExceptionWrapper exceptionWrapper = new ODataExceptionWrapper(req, serviceFactory);
+    ODataResponse response =
+        exceptionWrapper.wrapInExceptionResponse(new ODataMethodNotAllowedException(messageReference));
+    createResponse(resp, response);
+  }
+
+  private void createNotAcceptableResponse(final HttpServletRequest req, final MessageReference messageReference,
+      final HttpServletResponse resp, ODataServiceFactory serviceFactory) throws IOException {
+    ODataExceptionWrapper exceptionWrapper = new ODataExceptionWrapper(req, serviceFactory);
+    ODataResponse response =
+        exceptionWrapper.wrapInExceptionResponse(new ODataNotAcceptableException(messageReference));
+    createResponse(resp, response);
+  }
+
+  private void createServiceUnavailableResponse(HttpServletRequest req, MessageReference messageReference,
+      HttpServletResponse resp, ODataServiceFactory serviceFactory) throws IOException {
+    ODataExceptionWrapper exceptionWrapper = new ODataExceptionWrapper(req, serviceFactory);
+    ODataResponse response =
+        exceptionWrapper.wrapInExceptionResponse(new ODataInternalServerErrorException(messageReference));
+    createResponse(resp, response);
+  }
+
+  /**
+   * Create an instance of a ODataServiceFactory via factory class
+   * from servlet init parameter ODataServiceFactory.FACTORY_LABEL
+   * and ODataServiceFactory.FACTORY_CLASSLOADER_LABEL (if set).
+   *
+   * @see ODataServiceFactory#FACTORY_LABEL
+   * @see ODataServiceFactory#FACTORY_CLASSLOADER_LABEL
+   *
+   * @param req http servlet request
+   * @return instance of a ODataServiceFactory
+   */
+  private ODataServiceFactory createODataServiceFactory(HttpServletRequest req)
+      throws InstantiationException, IllegalAccessException, ClassNotFoundException {
+    final String factoryClassName = getInitParameter(ODataServiceFactory.FACTORY_LABEL);
+    if(factoryClassName == null) {
+      return null;
+    }
+
+    ClassLoader cl = (ClassLoader) req.getAttribute(ODataServiceFactory.FACTORY_CLASSLOADER_LABEL);
+    if (cl == null) {
+      return (ODataServiceFactory) Class.forName(factoryClassName).newInstance();
+    } else {
+      return (ODataServiceFactory) Class.forName(factoryClassName, true, cl).newInstance();
+    }
+  }
+
+  /**
+   * Get an instance of a ODataServiceFactory from request attribute
+   * ODataServiceFactory.FACTORY_INSTANCE_LABEL
+   *
+   * @see ODataServiceFactory#FACTORY_INSTANCE_LABEL
+   *
+   * @param req http servlet request
+   * @return instance of a ODataServiceFactory
+   */
+  private ODataServiceFactory getODataServiceFactoryInstance(HttpServletRequest req) {
+    Object factory = req.getAttribute(ODataServiceFactory.FACTORY_INSTANCE_LABEL);
+    if(factory == null) {
+      return null;
+    } else if(factory instanceof ODataServiceFactory) {
+      return (ODataServiceFactory) factory;
+    }
+    throw new ODataRuntimeException("Invalid service factory instance of type " + factory.getClass());
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/ac223196/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/servlet/AbstractODataServletTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/servlet/AbstractODataServletTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/servlet/AbstractODataServletTest.java
deleted file mode 100644
index de21917..0000000
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/servlet/AbstractODataServletTest.java
+++ /dev/null
@@ -1,280 +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.odata2.core.servlet;
-
-import junit.framework.Assert;
-import org.apache.olingo.odata2.api.ODataService;
-import org.apache.olingo.odata2.api.ODataServiceFactory;
-import org.apache.olingo.odata2.api.commons.HttpHeaders;
-import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
-import org.apache.olingo.odata2.api.processor.ODataContext;
-import org.apache.olingo.odata2.api.processor.ODataProcessor;
-import org.apache.olingo.odata2.api.processor.ODataResponse;
-import org.apache.olingo.odata2.api.servicedocument.Collection;
-import org.apache.olingo.odata2.core.ODataResponseImpl;
-import org.apache.olingo.odata2.core.rest.ODataServiceFactoryImpl;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-import javax.servlet.GenericServlet;
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.Collections;
-
-/**
- *
- */
-public class AbstractODataServletTest {
-
-  private HttpServletRequest reqMock;
-  private HttpServletResponse respMock;
-  private ServletConfig configMock;
-
-  public AbstractODataServletTest() {
-    reqMock = Mockito.mock(HttpServletRequest.class);
-    respMock = Mockito.mock(HttpServletResponse.class);
-    configMock = Mockito.mock(ServletConfig.class);
-  }
-
-  private static class MyTestODataServlet extends AbstractODataServlet {
-    enum ServiceFactorySource {INSTANCE, CLASSLOADER, MOCK};
-
-    ODataServiceFactory viaInstance;
-    ODataServiceFactory viaClassLoader;
-    ODataServiceFactory viaMock;
-    final ServiceFactorySource source;
-
-    public MyTestODataServlet() {
-      this(ServiceFactorySource.MOCK);
-    }
-
-    public MyTestODataServlet(ServiceFactorySource source) {
-      this.source = source;
-    }
-
-    @Override
-    protected ODataServiceFactory getServiceFactory(HttpServletRequest request) {
-      viaInstance = getServiceFactoryInstance(request);
-      try {
-        viaClassLoader = createODataServiceFactory(request);
-      } catch (Exception e) {
-        throw new RuntimeException(e);
-      }
-      viaMock = Mockito.mock(ODataServiceFactory.class);
-
-      switch (source) {
-        case INSTANCE: return viaInstance;
-        case CLASSLOADER: return viaClassLoader;
-        case MOCK: return viaMock;
-      }
-      return null;
-    }
-  }
-
-  @Test
-  public void handleRedirect() throws Exception {
-    AbstractODataServlet servlet = new MyTestODataServlet();
-    prepareServlet(servlet);
-    prepareRequest(reqMock);
-    servlet.service(reqMock, respMock);
-
-    Mockito.verify(respMock).setStatus(HttpStatusCodes.TEMPORARY_REDIRECT.getStatusCode());
-    Mockito.verify(respMock).setHeader(HttpHeaders.LOCATION, "/context-path/servlet-path/");
-  }
-
-  @Test
-  public void handleRedirectWoServletPath() throws Exception {
-    AbstractODataServlet servlet = new MyTestODataServlet();
-    prepareServlet(servlet);
-    prepareRequest(reqMock, "/context-path", null);
-    servlet.service(reqMock, respMock);
-
-    Mockito.verify(respMock).setStatus(HttpStatusCodes.TEMPORARY_REDIRECT.getStatusCode());
-    Mockito.verify(respMock).setHeader(HttpHeaders.LOCATION, "/context-path/");
-  }
-
-  @Test
-  public void handleRedirectWoContextPath() throws Exception {
-    AbstractODataServlet servlet = new MyTestODataServlet();
-    prepareServlet(servlet);
-    prepareRequest(reqMock, null, "/servlet-path");
-    servlet.service(reqMock, respMock);
-
-    Mockito.verify(respMock).setStatus(HttpStatusCodes.TEMPORARY_REDIRECT.getStatusCode());
-    Mockito.verify(respMock).setHeader(HttpHeaders.LOCATION, "/servlet-path/");
-  }
-
-  @Test
-  public void handleRedirectWoPath() throws Exception {
-    AbstractODataServlet servlet = new MyTestODataServlet();
-    prepareServlet(servlet);
-    prepareRequest(reqMock, null, null);
-    servlet.service(reqMock, respMock);
-
-    Mockito.verify(respMock).setStatus(HttpStatusCodes.TEMPORARY_REDIRECT.getStatusCode());
-    Mockito.verify(respMock).setHeader(HttpHeaders.LOCATION, "/");
-  }
-
-  @Test
-  public void contentLengthCalculatedString() throws Exception {
-    final Method createResponse =
-        AbstractODataServlet.class.getDeclaredMethod("createResponse", HttpServletResponse.class, ODataResponse.class);
-    createResponse.setAccessible(true);
-
-    final AbstractODataServlet servlet = new MyTestODataServlet();
-    final String content = "Test\r\n";
-    final ODataResponse response = ODataResponseImpl.status(HttpStatusCodes.OK).entity(content).build();
-    prepareResponseMockToWrite(respMock);
-    prepareServlet(servlet);
-
-    createResponse.invoke(servlet, respMock, response);
-    Mockito.verify(respMock).setContentLength(content.getBytes("utf-8").length);
-  }
-
-  @Test
-  public void contentLengthCalculatedStream() throws Exception {
-    final Method createResponse =
-        AbstractODataServlet.class.getDeclaredMethod("createResponse", HttpServletResponse.class, ODataResponse.class);
-    createResponse.setAccessible(true);
-
-    final AbstractODataServlet servlet = new MyTestODataServlet();
-    final String content = "Test\r\n";
-
-    final ODataResponse response =
-        ODataResponseImpl.status(HttpStatusCodes.OK).entity(new ByteArrayInputStream(content.getBytes("utf-8")))
-            .build();
-    prepareResponseMockToWrite(respMock);
-    prepareServlet(servlet);
-
-    createResponse.invoke(servlet, respMock, response);
-    Mockito.verify(respMock).setContentLength(content.getBytes("utf-8").length);
-  }
-
-  @Test
-  public void contentLengthHeader() throws Exception {
-    final Method createResponse =
-        AbstractODataServlet.class.getDeclaredMethod("createResponse", HttpServletResponse.class, ODataResponse.class);
-    createResponse.setAccessible(true);
-    final AbstractODataServlet servlet = new MyTestODataServlet();
-    final ODataResponse response =
-        ODataResponseImpl.status(HttpStatusCodes.OK).header(HttpHeaders.CONTENT_LENGTH, "15").entity("").build();
-    prepareResponseMockToWrite(respMock);
-    prepareServlet(servlet);
-
-    createResponse.invoke(servlet, respMock, response);
-
-    Mockito.verify(respMock).setHeader(HttpHeaders.CONTENT_LENGTH, "15");
-    Mockito.verify(respMock).setContentLength(15);
-  }
-
-  @Test
-  public void contentLengthHeaderInvalid() throws Exception {
-    final Method createResponse =
-        AbstractODataServlet.class.getDeclaredMethod("createResponse", HttpServletResponse.class, ODataResponse.class);
-    createResponse.setAccessible(true);
-    final AbstractODataServlet servlet = new MyTestODataServlet();
-    final ODataResponse response =
-        ODataResponseImpl.status(HttpStatusCodes.OK).header(HttpHeaders.CONTENT_LENGTH, "ab").entity("Test").build();
-    prepareResponseMockToWrite(respMock);
-    prepareServlet(servlet);
-
-    createResponse.invoke(servlet, respMock, response);
-
-    Mockito.verify(respMock).setHeader(HttpHeaders.CONTENT_LENGTH, "ab");
-    Mockito.verify(respMock).setContentLength(4); // ||"Test"|| = 4
-  }
-
-  @Test
-  public void serviceInstance() throws Exception {
-    MyTestODataServlet servlet = new MyTestODataServlet(MyTestODataServlet.ServiceFactorySource.INSTANCE);
-    prepareServlet(servlet, false);
-    prepareRequest(reqMock, "", "/servlet-path");
-    Mockito.when(reqMock.getPathInfo()).thenReturn("/request-path-info");
-    Mockito.when(reqMock.getRequestURI()).thenReturn("http://localhost:8080/servlet-path/request-path-info");
-    ODataServiceFactory factory = Mockito.mock(ODataServiceFactory.class);
-    ODataService service = Mockito.mock(ODataService.class);
-    Mockito.when(factory.createService(Mockito.any(ODataContext.class))).thenReturn(service);
-    ODataProcessor processor = Mockito.mock(ODataProcessor.class);
-    Mockito.when(service.getProcessor()).thenReturn(processor);
-    Mockito.when(reqMock.getAttribute(ODataServiceFactory.FACTORY_INSTANCE_LABEL)).thenReturn(factory);
-    Mockito.when(respMock.getOutputStream()).thenReturn(Mockito.mock(ServletOutputStream.class));
-
-    servlet.service(reqMock, respMock);
-
-    Mockito.verify(factory).createService(Mockito.any(ODataContext.class));
-    Assert.assertNotNull(servlet.viaInstance);
-    Assert.assertNull(servlet.viaClassLoader);
-  }
-
-  @Test
-  public void serviceClassloader() throws Exception {
-    MyTestODataServlet servlet = new MyTestODataServlet(MyTestODataServlet.ServiceFactorySource.CLASSLOADER);
-    prepareServlet(servlet);
-    prepareRequest(reqMock, "", "/servlet-path");
-    Mockito.when(reqMock.getPathInfo()).thenReturn("/request-path-info");
-    Mockito.when(reqMock.getRequestURI()).thenReturn("http://localhost:8080/servlet-path/request-path-info");
-    Mockito.when(respMock.getOutputStream()).thenReturn(Mockito.mock(ServletOutputStream.class));
-
-    servlet.service(reqMock, respMock);
-
-    Assert.assertNull(servlet.viaInstance);
-    Assert.assertNotNull(servlet.viaClassLoader);
-  }
-
-  private void prepareResponseMockToWrite(final HttpServletResponse response) throws IOException {
-    Mockito.when(response.getOutputStream()).thenReturn(new ServletOutputStream() {
-      @Override
-      public void write(int b) throws IOException {}
-    });
-  }
-
-  private void prepareRequest(final HttpServletRequest req, final String contextPath, final String servletPath) {
-    Mockito.when(req.getMethod()).thenReturn("GET");
-    Mockito.when(req.getContextPath()).thenReturn(contextPath);
-    Mockito.when(req.getServletPath()).thenReturn(servletPath);
-    Mockito.when(req.getHeaderNames()).thenReturn(Collections.emptyEnumeration());
-  }
-
-  private void prepareRequest(final HttpServletRequest req) {
-    prepareRequest(req, "/context-path", "/servlet-path");
-  }
-
-  private void prepareServlet(final GenericServlet servlet) throws Exception {
-    prepareServlet(servlet, true);
-  }
-
-  private void prepareServlet(final GenericServlet servlet, boolean withFactoryLabel) throws Exception {
-    // private transient ServletConfig config;
-    Field configField = GenericServlet.class.getDeclaredField("config");
-    configField.setAccessible(true);
-    configField.set(servlet, configMock);
-
-    if(withFactoryLabel) {
-      String factoryClassName = ODataServiceFactoryImpl.class.getName();
-      Mockito.when(configMock.getInitParameter(ODataServiceFactory.FACTORY_LABEL)).thenReturn(factoryClassName);
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/ac223196/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/servlet/ODataServletTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/servlet/ODataServletTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/servlet/ODataServletTest.java
index e1ad5dc..da985e5 100644
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/servlet/ODataServletTest.java
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/servlet/ODataServletTest.java
@@ -105,7 +105,7 @@ public class ODataServletTest {
   @Test
   public void contentLengthCalculatedString() throws Exception {
     final Method createResponse =
-        AbstractODataServlet.class.getDeclaredMethod("createResponse", HttpServletResponse.class, ODataResponse.class);
+        ODataServlet.class.getDeclaredMethod("createResponse", HttpServletResponse.class, ODataResponse.class);
     createResponse.setAccessible(true);
 
     final ODataServlet servlet = new ODataServlet();
@@ -121,7 +121,7 @@ public class ODataServletTest {
   @Test
   public void contentLengthCalculatedStream() throws Exception {
     final Method createResponse =
-        AbstractODataServlet.class.getDeclaredMethod("createResponse", HttpServletResponse.class, ODataResponse.class);
+        ODataServlet.class.getDeclaredMethod("createResponse", HttpServletResponse.class, ODataResponse.class);
     createResponse.setAccessible(true);
 
     final ODataServlet servlet = new ODataServlet();
@@ -171,7 +171,7 @@ public class ODataServletTest {
     Mockito.verify(configMock).getInitParameter(ODataServiceFactory.FACTORY_LABEL);
     Mockito.verify(reqMock).getAttribute(ODataServiceFactory.FACTORY_CLASSLOADER_LABEL);
 
-    Assert.assertEquals(ODataServiceFactoryImpl.class, servlet.createODataServiceFactory(reqMock).getClass());
+    Assert.assertEquals(ODataServiceFactoryImpl.class, servlet.getServiceFactory(reqMock).getClass());
   }
 
 
@@ -186,7 +186,7 @@ public class ODataServletTest {
     Mockito.when(req.getMethod()).thenReturn("GET");
     Mockito.when(req.getContextPath()).thenReturn(contextPath);
     Mockito.when(req.getServletPath()).thenReturn(servletPath);
-    Mockito.when(req.getHeaderNames()).thenReturn(Collections.emptyEnumeration());
+    Mockito.when(req.getHeaderNames()).thenReturn(Collections.enumeration(Collections.emptyList()));
   }
 
   private void prepareRequest(final HttpServletRequest req) {


[2/4] olingo-odata2 git commit: [OLINGO-709] Support injection of ODataServiceFactory instance

Posted by mi...@apache.org.
[OLINGO-709] Support injection of ODataServiceFactory instance


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

Branch: refs/heads/master
Commit: f1ca1a20492c4a6d2e74bda0c1a21d0996a24c32
Parents: 5fc3ed2
Author: mibo <mi...@mirb.de>
Authored: Sun Jun 21 16:26:55 2015 +0200
Committer: mibo <mi...@mirb.de>
Committed: Sun Jun 21 16:57:24 2015 +0200

----------------------------------------------------------------------
 .../olingo/odata2/api/ODataServiceFactory.java  |   5 +
 .../core/servlet/AbstractODataServlet.java      | 350 +++++++++++++++++++
 .../odata2/core/servlet/ODataServlet.java       | 287 +--------------
 .../olingo/odata2/core/servlet/RestUtil.java    |   5 +-
 .../core/servlet/AbstractODataServletTest.java  | 280 +++++++++++++++
 .../odata2/core/servlet/ODataServletTest.java   |  58 +--
 6 files changed, 682 insertions(+), 303 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f1ca1a20/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataServiceFactory.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataServiceFactory.java b/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataServiceFactory.java
index 7b6f7a3..4b408c5 100644
--- a/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataServiceFactory.java
+++ b/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataServiceFactory.java
@@ -42,6 +42,11 @@ public abstract class ODataServiceFactory {
   public static final String FACTORY_CLASSLOADER_LABEL = "org.apache.olingo.odata2.service.factory.classloader";
 
   /**
+   * Label used in web.xml to assign servlet init parameter to factory class instance.
+   */
+  public static final String FACTORY_INSTANCE_LABEL = "org.apache.olingo.odata2.service.factory.instance";
+
+  /**
    * Label used in web.xml to assign servlet init parameter for a path split (service resolution).
    */
   public static final String PATH_SPLIT_LABEL = "org.apache.olingo.odata2.path.split";

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f1ca1a20/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/AbstractODataServlet.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/AbstractODataServlet.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/AbstractODataServlet.java
new file mode 100644
index 0000000..2fc6972
--- /dev/null
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/AbstractODataServlet.java
@@ -0,0 +1,350 @@
+/*******************************************************************************
+ * 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.odata2.core.servlet;
+
+import org.apache.olingo.odata2.api.ODataService;
+import org.apache.olingo.odata2.api.ODataServiceFactory;
+import org.apache.olingo.odata2.api.commons.HttpHeaders;
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.api.commons.ODataHttpMethod;
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.api.exception.ODataBadRequestException;
+import org.apache.olingo.odata2.api.exception.ODataHttpException;
+import org.apache.olingo.odata2.api.exception.ODataInternalServerErrorException;
+import org.apache.olingo.odata2.api.exception.ODataMethodNotAllowedException;
+import org.apache.olingo.odata2.api.exception.ODataNotAcceptableException;
+import org.apache.olingo.odata2.api.exception.ODataNotImplementedException;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.processor.ODataRequest;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.core.ODataContextImpl;
+import org.apache.olingo.odata2.core.ODataRequestHandler;
+import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+
+public abstract class AbstractODataServlet extends HttpServlet {
+
+  private static final String HTTP_METHOD_OPTIONS = "OPTIONS";
+  private static final String HTTP_METHOD_HEAD = "HEAD";
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * Get the service factory instance which is used for creation of the
+   * <code>ODataService</code> which handles the processing of the request.
+   *
+   * @param request the http request which is processed as an OData request
+   * @return an instance of an ODataServiceFactory
+   */
+  protected abstract ODataServiceFactory getServiceFactory(HttpServletRequest request);
+
+  @Override
+  protected void service(final HttpServletRequest req, final HttpServletResponse resp) throws IOException {
+    // We have to create the Service Factory here because otherwise we do not have access to the error callback
+    ODataServiceFactory serviceFactory = getServiceFactory(req);
+    if(serviceFactory == null) {
+      throw new ODataRuntimeException("Unable to get Service Factory. Check either '" +
+          ODataServiceFactory.FACTORY_LABEL + "' or '" + ODataServiceFactory.FACTORY_INSTANCE_LABEL + "' config.");
+    }
+
+    String xHttpMethod = req.getHeader("X-HTTP-Method");
+    String xHttpMethodOverride = req.getHeader("X-HTTP-Method-Override");
+    if (xHttpMethod != null && xHttpMethodOverride != null) {
+      if (!xHttpMethod.equalsIgnoreCase(xHttpMethodOverride)) {
+        ODataExceptionWrapper wrapper = new ODataExceptionWrapper(req, serviceFactory);
+        createResponse(resp, wrapper.wrapInExceptionResponse(
+            new ODataBadRequestException(ODataBadRequestException.AMBIGUOUS_XMETHOD)));
+      }
+    }
+
+    if (req.getPathInfo() != null) {
+      handle(req, resp, xHttpMethod, xHttpMethodOverride, serviceFactory);
+    } else {
+      handleRedirect(req, resp, serviceFactory);
+    }
+  }
+
+
+  protected void handle(final HttpServletRequest req, final HttpServletResponse resp, final String xHttpMethod,
+      final String xHttpMethodOverride, ODataServiceFactory serviceFactory) throws IOException {
+    String method = req.getMethod();
+    if (ODataHttpMethod.GET.name().equals(method)) {
+      handleRequest(req, ODataHttpMethod.GET, resp, serviceFactory);
+    } else if (ODataHttpMethod.POST.name().equals(method)) {
+      if (xHttpMethod == null && xHttpMethodOverride == null) {
+        handleRequest(req, ODataHttpMethod.POST, resp, serviceFactory);
+      } else if (xHttpMethod == null) {
+        /* tunneling */
+        boolean methodHandled = handleHttpTunneling(req, resp, xHttpMethodOverride, serviceFactory);
+        if (!methodHandled) {
+          createMethodNotAllowedResponse(req, ODataHttpException.COMMON, resp, serviceFactory);
+        }
+      } else {
+        /* tunneling */
+        boolean methodHandled = handleHttpTunneling(req, resp, xHttpMethod, serviceFactory);
+        if (!methodHandled) {
+          createNotImplementedResponse(req, ODataNotImplementedException.TUNNELING, resp, serviceFactory);
+        }
+      }
+
+    } else if (ODataHttpMethod.PUT.name().equals(method)) {
+      handleRequest(req, ODataHttpMethod.PUT, resp, serviceFactory);
+    } else if (ODataHttpMethod.DELETE.name().equals(method)) {
+      handleRequest(req, ODataHttpMethod.DELETE, resp, serviceFactory);
+    } else if (ODataHttpMethod.PATCH.name().equals(method)) {
+      handleRequest(req, ODataHttpMethod.PATCH, resp, serviceFactory);
+    } else if (ODataHttpMethod.MERGE.name().equals(method)) {
+      handleRequest(req, ODataHttpMethod.MERGE, resp, serviceFactory);
+    } else if (HTTP_METHOD_HEAD.equals(method) || HTTP_METHOD_OPTIONS.equals(method)) {
+      createNotImplementedResponse(req, ODataNotImplementedException.COMMON, resp, serviceFactory);
+    } else {
+      createNotImplementedResponse(req, ODataHttpException.COMMON, resp, serviceFactory);
+    }
+  }
+
+  private boolean handleHttpTunneling(final HttpServletRequest req, final HttpServletResponse resp,
+      final String xHttpMethod, ODataServiceFactory serviceFactory) throws IOException {
+    if (ODataHttpMethod.MERGE.name().equals(xHttpMethod)) {
+      handleRequest(req, ODataHttpMethod.MERGE, resp, serviceFactory);
+    } else if (ODataHttpMethod.PATCH.name().equals(xHttpMethod)) {
+      handleRequest(req, ODataHttpMethod.PATCH, resp, serviceFactory);
+    } else if (ODataHttpMethod.DELETE.name().equals(xHttpMethod)) {
+      handleRequest(req, ODataHttpMethod.DELETE, resp, serviceFactory);
+    } else if (ODataHttpMethod.PUT.name().equals(xHttpMethod)) {
+      handleRequest(req, ODataHttpMethod.PUT, resp, serviceFactory);
+    } else if (ODataHttpMethod.GET.name().equals(xHttpMethod)) {
+      handleRequest(req, ODataHttpMethod.GET, resp, serviceFactory);
+    } else if (ODataHttpMethod.POST.name().equals(xHttpMethod)) {
+      handleRequest(req, ODataHttpMethod.POST, resp, serviceFactory);
+    } else if (HTTP_METHOD_HEAD.equals(xHttpMethod) || HTTP_METHOD_OPTIONS.equals(xHttpMethod)) {
+      createNotImplementedResponse(req, ODataNotImplementedException.COMMON, resp, serviceFactory);
+    } else {
+      createNotImplementedResponse(req, ODataNotImplementedException.COMMON, resp, serviceFactory);
+    }
+    return true;
+  }
+
+  private void
+      handleRequest(final HttpServletRequest req, final ODataHttpMethod method, final HttpServletResponse resp,
+          ODataServiceFactory serviceFactory)
+          throws IOException {
+    try {
+      final String pathSplitAsString = getInitParameter(ODataServiceFactory.PATH_SPLIT_LABEL);
+      int pathSplit = 0;
+      if (pathSplitAsString != null) {
+        pathSplit = Integer.parseInt(pathSplitAsString);
+      }
+      if (req.getHeader(HttpHeaders.ACCEPT) != null && req.getHeader(HttpHeaders.ACCEPT).isEmpty()) {
+        createNotAcceptableResponse(req, ODataNotAcceptableException.COMMON, resp, serviceFactory);
+      }
+      ODataRequest odataRequest = ODataRequest.method(method)
+          .contentType(RestUtil.extractRequestContentType(req.getContentType()).toContentTypeString())
+          .acceptHeaders(RestUtil.extractAcceptHeaders(req.getHeader(HttpHeaders.ACCEPT)))
+          .acceptableLanguages(RestUtil.extractAcceptableLanguage(req.getHeader(HttpHeaders.ACCEPT_LANGUAGE)))
+          .pathInfo(RestUtil.buildODataPathInfo(req, pathSplit))
+          .allQueryParameters(RestUtil.extractAllQueryParameters(req.getQueryString()))
+          .requestHeaders(RestUtil.extractHeaders(req))
+          .body(req.getInputStream())
+          .build();
+
+      ODataContextImpl context = new ODataContextImpl(odataRequest, serviceFactory);
+      context.setParameter(ODataContext.HTTP_SERVLET_REQUEST_OBJECT, req);
+
+      ODataService service = serviceFactory.createService(context);
+      if (service == null) {
+        createServiceUnavailableResponse(req, ODataInternalServerErrorException.NOSERVICE, resp, serviceFactory);
+      } else {
+        context.setService(service);
+        service.getProcessor().setContext(context);
+
+        ODataRequestHandler requestHandler = new ODataRequestHandler(serviceFactory, service, context);
+        final ODataResponse odataResponse = requestHandler.handle(odataRequest);
+        createResponse(resp, odataResponse);
+      }
+    } catch (Exception e) {
+      ODataExceptionWrapper wrapper = new ODataExceptionWrapper(req, serviceFactory);
+      createResponse(resp, wrapper.wrapInExceptionResponse(e));
+    }
+  }
+
+  protected void handleRedirect(final HttpServletRequest req, final HttpServletResponse resp,
+                                ODataServiceFactory serviceFactory) throws IOException {
+    String method = req.getMethod();
+    if (ODataHttpMethod.GET.name().equals(method) ||
+        ODataHttpMethod.POST.name().equals(method) ||
+        ODataHttpMethod.PUT.name().equals(method) ||
+        ODataHttpMethod.DELETE.name().equals(method) ||
+        ODataHttpMethod.PATCH.name().equals(method) ||
+        ODataHttpMethod.MERGE.name().equals(method) ||
+        HTTP_METHOD_HEAD.equals(method) ||
+        HTTP_METHOD_OPTIONS.equals(method)) {
+      ODataResponse odataResponse = ODataResponse.status(HttpStatusCodes.TEMPORARY_REDIRECT)
+          .header(HttpHeaders.LOCATION, createLocation(req))
+          .build();
+      createResponse(resp, odataResponse);
+    } else {
+      createNotImplementedResponse(req, ODataHttpException.COMMON, resp, serviceFactory);
+    }
+
+  }
+
+  private String createLocation(final HttpServletRequest req) {
+    StringBuilder location = new StringBuilder();
+    String contextPath = req.getContextPath();
+    if (contextPath != null) {
+      location.append(contextPath);
+    }
+    String servletPath = req.getServletPath();
+    if (servletPath != null) {
+      location.append(servletPath);
+    }
+    location.append("/");
+    return location.toString();
+  }
+
+  protected void createResponse(final HttpServletResponse resp, final ODataResponse response) throws IOException {
+    resp.setStatus(response.getStatus().getStatusCode());
+    resp.setContentType(response.getContentHeader());
+    for (String headerName : response.getHeaderNames()) {
+      resp.setHeader(headerName, response.getHeader(headerName));
+    }
+
+    Object entity = response.getEntity();
+    if (entity != null) {
+      ServletOutputStream out = resp.getOutputStream();
+      int curByte;
+      int contentLength = 0;
+
+      if (entity instanceof InputStream) {
+        while ((curByte = ((InputStream) entity).read()) != -1) {
+          contentLength++;
+          out.write((char) curByte);
+        }
+        ((InputStream) entity).close();
+      } else if (entity instanceof String) {
+        String body = (String) entity;
+        final byte[] entityBytes = body.getBytes("utf-8");
+        out.write(entityBytes);
+        contentLength = entityBytes.length;
+      }
+
+      if (response.getHeader(HttpHeaders.CONTENT_LENGTH) != null) {
+        // Override content length
+        try {
+          contentLength = Integer.parseInt(response.getHeader(HttpHeaders.CONTENT_LENGTH));
+        } catch (NumberFormatException e) {
+          // Ignore
+        }
+      }
+
+      resp.setContentLength(contentLength);
+      out.flush();
+      out.close();
+    }
+  }
+
+  private void createNotImplementedResponse(final HttpServletRequest req, final MessageReference messageReference,
+      final HttpServletResponse resp, ODataServiceFactory serviceFactory) throws IOException {
+    // RFC 2616, 5.1.1: "An origin server SHOULD return the status code [...]
+    // 501 (Not Implemented) if the method is unrecognized [...] by the origin server."
+    ODataExceptionWrapper exceptionWrapper = new ODataExceptionWrapper(req, serviceFactory);
+    ODataResponse response =
+        exceptionWrapper.wrapInExceptionResponse(new ODataNotImplementedException(messageReference));
+//    resp.setStatus(HttpStatusCodes.NOT_IMPLEMENTED.getStatusCode());
+    createResponse(resp, response);
+  }
+
+  private void createMethodNotAllowedResponse(final HttpServletRequest req, final MessageReference messageReference,
+      final HttpServletResponse resp, ODataServiceFactory serviceFactory) throws IOException {
+    ODataExceptionWrapper exceptionWrapper = new ODataExceptionWrapper(req, serviceFactory);
+    ODataResponse response =
+        exceptionWrapper.wrapInExceptionResponse(new ODataMethodNotAllowedException(messageReference));
+    createResponse(resp, response);
+  }
+
+  private void createNotAcceptableResponse(final HttpServletRequest req, final MessageReference messageReference,
+      final HttpServletResponse resp, ODataServiceFactory serviceFactory) throws IOException {
+    ODataExceptionWrapper exceptionWrapper = new ODataExceptionWrapper(req, serviceFactory);
+    ODataResponse response =
+        exceptionWrapper.wrapInExceptionResponse(new ODataNotAcceptableException(messageReference));
+    createResponse(resp, response);
+  }
+
+  private void createServiceUnavailableResponse(HttpServletRequest req, MessageReference messageReference,
+      HttpServletResponse resp, ODataServiceFactory serviceFactory) throws IOException {
+    ODataExceptionWrapper exceptionWrapper = new ODataExceptionWrapper(req, serviceFactory);
+    ODataResponse response =
+        exceptionWrapper.wrapInExceptionResponse(new ODataInternalServerErrorException(messageReference));
+    createResponse(resp, response);
+  }
+
+  /**
+   * Create an instance of a ODataServiceFactory via factory class
+   * from servlet init parameter ODataServiceFactory.FACTORY_LABEL
+   * and ODataServiceFactory.FACTORY_CLASSLOADER_LABEL (if set).
+   *
+   * @see ODataServiceFactory#FACTORY_LABEL
+   * @see ODataServiceFactory#FACTORY_CLASSLOADER_LABEL
+   *
+   * @param req http servlet request
+   * @return instance of a ODataServiceFactory
+   */
+  protected ODataServiceFactory createODataServiceFactory(HttpServletRequest req)
+      throws InstantiationException, IllegalAccessException, ClassNotFoundException {
+    final String factoryClassName = getInitParameter(ODataServiceFactory.FACTORY_LABEL);
+    if(factoryClassName == null) {
+      return null;
+    }
+
+    ClassLoader cl = (ClassLoader) req.getAttribute(ODataServiceFactory.FACTORY_CLASSLOADER_LABEL);
+    if (cl == null) {
+      return (ODataServiceFactory) Class.forName(factoryClassName).newInstance();
+    } else {
+      return (ODataServiceFactory) Class.forName(factoryClassName, true, cl).newInstance();
+    }
+  }
+
+  /**
+   * Get an instance of a ODataServiceFactory from request attribute
+   * ODataServiceFactory.FACTORY_INSTANCE_LABEL
+   *
+   * @see ODataServiceFactory#FACTORY_INSTANCE_LABEL
+   *
+   * @param req http servlet request
+   * @return instance of a ODataServiceFactory
+   */
+  protected ODataServiceFactory getServiceFactoryInstance(HttpServletRequest req) {
+    Object factory = req.getAttribute(ODataServiceFactory.FACTORY_INSTANCE_LABEL);
+    if(factory == null) {
+      return null;
+    } else if(factory instanceof ODataServiceFactory) {
+      return (ODataServiceFactory) factory;
+    }
+    throw new ODataRuntimeException("Invalid service factory instance of type " + factory.getClass());
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f1ca1a20/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/ODataServlet.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/ODataServlet.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/ODataServlet.java
index 5607025..d3e95e8 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/ODataServlet.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/ODataServlet.java
@@ -18,295 +18,28 @@
  ******************************************************************************/
 package org.apache.olingo.odata2.core.servlet;
 
-import java.io.IOException;
-import java.io.InputStream;
-
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.olingo.odata2.api.ODataService;
 import org.apache.olingo.odata2.api.ODataServiceFactory;
-import org.apache.olingo.odata2.api.commons.HttpHeaders;
-import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
-import org.apache.olingo.odata2.api.commons.ODataHttpMethod;
-import org.apache.olingo.odata2.api.exception.MessageReference;
-import org.apache.olingo.odata2.api.exception.ODataBadRequestException;
-import org.apache.olingo.odata2.api.exception.ODataHttpException;
-import org.apache.olingo.odata2.api.exception.ODataInternalServerErrorException;
-import org.apache.olingo.odata2.api.exception.ODataMethodNotAllowedException;
-import org.apache.olingo.odata2.api.exception.ODataNotAcceptableException;
-import org.apache.olingo.odata2.api.exception.ODataNotImplementedException;
-import org.apache.olingo.odata2.api.processor.ODataContext;
-import org.apache.olingo.odata2.api.processor.ODataRequest;
-import org.apache.olingo.odata2.api.processor.ODataResponse;
-import org.apache.olingo.odata2.core.ODataContextImpl;
-import org.apache.olingo.odata2.core.ODataRequestHandler;
 import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
 
-public class ODataServlet extends HttpServlet {
+import javax.servlet.http.HttpServletRequest;
 
-  private static final String HTTP_METHOD_OPTIONS = "OPTIONS";
-  private static final String HTTP_METHOD_HEAD = "HEAD";
+public final class ODataServlet extends AbstractODataServlet {
 
-  /**
-   * 
-   */
   private static final long serialVersionUID = 1L;
 
-  @Override
-  protected void service(final HttpServletRequest req, final HttpServletResponse resp) throws IOException {
-    final String factoryClassName = getInitParameter(ODataServiceFactory.FACTORY_LABEL);
-    if (factoryClassName == null) {
-      throw new ODataRuntimeException("config missing: " + ODataServiceFactory.FACTORY_LABEL);
-    }
-
-    // We have to create the Service Factory here because otherwise we do not have access to the error callback
-    ODataServiceFactory serviceFactory = createServiceFactory(req);
-
-    String xHttpMethod = req.getHeader("X-HTTP-Method");
-    String xHttpMethodOverride = req.getHeader("X-HTTP-Method-Override");
-    if (xHttpMethod != null && xHttpMethodOverride != null) {
-      if (!xHttpMethod.equalsIgnoreCase(xHttpMethodOverride)) {
-        ODataExceptionWrapper wrapper = new ODataExceptionWrapper(req, serviceFactory);
-        createResponse(resp, wrapper.wrapInExceptionResponse(
-            new ODataBadRequestException(ODataBadRequestException.AMBIGUOUS_XMETHOD)));
-      }
-    }
-
-    if (req.getPathInfo() != null) {
-      handle(req, resp, xHttpMethod, xHttpMethodOverride, serviceFactory);
-    } else {
-      handleRedirect(req, resp, serviceFactory);
-    }
-  }
-
-  private void handle(final HttpServletRequest req, final HttpServletResponse resp, final String xHttpMethod,
-      final String xHttpMethodOverride, ODataServiceFactory serviceFactory) throws IOException {
-    String method = req.getMethod();
-    if (ODataHttpMethod.GET.name().equals(method)) {
-      handleRequest(req, ODataHttpMethod.GET, resp, serviceFactory);
-    } else if (ODataHttpMethod.POST.name().equals(method)) {
-      if (xHttpMethod == null && xHttpMethodOverride == null) {
-        handleRequest(req, ODataHttpMethod.POST, resp, serviceFactory);
-      } else if (xHttpMethod == null) {
-        /* tunneling */
-        boolean methodHandled = handleHttpTunneling(req, resp, xHttpMethodOverride, serviceFactory);
-        if (!methodHandled) {
-          createMethodNotAllowedResponse(req, ODataHttpException.COMMON, resp, serviceFactory);
-        }
-      } else {
-        /* tunneling */
-        boolean methodHandled = handleHttpTunneling(req, resp, xHttpMethod, serviceFactory);
-        if (!methodHandled) {
-          createNotImplementedResponse(req, ODataNotImplementedException.TUNNELING, resp, serviceFactory);
-        }
-      }
-
-    } else if (ODataHttpMethod.PUT.name().equals(method)) {
-      handleRequest(req, ODataHttpMethod.PUT, resp, serviceFactory);
-    } else if (ODataHttpMethod.DELETE.name().equals(method)) {
-      handleRequest(req, ODataHttpMethod.DELETE, resp, serviceFactory);
-    } else if (ODataHttpMethod.PATCH.name().equals(method)) {
-      handleRequest(req, ODataHttpMethod.PATCH, resp, serviceFactory);
-    } else if (ODataHttpMethod.MERGE.name().equals(method)) {
-      handleRequest(req, ODataHttpMethod.MERGE, resp, serviceFactory);
-    } else if (HTTP_METHOD_HEAD.equals(method) || HTTP_METHOD_OPTIONS.equals(method)) {
-      createNotImplementedResponse(req, ODataNotImplementedException.COMMON, resp, serviceFactory);
-    } else {
-      createNotImplementedResponse(req, ODataHttpException.COMMON, resp, serviceFactory);
-    }
-  }
-
-  private boolean handleHttpTunneling(final HttpServletRequest req, final HttpServletResponse resp,
-      final String xHttpMethod, ODataServiceFactory serviceFactory) throws IOException {
-    if (ODataHttpMethod.MERGE.name().equals(xHttpMethod)) {
-      handleRequest(req, ODataHttpMethod.MERGE, resp, serviceFactory);
-    } else if (ODataHttpMethod.PATCH.name().equals(xHttpMethod)) {
-      handleRequest(req, ODataHttpMethod.PATCH, resp, serviceFactory);
-    } else if (ODataHttpMethod.DELETE.name().equals(xHttpMethod)) {
-      handleRequest(req, ODataHttpMethod.DELETE, resp, serviceFactory);
-    } else if (ODataHttpMethod.PUT.name().equals(xHttpMethod)) {
-      handleRequest(req, ODataHttpMethod.PUT, resp, serviceFactory);
-    } else if (ODataHttpMethod.GET.name().equals(xHttpMethod)) {
-      handleRequest(req, ODataHttpMethod.GET, resp, serviceFactory);
-    } else if (ODataHttpMethod.POST.name().equals(xHttpMethod)) {
-      handleRequest(req, ODataHttpMethod.POST, resp, serviceFactory);
-    } else if (HTTP_METHOD_HEAD.equals(xHttpMethod) || HTTP_METHOD_OPTIONS.equals(xHttpMethod)) {
-      createNotImplementedResponse(req, ODataNotImplementedException.COMMON, resp, serviceFactory);
-    } else {
-      createNotImplementedResponse(req, ODataNotImplementedException.COMMON, resp, serviceFactory);
-    }
-    return true;
-  }
-
-  private void
-      handleRequest(final HttpServletRequest req, final ODataHttpMethod method, final HttpServletResponse resp,
-          ODataServiceFactory serviceFactory)
-          throws IOException {
+  /**
+   * @{inherit}
+   */
+  protected ODataServiceFactory getServiceFactory(HttpServletRequest request) {
     try {
-      final String pathSplitAsString = getInitParameter(ODataServiceFactory.PATH_SPLIT_LABEL);
-      int pathSplit = 0;
-      if (pathSplitAsString != null) {
-        pathSplit = Integer.parseInt(pathSplitAsString);
-      }
-      if (req.getHeader(HttpHeaders.ACCEPT) != null && req.getHeader(HttpHeaders.ACCEPT).isEmpty()) {
-        createNotAcceptableResponse(req, ODataNotAcceptableException.COMMON, resp, serviceFactory);
+      ODataServiceFactory factoryInstance = getServiceFactoryInstance(request);
+      if(factoryInstance == null) {
+        return createODataServiceFactory(request);
       }
-      ODataRequest odataRequest = ODataRequest.method(method)
-          .contentType(RestUtil.extractRequestContentType(req.getContentType()).toContentTypeString())
-          .acceptHeaders(RestUtil.extractAcceptHeaders(req.getHeader(HttpHeaders.ACCEPT)))
-          .acceptableLanguages(RestUtil.extractAcceptableLanguage(req.getHeader(HttpHeaders.ACCEPT_LANGUAGE)))
-          .pathInfo(RestUtil.buildODataPathInfo(req, pathSplit))
-          .allQueryParameters(RestUtil.extractAllQueryParameters(req.getQueryString()))
-          .requestHeaders(RestUtil.extractHeaders(req))
-          .body(req.getInputStream())
-          .build();
-
-      ODataContextImpl context = new ODataContextImpl(odataRequest, serviceFactory);
-      context.setParameter(ODataContext.HTTP_SERVLET_REQUEST_OBJECT, req);
-
-      ODataService service = serviceFactory.createService(context);
-      if (service == null) {
-        createServiceUnavailableResponse(req, ODataInternalServerErrorException.NOSERVICE, resp, serviceFactory);
-      } else {
-        context.setService(service);
-        service.getProcessor().setContext(context);
-
-        ODataRequestHandler requestHandler = new ODataRequestHandler(serviceFactory, service, context);
-        final ODataResponse odataResponse = requestHandler.handle(odataRequest);
-        createResponse(resp, odataResponse);
-      }
-    } catch (Exception e) {
-      ODataExceptionWrapper wrapper = new ODataExceptionWrapper(req, serviceFactory);
-      createResponse(resp, wrapper.wrapInExceptionResponse(e));
-    }
-  }
+      return factoryInstance;
 
-  private ODataServiceFactory createServiceFactory(HttpServletRequest req) {
-    try {
-      final String factoryClassName = getInitParameter(ODataServiceFactory.FACTORY_LABEL);
-      ClassLoader cl = (ClassLoader) req.getAttribute(ODataServiceFactory.FACTORY_CLASSLOADER_LABEL);
-      if (cl == null) {
-        return (ODataServiceFactory) Class.forName(factoryClassName).newInstance();
-      } else {
-        return (ODataServiceFactory) Class.forName(factoryClassName, true, cl).newInstance();
-      }
     } catch (Exception e) {
       throw new ODataRuntimeException(e);
     }
   }
-
-  private void handleRedirect(final HttpServletRequest req, final HttpServletResponse resp,
-      ODataServiceFactory serviceFactory) throws IOException {
-    String method = req.getMethod();
-    if (ODataHttpMethod.GET.name().equals(method) ||
-        ODataHttpMethod.POST.name().equals(method) ||
-        ODataHttpMethod.PUT.name().equals(method) ||
-        ODataHttpMethod.DELETE.name().equals(method) ||
-        ODataHttpMethod.PATCH.name().equals(method) ||
-        ODataHttpMethod.MERGE.name().equals(method) ||
-        HTTP_METHOD_HEAD.equals(method) ||
-        HTTP_METHOD_OPTIONS.equals(method)) {
-      ODataResponse odataResponse = ODataResponse.status(HttpStatusCodes.TEMPORARY_REDIRECT)
-          .header(HttpHeaders.LOCATION, createLocation(req))
-          .build();
-      createResponse(resp, odataResponse);
-    } else {
-      createNotImplementedResponse(req, ODataHttpException.COMMON, resp, serviceFactory);
-    }
-
-  }
-
-  private String createLocation(final HttpServletRequest req) {
-    StringBuilder location = new StringBuilder();
-    String contextPath = req.getContextPath();
-    if (contextPath != null) {
-      location.append(contextPath);
-    }
-    String servletPath = req.getServletPath();
-    if (servletPath != null) {
-      location.append(servletPath);
-    }
-    location.append("/");
-    return location.toString();
-  }
-
-  private void createResponse(final HttpServletResponse resp, final ODataResponse response) throws IOException {
-    resp.setStatus(response.getStatus().getStatusCode());
-    resp.setContentType(response.getContentHeader());
-    for (String headerName : response.getHeaderNames()) {
-      resp.setHeader(headerName, response.getHeader(headerName));
-    }
-
-    Object entity = response.getEntity();
-    if (entity != null) {
-      ServletOutputStream out = resp.getOutputStream();
-      int curByte;
-      int contentLength = 0;
-
-      if (entity instanceof InputStream) {
-        while ((curByte = ((InputStream) entity).read()) != -1) {
-          contentLength++;
-          out.write((char) curByte);
-        }
-        ((InputStream) entity).close();
-      } else if (entity instanceof String) {
-        String body = (String) entity;
-        final byte[] entityBytes = body.getBytes("utf-8");
-        out.write(entityBytes);
-        contentLength = entityBytes.length;
-      }
-
-      if (response.getHeader(HttpHeaders.CONTENT_LENGTH) != null) {
-        // Override content length
-        try {
-          contentLength = Integer.parseInt(response.getHeader(HttpHeaders.CONTENT_LENGTH));
-        } catch (NumberFormatException e) {
-          // Ignore
-        }
-      }
-
-      resp.setContentLength(contentLength);
-      out.flush();
-      out.close();
-    }
-  }
-
-  private void createNotImplementedResponse(final HttpServletRequest req, final MessageReference messageReference,
-      final HttpServletResponse resp, ODataServiceFactory serviceFactory) throws IOException {
-    // RFC 2616, 5.1.1: "An origin server SHOULD return the status code [...]
-    // 501 (Not Implemented) if the method is unrecognized [...] by the origin server."
-    ODataExceptionWrapper exceptionWrapper = new ODataExceptionWrapper(req, serviceFactory);
-    ODataResponse response =
-        exceptionWrapper.wrapInExceptionResponse(new ODataNotImplementedException(messageReference));
-//    resp.setStatus(HttpStatusCodes.NOT_IMPLEMENTED.getStatusCode());
-    createResponse(resp, response);
-  }
-
-  private void createMethodNotAllowedResponse(final HttpServletRequest req, final MessageReference messageReference,
-      final HttpServletResponse resp, ODataServiceFactory serviceFactory) throws IOException {
-    ODataExceptionWrapper exceptionWrapper = new ODataExceptionWrapper(req, serviceFactory);
-    ODataResponse response =
-        exceptionWrapper.wrapInExceptionResponse(new ODataMethodNotAllowedException(messageReference));
-    createResponse(resp, response);
-  }
-
-  private void createNotAcceptableResponse(final HttpServletRequest req, final MessageReference messageReference,
-      final HttpServletResponse resp, ODataServiceFactory serviceFactory) throws IOException {
-    ODataExceptionWrapper exceptionWrapper = new ODataExceptionWrapper(req, serviceFactory);
-    ODataResponse response =
-        exceptionWrapper.wrapInExceptionResponse(new ODataNotAcceptableException(messageReference));
-    createResponse(resp, response);
-  }
-
-  private void createServiceUnavailableResponse(HttpServletRequest req, MessageReference messageReference,
-      HttpServletResponse resp, ODataServiceFactory serviceFactory) throws IOException {
-    ODataExceptionWrapper exceptionWrapper = new ODataExceptionWrapper(req, serviceFactory);
-    ODataResponse response =
-        exceptionWrapper.wrapInExceptionResponse(new ODataInternalServerErrorException(messageReference));
-    createResponse(resp, response);
-  }
-
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f1ca1a20/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/RestUtil.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/RestUtil.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/RestUtil.java
index 65aaf06..da7b05b 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/RestUtil.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/RestUtil.java
@@ -366,9 +366,10 @@ public class RestUtil {
       pathInfoString = pathInfoString.substring(servletRequest.getContextPath().length());
     }
 
-    int indexServletPath = requestUri.indexOf(servletRequest.getServletPath());
+    int indexServletPath = pathInfoString.indexOf(servletRequest.getServletPath());
     if (indexServletPath >= 0) {
-      pathInfoString = pathInfoString.substring(servletRequest.getServletPath().length());
+      int substringFromPos = indexServletPath + servletRequest.getServletPath().length();
+      pathInfoString = pathInfoString.substring(substringFromPos);
     }
     return pathInfoString;
   }

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f1ca1a20/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/servlet/AbstractODataServletTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/servlet/AbstractODataServletTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/servlet/AbstractODataServletTest.java
new file mode 100644
index 0000000..de21917
--- /dev/null
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/servlet/AbstractODataServletTest.java
@@ -0,0 +1,280 @@
+/*******************************************************************************
+ * 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.odata2.core.servlet;
+
+import junit.framework.Assert;
+import org.apache.olingo.odata2.api.ODataService;
+import org.apache.olingo.odata2.api.ODataServiceFactory;
+import org.apache.olingo.odata2.api.commons.HttpHeaders;
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.servicedocument.Collection;
+import org.apache.olingo.odata2.core.ODataResponseImpl;
+import org.apache.olingo.odata2.core.rest.ODataServiceFactoryImpl;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import javax.servlet.GenericServlet;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Collections;
+
+/**
+ *
+ */
+public class AbstractODataServletTest {
+
+  private HttpServletRequest reqMock;
+  private HttpServletResponse respMock;
+  private ServletConfig configMock;
+
+  public AbstractODataServletTest() {
+    reqMock = Mockito.mock(HttpServletRequest.class);
+    respMock = Mockito.mock(HttpServletResponse.class);
+    configMock = Mockito.mock(ServletConfig.class);
+  }
+
+  private static class MyTestODataServlet extends AbstractODataServlet {
+    enum ServiceFactorySource {INSTANCE, CLASSLOADER, MOCK};
+
+    ODataServiceFactory viaInstance;
+    ODataServiceFactory viaClassLoader;
+    ODataServiceFactory viaMock;
+    final ServiceFactorySource source;
+
+    public MyTestODataServlet() {
+      this(ServiceFactorySource.MOCK);
+    }
+
+    public MyTestODataServlet(ServiceFactorySource source) {
+      this.source = source;
+    }
+
+    @Override
+    protected ODataServiceFactory getServiceFactory(HttpServletRequest request) {
+      viaInstance = getServiceFactoryInstance(request);
+      try {
+        viaClassLoader = createODataServiceFactory(request);
+      } catch (Exception e) {
+        throw new RuntimeException(e);
+      }
+      viaMock = Mockito.mock(ODataServiceFactory.class);
+
+      switch (source) {
+        case INSTANCE: return viaInstance;
+        case CLASSLOADER: return viaClassLoader;
+        case MOCK: return viaMock;
+      }
+      return null;
+    }
+  }
+
+  @Test
+  public void handleRedirect() throws Exception {
+    AbstractODataServlet servlet = new MyTestODataServlet();
+    prepareServlet(servlet);
+    prepareRequest(reqMock);
+    servlet.service(reqMock, respMock);
+
+    Mockito.verify(respMock).setStatus(HttpStatusCodes.TEMPORARY_REDIRECT.getStatusCode());
+    Mockito.verify(respMock).setHeader(HttpHeaders.LOCATION, "/context-path/servlet-path/");
+  }
+
+  @Test
+  public void handleRedirectWoServletPath() throws Exception {
+    AbstractODataServlet servlet = new MyTestODataServlet();
+    prepareServlet(servlet);
+    prepareRequest(reqMock, "/context-path", null);
+    servlet.service(reqMock, respMock);
+
+    Mockito.verify(respMock).setStatus(HttpStatusCodes.TEMPORARY_REDIRECT.getStatusCode());
+    Mockito.verify(respMock).setHeader(HttpHeaders.LOCATION, "/context-path/");
+  }
+
+  @Test
+  public void handleRedirectWoContextPath() throws Exception {
+    AbstractODataServlet servlet = new MyTestODataServlet();
+    prepareServlet(servlet);
+    prepareRequest(reqMock, null, "/servlet-path");
+    servlet.service(reqMock, respMock);
+
+    Mockito.verify(respMock).setStatus(HttpStatusCodes.TEMPORARY_REDIRECT.getStatusCode());
+    Mockito.verify(respMock).setHeader(HttpHeaders.LOCATION, "/servlet-path/");
+  }
+
+  @Test
+  public void handleRedirectWoPath() throws Exception {
+    AbstractODataServlet servlet = new MyTestODataServlet();
+    prepareServlet(servlet);
+    prepareRequest(reqMock, null, null);
+    servlet.service(reqMock, respMock);
+
+    Mockito.verify(respMock).setStatus(HttpStatusCodes.TEMPORARY_REDIRECT.getStatusCode());
+    Mockito.verify(respMock).setHeader(HttpHeaders.LOCATION, "/");
+  }
+
+  @Test
+  public void contentLengthCalculatedString() throws Exception {
+    final Method createResponse =
+        AbstractODataServlet.class.getDeclaredMethod("createResponse", HttpServletResponse.class, ODataResponse.class);
+    createResponse.setAccessible(true);
+
+    final AbstractODataServlet servlet = new MyTestODataServlet();
+    final String content = "Test\r\n";
+    final ODataResponse response = ODataResponseImpl.status(HttpStatusCodes.OK).entity(content).build();
+    prepareResponseMockToWrite(respMock);
+    prepareServlet(servlet);
+
+    createResponse.invoke(servlet, respMock, response);
+    Mockito.verify(respMock).setContentLength(content.getBytes("utf-8").length);
+  }
+
+  @Test
+  public void contentLengthCalculatedStream() throws Exception {
+    final Method createResponse =
+        AbstractODataServlet.class.getDeclaredMethod("createResponse", HttpServletResponse.class, ODataResponse.class);
+    createResponse.setAccessible(true);
+
+    final AbstractODataServlet servlet = new MyTestODataServlet();
+    final String content = "Test\r\n";
+
+    final ODataResponse response =
+        ODataResponseImpl.status(HttpStatusCodes.OK).entity(new ByteArrayInputStream(content.getBytes("utf-8")))
+            .build();
+    prepareResponseMockToWrite(respMock);
+    prepareServlet(servlet);
+
+    createResponse.invoke(servlet, respMock, response);
+    Mockito.verify(respMock).setContentLength(content.getBytes("utf-8").length);
+  }
+
+  @Test
+  public void contentLengthHeader() throws Exception {
+    final Method createResponse =
+        AbstractODataServlet.class.getDeclaredMethod("createResponse", HttpServletResponse.class, ODataResponse.class);
+    createResponse.setAccessible(true);
+    final AbstractODataServlet servlet = new MyTestODataServlet();
+    final ODataResponse response =
+        ODataResponseImpl.status(HttpStatusCodes.OK).header(HttpHeaders.CONTENT_LENGTH, "15").entity("").build();
+    prepareResponseMockToWrite(respMock);
+    prepareServlet(servlet);
+
+    createResponse.invoke(servlet, respMock, response);
+
+    Mockito.verify(respMock).setHeader(HttpHeaders.CONTENT_LENGTH, "15");
+    Mockito.verify(respMock).setContentLength(15);
+  }
+
+  @Test
+  public void contentLengthHeaderInvalid() throws Exception {
+    final Method createResponse =
+        AbstractODataServlet.class.getDeclaredMethod("createResponse", HttpServletResponse.class, ODataResponse.class);
+    createResponse.setAccessible(true);
+    final AbstractODataServlet servlet = new MyTestODataServlet();
+    final ODataResponse response =
+        ODataResponseImpl.status(HttpStatusCodes.OK).header(HttpHeaders.CONTENT_LENGTH, "ab").entity("Test").build();
+    prepareResponseMockToWrite(respMock);
+    prepareServlet(servlet);
+
+    createResponse.invoke(servlet, respMock, response);
+
+    Mockito.verify(respMock).setHeader(HttpHeaders.CONTENT_LENGTH, "ab");
+    Mockito.verify(respMock).setContentLength(4); // ||"Test"|| = 4
+  }
+
+  @Test
+  public void serviceInstance() throws Exception {
+    MyTestODataServlet servlet = new MyTestODataServlet(MyTestODataServlet.ServiceFactorySource.INSTANCE);
+    prepareServlet(servlet, false);
+    prepareRequest(reqMock, "", "/servlet-path");
+    Mockito.when(reqMock.getPathInfo()).thenReturn("/request-path-info");
+    Mockito.when(reqMock.getRequestURI()).thenReturn("http://localhost:8080/servlet-path/request-path-info");
+    ODataServiceFactory factory = Mockito.mock(ODataServiceFactory.class);
+    ODataService service = Mockito.mock(ODataService.class);
+    Mockito.when(factory.createService(Mockito.any(ODataContext.class))).thenReturn(service);
+    ODataProcessor processor = Mockito.mock(ODataProcessor.class);
+    Mockito.when(service.getProcessor()).thenReturn(processor);
+    Mockito.when(reqMock.getAttribute(ODataServiceFactory.FACTORY_INSTANCE_LABEL)).thenReturn(factory);
+    Mockito.when(respMock.getOutputStream()).thenReturn(Mockito.mock(ServletOutputStream.class));
+
+    servlet.service(reqMock, respMock);
+
+    Mockito.verify(factory).createService(Mockito.any(ODataContext.class));
+    Assert.assertNotNull(servlet.viaInstance);
+    Assert.assertNull(servlet.viaClassLoader);
+  }
+
+  @Test
+  public void serviceClassloader() throws Exception {
+    MyTestODataServlet servlet = new MyTestODataServlet(MyTestODataServlet.ServiceFactorySource.CLASSLOADER);
+    prepareServlet(servlet);
+    prepareRequest(reqMock, "", "/servlet-path");
+    Mockito.when(reqMock.getPathInfo()).thenReturn("/request-path-info");
+    Mockito.when(reqMock.getRequestURI()).thenReturn("http://localhost:8080/servlet-path/request-path-info");
+    Mockito.when(respMock.getOutputStream()).thenReturn(Mockito.mock(ServletOutputStream.class));
+
+    servlet.service(reqMock, respMock);
+
+    Assert.assertNull(servlet.viaInstance);
+    Assert.assertNotNull(servlet.viaClassLoader);
+  }
+
+  private void prepareResponseMockToWrite(final HttpServletResponse response) throws IOException {
+    Mockito.when(response.getOutputStream()).thenReturn(new ServletOutputStream() {
+      @Override
+      public void write(int b) throws IOException {}
+    });
+  }
+
+  private void prepareRequest(final HttpServletRequest req, final String contextPath, final String servletPath) {
+    Mockito.when(req.getMethod()).thenReturn("GET");
+    Mockito.when(req.getContextPath()).thenReturn(contextPath);
+    Mockito.when(req.getServletPath()).thenReturn(servletPath);
+    Mockito.when(req.getHeaderNames()).thenReturn(Collections.emptyEnumeration());
+  }
+
+  private void prepareRequest(final HttpServletRequest req) {
+    prepareRequest(req, "/context-path", "/servlet-path");
+  }
+
+  private void prepareServlet(final GenericServlet servlet) throws Exception {
+    prepareServlet(servlet, true);
+  }
+
+  private void prepareServlet(final GenericServlet servlet, boolean withFactoryLabel) throws Exception {
+    // private transient ServletConfig config;
+    Field configField = GenericServlet.class.getDeclaredField("config");
+    configField.setAccessible(true);
+    configField.set(servlet, configMock);
+
+    if(withFactoryLabel) {
+      String factoryClassName = ODataServiceFactoryImpl.class.getName();
+      Mockito.when(configMock.getInitParameter(ODataServiceFactory.FACTORY_LABEL)).thenReturn(factoryClassName);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f1ca1a20/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/servlet/ODataServletTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/servlet/ODataServletTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/servlet/ODataServletTest.java
index 883ab96..e1ad5dc 100644
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/servlet/ODataServletTest.java
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/servlet/ODataServletTest.java
@@ -22,6 +22,7 @@ import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
+import java.util.Collections;
 
 import javax.servlet.GenericServlet;
 import javax.servlet.ServletConfig;
@@ -29,9 +30,13 @@ import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import junit.framework.Assert;
+import org.apache.olingo.odata2.api.ODataService;
 import org.apache.olingo.odata2.api.ODataServiceFactory;
 import org.apache.olingo.odata2.api.commons.HttpHeaders;
 import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
 import org.apache.olingo.odata2.api.processor.ODataResponse;
 import org.apache.olingo.odata2.core.ODataResponseImpl;
 import org.apache.olingo.odata2.core.rest.ODataServiceFactoryImpl;
@@ -100,7 +105,7 @@ public class ODataServletTest {
   @Test
   public void contentLengthCalculatedString() throws Exception {
     final Method createResponse =
-        ODataServlet.class.getDeclaredMethod("createResponse", HttpServletResponse.class, ODataResponse.class);
+        AbstractODataServlet.class.getDeclaredMethod("createResponse", HttpServletResponse.class, ODataResponse.class);
     createResponse.setAccessible(true);
 
     final ODataServlet servlet = new ODataServlet();
@@ -116,7 +121,7 @@ public class ODataServletTest {
   @Test
   public void contentLengthCalculatedStream() throws Exception {
     final Method createResponse =
-        ODataServlet.class.getDeclaredMethod("createResponse", HttpServletResponse.class, ODataResponse.class);
+        AbstractODataServlet.class.getDeclaredMethod("createResponse", HttpServletResponse.class, ODataResponse.class);
     createResponse.setAccessible(true);
 
     final ODataServlet servlet = new ODataServlet();
@@ -133,39 +138,43 @@ public class ODataServletTest {
   }
 
   @Test
-  public void contentLengthHeader() throws Exception {
-    final Method createResponse =
-        ODataServlet.class.getDeclaredMethod("createResponse", HttpServletResponse.class, ODataResponse.class);
-    createResponse.setAccessible(true);
-    final ODataServlet servlet = new ODataServlet();
-    final ODataResponse response =
-        ODataResponseImpl.status(HttpStatusCodes.OK).header(HttpHeaders.CONTENT_LENGTH, "15").entity("").build();
-    prepareResponseMockToWrite(respMock);
+  public void serviceInstance() throws Exception {
+    ODataServlet servlet = new ODataServlet();
     prepareServlet(servlet);
+    prepareRequest(reqMock, "", "/servlet-path");
+    Mockito.when(reqMock.getPathInfo()).thenReturn("/request-path-info");
+    Mockito.when(reqMock.getRequestURI()).thenReturn("http://localhost:8080/servlet-path/request-path-info");
+    ODataServiceFactory factory = Mockito.mock(ODataServiceFactory.class);
+    ODataService service = Mockito.mock(ODataService.class);
+    Mockito.when(factory.createService(Mockito.any(ODataContext.class))).thenReturn(service);
+    ODataProcessor processor = Mockito.mock(ODataProcessor.class);
+    Mockito.when(service.getProcessor()).thenReturn(processor);
+    Mockito.when(reqMock.getAttribute(ODataServiceFactory.FACTORY_INSTANCE_LABEL)).thenReturn(factory);
+    Mockito.when(respMock.getOutputStream()).thenReturn(Mockito.mock(ServletOutputStream.class));
 
-    createResponse.invoke(servlet, respMock, response);
+    servlet.service(reqMock, respMock);
 
-    Mockito.verify(respMock).setHeader(HttpHeaders.CONTENT_LENGTH, "15");
-    Mockito.verify(respMock).setContentLength(15);
+    Mockito.verify(factory).createService(Mockito.any(ODataContext.class));
   }
 
   @Test
-  public void contentLengthHeaderInvalid() throws Exception {
-    final Method createResponse =
-        ODataServlet.class.getDeclaredMethod("createResponse", HttpServletResponse.class, ODataResponse.class);
-    createResponse.setAccessible(true);
-    final ODataServlet servlet = new ODataServlet();
-    final ODataResponse response =
-        ODataResponseImpl.status(HttpStatusCodes.OK).header(HttpHeaders.CONTENT_LENGTH, "ab").entity("Test").build();
-    prepareResponseMockToWrite(respMock);
+  public void serviceClassloader() throws Exception {
+    ODataServlet servlet = new ODataServlet();
     prepareServlet(servlet);
+    prepareRequest(reqMock, "", "/servlet-path");
+    Mockito.when(reqMock.getPathInfo()).thenReturn("/request-path-info");
+    Mockito.when(reqMock.getRequestURI()).thenReturn("http://localhost:8080/servlet-path/request-path-info");
+    Mockito.when(respMock.getOutputStream()).thenReturn(Mockito.mock(ServletOutputStream.class));
 
-    createResponse.invoke(servlet, respMock, response);
+    servlet.service(reqMock, respMock);
 
-    Mockito.verify(respMock).setHeader(HttpHeaders.CONTENT_LENGTH, "ab");
-    Mockito.verify(respMock).setContentLength(4); // ||"Test"|| = 4
+    Mockito.verify(configMock).getInitParameter(ODataServiceFactory.FACTORY_LABEL);
+    Mockito.verify(reqMock).getAttribute(ODataServiceFactory.FACTORY_CLASSLOADER_LABEL);
+
+    Assert.assertEquals(ODataServiceFactoryImpl.class, servlet.createODataServiceFactory(reqMock).getClass());
   }
 
+
   private void prepareResponseMockToWrite(final HttpServletResponse response) throws IOException {
     Mockito.when(response.getOutputStream()).thenReturn(new ServletOutputStream() {
       @Override
@@ -177,6 +186,7 @@ public class ODataServletTest {
     Mockito.when(req.getMethod()).thenReturn("GET");
     Mockito.when(req.getContextPath()).thenReturn(contextPath);
     Mockito.when(req.getServletPath()).thenReturn(servletPath);
+    Mockito.when(req.getHeaderNames()).thenReturn(Collections.emptyEnumeration());
   }
 
   private void prepareRequest(final HttpServletRequest req) {