View Javadoc

1   /*
2    * $Id: ErrorServlet.java 269 2005-08-10 17:49:22Z josem $
3    *
4    * Tarsis
5    * Copyright (C) 2002 Talika Open Source Group
6    *
7    * This program is free software; you can redistribute it and/or modify
8    * it under the terms of the GNU General Public License as published by
9    * the Free Software Foundation; either version 2 of the License, or
10   * (at your option) any later version.
11   *
12   * This program is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Public License for more details.
16   *
17   * You should have received a copy of the GNU General Public License
18   * along with this program; if not, write to the Free Software
19   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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      // Constants
56      /**
57       * Default error page param name.
58       */
59      public static final String DEFAULT_ERROR_PAGE_PARAM = "default";
60  
61      // Fields
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      // Methods
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             // Log Error
171             logError(t);
172 
173             // Get Error Page
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         // Find t instance type
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 }