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 Throwable th= (Throwable)request.getAttribute(Dispatcher.ERROR_EXCEPTION);
65
66
67 while (error_page == null && th != null )
68 {
69 pageSource = PageLookupTechnique.THROWABLE;
70
71 Class<?> exClass=th.getClass();
72 error_page= (String)_errorPages.get(exClass.getName());
73
74
75 while (error_page == null)
76 {
77 exClass= exClass.getSuperclass();
78 if (exClass==null)
79 break;
80 error_page= (String)_errorPages.get(exClass.getName());
81 }
82
83 th=(th instanceof ServletException)?((ServletException)th).getRootCause():null;
84 }
85
86 Integer errorStatusCode = null;
87
88 if (error_page == null)
89 {
90 pageSource = PageLookupTechnique.STATUS_CODE;
91
92
93 errorStatusCode = (Integer)request.getAttribute(Dispatcher.ERROR_STATUS_CODE);
94 if (errorStatusCode!=null)
95 {
96 error_page= (String)_errorPages.get(Integer.toString(errorStatusCode));
97
98
99 if ((error_page == null) && (_errorPageList != null))
100 {
101
102 for (int i = 0; i < _errorPageList.size(); i++)
103 {
104 ErrorCodeRange errCode = (ErrorCodeRange) _errorPageList.get(i);
105 if (errCode.isInRange(errorStatusCode))
106 {
107 error_page = errCode.getUri();
108 break;
109 }
110 }
111 }
112 }
113 }
114
115
116 if (error_page == null)
117 {
118 pageSource = PageLookupTechnique.GLOBAL;
119 error_page = _errorPages.get(GLOBAL_ERROR_PAGE);
120 }
121
122 if (LOG.isDebugEnabled())
123 {
124 StringBuilder dbg = new StringBuilder();
125 dbg.append("getErrorPage(");
126 dbg.append(request.getMethod()).append(' ');
127 dbg.append(request.getRequestURI());
128 dbg.append(") => error_page=").append(error_page);
129 switch (pageSource)
130 {
131 case THROWABLE:
132 dbg.append(" (from Throwable ");
133 dbg.append(th.getClass().getName());
134 dbg.append(')');
135 LOG.debug(dbg.toString(),th);
136 break;
137 case STATUS_CODE:
138 dbg.append(" (from status code ");
139 dbg.append(errorStatusCode);
140 dbg.append(')');
141 LOG.debug(dbg.toString());
142 break;
143 case GLOBAL:
144 dbg.append(" (from global default)");
145 LOG.debug(dbg.toString());
146 break;
147 }
148 }
149
150 return error_page;
151 }
152
153
154
155
156
157
158 public Map<String,String> getErrorPages()
159 {
160 return _errorPages;
161 }
162
163
164
165
166
167 public void setErrorPages(Map<String,String> errorPages)
168 {
169 _errorPages.clear();
170 if (errorPages!=null)
171 _errorPages.putAll(errorPages);
172 }
173
174
175
176
177
178
179
180
181 public void addErrorPage(Class<? extends Throwable> exception,String uri)
182 {
183 _errorPages.put(exception.getName(),uri);
184 }
185
186
187
188
189
190
191
192
193 public void addErrorPage(String exceptionClassName,String uri)
194 {
195 _errorPages.put(exceptionClassName,uri);
196 }
197
198
199
200
201
202
203
204
205 public void addErrorPage(int code,String uri)
206 {
207 _errorPages.put(Integer.toString(code),uri);
208 }
209
210
211
212
213
214
215
216
217
218 public void addErrorPage(int from, int to, String uri)
219 {
220 _errorPageList.add(new ErrorCodeRange(from, to, uri));
221 }
222
223
224 @Override
225 protected void doStart() throws Exception
226 {
227 super.doStart();
228 _servletContext=ContextHandler.getCurrentContext();
229 }
230
231
232
233 private class ErrorCodeRange
234 {
235 private int _from;
236 private int _to;
237 private String _uri;
238
239 ErrorCodeRange(int from, int to, String uri)
240 throws IllegalArgumentException
241 {
242 if (from > to)
243 throw new IllegalArgumentException("from>to");
244
245 _from = from;
246 _to = to;
247 _uri = uri;
248 }
249
250 boolean isInRange(int value)
251 {
252 if ((value >= _from) && (value <= _to))
253 {
254 return true;
255 }
256
257 return false;
258 }
259
260 String getUri()
261 {
262 return _uri;
263 }
264
265 @Override
266 public String toString()
267 {
268 return "from: " + _from + ",to: " + _to + ",uri: " + _uri;
269 }
270 }
271 }