Author: fmeschbe
Date: Wed Dec 19 07:52:37 2007
New Revision: 605592
URL: http://svn.apache.org/viewvc?rev=605592&view=rev
Log:
SLING-141 Add RequestData.service method used to call a servlet. This method
keeps track of the currently running servlet as a request attribute (reset
after the request) and an internal field (reset only if the service method
returns normally). Third the request progress is tracked by logging the
entry and exit of the servlet.
Modified:
incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/CoreConstants.java
incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/SlingMainServlet.java
incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/filter/AbstractSlingFilterChain.java
incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/filter/RequestSlingFilterChain.java
incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/filter/SlingComponentFilterChain.java
incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/request/RequestData.java
Modified:
incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/CoreConstants.java
URL:
http://svn.apache.org/viewvc/incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/CoreConstants.java?rev=605592&r1=605591&r2=605592&view=diff
==============================================================================
---
incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/CoreConstants.java
(original)
+++
incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/CoreConstants.java
Wed Dec 19 07:52:37 2007
@@ -66,6 +66,15 @@
public static final String SLING_ID = "sling.id";
/**
+ * The name of the request attribute providing the name of the currently
+ * executing servlet (value is "sling.core.current.servletName"). This
+ * attribute is set immediately before calling the
+ * <code>Servlet.service()</code> method and reset to any previously
+ * stored value after the service method returns.
+ */
+ public static final String SLING_CURRENT_SERVLET_NAME =
"sling.core.current.servletName";
+
+ /**
* The name of the service registration property of a Servlet registered as
* a service containing the name of the servlet (value is
* "sling.core.servletName"). If this property is missing or empty, the
Modified:
incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/SlingMainServlet.java
URL:
http://svn.apache.org/viewvc/incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/SlingMainServlet.java?rev=605592&r1=605591&r2=605592&view=diff
==============================================================================
---
incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/SlingMainServlet.java
(original)
+++
incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/SlingMainServlet.java
Wed Dec 19 07:52:37 2007
@@ -18,6 +18,9 @@
*/
package org.apache.sling.core.impl;
+import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
+import static org.apache.sling.api.SlingConstants.ERROR_SERVLET_NAME;
+
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URL;
@@ -42,6 +45,7 @@
import javax.servlet.http.HttpServletResponse;
import org.apache.sling.api.HttpStatusCodeException;
+import org.apache.sling.api.SlingConstants;
import org.apache.sling.api.SlingException;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
@@ -182,8 +186,7 @@
} else {
log.error("service: No Request Handling filters, cannot
process request");
- response.sendError(
- HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+ response.sendError(SC_INTERNAL_SERVER_ERROR,
"Cannot process Request");
}
@@ -199,6 +202,15 @@
hsce.getMessage(), clientRequest, clientResponse);
} catch (Throwable t) {
+
+ // if we have request data and a non-null active servlet name
+ // we assume, that this is the name of the causing servlet
+ if (requestData != null
+ && requestData.getActiveServletName() != null) {
+ clientRequest.setAttribute(ERROR_SERVLET_NAME,
+ requestData.getActiveServletName());
+ }
+
getErrorHandler().handleError(t, clientRequest,
clientResponse);
} finally {
@@ -270,14 +282,7 @@
processor.doFilter(request, response);
} else {
log.debug("service: No Resource level filters, calling servlet");
- Servlet servlet =
RequestData.getRequestData(request).getContentData().getServlet();
- if (servlet != null) {
- servlet.service(request, response);
- } else {
- response.sendError(HttpServletResponse.SC_NOT_FOUND,
- "No Servlet or Script to handle request to "
- + request.getResource().getURI());
- }
+ RequestData.service(request, response);
}
}
Modified:
incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/filter/AbstractSlingFilterChain.java
URL:
http://svn.apache.org/viewvc/incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/filter/AbstractSlingFilterChain.java?rev=605592&r1=605591&r2=605592&view=diff
==============================================================================
---
incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/filter/AbstractSlingFilterChain.java
(original)
+++
incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/filter/AbstractSlingFilterChain.java
Wed Dec 19 07:52:37 2007
@@ -26,6 +26,9 @@
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+
public abstract class AbstractSlingFilterChain implements FilterChain {
private Filter[] filters;
@@ -38,7 +41,8 @@
}
/**
- * @see javax.servlet.FilterChain#doFilter(javax.servlet.ServletRequest,
javax.servlet.ServletResponse)
+ * @see javax.servlet.FilterChain#doFilter(javax.servlet.ServletRequest,
+ * javax.servlet.ServletResponse)
*/
public void doFilter(ServletRequest request, ServletResponse response)
throws ServletException, IOException {
@@ -47,10 +51,12 @@
if (this.current < this.filters.length) {
this.filters[this.current].doFilter(request, response, this);
} else {
- this.render(request, response);
+ this.render((SlingHttpServletRequest) request,
+ (SlingHttpServletResponse) response);
}
}
- protected abstract void render(ServletRequest request,
- ServletResponse response) throws IOException, ServletException;
+ protected abstract void render(SlingHttpServletRequest request,
+ SlingHttpServletResponse response) throws IOException,
+ ServletException;
}
Modified:
incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/filter/RequestSlingFilterChain.java
URL:
http://svn.apache.org/viewvc/incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/filter/RequestSlingFilterChain.java?rev=605592&r1=605591&r2=605592&view=diff
==============================================================================
---
incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/filter/RequestSlingFilterChain.java
(original)
+++
incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/filter/RequestSlingFilterChain.java
Wed Dec 19 07:52:37 2007
@@ -22,8 +22,6 @@
import javax.servlet.Filter;
import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
@@ -39,15 +37,14 @@
private final SlingMainServlet handler;
- public RequestSlingFilterChain(SlingMainServlet handler,
- Filter[] filters) {
+ public RequestSlingFilterChain(SlingMainServlet handler, Filter[] filters)
{
super(filters);
this.handler = handler;
}
- protected void render(ServletRequest request, ServletResponse response)
- throws ServletException, IOException {
- handler.processRequest((SlingHttpServletRequest) request,
- (SlingHttpServletResponse) response);
+ protected void render(SlingHttpServletRequest request,
+ SlingHttpServletResponse response) throws ServletException,
+ IOException {
+ handler.processRequest(request, response);
}
}
Modified:
incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/filter/SlingComponentFilterChain.java
URL:
http://svn.apache.org/viewvc/incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/filter/SlingComponentFilterChain.java?rev=605592&r1=605591&r2=605592&view=diff
==============================================================================
---
incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/filter/SlingComponentFilterChain.java
(original)
+++
incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/filter/SlingComponentFilterChain.java
Wed Dec 19 07:52:37 2007
@@ -21,14 +21,12 @@
import java.io.IOException;
import javax.servlet.Filter;
-import javax.servlet.Servlet;
import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.core.impl.request.RequestData;
-
/**
* The <code>SlingComponentFilterChain</code> implements the filter chain for
* component scoped filters. It is used by the
@@ -41,9 +39,9 @@
super(filters);
}
- protected void render(ServletRequest request, ServletResponse response)
- throws IOException, ServletException {
- Servlet servlet =
RequestData.getRequestData(request).getContentData().getServlet();
- servlet.service(request, response);
+ protected void render(SlingHttpServletRequest request,
+ SlingHttpServletResponse response) throws IOException,
+ ServletException {
+ RequestData.service(request, response);
}
}
Modified:
incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/request/RequestData.java
URL:
http://svn.apache.org/viewvc/incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/request/RequestData.java?rev=605592&r1=605591&r2=605592&view=diff
==============================================================================
---
incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/request/RequestData.java
(original)
+++
incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/request/RequestData.java
Wed Dec 19 07:52:37 2007
@@ -20,6 +20,7 @@
import static org.apache.sling.api.SlingConstants.ATTR_REQUEST_CONTENT;
import static org.apache.sling.api.SlingConstants.ATTR_REQUEST_SERVLET;
+import static org.apache.sling.core.CoreConstants.SLING_CURRENT_SERVLET_NAME;
import java.io.BufferedReader;
import java.io.IOException;
@@ -53,6 +54,8 @@
import org.apache.sling.api.servlets.ServletResolver;
import org.apache.sling.api.wrappers.SlingHttpServletRequestWrapper;
import org.apache.sling.api.wrappers.SlingHttpServletResponseWrapper;
+import org.apache.sling.core.CoreConstants;
+import org.apache.sling.core.RequestUtil;
import org.apache.sling.core.impl.SlingHttpServletRequestImpl;
import org.apache.sling.core.impl.SlingHttpServletResponseImpl;
import org.apache.sling.core.impl.SlingMainServlet;
@@ -68,7 +71,7 @@
* The <code>RequestData</code> class provides access to objects which are set
* on a Servlet Request wide basis such as the repository session, the
* persistence manager, etc.
- *
+ *
* @see ContentData
*/
public class RequestData implements BufferProvider {
@@ -107,17 +110,34 @@
/** the stack of ContentData objects */
private LinkedList<ContentData> contentDataStack;
+
+ /**
+ * the number of servlets called by
+ * [EMAIL PROTECTED] #service(SlingHttpServletRequest,
SlingHttpServletResponse)}
+ */
+ private int servletCallCounter;
+
+ /**
+ * The name of the currently active serlvet.
+ *
+ * @see #setActiveServletName(String)
+ * @see #getActiveServletName()
+ */
+ private String activeServletName;
public RequestData(SlingMainServlet slingMainServlet, Session session,
- HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
+ HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
this.slingMainServlet = slingMainServlet;
this.servletRequest = request;
this.servletResponse = response;
- this.slingRequest = new SlingHttpServletRequestImpl(this,
servletRequest);
- this.slingResponse = new SlingHttpServletResponseImpl(this,
servletResponse);
+ this.slingRequest = new SlingHttpServletRequestImpl(this,
+ servletRequest);
+ this.slingResponse = new SlingHttpServletResponseImpl(this,
+ servletResponse);
this.requestProgressTracker = new SlingRequestProgressTracker();
@@ -129,7 +149,8 @@
"No resource can be found");
}
- // officially, getting the manager may fail, but not i this
implementation
+ // officially, getting the manager may fail, but not i this
+ // implementation
this.resourceResolver = rmf.getResourceResolver(session);
// resolve the resource and the request path info, will never be null
@@ -223,7 +244,7 @@
/**
* Unwraps the SlingHttpServletRequest to a SlingHttpServletRequestImpl
- *
+ *
* @param request
* @return
* @throws SlingException
@@ -238,8 +259,7 @@
return (SlingHttpServletRequestImpl) request;
}
- throw new SlingException(
- "SlingHttpServletRequest not of correct type");
+ throw new SlingException("SlingHttpServletRequest not of correct
type");
}
/**
@@ -271,7 +291,7 @@
/**
* Unwraps a SlingHttpServletResponse to a SlingHttpServletResponseImpl
- *
+ *
* @param response
* @return
* @throws SlingException
@@ -286,8 +306,7 @@
return (SlingHttpServletResponseImpl) response;
}
- throw new SlingException(
- "SlingHttpServletResponse not of correct type");
+ throw new SlingException("SlingHttpServletResponse not of correct
type");
}
public static RequestData getRequestData(SlingHttpServletRequest request)
@@ -348,6 +367,67 @@
// and unwrapped component response
return null;
}
+
+ /**
+ * Helper method to call the servlet for the current content data. If the
+ * current content data has no servlet, <em>NOT_FOUND</em> (404) error is
+ * sent and the method terminates.
+ * <p>
+ * If the the servlet exists, the
+ * [EMAIL PROTECTED] CoreConstants#SLING_CURRENT_SERVLET_NAME} request
attribute is set
+ * to the name of that servlet and that servlet name is also set as the
+ * [EMAIL PROTECTED] #setActiveServletName(String) currently active
servlet}. After
+ * the termination of the servlet (normal or throwing a Throwable) the
+ * request attribute is reset to the previous value. The name of the
+ * currently active servlet is only reset to the previous value if the
+ * servlet terminates normally. In case of a Throwable, the active servlet
+ * name is not reset and indicates which servlet caused the potential abort
+ * of the request.
+ *
+ * @param request The request object for the service method
+ * @param response The response object for the service method
+ * @throws IOException May be thrown by the servlet's service method
+ * @throws ServletException May be thrown by the servlet's service method
+ */
+ public static void service(SlingHttpServletRequest request,
+ SlingHttpServletResponse response) throws IOException,
+ ServletException {
+
+ RequestData requestData = RequestData.getRequestData(request);
+ Servlet servlet = requestData.getContentData().getServlet();
+ if (servlet == null) {
+
+ response.sendError(HttpServletResponse.SC_NOT_FOUND,
+ "No Servlet to handle request");
+
+ } else {
+
+ String name = RequestUtil.getServletName(servlet);
+ Object oldValue = request.getAttribute(SLING_CURRENT_SERVLET_NAME);
+ request.setAttribute(SLING_CURRENT_SERVLET_NAME, name);
+
+ 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(SLING_CURRENT_SERVLET_NAME, oldValue);
+
+ requestData.getRequestProgressTracker().logTimer(timerName);
+ requestData.servletCallCounter--;
+
+ }
+ }
+ }
// ---------- Content inclusion stacking
-----------------------------------
@@ -454,6 +534,27 @@
servletRequest.setAttribute(Theme.class.getName(), theme);
}
+ /**
+ * 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;
+ }
+
// ---------- BufferProvider -----------------------------------------
public BufferProvider getBufferProvider() {
@@ -483,7 +584,8 @@
return getServletRequest().getInputStream();
}
- public BufferedReader getReader() throws UnsupportedEncodingException,
IOException {
+ public BufferedReader getReader() throws UnsupportedEncodingException,
+ IOException {
if (parameterSupport != null && parameterSupport.requestDataUsed()) {
throw new IllegalStateException(
"Request Data has already been read");