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>");
     }


Reply via email to