View Javadoc

    1   // ========================================================================
    2   // Copyright 1999-2005 Mort Bay Consulting Pty. Ltd.
    3   // ------------------------------------------------------------------------
    4   // Licensed under the Apache License, Version 2.0 (the "License");
    5   // you may not use this file except in compliance with the License.
    6   // You may obtain a copy of the License at
    7   // http://www.apache.org/licenses/LICENSE-2.0
    8   // Unless required by applicable law or agreed to in writing, software
    9   // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  // ========================================================================
    14  package org.mortbay.jetty.handler;
    15  import java.io.IOException;
    16  import java.io.PrintWriter;
    17  import java.io.StringWriter;
    18  import java.io.Writer;
    19
    20  import javax.servlet.http.HttpServletRequest;
    21  import javax.servlet.http.HttpServletResponse;
    22
    23  import org.mortbay.jetty.HttpConnection;
    24  import org.mortbay.jetty.HttpGenerator;
    25  import org.mortbay.jetty.HttpHeaders;
    26  import org.mortbay.jetty.HttpMethods;
    27  import org.mortbay.jetty.MimeTypes;
    28  import org.mortbay.util.ByteArrayISO8859Writer;
    29  import org.mortbay.util.StringUtil;
    30
    31
    32  /* ------------------------------------------------------------ */
    33  /** Handler for Error pages
    34   * A handler that is registered at the org.mortbay.http.ErrorHandler
    35   * context attributed and called by the HttpResponse.sendError method to write a
    36   * error page.
    37   *
    38   * @author Greg Wilkins (gregw)
    39   */
    40  public class ErrorHandler extends AbstractHandler
    41  {
    42      boolean _showStacks=true;
    43      String _cacheControl="must-revalidate,no-cache,no-store";
    44
    45      /* ------------------------------------------------------------ */
    46      /*
    47       * @see org.mortbay.jetty.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int)
    48       */
    49      public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) throws IOException
    50      {
    51          HttpConnection connection = HttpConnection.getCurrentConnection();
    52          connection.getRequest().setHandled(true);
    53          String method = request.getMethod();
    54          if(!method.equals(HttpMethods.GET) && !method.equals(HttpMethods.POST) && !method.equals(HttpMethods.HEAD))
    55              return;
    56          response.setContentType(MimeTypes.TEXT_HTML_8859_1);
    57          if (_cacheControl!=null)
    58              response.setHeader(HttpHeaders.CACHE_CONTROL, _cacheControl);
    59          ByteArrayISO8859Writer writer= new ByteArrayISO8859Writer(4096);
    60          handleErrorPage(request, writer, connection.getResponse().getStatus(), connection.getResponse().getReason());
    61          writer.flush();
    62          response.setContentLength(writer.size());
    63          writer.writeTo(response.getOutputStream());
    64          writer.destroy();
    65      }
    66
    67      /* ------------------------------------------------------------ */
    68      protected void handleErrorPage(HttpServletRequest request, Writer writer, int code, String message)
    69          throws IOException
    70      {
    71          writeErrorPage(request, writer, code, message, _showStacks);
    72      }
    73
    74      /* ------------------------------------------------------------ */
    75      protected void writeErrorPage(HttpServletRequest request, Writer writer, int code, String message, boolean showStacks)
    76          throws IOException
    77      {
    78          if (message == null)
    79              message=HttpGenerator.getReason(code);
    80
    81          writer.write("<html>\n<head>\n");
    82          writeErrorPageHead(request,writer,code,message);
    83          writer.write("</head>\n<body>");
    84          writeErrorPageBody(request,writer,code,message,showStacks);
    85          writer.write("\n</body>\n</html>\n");
    86      }
    87
    88      /* ------------------------------------------------------------ */
    89      protected void writeErrorPageHead(HttpServletRequest request, Writer writer, int code, String message)
    90          throws IOException
    91      {
    92          writer.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\"/>\n");
    93          writer.write("<title>Error ");
    94          writer.write(Integer.toString(code));
    95          writer.write(' ');
    96          write(writer,message);
    97          writer.write("</title>\n");
    98      }
    99
    100     /* ------------------------------------------------------------ */
    101     protected void writeErrorPageBody(HttpServletRequest request, Writer writer, int code, String message, boolean showStacks)
    102         throws IOException
    103     {
    104         String uri= request.getRequestURI();
    105
    106         writeErrorPageMessage(request,writer,code,message,uri);
    107         if (showStacks)
    108             writeErrorPageStacks(request,writer);
    109         writer.write("<hr /><i><small>Powered by Jetty://</small></i>");
    110         for (int i= 0; i < 20; i++)
    111             writer.write("<br/>                                                \n");
    112     }
    113
    114     /* ------------------------------------------------------------ */
    115     protected void writeErrorPageMessage(HttpServletRequest request, Writer writer, int code, String message,String uri)
    116     throws IOException
    117     {
    118         writer.write("<h2>HTTP ERROR ");
    119         writer.write(Integer.toString(code));
    120         writer.write("</h2>\n<p>Problem accessing ");
    121         write(writer,uri);
    122         writer.write(". Reason:\n<pre>    ");
    123         write(writer,message);
    124         writer.write("</pre></p>");
    125     }
    126
    127     /* ------------------------------------------------------------ */
    128     protected void writeErrorPageStacks(HttpServletRequest request, Writer writer)
    129         throws IOException
    130     {
    131         Throwable th = (Throwable)request.getAttribute("javax.servlet.error.exception");
    132         while(th!=null)
    133         {
    134             writer.write("<h3>Caused by:</h3><pre>");
    135             StringWriter sw = new StringWriter();
    136             PrintWriter pw = new PrintWriter(sw);
    137             th.printStackTrace(pw);
    138             pw.flush();
    139             write(writer,sw.getBuffer().toString());
    140             writer.write("</pre>\n");
    141
    142             th =th.getCause();
    143         }
    144     }
    145
    146
    147
    148     /* ------------------------------------------------------------ */
    149     /** Get the cacheControl.
    150      * @return the cacheControl header to set on error responses.
    151      */
    152     public String getCacheControl()
    153     {
    154         return _cacheControl;
    155     }
    156
    157     /* ------------------------------------------------------------ */
    158     /** Set the cacheControl.
    159      * @param cacheControl the cacheControl header to set on error responses.
    160      */
    161     public void setCacheControl(String cacheControl)
    162     {
    163         _cacheControl = cacheControl;
    164     }
    165
    166     /* ------------------------------------------------------------ */
    167     /**
    168      * @return True if stack traces are shown in the error pages
    169      */
    170     public boolean isShowStacks()
    171     {
    172         return _showStacks;
    173     }
    174
    175     /* ------------------------------------------------------------ */
    176     /**
    177      * @param showStacks True if stack traces are shown in the error pages
    178      */
    179     public void setShowStacks(boolean showStacks)
    180     {
    181         _showStacks = showStacks;
    182     }
    183
    184     /* ------------------------------------------------------------ */
    185     protected void write(Writer writer,String string)
    186         throws IOException
    187     {
    188         if (string==null)
    189             return;
    190
    191         for (int i=0;i<string.length();i++)
    192         {
    193             char c=string.charAt(i);
    194
    195             switch(c)
    196             {
    197                 case '&' :
    198                     writer.write("&amp;");
    199                     break;
    200                 case '<' :
    201                     writer.write("&lt;");
    202                     break;
    203                 case '>' :
    204                     writer.write("&gt;");
    205                     break;
    206
    207                 default:
    208                     if (Character.isISOControl(c) && !Character.isWhitespace(c))
    209                         writer.write('?');
    210                     else
    211                         writer.write(c);
    212             }
    213         }
    214     }
    215 }