1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.servlet;
20
21 import java.util.ArrayList;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25
26 import javax.servlet.ServletContext;
27 import javax.servlet.ServletException;
28 import javax.servlet.http.HttpServletRequest;
29
30 import org.eclipse.jetty.server.Dispatcher;
31 import org.eclipse.jetty.server.handler.ContextHandler;
32 import org.eclipse.jetty.server.handler.ErrorHandler;
33 import org.eclipse.jetty.util.log.Log;
34 import org.eclipse.jetty.util.log.Logger;
35
36
37
38
39
40
41
42 public class ErrorPageErrorHandler extends ErrorHandler implements ErrorHandler.ErrorPageMapper
43 {
44 public final static String GLOBAL_ERROR_PAGE = "org.eclipse.jetty.server.error_page.global";
45 private static final Logger LOG = Log.getLogger(ErrorPageErrorHandler.class);
46 enum PageLookupTechnique{ THROWABLE, STATUS_CODE, GLOBAL }
47
48 protected ServletContext _servletContext;
49 private final Map<String,String> _errorPages= new HashMap<String,String>();
50 private final List<ErrorCodeRange> _errorPageList=new ArrayList<ErrorCodeRange>();
51
52
53 public ErrorPageErrorHandler()
54 {}
55
56
57 @Override
58 public String getErrorPage(HttpServletRequest request)
59 {
60 String error_page= null;
61
62 PageLookupTechnique pageSource = null;
63
64 Class<?> matchedThrowable = null;
65 Throwable th= (Throwable)request.getAttribute(Dispatcher.ERROR_EXCEPTION);
66
67
68 while (error_page == null && th != null )
69 {
70 pageSource = PageLookupTechnique.THROWABLE;
71
72 Class<?> exClass=th.getClass();
73 error_page= _errorPages.get(exClass.getName());
74
75
76 while (error_page == null)
77 {
78 exClass= exClass.getSuperclass();
79 if (exClass==null)
80 break;
81 error_page = _errorPages.get(exClass.getName());
82 }
83
84 if(error_page != null)
85 matchedThrowable = exClass;
86
87 th=(th instanceof ServletException)?((ServletException)th).getRootCause():null;
88 }
89
90 Integer errorStatusCode = null;
91
92 if (error_page == null)
93 {
94 pageSource = PageLookupTechnique.STATUS_CODE;
95
96
97 errorStatusCode = (Integer)request.getAttribute(Dispatcher.ERROR_STATUS_CODE);
98 if (errorStatusCode!=null)
99 {
100 error_page= (String)_errorPages.get(Integer.toString(errorStatusCode));
101
102
103 if ((error_page == null) && (_errorPageList != null))
104 {
105
106 for (int i = 0; i < _errorPageList.size(); i++)
107 {
108 ErrorCodeRange errCode = (ErrorCodeRange) _errorPageList.get(i);
109 if (errCode.isInRange(errorStatusCode))
110 {
111 error_page = errCode.getUri();
112 break;
113 }
114 }
115 }
116 }
117 }
118
119
120 if (error_page == null)
121 {
122 pageSource = PageLookupTechnique.GLOBAL;
123 error_page = _errorPages.get(GLOBAL_ERROR_PAGE);
124 }
125
126 if (LOG.isDebugEnabled())
127 {
128 StringBuilder dbg = new StringBuilder();
129 dbg.append("getErrorPage(");
130 dbg.append(request.getMethod()).append(' ');
131 dbg.append(request.getRequestURI());
132 dbg.append(") => error_page=").append(error_page);
133 switch (pageSource)
134 {
135 case THROWABLE:
136 dbg.append(" (using matched Throwable ");
137 dbg.append(matchedThrowable.getName());
138 dbg.append(" / actually thrown as ");
139 Throwable originalThrowable = (Throwable)request.getAttribute(Dispatcher.ERROR_EXCEPTION);
140 dbg.append(originalThrowable.getClass().getName());
141 dbg.append(')');
142 LOG.debug(dbg.toString(),th);
143 break;
144 case STATUS_CODE:
145 dbg.append(" (from status code ");
146 dbg.append(errorStatusCode);
147 dbg.append(')');
148 LOG.debug(dbg.toString());
149 break;
150 case GLOBAL:
151 dbg.append(" (from global default)");
152 LOG.debug(dbg.toString());
153 break;
154 }
155 }
156
157 return error_page;
158 }
159
160
161
162
163
164
165 public Map<String,String> getErrorPages()
166 {
167 return _errorPages;
168 }
169
170
171
172
173
174 public void setErrorPages(Map<String,String> errorPages)
175 {
176 _errorPages.clear();
177 if (errorPages!=null)
178 _errorPages.putAll(errorPages);
179 }
180
181
182
183
184
185
186
187
188 public void addErrorPage(Class<? extends Throwable> exception,String uri)
189 {
190 _errorPages.put(exception.getName(),uri);
191 }
192
193
194
195
196
197
198
199
200 public void addErrorPage(String exceptionClassName,String uri)
201 {
202 _errorPages.put(exceptionClassName,uri);
203 }
204
205
206
207
208
209
210
211
212 public void addErrorPage(int code,String uri)
213 {
214 _errorPages.put(Integer.toString(code),uri);
215 }
216
217
218
219
220
221
222
223
224
225 public void addErrorPage(int from, int to, String uri)
226 {
227 _errorPageList.add(new ErrorCodeRange(from, to, uri));
228 }
229
230
231 @Override
232 protected void doStart() throws Exception
233 {
234 super.doStart();
235 _servletContext=ContextHandler.getCurrentContext();
236 }
237
238
239
240 private class ErrorCodeRange
241 {
242 private int _from;
243 private int _to;
244 private String _uri;
245
246 ErrorCodeRange(int from, int to, String uri)
247 throws IllegalArgumentException
248 {
249 if (from > to)
250 throw new IllegalArgumentException("from>to");
251
252 _from = from;
253 _to = to;
254 _uri = uri;
255 }
256
257 boolean isInRange(int value)
258 {
259 if ((value >= _from) && (value <= _to))
260 {
261 return true;
262 }
263
264 return false;
265 }
266
267 String getUri()
268 {
269 return _uri;
270 }
271
272 @Override
273 public String toString()
274 {
275 return "from: " + _from + ",to: " + _to + ",uri: " + _uri;
276 }
277 }
278 }