1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.talika.tarsis.servlets;
24
25 import java.io.IOException;
26 import java.io.PrintWriter;
27 import java.util.Enumeration;
28 import java.util.HashMap;
29 import java.util.Iterator;
30 import java.util.LinkedList;
31 import java.util.List;
32 import java.util.Map;
33
34 import javax.servlet.ServletConfig;
35 import javax.servlet.ServletException;
36 import javax.servlet.http.HttpServletRequest;
37 import javax.servlet.http.HttpServletResponse;
38
39 import org.talika.tarsis.Globals;
40 import org.talika.tarsis.command.action.UnrecoverableException;
41 import org.talika.tarsis.error.SystemException;
42 import org.talika.tarsis.error.UserException;
43 import org.talika.tarsis.filters.validator.InvalidParametersException;
44 import org.talika.tarsis.security.SecurityException;
45
46 /**
47 * Error servlet of Tarsis MVC Framework.<br>
48 * <br>
49 *
50 * @author Jose M. Palomar
51 * @version $Revision: 269 $
52 */
53 public final class ErrorServlet extends AbstractServlet {
54
55
56 /**
57 * Default error page param name.
58 */
59 public static final String DEFAULT_ERROR_PAGE_PARAM = "default";
60
61
62 /**
63 * Default error page.
64 */
65 private String defaultErrorPage;
66
67 /**
68 * Error pages map.
69 */
70 private Map errorPages;
71
72 /**
73 * Exception types list.
74 */
75 private List exceptionTypes;
76
77
78 /**
79 * Called by the servlet container to indicate to a servlet that the servlet is
80 * being placed into service.<br>
81 * <br>
82 *
83 * @param config ServletConfig the <code>ServletConfig</code> object that contains
84 * configutation information for this servlet.
85 * @throws ServletException if an exception occurs that interrupts the servlet's
86 * normal operation.
87 * @see javax.servlet.Servlet#init(ServletConfig)
88 */
89 public void init(ServletConfig config) throws ServletException {
90 super.init(config);
91
92 this.defaultErrorPage = config.getInitParameter(DEFAULT_ERROR_PAGE_PARAM);
93
94 this.errorPages = new HashMap();
95 this.exceptionTypes = new LinkedList();
96
97 Enumeration paramsEnumeration = config.getInitParameterNames();
98 while (paramsEnumeration.hasMoreElements()) {
99 String exceptionName = (String) paramsEnumeration.nextElement();
100 String errorPage = config.getInitParameter(exceptionName);
101
102 if (!exceptionName.equals(DEFAULT_ERROR_PAGE_PARAM)) {
103
104 try {
105
106 Class exceptionClass = Class.forName(exceptionName);
107
108 if (Throwable.class.isAssignableFrom(exceptionClass)) {
109
110 exceptionTypes.add(exceptionClass);
111 errorPages.put(exceptionClass, errorPage);
112
113 }
114 else {
115 if (getLogger().isWarningEnabled()) {
116 getLogger().logWarning(exceptionName + " not extends java.lang.Throwable");
117 }
118 }
119
120 }
121 catch (ClassNotFoundException cnfe) {
122 if (getLogger().isWarningEnabled()) {
123 getLogger().logWarning(exceptionName + " class not found");
124 }
125 }
126
127 }
128
129 }
130
131 }
132
133 /**
134 * Called by the servlet container to indicate to a servlet that the servlet is
135 * being taken out of service.
136 *
137 * @see javax.servlet.Servlet#destroy()
138 */
139 public void destroy() {
140 super.destroy();
141 }
142
143 /**
144 * Processes requests for both HTTP GET and POST methods.<br>
145 * <br>
146 *
147 * @param request servlet object that contains the request the client has made of
148 * the servlet.
149 * @param response servlet object that contains the response the servlet sends to
150 * the client.
151 * @throws ServletException if the request could not be handled.
152 * @throws IOException if an input or output error is detected when the servlet
153 * handles request.
154 */
155 protected void process(HttpServletRequest request, HttpServletResponse response)
156 throws ServletException, java.io.IOException {
157
158 try {
159
160 Throwable t = (Throwable) request.getAttribute("javax.servlet.error.exception");
161
162 if (t instanceof ServletException && ((ServletException) t).getRootCause() != null) {
163 t = ((ServletException) t).getRootCause();
164 }
165
166 if (request.getAttribute("javax.servlet.jsp.jspException") == null) {
167 request.setAttribute("javax.servlet.jsp.jspException", t);
168 }
169
170
171 logError(t);
172
173
174 String errorPage = getErrorPage(t);
175 if (errorPage == null) {
176 printErrorPage(response, t);
177 }
178 else {
179 request.getRequestDispatcher(errorPage).forward(request, response);
180 }
181
182 }
183 catch (Throwable t) {
184 if (getLogger().isPanicEnabled()) {
185 getLogger().logPanic("ErrorServlet: panic", t);
186 }
187 }
188
189 }
190
191 /**
192 * Returns error page for given <code>Throwable</code> object.
193 *
194 * @param t Throwable a <code>Throwable</code> object.
195 * @return String error page for given <code>Throwable</code> object.
196 */
197 private String getErrorPage(Throwable t) {
198
199
200 Class exceptionTypeFound = null;
201 Iterator exceptionTypesIterator = this.exceptionTypes.iterator();
202 while (exceptionTypesIterator.hasNext() && (exceptionTypeFound == null)) {
203 Class exceptionType = (Class) exceptionTypesIterator.next();
204 if (exceptionType.isInstance(t)) {
205 exceptionTypeFound = exceptionType;
206 }
207 }
208
209 String errorPage = null;
210 if (exceptionTypeFound != null) {
211 errorPage = (String) this.errorPages.get(exceptionTypeFound);
212 }
213
214 if (errorPage == null) {
215 errorPage = this.defaultErrorPage;
216 }
217
218 return errorPage;
219
220 }
221
222 /**
223 * Logs given <code>Throwable</code> object.
224 *
225 * @param t Throwable a <code>Throwable</code> object.
226 */
227 private void logError(Throwable t) {
228
229 if (t instanceof InvalidParametersException) {
230 if (getLogger().isDebugEnabled()) {
231 getLogger().logDebug("InvalidParametersException: " + t.getMessage());
232 }
233 }
234 else if (t instanceof UnrecoverableException) {
235 if (getLogger().isErrorEnabled()) {
236 getLogger().logError("UnrecoverableException", t);
237 }
238 }
239 else if (t instanceof UserException) {
240 if (getLogger().isWarningEnabled()) {
241 getLogger().logWarning("UserException: " + t.getMessage());
242 }
243 }
244 else if (t instanceof SystemException) {
245 if (getLogger().isErrorEnabled()) {
246 getLogger().logError("SystemException", t);
247 }
248 }
249 else if (t instanceof SecurityException) {
250 if (getLogger().isWarningEnabled()) {
251 getLogger().logWarning("SecurityException: " + t.getMessage());
252 }
253 }
254 else {
255 if (getLogger().isErrorEnabled()) {
256 getLogger().logError("Exception", t);
257 }
258 }
259
260 }
261
262 /**
263 * Prints error page.
264 *
265 * @param response HttpServletResponse client's response.
266 * @param t Throwable a <code>Throwable</code> object.
267 * @throws IOException if an input or output error is detected when the servlet
268 * handles request.
269 */
270 private void printErrorPage(HttpServletResponse response, Throwable t)
271 throws IOException {
272
273 response.setContentType("text/html");
274
275 PrintWriter out = response.getWriter();
276
277 out.write("\r\n");
278 out.write("<html>\r\n");
279 out.write("<head><title>" + Globals.PROJECT_INFO + " Error Report</title></head>\r\n");
280 out.write("<body>\r\n");
281 out.write("<h1>" + Globals.PROJECT_INFO + " Error Report</h1>\r\n");
282 out.write("\r\n");
283 out.write("<pre>\r\n");
284 t.printStackTrace(out);
285 out.write("</pre>\r\n");
286 out.write("</body>\r\n");
287 out.write("</html>\r\n");
288
289 }
290
291 }