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.HttpHeaders;
30  import org.eclipse.jetty.http.HttpMethods;
31  import org.eclipse.jetty.http.HttpStatus;
32  import org.eclipse.jetty.http.MimeTypes;
33  import org.eclipse.jetty.server.AbstractHttpConnection;
34  import org.eclipse.jetty.server.Request;
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      public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException
55      {
56          AbstractHttpConnection connection = AbstractHttpConnection.getCurrentConnection();
57          connection.getRequest().setHandled(true);
58          String method = request.getMethod();
59          if(!method.equals(HttpMethods.GET) && !method.equals(HttpMethods.POST) && !method.equals(HttpMethods.HEAD))
60              return;
61          response.setContentType(MimeTypes.TEXT_HTML_8859_1);    
62          if (_cacheControl!=null)
63              response.setHeader(HttpHeaders.CACHE_CONTROL, _cacheControl);
64          ByteArrayISO8859Writer writer= new ByteArrayISO8859Writer(4096);
65          handleErrorPage(request, writer, connection.getResponse().getStatus(), connection.getResponse().getReason());
66          writer.flush();
67          response.setContentLength(writer.size());
68          writer.writeTo(response.getOutputStream());
69          writer.destroy();
70      }
71  
72      /* ------------------------------------------------------------ */
73      protected void handleErrorPage(HttpServletRequest request, Writer writer, int code, String message)
74          throws IOException
75      {
76          writeErrorPage(request, writer, code, message, _showStacks);
77      }
78      
79      /* ------------------------------------------------------------ */
80      protected void writeErrorPage(HttpServletRequest request, Writer writer, int code, String message, boolean showStacks)
81          throws IOException
82      {
83          if (message == null)
84              message=HttpStatus.getMessage(code);
85  
86          writer.write("<html>\n<head>\n");
87          writeErrorPageHead(request,writer,code,message);
88          writer.write("</head>\n<body>");
89          writeErrorPageBody(request,writer,code,message,showStacks);
90          writer.write("\n</body>\n</html>\n");
91      }
92  
93      /* ------------------------------------------------------------ */
94      protected void writeErrorPageHead(HttpServletRequest request, Writer writer, int code, String message)
95          throws IOException
96          {
97          writer.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\"/>\n");
98          writer.write("<title>Error ");
99          writer.write(Integer.toString(code));
100 
101         if (_showMessageInTitle)
102         {
103             writer.write(' ');
104             write(writer,message);
105         }
106         writer.write("</title>\n");    
107     }
108 
109     /* ------------------------------------------------------------ */
110     protected void writeErrorPageBody(HttpServletRequest request, Writer writer, int code, String message, boolean showStacks)
111         throws IOException
112     {
113         String uri= request.getRequestURI();
114         
115         writeErrorPageMessage(request,writer,code,message,uri);
116         if (showStacks)
117             writeErrorPageStacks(request,writer);
118         writer.write("<hr /><i><small>Powered by Jetty://</small></i>");
119         for (int i= 0; i < 20; i++)
120             writer.write("<br/>                                                \n");
121     }
122 
123     /* ------------------------------------------------------------ */
124     protected void writeErrorPageMessage(HttpServletRequest request, Writer writer, int code, String message,String uri)
125     throws IOException
126     {
127         writer.write("<h2>HTTP ERROR ");
128         writer.write(Integer.toString(code));
129         writer.write("</h2>\n<p>Problem accessing ");
130         write(writer,uri);
131         writer.write(". Reason:\n<pre>    ");
132         write(writer,message);
133         writer.write("</pre></p>");
134     }
135 
136     /* ------------------------------------------------------------ */
137     protected void writeErrorPageStacks(HttpServletRequest request, Writer writer)
138         throws IOException
139     {
140         Throwable th = (Throwable)request.getAttribute("javax.servlet.error.exception");
141         while(th!=null)
142         {
143             writer.write("<h3>Caused by:</h3><pre>");
144             StringWriter sw = new StringWriter();
145             PrintWriter pw = new PrintWriter(sw);
146             th.printStackTrace(pw);
147             pw.flush();
148             write(writer,sw.getBuffer().toString());
149             writer.write("</pre>\n");
150 
151             th =th.getCause();
152         }
153     }
154         
155 
156     /* ------------------------------------------------------------ */
157     /** Get the cacheControl.
158      * @return the cacheControl header to set on error responses.
159      */
160     public String getCacheControl()
161     {
162         return _cacheControl;
163     }
164 
165     /* ------------------------------------------------------------ */
166     /** Set the cacheControl.
167      * @param cacheControl the cacheControl header to set on error responses.
168      */
169     public void setCacheControl(String cacheControl)
170     {
171         _cacheControl = cacheControl;
172     }
173 
174     /* ------------------------------------------------------------ */
175     /**
176      * @return True if stack traces are shown in the error pages
177      */
178     public boolean isShowStacks()
179     {
180         return _showStacks;
181     }
182 
183     /* ------------------------------------------------------------ */
184     /**
185      * @param showStacks True if stack traces are shown in the error pages
186      */
187     public void setShowStacks(boolean showStacks)
188     {
189         _showStacks = showStacks;
190     }
191     
192     /* ------------------------------------------------------------ */
193     /**
194      * @param showMessageInTitle if true, the error message appears in page title
195      */
196     public void setShowMessageInTitle(boolean showMessageInTitle)
197     {
198         _showMessageInTitle = showMessageInTitle;
199     }
200     
201     
202     /* ------------------------------------------------------------ */
203     public boolean getShowMessageInTitle()
204     {
205         return _showMessageInTitle;
206     }
207 
208     /* ------------------------------------------------------------ */
209     protected void write(Writer writer,String string)
210         throws IOException
211     {
212         if (string==null)
213             return;
214         
215         for (int i=0;i<string.length();i++)
216         {
217             char c=string.charAt(i);
218             
219             switch(c)
220             {
221                 case '&' :
222                     writer.write("&amp;");
223                     break;
224                 case '<' :
225                     writer.write("&lt;");
226                     break;
227                 case '>' :
228                     writer.write("&gt;");
229                     break;
230                     
231                 default:
232                     if (Character.isISOControl(c) && !Character.isWhitespace(c))
233                         writer.write('?');
234                     else 
235                         writer.write(c);
236             }          
237         }
238     }
239 }