Save This Page
Home » apache-tomcat-6.0.26-src » org.apache » catalina » valves » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    * 
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    * 
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   
   18   
   19   package org.apache.catalina.valves;
   20   
   21   
   22   import java.io.IOException;
   23   import java.io.Writer;
   24   
   25   import javax.servlet.ServletException;
   26   import javax.servlet.http.HttpServletResponse;
   27   
   28   import org.apache.catalina.Globals;
   29   import org.apache.catalina.connector.Request;
   30   import org.apache.catalina.connector.Response;
   31   import org.apache.catalina.util.RequestUtil;
   32   import org.apache.catalina.util.ServerInfo;
   33   import org.apache.catalina.util.StringManager;
   34   
   35   /**
   36    * <p>Implementation of a Valve that outputs HTML error pages.</p>
   37    *
   38    * <p>This Valve should be attached at the Host level, although it will work
   39    * if attached to a Context.</p>
   40    *
   41    * <p>HTML code from the Cocoon 2 project.</p>
   42    *
   43    * @author Remy Maucherat
   44    * @author Craig R. McClanahan
   45    * @author <a href="mailto:nicolaken@supereva.it">Nicola Ken Barozzi</a> Aisa
   46    * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
   47    * @author Yoav Shapira
   48    * @version $Revision: 543307 $ $Date: 2007-06-01 01:08:24 +0200 (Fri, 01 Jun 2007) $
   49    */
   50   
   51   public class ErrorReportValve
   52       extends ValveBase {
   53   
   54   
   55       // ----------------------------------------------------- Instance Variables
   56   
   57   
   58       /**
   59        * The descriptive information related to this implementation.
   60        */
   61       private static final String info =
   62           "org.apache.catalina.valves.ErrorReportValve/1.0";
   63   
   64   
   65       /**
   66        * The StringManager for this package.
   67        */
   68       protected static StringManager sm =
   69           StringManager.getManager(Constants.Package);
   70   
   71   
   72       // ------------------------------------------------------------- Properties
   73   
   74   
   75       /**
   76        * Return descriptive information about this Valve implementation.
   77        */
   78       public String getInfo() {
   79   
   80           return (info);
   81   
   82       }
   83   
   84   
   85       // --------------------------------------------------------- Public Methods
   86   
   87   
   88       /**
   89        * Invoke the next Valve in the sequence. When the invoke returns, check
   90        * the response state, and output an error report is necessary.
   91        *
   92        * @param request The servlet request to be processed
   93        * @param response The servlet response to be created
   94        *
   95        * @exception IOException if an input/output error occurs
   96        * @exception ServletException if a servlet error occurs
   97        */
   98       public void invoke(Request request, Response response)
   99           throws IOException, ServletException {
  100   
  101           // Perform the request
  102           getNext().invoke(request, response);
  103   
  104           Throwable throwable =
  105               (Throwable) request.getAttribute(Globals.EXCEPTION_ATTR);
  106   
  107           if (response.isCommitted()) {
  108               return;
  109           }
  110   
  111           if (throwable != null) {
  112   
  113               // The response is an error
  114               response.setError();
  115   
  116               // Reset the response (if possible)
  117               try {
  118                   response.reset();
  119               } catch (IllegalStateException e) {
  120                   ;
  121               }
  122   
  123               response.sendError
  124                   (HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
  125   
  126           }
  127   
  128           response.setSuspended(false);
  129   
  130           try {
  131               report(request, response, throwable);
  132           } catch (Throwable tt) {
  133               ;
  134           }
  135   
  136       }
  137   
  138   
  139       // ------------------------------------------------------ Protected Methods
  140   
  141   
  142       /**
  143        * Prints out an error report.
  144        *
  145        * @param request The request being processed
  146        * @param response The response being generated
  147        * @param throwable The exception that occurred (which possibly wraps
  148        *  a root cause exception
  149        */
  150       protected void report(Request request, Response response,
  151                             Throwable throwable) {
  152   
  153           // Do nothing on non-HTTP responses
  154           int statusCode = response.getStatus();
  155   
  156           // Do nothing on a 1xx, 2xx and 3xx status
  157           // Do nothing if anything has been written already
  158           if ((statusCode < 400) || (response.getContentCount() > 0))
  159               return;
  160   
  161           String message = RequestUtil.filter(response.getMessage());
  162           if (message == null)
  163               message = "";
  164   
  165           // Do nothing if there is no report for the specified status code
  166           String report = null;
  167           try {
  168               report = sm.getString("http." + statusCode, message);
  169           } catch (Throwable t) {
  170               ;
  171           }
  172           if (report == null)
  173               return;
  174   
  175           StringBuffer sb = new StringBuffer();
  176   
  177           sb.append("<html><head><title>");
  178           sb.append(ServerInfo.getServerInfo()).append(" - ");
  179           sb.append(sm.getString("errorReportValve.errorReport"));
  180           sb.append("</title>");
  181           sb.append("<style><!--");
  182           sb.append(org.apache.catalina.util.TomcatCSS.TOMCAT_CSS);
  183           sb.append("--></style> ");
  184           sb.append("</head><body>");
  185           sb.append("<h1>");
  186           sb.append(sm.getString("errorReportValve.statusHeader",
  187                                  "" + statusCode, message)).append("</h1>");
  188           sb.append("<HR size=\"1\" noshade=\"noshade\">");
  189           sb.append("<p><b>type</b> ");
  190           if (throwable != null) {
  191               sb.append(sm.getString("errorReportValve.exceptionReport"));
  192           } else {
  193               sb.append(sm.getString("errorReportValve.statusReport"));
  194           }
  195           sb.append("</p>");
  196           sb.append("<p><b>");
  197           sb.append(sm.getString("errorReportValve.message"));
  198           sb.append("</b> <u>");
  199           sb.append(message).append("</u></p>");
  200           sb.append("<p><b>");
  201           sb.append(sm.getString("errorReportValve.description"));
  202           sb.append("</b> <u>");
  203           sb.append(report);
  204           sb.append("</u></p>");
  205   
  206           if (throwable != null) {
  207   
  208               String stackTrace = getPartialServletStackTrace(throwable);
  209               sb.append("<p><b>");
  210               sb.append(sm.getString("errorReportValve.exception"));
  211               sb.append("</b> <pre>");
  212               sb.append(RequestUtil.filter(stackTrace));
  213               sb.append("</pre></p>");
  214   
  215               int loops = 0;
  216               Throwable rootCause = throwable.getCause();
  217               while (rootCause != null && (loops < 10)) {
  218                   stackTrace = getPartialServletStackTrace(rootCause);
  219                   sb.append("<p><b>");
  220                   sb.append(sm.getString("errorReportValve.rootCause"));
  221                   sb.append("</b> <pre>");
  222                   sb.append(RequestUtil.filter(stackTrace));
  223                   sb.append("</pre></p>");
  224                   // In case root cause is somehow heavily nested
  225                   rootCause = rootCause.getCause();
  226                   loops++;
  227               }
  228   
  229               sb.append("<p><b>");
  230               sb.append(sm.getString("errorReportValve.note"));
  231               sb.append("</b> <u>");
  232               sb.append(sm.getString("errorReportValve.rootCauseInLogs",
  233                                      ServerInfo.getServerInfo()));
  234               sb.append("</u></p>");
  235   
  236           }
  237   
  238           sb.append("<HR size=\"1\" noshade=\"noshade\">");
  239           sb.append("<h3>").append(ServerInfo.getServerInfo()).append("</h3>");
  240           sb.append("</body></html>");
  241   
  242           try {
  243               try {
  244                   response.setContentType("text/html");
  245                   response.setCharacterEncoding("utf-8");
  246               } catch (Throwable t) {
  247                   if (container.getLogger().isDebugEnabled())
  248                       container.getLogger().debug("status.setContentType", t);
  249               }
  250               Writer writer = response.getReporter();
  251               if (writer != null) {
  252                   // If writer is null, it's an indication that the response has
  253                   // been hard committed already, which should never happen
  254                   writer.write(sb.toString());
  255               }
  256           } catch (IOException e) {
  257               ;
  258           } catch (IllegalStateException e) {
  259               ;
  260           }
  261           
  262       }
  263   
  264   
  265       /**
  266        * Print out a partial servlet stack trace (truncating at the last 
  267        * occurrence of javax.servlet.).
  268        */
  269       protected String getPartialServletStackTrace(Throwable t) {
  270           StringBuffer trace = new StringBuffer();
  271           trace.append(t.toString()).append('\n');
  272           StackTraceElement[] elements = t.getStackTrace();
  273           int pos = elements.length;
  274           for (int i = 0; i < elements.length; i++) {
  275               if ((elements[i].getClassName().startsWith
  276                    ("org.apache.catalina.core.ApplicationFilterChain"))
  277                   && (elements[i].getMethodName().equals("internalDoFilter"))) {
  278                   pos = i;
  279               }
  280           }
  281           for (int i = 0; i < pos; i++) {
  282               if (!(elements[i].getClassName().startsWith
  283                     ("org.apache.catalina.core."))) {
  284                   trace.append('\t').append(elements[i].toString()).append('\n');
  285               }
  286           }
  287           return trace.toString();
  288       }
  289   
  290   }

Save This Page
Home » apache-tomcat-6.0.26-src » org.apache » catalina » valves » [javadoc | source]