All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sap.cds.adapter.odata.v2.CdsODataV2Servlet Maven / Gradle / Ivy

There is a newer version: 3.6.0
Show newest version
/**************************************************************************
 * (C) 2019-2024 SAP SE or an SAP affiliate company. All rights reserved. *
 **************************************************************************/
package com.sap.cds.adapter.odata.v2;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Locale;
import java.util.Optional;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import jakarta.servlet.http.HttpServletResponse;

import org.apache.olingo.odata2.api.ODataServiceFactory;
import org.apache.olingo.odata2.core.commons.ContentType;
import org.apache.olingo.odata2.core.servlet.ODataServlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sap.cds.services.ErrorStatuses;
import com.sap.cds.services.ServiceException;
import com.sap.cds.services.request.ParameterInfo;
import com.sap.cds.services.runtime.CdsRuntime;
import com.sap.cds.services.utils.ErrorStatusException;
import com.sap.cds.services.utils.path.UrlPathUtil;

@SuppressWarnings("serial")
public class CdsODataV2Servlet extends ODataServlet {

	public static final String ATTRIBUTE_REQUEST_GLOBALS = "requestGlobals";
	private static final Logger logger = LoggerFactory.getLogger(CdsODataV2Servlet.class);
	private static final String UNEXPECTED_ERROR_MESSAGE = "An unexpected error occurred during servlet processing";

	private final CdsRuntime runtime;
	private final CdsODataV2ServiceFactory serviceFactory;

	public CdsODataV2Servlet(CdsRuntime runtime) {
		this.runtime = runtime;
		this.serviceFactory = new CdsODataV2ServiceFactory(runtime);
	}

	@Override
	protected ODataServiceFactory getServiceFactory(HttpServletRequest request) {
		return serviceFactory;

	}

	@Override
	public String getInitParameter(String name) {
		return null;
	}

	@Override
	protected void service(final HttpServletRequest request, final HttpServletResponse response) throws IOException {
		HttpServletRequest wrappedRequest = new HttpServletRequestWrapper(request) {
			@Override
			public String getServletPath() {
				String pathInfo = getPathInfo();

				// try to find the best matching service path
				Optional servicePath = serviceFactory.getServicePath(pathInfo);
				if (servicePath.isPresent()) {
					return "/" + servicePath.get();
				}
				// fall back to just the first path element
				pathInfo = pathInfo.substring(1);
				return pathInfo.indexOf("/") != -1 ? ("/" + pathInfo.substring(0, pathInfo.indexOf("/"))) : ("/" + pathInfo);
			}
			@Override
			public String getContextPath() {
				return UrlPathUtil.normalizeBasePath(runtime.getEnvironment().getCdsProperties().getOdataV2().getEndpoint().getPath());
			}
		};

		// extract the locale according to request parameters
		ParameterInfo parameterInfo = runtime.getProvidedParameterInfo();
		Locale locale = parameterInfo.getLocale();
		try {
			runtime.requestContext().parameters(parameterInfo).run((context) -> {
				CdsRequestGlobals requestGlobals = new CdsRequestGlobals(runtime, context.getModel());
				wrappedRequest.setAttribute(ATTRIBUTE_REQUEST_GLOBALS, requestGlobals);

				try {
					super.service(wrappedRequest, response);
				} catch (IOException e) {
					throw new UncheckedIOException(e);
				}
			});
		} catch (ServiceException e) {
			int httpStatus = e.getErrorStatus().getHttpStatus();
			if(httpStatus >= 500 && httpStatus < 600) {
				logger.error(UNEXPECTED_ERROR_MESSAGE, e);
			} else {
				logger.debug(UNEXPECTED_ERROR_MESSAGE, e);
			}

			writeErrorResponse(request, response, httpStatus, e.getLocalizedMessage(locale));
		} catch (Exception e) { // NOSONAR
			logger.error(UNEXPECTED_ERROR_MESSAGE, e);
			writeErrorResponse(request, response, 500, new ErrorStatusException(ErrorStatuses.SERVER_ERROR).getLocalizedMessage(locale));
		}

	}

	private void writeErrorResponse(HttpServletRequest req, HttpServletResponse resp, int httpStatus, String message) throws IOException {
		String responseContent = "" + httpStatus + "" + message + "";
		// TODO can we do better here in guessing the content type?
		resp.setHeader("Content-Type", ContentType.APPLICATION_XML.toContentTypeString());
		resp.setStatus(httpStatus);
		resp.getWriter().println(responseContent);
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy