View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.server.handler;
20  
21  import java.io.IOException;
22  import java.io.PrintWriter;
23  import java.io.StringWriter;
24  import java.io.Writer;
25  
26  import javax.servlet.http.HttpServletRequest;
27  import javax.servlet.http.HttpServletResponse;
28  
29  import org.eclipse.jetty.http.HttpHeader;
30  import org.eclipse.jetty.http.HttpMethod;
31  import org.eclipse.jetty.http.HttpStatus;
32  import org.eclipse.jetty.http.MimeTypes;
33  import org.eclipse.jetty.server.Request;
34  import org.eclipse.jetty.server.Response;
35  import org.eclipse.jetty.util.ByteArrayISO8859Writer;
36  
37  /* ------------------------------------------------------------ */
38  /** Handler for Error pages
39   * An ErrorHandler is registered with {@link ContextHandler#setErrorHandler(ErrorHandler)} or
40   * {@link org.eclipse.jetty.server.Server#addBean(Object)}.
41   * It is called by the HttpResponse.sendError method to write a error page.
42   *
43   */
44  public class ErrorHandler extends AbstractHandler
45  {
46      boolean _showStacks=true;
47      boolean _showMessageInTitle=true;
48      String _cacheControl="must-revalidate,no-cache,no-store";
49  
50      /* ------------------------------------------------------------ */
51      /*
52       * @see org.eclipse.jetty.server.server.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int)
53       */
54      @Override
55      public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException
56      {
57          baseRequest.setHandled(true);
58          String method = request.getMethod();
59          if(!HttpMethod.GET.is(method) && !HttpMethod.POST.is(method) && !HttpMethod.HEAD.is(method))
60              return;
61          response.setContentType(MimeTypes.Type.TEXT_HTML_8859_1.asString());
62          if (_cacheControl!=null)
63              response.setHeader(HttpHeader.CACHE_CONTROL.asString(), _cacheControl);
64          ByteArrayISO8859Writer writer= new ByteArrayISO8859Writer(4096);
65          String reason=(response instanceof Response)?((Response)response).getReason():null;
66          handleErrorPage(request, writer, response.getStatus(), reason);
67          writer.flush();
68          response.setContentLength(writer.size());
69          writer.writeTo(response.getOutputStream());
70          writer.destroy();
71      }
72  
73      /* ------------------------------------------------------------ */
74      protected void handleErrorPage(HttpServletRequest request, Writer writer, int code, String message)
75          throws IOException
76      {
77          writeErrorPage(request, writer, code, message, _showStacks);
78      }
79  
80      /* ------------------------------------------------------------ */
81      protected void writeErrorPage(HttpServletRequest request, Writer writer, int code, String message, boolean showStacks)
82          throws IOException
83      {
84          if (message == null)
85              message=HttpStatus.getMessage(code);
86  
87          writer.write("<html>\n<head>\n");
88          writeErrorPageHead(request,writer,code,message);
89          writer.write("</head>\n<body>");
90          writeErrorPageBody(request,writer,code,message,showStacks);
91          writer.write("\n</body>\n</html>\n");
92      }
93  
94      /* ------------------------------------------------------------ */
95      protected void writeErrorPageHead(HttpServletRequest request, Writer writer, int code, String message)
96          throws IOException
97          {
98          writer.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\"/>\n");
99          writer.write("<title>Error ");
100         writer.write(Integer.toString(code));
101 
102         if (_showMessageInTitle)
103         {
104             writer.write(' ');
105             write(writer,message);
106         }
107         writer.write("</title>\n");
108     }
109 
110     /* ------------------------------------------------------------ */
111     protected void writeErrorPageBody(HttpServletRequest request, Writer writer, int code, String message, boolean showStacks)
112         throws IOException
113     {
114         String uri= request.getRequestURI();
115 
116         writeErrorPageMessage(request,writer,code,message,uri);
117         if (showStacks)
118             writeErrorPageStacks(request,writer);
119         writer.write("<hr><i><small>Powered by Jetty://</small></i><hr/>\n");
120     }
121 
122     /* ------------------------------------------------------------ */
123     protected void writeErrorPageMessage(HttpServletRequest request, Writer writer, int code, String message,String uri)
124     throws IOException
125     {
126         writer.write("<h2>HTTP ERROR ");
127         writer.write(Integer.toString(code));
128         writer.write("</h2>\n<p>Problem accessing ");
129         write(writer,uri);
130         writer.write(". Reason:\n<pre>    ");
131         write(writer,message);
132         writer.write("</pre></p>");
133     }
134 
135     /* ------------------------------------------------------------ */
136     protected void writeErrorPageStacks(HttpServletRequest request, Writer writer)
137         throws IOException
138     {
139         Throwable th = (Throwable)request.getAttribute("javax.servlet.error.exception");
140         while(th!=null)
141         {
142             writer.write("<h3>Caused by:</h3><pre>");
143             StringWriter sw = new StringWriter();
144             PrintWriter pw = new PrintWriter(sw);
145             th.printStackTrace(pw);
146             pw.flush();
147             write(writer,sw.getBuffer().toString());
148             writer.write("</pre>\n");
149 
150             th =th.getCause();
151         }
152     }
153 
154 
155     /* ------------------------------------------------------------ */
156     /** Get the cacheControl.
157      * @return the cacheControl header to set on error responses.
158      */
159     public String getCacheControl()
160     {
161         return _cacheControl;
162     }
163 
164     /* ------------------------------------------------------------ */
165     /** Set the cacheControl.
166      * @param cacheControl the cacheControl header to set on error responses.
167      */
168     public void setCacheControl(String cacheControl)
169     {
170         _cacheControl = cacheControl;
171     }
172 
173     /* ------------------------------------------------------------ */
174     /**
175      * @return True if stack traces are shown in the error pages
176      */
177     public boolean isShowStacks()
178     {
179         return _showStacks;
180     }
181 
182     /* ------------------------------------------------------------ */
183     /**
184      * @param showStacks True if stack traces are shown in the error pages
185      */
186     public void setShowStacks(boolean showStacks)
187     {
188         _showStacks = showStacks;
189     }
190 
191     /* ------------------------------------------------------------ */
192     /**
193      * @param showMessageInTitle if true, the error message appears in page title
194      */
195     public void setShowMessageInTitle(boolean showMessageInTitle)
196     {
197         _showMessageInTitle = showMessageInTitle;
198     }
199 
200 
201     /* ------------------------------------------------------------ */
202     public boolean getShowMessageInTitle()
203     {
204         return _showMessageInTitle;
205     }
206 
207     /* ------------------------------------------------------------ */
208     protected void write(Writer writer,String string)
209         throws IOException
210     {
211         if (string==null)
212             return;
213 
214         for (int i=0;i<string.length();i++)
215         {
216             char c=string.charAt(i);
217 
218             switch(c)
219             {
220                 case '&' :
221                     writer.write("&amp;");
222                     break;
223                 case '<' :
224                     writer.write("&lt;");
225                     break;
226                 case '>' :
227                     writer.write("&gt;");
228                     break;
229 
230                 default:
231                     if (Character.isISOControl(c) && !Character.isWhitespace(c))
232                         writer.write('?');
233                     else
234                         writer.write(c);
235             }
236         }
237     }
238 }