1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 import java.nio.ByteBuffer;
26
27 import javax.servlet.ServletException;
28 import javax.servlet.http.HttpServletRequest;
29 import javax.servlet.http.HttpServletResponse;
30
31 import org.eclipse.jetty.http.HttpFields;
32 import org.eclipse.jetty.http.HttpHeader;
33 import org.eclipse.jetty.http.HttpMethod;
34 import org.eclipse.jetty.http.HttpStatus;
35 import org.eclipse.jetty.http.MimeTypes;
36 import org.eclipse.jetty.server.Dispatcher;
37 import org.eclipse.jetty.server.Request;
38 import org.eclipse.jetty.server.Response;
39 import org.eclipse.jetty.server.Server;
40 import org.eclipse.jetty.util.BufferUtil;
41 import org.eclipse.jetty.util.ByteArrayISO8859Writer;
42 import org.eclipse.jetty.util.log.Log;
43 import org.eclipse.jetty.util.log.Logger;
44
45
46
47
48
49
50
51
52
53 public class ErrorHandler extends AbstractHandler
54 {
55 private static final Logger LOG = Log.getLogger(ErrorHandler.class);
56 public final static String ERROR_PAGE="org.eclipse.jetty.server.error_page";
57
58 boolean _showStacks=true;
59 boolean _showMessageInTitle=true;
60 String _cacheControl="must-revalidate,no-cache,no-store";
61
62
63
64
65
66 @Override
67 public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException
68 {
69 String method = request.getMethod();
70 if (!HttpMethod.GET.is(method) && !HttpMethod.POST.is(method) && !HttpMethod.HEAD.is(method))
71 {
72 baseRequest.setHandled(true);
73 return;
74 }
75
76 if (this instanceof ErrorPageMapper)
77 {
78 String error_page=((ErrorPageMapper)this).getErrorPage(request);
79 if (error_page!=null && request.getServletContext()!=null)
80 {
81 String old_error_page=(String)request.getAttribute(ERROR_PAGE);
82 if (old_error_page==null || !old_error_page.equals(error_page))
83 {
84 request.setAttribute(ERROR_PAGE, error_page);
85
86 Dispatcher dispatcher = (Dispatcher) request.getServletContext().getRequestDispatcher(error_page);
87 try
88 {
89 if(dispatcher!=null)
90 {
91 dispatcher.error(request, response);
92 return;
93 }
94 LOG.warn("No error page "+error_page);
95 }
96 catch (ServletException e)
97 {
98 LOG.warn(Log.EXCEPTION, e);
99 return;
100 }
101 }
102 }
103 }
104
105 baseRequest.setHandled(true);
106 response.setContentType(MimeTypes.Type.TEXT_HTML_8859_1.asString());
107 if (_cacheControl!=null)
108 response.setHeader(HttpHeader.CACHE_CONTROL.asString(), _cacheControl);
109 ByteArrayISO8859Writer writer= new ByteArrayISO8859Writer(4096);
110 String reason=(response instanceof Response)?((Response)response).getReason():null;
111 handleErrorPage(request, writer, response.getStatus(), reason);
112 writer.flush();
113 response.setContentLength(writer.size());
114 writer.writeTo(response.getOutputStream());
115 writer.destroy();
116 }
117
118
119 protected void handleErrorPage(HttpServletRequest request, Writer writer, int code, String message)
120 throws IOException
121 {
122 writeErrorPage(request, writer, code, message, _showStacks);
123 }
124
125
126 protected void writeErrorPage(HttpServletRequest request, Writer writer, int code, String message, boolean showStacks)
127 throws IOException
128 {
129 if (message == null)
130 message=HttpStatus.getMessage(code);
131
132 writer.write("<html>\n<head>\n");
133 writeErrorPageHead(request,writer,code,message);
134 writer.write("</head>\n<body>");
135 writeErrorPageBody(request,writer,code,message,showStacks);
136 writer.write("\n</body>\n</html>\n");
137 }
138
139
140 protected void writeErrorPageHead(HttpServletRequest request, Writer writer, int code, String message)
141 throws IOException
142 {
143 writer.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/>\n");
144 writer.write("<title>Error ");
145 writer.write(Integer.toString(code));
146
147 if (_showMessageInTitle)
148 {
149 writer.write(' ');
150 write(writer,message);
151 }
152 writer.write("</title>\n");
153 }
154
155
156 protected void writeErrorPageBody(HttpServletRequest request, Writer writer, int code, String message, boolean showStacks)
157 throws IOException
158 {
159 String uri= request.getRequestURI();
160
161 writeErrorPageMessage(request,writer,code,message,uri);
162 if (showStacks)
163 writeErrorPageStacks(request,writer);
164 writer.write("<hr><i><small>Powered by Jetty://</small></i><hr/>\n");
165 }
166
167
168 protected void writeErrorPageMessage(HttpServletRequest request, Writer writer, int code, String message,String uri)
169 throws IOException
170 {
171 writer.write("<h2>HTTP ERROR ");
172 writer.write(Integer.toString(code));
173 writer.write("</h2>\n<p>Problem accessing ");
174 write(writer,uri);
175 writer.write(". Reason:\n<pre> ");
176 write(writer,message);
177 writer.write("</pre></p>");
178 }
179
180
181 protected void writeErrorPageStacks(HttpServletRequest request, Writer writer)
182 throws IOException
183 {
184 Throwable th = (Throwable)request.getAttribute("javax.servlet.error.exception");
185 while(th!=null)
186 {
187 writer.write("<h3>Caused by:</h3><pre>");
188 StringWriter sw = new StringWriter();
189 PrintWriter pw = new PrintWriter(sw);
190 th.printStackTrace(pw);
191 pw.flush();
192 write(writer,sw.getBuffer().toString());
193 writer.write("</pre>\n");
194
195 th =th.getCause();
196 }
197 }
198
199
200
201
202
203
204
205
206
207
208
209
210
211 public ByteBuffer badMessageError(int status, String reason, HttpFields fields)
212 {
213 if (reason==null)
214 reason=HttpStatus.getMessage(status);
215 fields.put(HttpHeader.CONTENT_TYPE,MimeTypes.Type.TEXT_HTML_8859_1.asString());
216 return BufferUtil.toBuffer("<h1>Bad Message " + status + "</h1><pre>reason: " + reason + "</pre>");
217 }
218
219
220
221
222
223 public String getCacheControl()
224 {
225 return _cacheControl;
226 }
227
228
229
230
231
232 public void setCacheControl(String cacheControl)
233 {
234 _cacheControl = cacheControl;
235 }
236
237
238
239
240
241 public boolean isShowStacks()
242 {
243 return _showStacks;
244 }
245
246
247
248
249
250 public void setShowStacks(boolean showStacks)
251 {
252 _showStacks = showStacks;
253 }
254
255
256
257
258
259 public void setShowMessageInTitle(boolean showMessageInTitle)
260 {
261 _showMessageInTitle = showMessageInTitle;
262 }
263
264
265
266 public boolean getShowMessageInTitle()
267 {
268 return _showMessageInTitle;
269 }
270
271
272 protected void write(Writer writer,String string)
273 throws IOException
274 {
275 if (string==null)
276 return;
277
278 for (int i=0;i<string.length();i++)
279 {
280 char c=string.charAt(i);
281
282 switch(c)
283 {
284 case '&' :
285 writer.write("&");
286 break;
287 case '<' :
288 writer.write("<");
289 break;
290 case '>' :
291 writer.write(">");
292 break;
293
294 default:
295 if (Character.isISOControl(c) && !Character.isWhitespace(c))
296 writer.write('?');
297 else
298 writer.write(c);
299 }
300 }
301 }
302
303
304 public interface ErrorPageMapper
305 {
306 String getErrorPage(HttpServletRequest request);
307 }
308
309
310 public static ErrorHandler getErrorHandler(Server server, ContextHandler context)
311 {
312 ErrorHandler error_handler=null;
313 if (context!=null)
314 error_handler=context.getErrorHandler();
315 if (error_handler==null && server!=null)
316 error_handler = server.getBean(ErrorHandler.class);
317 return error_handler;
318 }
319 }