/******************************************************************************* * Copyright 2013 SAP AG * * Licensed 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 com.sap.core.odata.core.rest; import java.util.List; import javax.servlet.ServletConfig; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Encoded; import javax.ws.rs.HeaderParam; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.PathSegment; import javax.ws.rs.core.Request; import javax.ws.rs.core.UriInfo; import com.sap.core.odata.api.ODataServiceFactory; import com.sap.core.odata.api.exception.ODataBadRequestException; import com.sap.core.odata.api.exception.ODataException; import com.sap.core.odata.core.exception.ODataRuntimeException; /** * Default OData root locator responsible to handle the whole path and delegate all calls to a sub locator:<p> * <code>/{odata path} e.g. http://host:port/webapp/odata.svc/$metadata</code><br> * All path segments defined by a servlet mapping belong to the odata uri. * </p> * This behavior can be changed:<p> * <code>/{custom path}{odata path} e.g. http://host:port/webapp/bmw/odata.svc/$metadata</code><br> * The first segment defined by a servlet mapping belong to customer context and the following segments are OData specific. * </p> * @author SAP AG */ public class ODataRootLocator { @Context private HttpHeaders httpHeaders; @Context private UriInfo uriInfo; @Context private Request request; @Context private ServletConfig servletConfig; @Context private HttpServletRequest servletRequest; /** * Default root behavior which will delegate all paths to a ODataLocator. * @param pathSegments URI path segments - all segments have to be OData * @param xHttpMethod HTTP Header X-HTTP-Method for tunneling through POST * @param xHttpMethodOverride HTTP Header X-HTTP-Method-Override for tunneling through POST * @return a locator handling OData protocol * @throws ODataException * @throws ClassNotFoundException * @throws IllegalAccessException * @throws InstantiationException */ @Path("/{pathSegments: .*}") public Object handleRequest( @Encoded @PathParam("pathSegments") final List<PathSegment> pathSegments, @HeaderParam("X-HTTP-Method") final String xHttpMethod, @HeaderParam("X-HTTP-Method-Override") final String xHttpMethodOverride) throws ODataException, ClassNotFoundException, InstantiationException, IllegalAccessException { if (xHttpMethod != null && xHttpMethodOverride != null) { /* * X-HTTP-Method-Override : implemented by CXF * X-HTTP-Method : implemented in ODataSubLocator:handlePost */ if (!xHttpMethod.equalsIgnoreCase(xHttpMethodOverride)) { throw new ODataBadRequestException(ODataBadRequestException.AMBIGUOUS_XMETHOD); } } if (servletRequest.getPathInfo() == null) { return handleRedirect(); } final String factoryClassName = servletConfig.getInitParameter(ODataServiceFactory.FACTORY_LABEL); if (factoryClassName == null) { throw new ODataRuntimeException("servlet config missing: com.sap.core.odata.processor.factory"); } ClassLoader cl = (ClassLoader) servletRequest.getAttribute(ODataServiceFactory.FACTORY_CLASSLOADER_LABEL); Class<?> factoryClass; if (cl == null) { factoryClass = Class.forName(factoryClassName); } else { factoryClass = Class.forName(factoryClassName, true, cl); } ODataServiceFactory serviceFactory = (ODataServiceFactory) factoryClass.newInstance(); int pathSplit = 0; final String pathSplitAsString = servletConfig.getInitParameter(ODataServiceFactory.PATH_SPLIT_LABEL); if (pathSplitAsString != null) { pathSplit = Integer.parseInt(pathSplitAsString); } final SubLocatorParameter param = new SubLocatorParameter(); param.setServiceFactory(serviceFactory); param.setPathSegments(pathSegments); param.setHttpHeaders(httpHeaders); param.setUriInfo(uriInfo); param.setRequest(request); param.setServletRequest(servletRequest); param.setPathSplit(pathSplit); return ODataSubLocator.create(param); } private Object handleRedirect() { return new ODataRedirectLocator(); } }