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 }