You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by fm...@apache.org on 2008/01/14 15:22:38 UTC

svn commit: r611810 - in /incubator/sling/whiteboard/fmeschbe/resource/sling/core/src/main/java/org/apache/sling/core: impl/SlingMainServlet.java impl/request/RequestData.java servlets/ErrorHandler.java

Author: fmeschbe
Date: Mon Jan 14 06:22:35 2008
New Revision: 611810

URL: http://svn.apache.org/viewvc?rev=611810&view=rev
Log:
Improve error handling

Modified:
    incubator/sling/whiteboard/fmeschbe/resource/sling/core/src/main/java/org/apache/sling/core/impl/SlingMainServlet.java
    incubator/sling/whiteboard/fmeschbe/resource/sling/core/src/main/java/org/apache/sling/core/impl/request/RequestData.java
    incubator/sling/whiteboard/fmeschbe/resource/sling/core/src/main/java/org/apache/sling/core/servlets/ErrorHandler.java

Modified: incubator/sling/whiteboard/fmeschbe/resource/sling/core/src/main/java/org/apache/sling/core/impl/SlingMainServlet.java
URL: http://svn.apache.org/viewvc/incubator/sling/whiteboard/fmeschbe/resource/sling/core/src/main/java/org/apache/sling/core/impl/SlingMainServlet.java?rev=611810&r1=611809&r2=611810&view=diff
==============================================================================
--- incubator/sling/whiteboard/fmeschbe/resource/sling/core/src/main/java/org/apache/sling/core/impl/SlingMainServlet.java (original)
+++ incubator/sling/whiteboard/fmeschbe/resource/sling/core/src/main/java/org/apache/sling/core/impl/SlingMainServlet.java Mon Jan 14 06:22:35 2008
@@ -24,6 +24,7 @@
 
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.net.SocketException;
 import java.net.URL;
 import java.security.AccessControlException;
 import java.util.ArrayList;
@@ -79,7 +80,7 @@
 
 /**
  * The <code>SlingMainServlet</code> TODO
- *
+ * 
  * @scr.component immediate="true" label="%sling.name"
  *                description="%sling.description"
  * @scr.property name="sling.root" value="/" private="true"
@@ -136,7 +137,7 @@
 
     /** @scr.reference cardinality="0..1" policy="dynamic" */
     private ErrorHandler errorHandler;
-    
+
     private SlingFilterChainHelper requestFilterChain = new SlingFilterChainHelper();
 
     private SlingFilterChainHelper innerFilterChain = new SlingFilterChainHelper();
@@ -150,12 +151,51 @@
     // ---------- Servlet API -------------------------------------------------
 
     public void service(ServletRequest req, ServletResponse res)
-            throws ServletException, IOException {
+            throws ServletException {
 
         if (req instanceof HttpServletRequest
             && res instanceof HttpServletResponse) {
 
-            this.service((HttpServletRequest) req, (HttpServletResponse) res);
+            try {
+                
+                // real request handling for HTTP requests
+                service((HttpServletRequest) req, (HttpServletResponse) res);
+                
+            } catch (IOException ioe) {
+                
+                // unwrap any causes (Jetty wraps SocketException in EofException)
+                Throwable cause = ioe;
+                while (cause.getCause() != null) {
+                    cause = cause.getCause();
+                }
+             
+                if (cause instanceof SocketException) {
+
+                    // if the cause is a SocketException, the client most probably
+                    // aborted the request, we do not fill the log with errors
+                    // in this case
+                    log.debug(
+                        "service: Socketexception (Client abort or network problem",
+                        ioe);
+                    
+                } else {
+                    
+                    // otherwise we want to know why the servlet failed
+                    log.error(
+                        "service: Uncaught IO Problem while handling the request",
+                        ioe);
+                }
+                
+            } catch (Throwable t) {
+                
+                // some failure while handling the request, log the issue
+                // and terminate. We do not call error handling here, because
+                // we assume the real request handling would have done this.
+                // So here we just log
+                
+                log.error("service: Uncaught Problem handling the request", t);
+            }
+
         } else {
             throw new ServletException(
                 "Apache Sling must be run in an HTTP servlet environment.");
@@ -164,65 +204,80 @@
 
     // ---------- Request Handling on behalf of the servlet -------------------
 
-    public void service(HttpServletRequest clientRequest,
-            HttpServletResponse clientResponse) throws ServletException, IOException {
+    public void service(HttpServletRequest servletRequest,
+            HttpServletResponse servletResponse) throws IOException {
 
-        Session session = (Session) clientRequest.getAttribute(SlingHttpContext.SESSION);
-        if (session != null) {
-            RequestData requestData = null;
-            try {
+        // the resource manager factory may be missing
+        if (getResourceResolverFactory() == null) {
+            log.error("service: Cannot handle requests without a ResourceResolverFactory");
+            sendError(HttpServletResponse.SC_NOT_FOUND,
+                "No resource can be found", null, servletRequest,
+                servletResponse);
+            return;
+        }
 
-                // prepare internal request stuff
-                requestData = new RequestData(this, session, clientRequest,
-                    clientResponse);
-                clientRequest = requestData.getSlingRequest();
-                clientResponse = requestData.getSlingResponse();
-
-                Filter[] filters = requestFilterChain.getFilters();
-                if (filters != null) {
-                    FilterChain processor = new RequestSlingFilterChain(this,
-                        filters);
+        Session session = (Session) servletRequest.getAttribute(SlingHttpContext.SESSION);
+        if (session == null) {
+            log.error("service: Cannot handle request: Missing JCR Session");
+            sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+                "Missing JCR Session", null, servletRequest, servletResponse);
+            return;
+        }
 
-                    processor.doFilter(clientRequest, clientResponse);
+        // setting the Sling request and response
+        RequestData requestData = new RequestData(this,
+            getResourceResolverFactory().getResourceResolver(session),
+            servletRequest, servletResponse);
+        SlingHttpServletRequest request = requestData.getSlingRequest();
+        SlingHttpServletResponse response = requestData.getSlingResponse();
 
-                } else {
-                    log.error("service: No Request Handling filters, cannot process request");
-                    clientResponse.sendError(SC_INTERNAL_SERVER_ERROR,
-                        "Cannot process Request");
-                }
+        try {
 
-            } catch (AccessControlException ace) {
+            // initialize the request data - resolve resource and servlet
+            requestData.init();
 
-                // try to request authentication fail, if not possible
-                getSlingAuthenticator().requestAuthentication(clientRequest,
-                    clientResponse);
-
-            } catch (HttpStatusCodeException hsce) {
-                // convert the status code exception to sendError
-                getErrorHandler().handleError(hsce.getStatusCode(),
-                    hsce.getMessage(), clientRequest, clientResponse);
+            Filter[] filters = requestFilterChain.getFilters();
+            if (filters != null) {
+                FilterChain processor = new RequestSlingFilterChain(this,
+                    filters);
+
+                processor.doFilter(request, response);
+
+            } else {
+                log.error("service: No Request Handling filters, cannot process request");
+                response.sendError(SC_INTERNAL_SERVER_ERROR,
+                    "Cannot process Request");
+            }
 
-            } 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);
+        } catch (AccessControlException ace) {
 
-            } finally {
-                if (requestData != null) {
-                    requestData.dispose();
-                }
+            // try to request authentication fail, if not possible
+            getSlingAuthenticator().requestAuthentication(request, response);
 
-                session.logout();
+        } catch (HttpStatusCodeException hsce) {
+            // convert the status code exception to sendError
+            getErrorHandler().handleError(hsce.getStatusCode(),
+                hsce.getMessage(), request, response);
+
+        } 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) {
+                request.setAttribute(ERROR_SERVLET_NAME,
+                    requestData.getActiveServletName());
             }
-        }
 
+            getErrorHandler().handleError(t, request, response);
+
+        } finally {
+            if (requestData != null) {
+                requestData.dispose();
+            }
+
+            session.logout();
+        }
     }
 
     // ---------- Generic Content Request processor ----------------------------
@@ -288,67 +343,39 @@
     }
 
     // ---------- ErrorHandler interface (default implementation) --------------
-    
+
     // reset the response, set the status and write a simple message
     public void handleError(int status, String message,
-            HttpServletRequest request, HttpServletResponse response)
+            SlingHttpServletRequest request, SlingHttpServletResponse response)
             throws IOException {
 
         if (message == null) {
-            message = String.valueOf(status);
+            message = "HTTP ERROR:" + String.valueOf(status);
         } else {
-            message = status + " - " + message;
+            message = "HTTP ERROR:" + status + " - " + message;
         }
-        
-        if (response.isCommitted()) {
-            log.error("handleError: Response already committed; cannot send error "
-                + status + message);
-        } else {
-        
-            // error situation
-            String servletName = (String) request.getAttribute(ERROR_SERVLET_NAME);
-            String requestURI = (String) request.getAttribute(ERROR_REQUEST_URI);
-            if (requestURI == null) {
-                requestURI = request.getRequestURI();
-            }
-
-            // reset anything in the response first
-            response.reset();
-            
-            // set the status, content type and encoding
-            response.setStatus(status);
-            response.setContentType("text/html; charset=UTF-8");
-            
-            PrintWriter pw = response.getWriter();
-            pw.println("<html><head><title>");
-            pw.println(message);
-            pw.println("</title></head><body><h1>");
-            pw.println("HTTP ERROR:" + message);
-            pw.println("</h1><p>");
-            pw.println("RequestURI=" + requestURI);
-            if (servletName != null) {
-                pw.println("</p>Servlet=" + servletName + "<p>");
-            }
-            pw.println("</p><hr /><address>");
-            pw.println(getServerInfo());
-            pw.println("</address></body></html>");
 
-            // commit the response
-            response.flushBuffer();
-
-        }
+        sendError(status, message, null, request, response);
     }
 
     // just rethrow the exception as explained in the class comment
-    public void handleError(Throwable throwable, HttpServletRequest request,
-            HttpServletResponse response) throws IOException {
+    public void handleError(Throwable throwable,
+            SlingHttpServletRequest request, SlingHttpServletResponse response)
+            throws IOException {
+        sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+            throwable.getMessage(), throwable, request, response);
+    }
+
+    private void sendError(int status, String message, Throwable throwable,
+            HttpServletRequest request, HttpServletResponse response)
+            throws IOException {
 
         if (response.isCommitted()) {
             log.error(
-                "handleError: Response already committed; cannot send error",
-                throwable);
+                "handleError: Response already committed; cannot send error "
+                    + status + message, throwable);
         } else {
-        
+
             // error situation
             String servletName = (String) request.getAttribute(ERROR_SERVLET_NAME);
             String requestURI = (String) request.getAttribute(ERROR_REQUEST_URI);
@@ -358,14 +385,14 @@
 
             // reset anything in the response first
             response.reset();
-            
+
             // set the status, content type and encoding
-            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+            response.setStatus(status);
             response.setContentType("text/html; charset=UTF-8");
 
             PrintWriter pw = response.getWriter();
             pw.println("<html><head><title>");
-            pw.println(throwable.getMessage());
+            pw.println(message);
             pw.println("</title></head><body><h1>");
             pw.println(throwable.toString());
             pw.println("</h1><p>");
@@ -373,18 +400,24 @@
             if (servletName != null) {
                 pw.println("</p>Servlet=" + servletName + "<p>");
             }
-            pw.println("</p><pre>");
-            throwable.printStackTrace(pw);
-            pw.println("</pre><hr /><address>");
+            pw.println("</p>");
+
+            if (throwable != null) {
+                pw.println("<pre>");
+                throwable.printStackTrace(pw);
+                pw.println("</pre>");
+            }
+
+            pw.println("<hr /><address>");
             pw.println(getServerInfo());
             pw.println("</address></body></html>");
-            
+
             // commit the response
             response.flushBuffer();
 
         }
     }
-    
+
     // ---------- Internal helper ----------------------------------------------
 
     public String getServerInfo() {

Modified: incubator/sling/whiteboard/fmeschbe/resource/sling/core/src/main/java/org/apache/sling/core/impl/request/RequestData.java
URL: http://svn.apache.org/viewvc/incubator/sling/whiteboard/fmeschbe/resource/sling/core/src/main/java/org/apache/sling/core/impl/request/RequestData.java?rev=611810&r1=611809&r2=611810&view=diff
==============================================================================
--- incubator/sling/whiteboard/fmeschbe/resource/sling/core/src/main/java/org/apache/sling/core/impl/request/RequestData.java (original)
+++ incubator/sling/whiteboard/fmeschbe/resource/sling/core/src/main/java/org/apache/sling/core/impl/request/RequestData.java Mon Jan 14 06:22:35 2008
@@ -125,9 +125,9 @@
      */
     private String activeServletName;
 
-    public RequestData(SlingMainServlet slingMainServlet, Session session,
-            HttpServletRequest request, HttpServletResponse response)
-            throws ServletException, IOException {
+    public RequestData(SlingMainServlet slingMainServlet,
+            ResourceResolver resourceResolver, HttpServletRequest request,
+            HttpServletResponse response) {
 
         this.slingMainServlet = slingMainServlet;
 
@@ -141,22 +141,15 @@
 
         this.requestProgressTracker = new SlingRequestProgressTracker();
 
-        // the resource manager factory may be missing
-        JcrResourceResolverFactory rmf = slingMainServlet.getResourceResolverFactory();
-        if (rmf == null) {
-            log.error("RequestData: Missing JcrResourceResolverFactory");
-            throw new HttpStatusCodeException(HttpServletResponse.SC_NOT_FOUND,
-                "No resource can be found");
-        }
-
-        // officially, getting the manager may fail, but not i this
-        // implementation
-        this.resourceResolver = rmf.getResourceResolver(session);
+        this.resourceResolver = resourceResolver;
+    }
+    
+    public void init() throws ServletException {
 
         // resolve the resource and the request path info, will never be null
-        Resource resource = resourceResolver.resolve(request);
+        Resource resource = resourceResolver.resolve(getServletRequest());
         RequestPathInfo requestPathInfo = new SlingRequestPathInfo(resource,
-            request.getPathInfo());
+            getServletRequest().getPathInfo());
         ContentData contentData = pushContent(resource, requestPathInfo);
 
         // finally resolve the servlet for the resource

Modified: incubator/sling/whiteboard/fmeschbe/resource/sling/core/src/main/java/org/apache/sling/core/servlets/ErrorHandler.java
URL: http://svn.apache.org/viewvc/incubator/sling/whiteboard/fmeschbe/resource/sling/core/src/main/java/org/apache/sling/core/servlets/ErrorHandler.java?rev=611810&r1=611809&r2=611810&view=diff
==============================================================================
--- incubator/sling/whiteboard/fmeschbe/resource/sling/core/src/main/java/org/apache/sling/core/servlets/ErrorHandler.java (original)
+++ incubator/sling/whiteboard/fmeschbe/resource/sling/core/src/main/java/org/apache/sling/core/servlets/ErrorHandler.java Mon Jan 14 06:22:35 2008
@@ -21,9 +21,9 @@
 import java.io.IOException;
 
 import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpServletResponseWrapper;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
 
 /**
  * The <code>ErrorHandler</code> defines the interface of the service used by
@@ -48,8 +48,9 @@
      * @throws IOException May be thrown if an error occurrs sending the
      *             response.
      */
-    void handleError(int status, String message, HttpServletRequest request,
-            HttpServletResponse response) throws IOException;
+    void handleError(int status, String message,
+            SlingHttpServletRequest request, SlingHttpServletResponse response)
+            throws IOException;
 
     /**
      * Called to render a response for an uncaught <code>Throwable</code>.
@@ -66,7 +67,7 @@
      * @throws IOException May be thrown if an error occurrs sending the
      *             response.
      */
-    void handleError(Throwable throwable, HttpServletRequest request,
-            HttpServletResponse response) throws ServletException, IOException;
+    void handleError(Throwable throwable, SlingHttpServletRequest request,
+            SlingHttpServletResponse response) throws IOException;
 
 }