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.MimeTypes;
26  import org.mortbay.util.ByteArrayISO8859Writer;
27  import org.mortbay.util.StringUtil;
28  
29  
30  /* ------------------------------------------------------------ */
31  /** Handler for Error pages
32   * A handler that is registered at the org.mortbay.http.ErrorHandler
33   * context attributed and called by the HttpResponse.sendError method to write a
34   * error page.
35   * 
36   * @author Greg Wilkins (gregw)
37   */
38  public class ErrorHandler extends AbstractHandler
39  {
40      boolean _showStacks=true;
41      
42      /* ------------------------------------------------------------ */
43      /* 
44       * @see org.mortbay.jetty.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int)
45       */
46      public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) throws IOException
47      {
48          HttpConnection.getCurrentConnection().getRequest().setHandled(true);
49          response.setContentType(MimeTypes.TEXT_HTML_8859_1);
50          ByteArrayISO8859Writer writer= new ByteArrayISO8859Writer(4096);
51          HttpConnection connection = HttpConnection.getCurrentConnection();
52          handleErrorPage(request, writer, connection.getResponse().getStatus(), connection.getResponse().getReason());
53          writer.flush();
54          response.setContentLength(writer.size());
55          writer.writeTo(response.getOutputStream());
56          writer.destroy();
57      }
58  
59      /* ------------------------------------------------------------ */
60      protected void handleErrorPage(HttpServletRequest request, Writer writer, int code, String message)
61          throws IOException
62      {
63          writeErrorPage(request, writer, code, message, _showStacks);
64      }
65      
66      /* ------------------------------------------------------------ */
67      protected void writeErrorPage(HttpServletRequest request, Writer writer, int code, String message, boolean showStacks)
68          throws IOException
69      {
70          if (message == null)
71              message=HttpGenerator.getReason(code);
72          else
73          {
74              message= StringUtil.replace(message, "&", "&");
75              message= StringUtil.replace(message, "<", "&lt;");
76              message= StringUtil.replace(message, ">", "&gt;");
77          }
78  
79          writer.write("<html>\n<head>\n");
80          writeErrorPageHead(request,writer,code,message);
81          writer.write("</head>\n<body>");
82          writeErrorPageBody(request,writer,code,message,showStacks);
83          writer.write("\n</body>\n</html>\n");
84      }
85  
86      /* ------------------------------------------------------------ */
87      protected void writeErrorPageHead(HttpServletRequest request, Writer writer, int code, String message)
88          throws IOException
89      {
90          writer.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\"/>\n");
91          writer.write("<title>Error ");
92          writer.write(Integer.toString(code));
93          writer.write(' ');
94          if (message!=null)
95              writer.write(message);
96          writer.write("</title>\n");    
97      }
98  
99      /* ------------------------------------------------------------ */
100     protected void writeErrorPageBody(HttpServletRequest request, Writer writer, int code, String message, boolean showStacks)
101         throws IOException
102     {
103         String uri= request.getRequestURI();
104         if (uri!=null)
105         {
106             uri= StringUtil.replace(uri, "&", "&amp;");
107             uri= StringUtil.replace(uri, "<", "&lt;");
108             uri= StringUtil.replace(uri, ">", "&gt;");
109         }
110         
111         writeErrorPageMessage(request,writer,code,message,uri);
112         if (showStacks)
113             writeErrorPageStacks(request,writer);
114         writer.write("<p><i><small><a href=\"http://jetty.mortbay.org/\">Powered by Jetty://</a></small></i></p>");
115         for (int i= 0; i < 20; i++)
116             writer.write("<br/>                                                \n");
117     }
118 
119     /* ------------------------------------------------------------ */
120     protected void writeErrorPageMessage(HttpServletRequest request, Writer writer, int code, String message,String uri)
121     throws IOException
122     {
123         writer.write("<h2>HTTP ERROR: ");
124         writer.write(Integer.toString(code));
125         writer.write("</h2><pre>");
126         writer.write(message);
127         writer.write("</pre>\n<p>RequestURI=");
128         writer.write(uri);
129         writer.write("</p>");
130     }
131 
132     /* ------------------------------------------------------------ */
133     protected void writeErrorPageStacks(HttpServletRequest request, Writer writer)
134         throws IOException
135     {
136         Throwable th = (Throwable)request.getAttribute("javax.servlet.error.exception");
137         while(th!=null)
138         {
139             writer.write("<h3>Caused by:</h3><pre>");
140             StringWriter sw = new StringWriter();
141             PrintWriter pw = new PrintWriter(sw);
142             th.printStackTrace(pw);
143             pw.flush();
144             writer.write(sw.getBuffer().toString());
145             writer.write("</pre>\n");
146 
147             th =th.getCause();
148         }
149     }
150         
151 
152     /* ------------------------------------------------------------ */
153     /**
154      * @return True if stack traces are shown in the error pages
155      */
156     public boolean isShowStacks()
157     {
158         return _showStacks;
159     }
160 
161     /* ------------------------------------------------------------ */
162     /**
163      * @param showStacks True if stack traces are shown in the error pages
164      */
165     public void setShowStacks(boolean showStacks)
166     {
167         _showStacks = showStacks;
168     }
169 
170 }