/* * Copyright 2012 The Solmix Project * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.gnu.org/licenses/ * or see the FSF site: http://www.fsf.org. */ package org.solmix.fmk.engine.internal.request; import static org.solmix.SlxConstants.CURRENT_SERVLET_NAME; import java.io.IOException; import javax.servlet.Servlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletRequestWrapper; import javax.servlet.ServletResponse; import javax.servlet.ServletResponseWrapper; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.solmix.api.request.RequestProgressTracker; import org.solmix.api.request.RequestUtil; import org.solmix.api.request.SlxHttpServletRequest; import org.solmix.api.request.SlxHttpServletResponse; import org.solmix.api.servlet.ServletManager; import org.solmix.fmk.engine.MainServlet; /** * Wrapper Httprequest and httpresponse. */ public class RequestData { private MainServlet MAIN_SERVLET; private RequestProgressTracker requestProgressTracker; private final SlxRequestProcessor requestProcessor; private HttpServletRequest servletRequest; private HttpServletResponse servletResponse; private final SlxHttpServletRequestImpl slxRequest; private final SlxHttpServletResponseImpl slxResponse; private String activeServletName; private Servlet currentServlet; private int servletCallCounter; public RequestData(SlxRequestProcessor requestProcessor, HttpServletRequest request, HttpServletResponse response) { this.requestProcessor = requestProcessor; this.servletRequest = request; this.servletResponse = response; this.slxRequest = new SlxHttpServletRequestImpl(this, request); this.slxResponse = new SlxHttpServletResponseImpl(this, response); this.requestProgressTracker = new SlxRequestProgressTracker(); this.requestProgressTracker.log("Method={0}, PathInfo={1}", this.slxRequest.getMethod(), this.slxRequest.getPathInfo()); } @Deprecated public <Type> Type adaptTo(Object object, Class<Type> type) { return MAIN_SERVLET.adaptTo(object, type); } /** * @return */ public RequestProgressTracker getRequestProgressTracker() { return requestProgressTracker; } /** * @param requestProgressTracker the requestProgressTracker to set */ public void setRequestProgressTracker(RequestProgressTracker requestProgressTracker) { this.requestProgressTracker = requestProgressTracker; } /** * @return the slxRequest */ public SlxHttpServletRequestImpl getSlxRequest() { return slxRequest; } /** * @return the slxResponse */ public SlxHttpServletResponseImpl getSlxResponse() { return slxResponse; } /** * Sets the name of the currently active servlet and returns the name of the previously active servlet. */ public String setActiveServletName(String servletName) { String old = activeServletName; activeServletName = servletName; return old; } /** * Returns the name of the currently active servlet. If this name is not <code>null</code> at the end of request * processing, more precisly in the case of an uncaught <code>Throwable</code> at the end of request processing, * this is the name of the servlet causing the uncaught <code>Throwable</code>. */ public String getActiveServletName() { return activeServletName; } /** * @param servletManager */ public void initServlet(ServletManager servletManager) { requestProgressTracker.log("Resource Path Info: {0}", servletRequest.getPathInfo()); // finally resolve the servlet for the resource requestProgressTracker.startTimer("ServletResolution"); Servlet servlet = servletManager.resolveServlet(slxRequest); requestProgressTracker.logTimer("ServletResolution", "URI={0} handled by Servlet={1}", getServletRequest().getRequestURI(), (servlet == null ? "-none-" : RequestUtil.getServletName(servlet))); this.setCurrentServlet(servlet); } public static void service(SlxHttpServletRequest request, SlxHttpServletResponse response) throws IOException, ServletException { RequestData requestData = RequestData.getRequestData(request); Servlet servlet = requestData.getCurrentServlet(); if (servlet == null) { response.sendError(HttpServletResponse.SC_NOT_FOUND, "No Servlet to handle request"); } else { String name = RequestUtil.getServletName(servlet); // TODO add max call controls. // replace the current servlet name in the request Object oldValue = request.getAttribute(CURRENT_SERVLET_NAME); request.setAttribute(CURRENT_SERVLET_NAME, name); // setup the tracker for this service call String timerName = name + "#" + requestData.servletCallCounter; requestData.servletCallCounter++; requestData.getRequestProgressTracker().startTimer(timerName); try { String callerServlet = requestData.setActiveServletName(name); servlet.service(request, response); requestData.setActiveServletName(callerServlet); } finally { request.setAttribute(CURRENT_SERVLET_NAME, oldValue); requestData.getRequestProgressTracker().logTimer(timerName); } } } /** * @param request * @return */ public static RequestData getRequestData(ServletRequest request) { return unwrap(unwrap(request)).getRequestData(); } /** * @param request * @return */ private static SlxHttpServletRequestImpl unwrap(SlxHttpServletRequest request) { if (request instanceof SlxHttpServletRequestImpl) { return (SlxHttpServletRequestImpl) request; } throw new IllegalArgumentException("SlxHttpServletRequest not of correct type"); } private static SlxHttpServletResponse unwrap(ServletResponse response) { // early check for most cases if (response instanceof SlxHttpServletResponse) { return (SlxHttpServletResponse) response; } // unwrap wrappers while (response instanceof ServletResponseWrapper) { response = ((ServletResponseWrapper) response).getResponse(); ; // immediate termination if we found one if (response instanceof SlxHttpServletRequest) { return (SlxHttpServletResponse) response; } } // if we unwrapped everything and did not find a // SlingHttpServletRequest, we lost throw new IllegalArgumentException("ServletRequest not wrapping SlxHttpServletRequest"); } private static SlxHttpServletRequest unwrap(ServletRequest request) { // early check for most cases if (request instanceof SlxHttpServletRequest) { return (SlxHttpServletRequest) request; } // unwrap wrappers while (request instanceof ServletRequestWrapper) { request = ((ServletRequestWrapper) request).getRequest(); // immediate termination if we found one if (request instanceof SlxHttpServletRequest) { return (SlxHttpServletRequest) request; } } // if we unwrapped everything and did not find a // SlingHttpServletRequest, we lost throw new IllegalArgumentException("ServletRequest not wrapping SlxHttpServletRequest"); } /** * @return the servletRequest */ public HttpServletRequest getServletRequest() { return servletRequest; } /** * @param servletRequest the servletRequest to set */ public void setServletRequest(HttpServletRequest servletRequest) { this.servletRequest = servletRequest; } /** * @return the servletResponse */ public HttpServletResponse getServletResponse() { return servletResponse; } /** * @param servletResponse the servletResponse to set */ public void setServletResponse(HttpServletResponse servletResponse) { this.servletResponse = servletResponse; } /** * @return the currentServlet */ public Servlet getCurrentServlet() { return currentServlet; } /** * @param currentServlet the currentServlet to set */ public void setCurrentServlet(Servlet currentServlet) { this.currentServlet = currentServlet; } /** * @param request * @return */ public static SlxHttpServletRequest toSlxHttpServletRequest(ServletRequest request) { return unwrap(request); } public static SlxHttpServletResponse toSlxHttpServletResponse(ServletResponse response) { return unwrap(response); } }