View Javadoc

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