Author: fmeschbe
Date: Thu Mar 25 10:46:38 2010
New Revision: 927338
URL: http://svn.apache.org/viewvc?rev=927338&view=rev
Log:
SLING-1160 Allow replacement of the default error handler by application
provided variants.
Modified:
sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/ServletResolverConstants.java
sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java
sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/defaults/DefaultErrorHandlerServlet.java
Modified:
sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/ServletResolverConstants.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/ServletResolverConstants.java?rev=927338&r1=927337&r2=927338&view=diff
==============================================================================
---
sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/ServletResolverConstants.java
(original)
+++
sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/ServletResolverConstants.java
Thu Mar 25 10:46:38 2010
@@ -115,4 +115,9 @@ public class ServletResolverConstants {
*/
public static final String ERROR_HANDLER_PATH =
"sling/servlet/errorhandler";
+ /**
+ * The "method" name of an error handler used as the default (value is
+ * "default").
+ */
+ public static final String DEFAULT_ERROR_HANDLER_NAME = "default";
}
Modified:
sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java?rev=927338&r1=927337&r2=927338&view=diff
==============================================================================
---
sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java
(original)
+++
sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java
Thu Mar 25 10:46:38 2010
@@ -182,7 +182,7 @@ public class SlingServletResolver implem
// the default error handler servlet if no other error servlet applies for
// a request. This field is set on demand by getDefaultErrorServlet()
- private Servlet defaultErrorServlet;
+ private Servlet fallbackErrorServlet;
private Map<ResourceCollector, Servlet> cache;
@@ -341,7 +341,8 @@ public class SlingServletResolver implem
// fall back to default servlet if none
if (servlet == null) {
- servlet = getDefaultErrorServlet();
+ servlet = getDefaultErrorServlet(request, scriptResolver,
+ resource);
}
// set the message properties
@@ -401,7 +402,8 @@ public class SlingServletResolver implem
}
if (servlet == null) {
- servlet = getDefaultErrorServlet();
+ servlet = getDefaultErrorServlet(request, scriptResolver,
+ resource);
}
// set the message properties
@@ -573,22 +575,48 @@ public class SlingServletResolver implem
/**
* Returns the default error handler servlet, which is called in case there
* is no other - better matching - servlet registered to handle an error or
- * exception. As it is expected, that most of the time, there will be no
- * such more specific servlet, the default error handler servlet is quite
- * complete.
- */
- private Servlet getDefaultErrorServlet() {
- if (defaultErrorServlet == null) {
+ * exception.
+ * <p>
+ * The default error handler servlet is registered for the resource type
+ * "sling/servlet/errorhandler" and method "default". This may be
+ * overwritten by applications globally or according to the resource type
+ * hierarchy of the resource.
+ * <p>
+ * If no default error handler servlet can be found an adhoc error handler
+ * is used as a final fallback.
+ */
+ private Servlet getDefaultErrorServlet(
+ final SlingHttpServletRequest request,
+ final WorkspaceResourceResolver scriptResolver,
+ final Resource resource) {
+
+ // find a default error handler according to the resource type
+ // tree of the given resource
+ final ResourceCollector locationUtil = new ResourceCollector(
+ ServletResolverConstants.DEFAULT_ERROR_HANDLER_NAME,
+ ServletResolverConstants.ERROR_HANDLER_PATH, resource,
+ scriptResolver.getWorkspaceName());
+ final Servlet servlet = getServlet(locationUtil, request,
+ scriptResolver);
+ if (servlet != null) {
+ return servlet;
+ }
+
+ // if no registered default error handler could be found use
+ // the DefaultErrorHandlerServlet as an ad-hoc fallback
+ if (fallbackErrorServlet == null) {
+ // fall back to an adhoc instance of the DefaultErrorHandlerServlet
+ // if the actual service is not registered (yet ?)
try {
- Servlet servlet = new DefaultErrorHandlerServlet();
- servlet.init(new SlingServletConfig(servletContext, null,
"Sling Default Error Handler Servlet"));
- defaultErrorServlet = servlet;
+ final Servlet defaultServlet = new
DefaultErrorHandlerServlet();
+ defaultServlet.init(new SlingServletConfig(servletContext,
+ null, "Sling (Ad Hoc) Default Error Handler Servlet"));
+ fallbackErrorServlet = defaultServlet;
} catch (ServletException se) {
log.error("Failed to initialize error servlet", se);
}
}
-
- return defaultErrorServlet;
+ return fallbackErrorServlet;
}
private void handleError(Servlet errorHandler, HttpServletRequest request,
HttpServletResponse response)
@@ -741,6 +769,17 @@ public class SlingServletResolver implem
refs = new
ArrayList<ServiceReference>(servletsByReference.keySet());
}
+ // destroy the fallback error handler servlet
+ if (fallbackErrorServlet != null) {
+ try {
+ fallbackErrorServlet.destroy();
+ } catch (Throwable t) {
+ // ignore
+ } finally {
+ fallbackErrorServlet = null;
+ }
+ }
+
// destroy all servlets
destroyAllServlets(refs);
if (this.scriptSessions != null && (!this.scriptSessions.isEmpty())) {
Modified:
sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/defaults/DefaultErrorHandlerServlet.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/defaults/DefaultErrorHandlerServlet.java?rev=927338&r1=927337&r2=927338&view=diff
==============================================================================
---
sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/defaults/DefaultErrorHandlerServlet.java
(original)
+++
sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/defaults/DefaultErrorHandlerServlet.java
Thu Mar 25 10:46:38 2010
@@ -36,13 +36,21 @@ import org.slf4j.LoggerFactory;
/**
* The <code>DefaultErrorHandlerServlet</code> TODO
+ *
+ * @scr.component metatype="no" immediate="true"
+ * @scr.service interface="javax.servlet.Servlet"
+ *
+ * This is the default error handler servlet registered at the end of the
+ * global search path
+ * @scr.property name="sling.servlet.paths"
value="sling/servlet/errorhandler/default"
+ * @scr.property name="sling.servlet.prefix" value="-1"
*/
@SuppressWarnings("serial")
public class DefaultErrorHandlerServlet extends GenericServlet {
/** default log */
- private static final Logger log =
LoggerFactory.getLogger(DefaultErrorHandlerServlet.class);
-
+ private final Logger log =
LoggerFactory.getLogger(DefaultErrorHandlerServlet.class);
+
@Override
public void service(ServletRequest req, ServletResponse res)
throws IOException {
@@ -66,8 +74,11 @@ public class DefaultErrorHandlerServlet
statusMessage, requestUri, servletName);
// write the exception message
+ final PrintWriter escapingWriter = new PrintWriter(
+ ResponseUtil.getXmlEscapingWriter(pw));
+
+ // dump the stack trace
if (req.getAttribute(SlingConstants.ERROR_EXCEPTION) instanceof
Throwable) {
- final PrintWriter escapingWriter = new
PrintWriter(ResponseUtil.getXmlEscapingWriter(pw));
Throwable throwable = (Throwable)
req.getAttribute(SlingConstants.ERROR_EXCEPTION);
pw.println("<h3>Exception:</h3>");
pw.println("<pre>");
@@ -75,16 +86,17 @@ public class DefaultErrorHandlerServlet
printStackTrace(escapingWriter, throwable);
escapingWriter.flush();
pw.println("</pre>");
-
- if (req instanceof SlingHttpServletRequest) {
- RequestProgressTracker tracker = ((SlingHttpServletRequest)
req).getRequestProgressTracker();
- pw.println("<h3>Request Progress:</h3>");
- pw.println("<pre>");
- pw.flush();
- tracker.dump(escapingWriter);
- escapingWriter.flush();
- pw.println("</pre>");
- }
+ }
+
+ // dump the request progress tracker
+ if (req instanceof SlingHttpServletRequest) {
+ RequestProgressTracker tracker = ((SlingHttpServletRequest)
req).getRequestProgressTracker();
+ pw.println("<h3>Request Progress:</h3>");
+ pw.println("<pre>");
+ pw.flush();
+ tracker.dump(escapingWriter);
+ escapingWriter.flush();
+ pw.println("</pre>");
}
// conclude the response message
@@ -128,13 +140,13 @@ public class DefaultErrorHandlerServlet
throws IOException {
final String statusMessage = ResponseUtil.escapeXml(statusMessageIn);
-
+
// set the status code and content type in the response
final PrintWriter pw = response.getWriter();
if(!response.isCommitted()) {
response.setStatus(statusCode);
response.setContentType("text/html; charset=UTF-8");
-
+
pw.println("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">");
pw.println("<html>");
pw.println("<head>");
@@ -167,6 +179,7 @@ public class DefaultErrorHandlerServlet
pw.println("<hr>");
pw.println("<address>" + getServletContext().getServerInfo()
+ "</address>");
+
pw.println("</body>");
pw.println("</html>");
}