KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jahia > bin > JahiaErrorDisplay


1 // $Id: JahiaErrorDisplay.java 16367 2007-02-07 15:52:22Z bpapez $
2
//
3
// ____.
4
// __/\ ______| |__/\. _______
5
// __ .____| | \ | +----+ \
6
// _______| /--| | | - \ _ | : - \_________
7
// \\______: :---| : : | : | \________>
8
// |__\---\_____________:______: :____|____:_____\
9
// /_____|
10
//
11
// . . . i n j a h i a w e t r u s t . . .
12
//
13
//
14

15 package org.jahia.bin;
16
17 /**
18  * Title: Jahia
19  * desc: Portal & Publishing server project by Jahia
20  * Copyright: Copyright (c) 2002
21  * Company: Jahia Ltd
22  * @author Serge Huber
23  * @version 1.0
24  */

25
26 import java.io.File JavaDoc;
27 import java.io.IOException JavaDoc;
28 import java.io.PrintWriter JavaDoc;
29 import java.io.StringWriter JavaDoc;
30 import java.lang.reflect.InvocationTargetException JavaDoc;
31 import java.util.Date JavaDoc;
32 import java.util.Enumeration JavaDoc;
33 import java.util.Properties JavaDoc;
34 import java.util.regex.Matcher JavaDoc;
35 import java.util.regex.Pattern JavaDoc;
36
37 import javax.mail.Message JavaDoc;
38 import javax.mail.Session JavaDoc;
39 import javax.mail.Transport JavaDoc;
40 import javax.mail.internet.InternetAddress JavaDoc;
41 import javax.mail.internet.MimeMessage JavaDoc;
42 import javax.servlet.RequestDispatcher JavaDoc;
43 import javax.servlet.ServletContext JavaDoc;
44 import javax.servlet.ServletException JavaDoc;
45 import javax.servlet.http.HttpServletRequest JavaDoc;
46 import javax.servlet.http.HttpServletResponse JavaDoc;
47
48 import org.jahia.exceptions.JahiaException;
49 import org.jahia.settings.SettingsBean;
50
51 /**
52  * This class is in charge of generating output to the client of error messages.
53  * It is kept simple because it's aim is to be quite solid, and this is easier to
54  * achieve by keeping it minimal. It includes a hardcoded HTML display method in
55  * the case where a dispatching ressource is not available (such as an error in
56  * the configuration of Jahia).
57  *
58  * When throwing a JahiaException, if its "userErrorMsg" message starts with an integer,
59  * ie. "404 Page not found" then this class forwards the error to the "404.jsp" page
60  * if found in the errors directory. For details about those error codes,
61  * see <a HREF="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10">RFC 2616</a>
62  */

63
64 public class JahiaErrorDisplay {
65
66     private static org.apache.log4j.Logger logger =
67             org.apache.log4j.Logger.getLogger(JahiaErrorDisplay.class);
68
69     private static final String JavaDoc DISPATCH_DESTINATION = "/jsp/jahia/errors/error.jsp";
70     private static final String JavaDoc DISPATCH_DIRECTORY = "/jsp/jahia/errors/";
71     private static final String JavaDoc DISPATCH_PREFIX="error_";
72     private static final boolean IS_STACK_INCLUDED = true;
73
74     public static final String JavaDoc DISPLAY_JAHIA_ERROR = "displayJahiaError";
75
76     static {
77         logger.debug("Initialized with destination = [" +
78                      DISPATCH_DESTINATION + "]");
79     }
80
81     public JahiaErrorDisplay() {
82     }
83
84     /**
85      * This is a fallback method that is called in the case where the dispatching
86      * to a ressource is not possible. It is hardcoded in order to be as failproof
87      * as possible.
88      */

89     public static boolean HTMLFallBackDisplay(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response, Throwable JavaDoc t) {
90         PrintWriter JavaDoc out = null;
91         try {
92             out = response.getWriter();
93         } catch (Throwable JavaDoc newt) {
94             return false;
95         }
96         if (out != null) {
97             /** @todo : fixme : this is not update to date with the lastest
98              * chaining stuff
99              */

100             out.println("<html>");
101             out.println(" <head>");
102             out.println(" <title>Jahia Error</title>");
103             out.println(" </head>");
104             out.println(" <body>");
105             out.println(" <table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">");
106             out.println(" <tr>");
107             out.println(" <td colspan=\"2\"><h1>Jahia Error</h1></td>");
108             out.println(" </tr>");
109             out.println(" <tr>");
110             out.println(" <td colspan=\"2\">An error has occured while Jahia was processing data. Consult the info below for more precise information</td>");
111             out.println(" </tr>");
112             out.println(" <tr>");
113             out.println(" <td>Exception :</td>");
114             out.println(" <td>" + t.getMessage() + "</td>");
115             out.println(" </tr>");
116             if (IS_STACK_INCLUDED) {
117                 out.println(" <tr>");
118                 out.println(" <td>Stack trace : </td>");
119                 out.println(" <td><pre>");
120                 String JavaDoc stackTraceStr = stackTraceToString(t);
121                 out.println(stackTraceStr);
122                 out.println(" </pre></td>");
123                 out.println(" </tr>");
124             }
125             out.println(" </table>");
126             out.println(" </body>");
127             out.println("</html>");
128         } else {
129             ;
130         }
131         return false;
132     }
133
134     public static boolean DisplayException(HttpServletRequest JavaDoc request,
135                                            HttpServletResponse JavaDoc response,
136                                            ServletContext JavaDoc context,
137                                            Throwable JavaDoc t) {
138         return DisplayException(request, response, context, null, t);
139     }
140
141     public static boolean DisplayException(HttpServletRequest JavaDoc request,
142                                            HttpServletResponse JavaDoc response,
143                                            ServletContext JavaDoc context,
144                                            SettingsBean jSettings,
145                                            Throwable JavaDoc t) {
146         return DisplayException(request, response, context, jSettings, true, true, t);
147     }
148
149     /**
150      * Displays an exception on a HTML browser using either JSP pages or
151      * static hardcoded HTML output. Also sends out an email to the administrator
152      * is this feature was activated.
153      *
154      */

155     public static boolean DisplayException(HttpServletRequest JavaDoc request,
156                                            HttpServletResponse JavaDoc response,
157                                            ServletContext JavaDoc context,
158                                            SettingsBean jSettings,
159                                            boolean sendEmail,
160                                            boolean displayInConsole,
161                                            Throwable JavaDoc t) {
162         try {
163
164             Boolean JavaDoc displayJahiaError = (Boolean JavaDoc)request.getAttribute(DISPLAY_JAHIA_ERROR);
165             if ( displayJahiaError != null && !displayJahiaError.booleanValue() ){
166                 return false;
167             }
168
169             if ((request == null) ||
170                 (response == null) ||
171                 (context == null) ||
172                 (t == null)) {
173                 logger.debug("Can't display exception, not enough information available...");
174                 return false;
175             }
176             // let's log the exception in Tomcat's log system.
177
context.log(throwableToString(t, request, response));
178
179             if (response.isCommitted()) {
180                 logger.debug("Response already committed, aborting client display, exception has been logged...");
181                 return false;
182             }
183
184             if (displayInConsole) {
185                 // let's log the exception in Tomcat's log system.
186
context.log(throwableToString(t, request, response));
187                 if (t instanceof JahiaException) {
188                     JahiaException je = (JahiaException) t;
189                     logger.error("ERROR : " + je.getUserErrorMsg() +
190                             ", " + je.getJahiaErrorMsg(), getNestedException(t));
191                 } else if (t != null) {
192                     logger.error("ERROR : " + t.getMessage(), getNestedException(t));
193                 }
194             }
195
196             // By default, uses the standard error message
197
String JavaDoc fullPathToDestination = context.getRealPath(DISPATCH_DESTINATION);
198             String JavaDoc contextPathToDestination = DISPATCH_DESTINATION;
199
200             File JavaDoc jspFile = new File JavaDoc(fullPathToDestination);
201             File JavaDoc jspFileErrorCode = null;
202
203             // check if error contains a standard HTTP/1.1 error code, if so, tries to forward to
204
// the corresponding JSP
205
String JavaDoc errorstring = "";
206             try {
207                 errorstring = t.getMessage().trim();
208             } catch (Throwable JavaDoc tho) {}
209
210             int errorint = 0;
211             
212             // 2005/05/20 :: uses regexp to extract html error code.
213
Pattern JavaDoc p = Pattern.compile("\\d\\d\\d");
214             Matcher JavaDoc m = p.matcher(errorstring);
215             if (m.find())
216                 errorstring = m.group();
217             
218             try {
219                 errorint = Integer.parseInt(errorstring);
220             } catch (NumberFormatException JavaDoc nfe) {}
221               catch (Throwable JavaDoc th) {}
222
223             // yes the error string contains an error code! let's specify the special jsp!
224
if (errorint!=0)
225             {
226                 response.setStatus(errorint); // sets response status
227
fullPathToDestination = context.getRealPath (DISPATCH_DIRECTORY + DISPATCH_PREFIX + errorint + ".jsp");
228                 jspFileErrorCode = new File JavaDoc(fullPathToDestination);
229                 if (jspFileErrorCode.exists())
230                     { jspFile = jspFileErrorCode;
231                         contextPathToDestination = DISPATCH_DIRECTORY + DISPATCH_PREFIX + errorint + ".jsp";
232                         logger.debug("Forwarding error to "+fullPathToDestination);
233                     } else {
234                         logger.debug("Dispatcher not found at "+fullPathToDestination+ " - using standard error");
235                     }
236             }
237
238             if (jSettings != null) {
239                 if (sendEmail) {
240                     logger.debug("Jahia Settings available, mailing...");
241                     MailException(t, request, response, jSettings, errorint);
242                 }
243             } else {
244                 logger.debug("No Jahia Settings, can't mail...");
245             }
246
247             logger.debug("context is : "+contextPathToDestination);
248             // forwards to the jsp
249
if (jspFile.exists()) {
250                 RequestDispatcher JavaDoc dispatcher = context.getRequestDispatcher( contextPathToDestination );
251                 if (dispatcher != null) {
252                     request.setAttribute("org.jahia.exception.Message", t.getMessage());
253                     if (IS_STACK_INCLUDED) {
254                         String JavaDoc stackTraceStr = stackTraceToString(t);
255                         request.setAttribute("org.jahia.exception.StackTrace", stackTraceStr);
256                     }
257                     dispatcher.forward(request, response);
258                     return true;
259                 } else {
260                     return HTMLFallBackDisplay(request, response, t);
261                 }
262             } else {
263                 logger.debug("JSP file " + fullPathToDestination + " not found, defaulting to built-in message generator");
264                 return HTMLFallBackDisplay(request, response, t);
265             }
266
267
268         } catch (ServletException JavaDoc se) {
269             logger.debug("JSP caused a Servlet Exception : ", se);
270             logger.debug("Root exception : ", se.getRootCause());
271
272         } catch (IOException JavaDoc ioe) {
273             logger.debug("Dispatching caused an IOException", ioe);
274
275         } catch (java.lang.IllegalStateException JavaDoc ise) {
276             logger.debug("Cannot forward because response was already committed !", ise);
277
278         } catch (Throwable JavaDoc newt) {
279             logger.debug("Unknown exception during DisplayException : " + t.getMessage(), newt);
280         }
281         return false;
282     }
283
284     /**
285      * Mails an exception to the administrator according to the settings in
286      * the Jahia installation.
287      */

288     public static boolean MailException(Throwable JavaDoc t,
289                                         HttpServletRequest JavaDoc request,
290                                         HttpServletResponse JavaDoc response,
291                                         SettingsBean jSettings,
292                                         int errorInt) {
293         try {
294             String JavaDoc to = null, subject = null, from = null,
295                 cc = null, bcc = null, url = null;
296             String JavaDoc mailhost = null;
297             String JavaDoc mailer = "Jahia Server 1.0";
298             String JavaDoc protocol = null, host = null, user = null, password = null;
299             String JavaDoc record = null; // name of folder in which to record mail
300

301             to = jSettings.mail_administrator;
302             from = jSettings.mail_from;
303             mailhost = jSettings.mail_server;
304
305             if ((mailhost.equals("")) || (to.equals("")) || (from.equals(""))) {
306                 logger.debug("Mail settings not valid, ignoring...");
307                 return false;
308             }
309
310             if ((mailhost == null) || (to == null) || (from == null)) {
311                 logger.debug("Mail settings not valid, ignoring...");
312                 return false;
313             }
314
315             logger.debug("Using settings mailhost=[" + mailhost +
316                          "] to=[" + to + "] from=[" + from +
317                          "] paranoia=" +
318                          Integer.toString(jSettings.mail_paranoia));
319
320             if (t instanceof JahiaException) {
321                 JahiaException je = (JahiaException) t;
322                 if (je.getSeverity() < jSettings.mail_paranoia) {
323                     return true;
324                 }
325             }
326
327             boolean debug = false;
328
329             Properties JavaDoc props = System.getProperties();
330             if (mailhost != null)
331                 props.put("mail.smtp.host", mailhost);
332
333             // Get a Session object
334
Session JavaDoc session = Session.getDefaultInstance(props, null);
335             if (debug)
336                 session.setDebug(true);
337
338             // construct the message
339
Message JavaDoc msg = new MimeMessage JavaDoc(session);
340             if (from != null)
341                 msg.setFrom(new InternetAddress JavaDoc(from));
342             else
343                 msg.setFrom();
344
345             msg.setRecipients(Message.RecipientType.TO,
346                         InternetAddress.parse(to, false));
347             if (cc != null)
348             msg.setRecipients(Message.RecipientType.CC,
349                         InternetAddress.parse(cc, false));
350             if (bcc != null)
351             msg.setRecipients(Message.RecipientType.BCC,
352                         InternetAddress.parse(bcc, false));
353
354             subject = "[JAHIA] Jahia Error : " + t.getMessage();
355
356             msg.setSubject(subject);
357
358             StringWriter JavaDoc msgBodyWriter = new StringWriter JavaDoc();
359             PrintWriter JavaDoc strOut = new PrintWriter JavaDoc(msgBodyWriter);
360             strOut.println("");
361             strOut.println("Your Jahia Server has generated an error. Please review the details below for additional information: ");
362             strOut.println("");
363             if (t instanceof JahiaException) {
364                 JahiaException nje = (JahiaException) t;
365                 String JavaDoc severityMsg = "Undefined";
366                 switch (nje.getSeverity()) {
367                     case JahiaException.WARNING_SEVERITY : severityMsg = "WARNING"; break;
368                     case JahiaException.ERROR_SEVERITY : severityMsg = "ERROR"; break;
369                     case JahiaException.CRITICAL_SEVERITY : severityMsg = "CRITICAL"; break;
370                     case JahiaException.KISSYOURASSGOODBYE_SEVERITY : severityMsg = "FATAL"; break;
371                 }
372                 strOut.println("Severity : " + severityMsg);
373             }
374             strOut.println("");
375             strOut.println("Error : " + t.getMessage());
376             strOut.println("");
377             strOut.println("URL : " + request.getRequestURL());
378             if (request.getQueryString() != null) {
379                 strOut.println("?" + request.getQueryString());
380             }
381             strOut.println(" Method : " + request.getMethod());
382             strOut.println("");
383             strOut.println("Remote host : " + request.getRemoteHost() + " Remote Address : " + request.getRemoteAddr());
384             strOut.println("");
385             strOut.println("Request headers : ");
386             Enumeration JavaDoc headerNames = request.getHeaderNames();
387             while (headerNames.hasMoreElements()) {
388                 String JavaDoc headerName = (String JavaDoc) headerNames.nextElement();
389                 String JavaDoc headerValue = request.getHeader(headerName);
390                 strOut.println(" " + headerName + ":" + headerValue);
391             }
392             if (errorInt == 0) {
393                 strOut.println("");
394                 strOut.println("Stack trace : ");
395                 String JavaDoc stackTraceStr = stackTraceToString(t);
396                 strOut.println(stackTraceStr);
397             }
398             strOut.println("");
399             strOut.println("Depending on the severity of this error, Jahia may still be operational or not. Please check your");
400             strOut.println("installation as soon as possible.");
401             strOut.println("");
402             strOut.println("Yours Faithfully, ");
403             strOut.println(" Jahia Server");
404
405             msg.setText(msgBodyWriter.toString());
406
407             msg.setHeader("X-Mailer", mailer);
408             msg.setSentDate(new Date JavaDoc());
409
410             logger.debug("Mailing to " + to + " via " + mailhost + "...");
411
412             // send the thing off
413
Transport.send(msg);
414
415             logger.debug("Mail was sent successfully.");
416
417         } catch (Throwable JavaDoc th) {
418             logger.debug("Error while sending mail : " + th.getMessage(), th);
419             return false;
420         }
421
422         return true;
423     }
424
425     /**
426      * Converts an exception to a string, dump everything in a simple manner,
427      * using typecasting if it is a JahiaException or a ServletException that
428      * can contain other exception.
429      * Warning : the result String contains return chars.
430      *
431      * @param t the exception to be converted to a String
432      * @param request the http request object
433      * @param response the http response object
434      *
435      * @returns A string containing the full dump with stack trace of the
436      * exception. Return chars are inserted to make it more readable...
437      */

438     private static String JavaDoc throwableToString(Throwable JavaDoc t,
439                                             HttpServletRequest JavaDoc request,
440                                             HttpServletResponse JavaDoc response) {
441         StringWriter JavaDoc msgBodyWriter = new StringWriter JavaDoc();
442         PrintWriter JavaDoc strOut = new PrintWriter JavaDoc(msgBodyWriter);
443         strOut.println("Your Jahia Server has generated an error. Please review the details below for additional information: ");
444         if (t instanceof JahiaException) {
445             JahiaException nje = (JahiaException) t;
446             String JavaDoc severityMsg = "Undefined";
447             switch (nje.getSeverity()) {
448                 case JahiaException.WARNING_SEVERITY : severityMsg = "WARNING"; break;
449                 case JahiaException.ERROR_SEVERITY : severityMsg = "ERROR"; break;
450                 case JahiaException.CRITICAL_SEVERITY : severityMsg = "CRITICAL"; break;
451                 case JahiaException.KISSYOURASSGOODBYE_SEVERITY : severityMsg = "FATAL"; break;
452             }
453             strOut.println("Severity : " + severityMsg);
454         }
455         strOut.println("Error : " + t.getMessage());
456
457         if ((request != null) && (response != null)) {
458             strOut.println("URL : " + request.getRequestURL() + " Method : " + request.getMethod());
459             strOut.println("Remote host : " + request.getRemoteHost() + " Remote Address : " + request.getRemoteAddr());
460             strOut.println("Request headers : ");
461             Enumeration JavaDoc headerNames = request.getHeaderNames();
462             while (headerNames.hasMoreElements()) {
463                 String JavaDoc headerName = (String JavaDoc) headerNames.nextElement();
464                 String JavaDoc headerValue = request.getHeader(headerName);
465                 strOut.println(" " + headerName + ":" + headerValue);
466             }
467         }
468         strOut.println("Stack trace : ");
469         String JavaDoc stackTraceStr = stackTraceToString(t);
470         strOut.println(stackTraceStr);
471         strOut.println("");
472         return msgBodyWriter.toString();
473     }
474
475     /**
476      * Converts an exception stack trace to a string, going doing into all
477      * the embedded exceptions too to detail as much as possible the real
478      * causes of the error.
479      *
480      * @param t the exception (eventually that contains other exceptions) for
481      * which we want to convert the stack trace into a string.
482      *
483      * @return a string containing all the stack traces of all the exceptions
484      * contained inside this exception, or an empty string if passed an
485      * empty string.
486      */

487     public static String JavaDoc stackTraceToString(Throwable JavaDoc t) {
488         int nestingDepth = getNestedExceptionDepth(t, 0);
489         return recursiveStackTraceToString(t, nestingDepth);
490     }
491
492     private static String JavaDoc recursiveStackTraceToString(Throwable JavaDoc t, int curDepth) {
493         if (t == null) {
494             return "";
495         }
496         StringWriter JavaDoc msgBodyWriter = new StringWriter JavaDoc();
497         PrintWriter JavaDoc strOut = new PrintWriter JavaDoc(msgBodyWriter);
498         Throwable JavaDoc innerThrowable = null;
499         if (t instanceof ServletException JavaDoc) {
500             ServletException JavaDoc se = (ServletException JavaDoc) t;
501             innerThrowable = se.getRootCause();
502         } else if (t instanceof JahiaException) {
503             JahiaException je = (JahiaException) t;
504             innerThrowable = je.getRootCause();
505         } else if (t instanceof InvocationTargetException JavaDoc) {
506             InvocationTargetException JavaDoc ite = (InvocationTargetException JavaDoc) t;
507             innerThrowable = ite.getTargetException();
508         }
509         if (innerThrowable != null) {
510             String JavaDoc innerExceptionTrace = recursiveStackTraceToString(innerThrowable, curDepth-1);
511             msgBodyWriter.write(innerExceptionTrace);
512         }
513         if (curDepth == 0) {
514             strOut.println("Cause level : " + curDepth + " (level 0 is the most precise exception)");
515
516         } else {
517             strOut.println("Cause level : " + curDepth);
518         }
519         t.printStackTrace(strOut);
520         return msgBodyWriter.toString();
521     }
522
523     public static int getNestedExceptionDepth(Throwable JavaDoc t, int curDepth) {
524         if (t == null) {
525             return curDepth;
526         }
527         int newDepth = curDepth;
528         Throwable JavaDoc innerThrowable = null;
529         if (t instanceof ServletException JavaDoc) {
530             ServletException JavaDoc se = (ServletException JavaDoc) t;
531             innerThrowable = se.getRootCause();
532         } else if (t instanceof JahiaException) {
533             JahiaException je = (JahiaException) t;
534             innerThrowable = je.getRootCause();
535         } else if (t instanceof InvocationTargetException JavaDoc) {
536             InvocationTargetException JavaDoc ite = (InvocationTargetException JavaDoc) t;
537             innerThrowable = ite.getTargetException();
538         }
539         if (innerThrowable != null) {
540             newDepth = getNestedExceptionDepth(innerThrowable, curDepth+1);
541         }
542         return newDepth;
543     }
544
545     /**
546      * Returns the nested exception if there is one, otherwise returns the
547      * current exception.
548      * @param t Throwable
549      * @return Throwable this method never returns null so don't put it in a
550      * loop !
551      */

552     public static Throwable JavaDoc getNestedException(Throwable JavaDoc t) {
553         if (t == null) {
554             return null;
555         }
556         Throwable JavaDoc innerThrowable = null;
557         if (t instanceof ServletException JavaDoc) {
558             ServletException JavaDoc se = (ServletException JavaDoc) t;
559             innerThrowable = se.getRootCause();
560         } else if (t instanceof JahiaException) {
561             JahiaException je = (JahiaException) t;
562             innerThrowable = je.getRootCause();
563         } else if (t instanceof InvocationTargetException JavaDoc) {
564             InvocationTargetException JavaDoc ite = (InvocationTargetException JavaDoc) t;
565             innerThrowable = ite.getTargetException();
566         }
567         if (innerThrowable != null) {
568             return getNestedException(innerThrowable);
569         } else {
570             return t;
571         }
572     }
573 }
574
Popular Tags