blob: 50e4a6e265fae0d5a069973669904c74d4987bbd [file] [log] [blame]
/*******************************************************************************
* 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.rest;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HEAD;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.OPTIONS;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.core.Response;
import org.apache.olingo.odata2.api.ODataService;
import org.apache.olingo.odata2.api.ODataServiceFactory;
import org.apache.olingo.odata2.api.commons.ODataHttpMethod;
import org.apache.olingo.odata2.api.exception.MessageReference;
import org.apache.olingo.odata2.api.exception.ODataException;
import org.apache.olingo.odata2.api.exception.ODataInternalServerErrorException;
import org.apache.olingo.odata2.api.exception.ODataMessageException;
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;
/**
*
*/
public final class ODataSubLocator {
private ODataServiceFactory serviceFactory;
private ODataRequest request;
private HttpServletRequest httpRequest;
@GET
public Response handleGet() throws ODataException {
return handle(ODataHttpMethod.GET);
}
@PUT
public Response handlePut() throws ODataException {
return handle(ODataHttpMethod.PUT);
}
@PATCH
public Response handlePatch() throws ODataException {
return handle(ODataHttpMethod.PATCH);
}
@MERGE
public Response handleMerge() throws ODataException {
return handle(ODataHttpMethod.MERGE);
}
@DELETE
public Response handleDelete() throws ODataException {
return handle(ODataHttpMethod.DELETE);
}
@POST
public Response handlePost(@HeaderParam("X-HTTP-Method") final String xHttpMethod) throws ODataException {
Response response;
if (xHttpMethod == null) {
response = handle(ODataHttpMethod.POST);
} else {
/* tunneling */
if ("MERGE".equals(xHttpMethod)) {
response = handle(ODataHttpMethod.MERGE);
} else if ("PATCH".equals(xHttpMethod)) {
response = handle(ODataHttpMethod.PATCH);
} else if (HttpMethod.DELETE.equals(xHttpMethod)) {
response = handle(ODataHttpMethod.DELETE);
} else if (HttpMethod.PUT.equals(xHttpMethod)) {
response = handle(ODataHttpMethod.PUT);
} else if (HttpMethod.GET.equals(xHttpMethod)) {
response = handle(ODataHttpMethod.GET);
} else if (HttpMethod.POST.equals(xHttpMethod)) {
response = handle(ODataHttpMethod.POST);
} else if (HttpMethod.HEAD.equals(xHttpMethod)) {
response = handleHead();
} else if (HttpMethod.OPTIONS.equals(xHttpMethod)) {
response = handleOptions();
} else {
response = returnNotImplementedResponse(ODataNotImplementedException.TUNNELING);
}
}
return response;
}
private Response returnNotImplementedResponse(final MessageReference messageReference) {
// 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."
return returnException(new ODataNotImplementedException(messageReference));
}
private Response returnException(final ODataMessageException messageException) {
ODataContextImpl context = new ODataContextImpl(request, serviceFactory);
context.setRequest(request);
context.setAcceptableLanguages(request.getAcceptableLanguages());
context.setPathInfo(request.getPathInfo());
context.setServiceFactory(serviceFactory);
context.setParameter(ODataContext.HTTP_SERVLET_REQUEST_OBJECT, httpRequest);
ODataExceptionWrapper exceptionWrapper =
new ODataExceptionWrapper(context, request.getQueryParameters(), request.getAcceptHeaders());
ODataResponse response =
exceptionWrapper.wrapInExceptionResponse(messageException);
return RestUtil.convertResponse(response);
}
private Response returnNoServiceResponse(MessageReference messageReference) {
return returnException(new ODataInternalServerErrorException(messageReference));
}
@OPTIONS
public Response handleOptions() throws ODataException {
// RFC 2616, 5.1.1: "An origin server SHOULD return the status code [...]
// 501 (Not Implemented) if the method is unrecognized or not implemented
// by the origin server."
return returnNotImplementedResponse(ODataNotImplementedException.COMMON);
}
@HEAD
public Response handleHead() throws ODataException {
return handleGet();
}
private Response handle(final ODataHttpMethod method) throws ODataException {
request = ODataRequest.fromRequest(request).method(method).build();
ODataContextImpl context = new ODataContextImpl(request, serviceFactory);
context.setParameter(ODataContext.HTTP_SERVLET_REQUEST_OBJECT, httpRequest);
ODataService service = serviceFactory.createService(context);
if(service == null){
return returnNoServiceResponse(ODataInternalServerErrorException.NOSERVICE);
}
service.getProcessor().setContext(context);
context.setService(service);
ODataRequestHandler requestHandler = new ODataRequestHandler(serviceFactory, service, context);
final ODataResponse odataResponse = requestHandler.handle(request);
final Response response = RestUtil.convertResponse(odataResponse);
return response;
}
public static ODataSubLocator create(final SubLocatorParameter param) throws ODataException {
ODataSubLocator subLocator = new ODataSubLocator();
subLocator.serviceFactory = param.getServiceFactory();
subLocator.request = ODataRequest.acceptableLanguages(param.getHttpHeaders().getAcceptableLanguages())
.httpMethod(param.getServletRequest().getMethod())
.acceptHeaders(RestUtil.extractAcceptHeaders(param))
.body(RestUtil.contentAsStream(RestUtil.extractRequestContent(param)))
.pathInfo(RestUtil.buildODataPathInfo(param))
.allQueryParameters(param.getUriInfo().getQueryParameters())
.requestHeaders(param.getHttpHeaders().getRequestHeaders())
.contentType(RestUtil.extractRequestContentType(param).toContentTypeString())
.build();
subLocator.httpRequest = param.getServletRequest();
return subLocator;
}
private ODataSubLocator() {
super();
}
}