| /******************************************************************************* |
| * 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(); |
| } |
| } |