KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jcorporate > expresso > services > controller > ErrorHandler


1 /* ====================================================================
2  * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
3  *
4  * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  *
18  * 3. The end-user documentation included with the redistribution,
19  * if any, must include the following acknowledgment:
20  * "This product includes software developed by Jcorporate Ltd.
21  * (http://www.jcorporate.com/)."
22  * Alternately, this acknowledgment may appear in the software itself,
23  * if and wherever such third-party acknowledgments normally appear.
24  *
25  * 4. "Jcorporate" and product names such as "Expresso" must
26  * not be used to endorse or promote products derived from this
27  * software without prior written permission. For written permission,
28  * please contact info@jcorporate.com.
29  *
30  * 5. Products derived from this software may not be called "Expresso",
31  * or other Jcorporate product names; nor may "Expresso" or other
32  * Jcorporate product names appear in their name, without prior
33  * written permission of Jcorporate Ltd.
34  *
35  * 6. No product derived from this software may compete in the same
36  * market space, i.e. framework, without prior written permission
37  * of Jcorporate Ltd. For written permission, please contact
38  * partners@jcorporate.com.
39  *
40  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
41  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
42  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
43  * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
44  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
46  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
47  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
48  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
49  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
50  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * ====================================================================
53  *
54  * This software consists of voluntary contributions made by many
55  * individuals on behalf of the Jcorporate Ltd. Contributions back
56  * to the project(s) are encouraged when you make modifications.
57  * Please send them to support@jcorporate.com. For more information
58  * on Jcorporate Ltd. and its products, please see
59  * <http://www.jcorporate.com/>.
60  *
61  * Portions of this software are based upon other open source
62  * products and are subject to their respective licenses.
63  */

64
65 package com.jcorporate.expresso.services.controller;
66
67 import com.jcorporate.expresso.core.controller.ControllerException;
68 import com.jcorporate.expresso.core.controller.ControllerRequest;
69 import com.jcorporate.expresso.core.controller.ControllerResponse;
70 import com.jcorporate.expresso.core.controller.DBController;
71 import com.jcorporate.expresso.core.controller.NonHandleableException;
72 import com.jcorporate.expresso.core.controller.Output;
73 import com.jcorporate.expresso.core.controller.State;
74 import com.jcorporate.expresso.core.db.DBException;
75 import com.jcorporate.expresso.core.dbobj.SecuredDBObject;
76 import com.jcorporate.expresso.core.misc.ConfigManager;
77 import com.jcorporate.expresso.core.misc.ConfigurationException;
78 import com.jcorporate.expresso.core.misc.DateTime;
79 import com.jcorporate.expresso.core.misc.EMailSender;
80 import com.jcorporate.expresso.core.misc.EventHandler;
81 import com.jcorporate.expresso.core.misc.SerializableString;
82 import com.jcorporate.expresso.core.misc.StringUtil;
83 import com.jcorporate.expresso.core.security.User;
84 import com.jcorporate.expresso.kernel.exception.ChainedException;
85 import com.jcorporate.expresso.services.dbobj.DBMessage;
86 import com.jcorporate.expresso.services.dbobj.Setup;
87 import org.apache.log4j.Logger;
88
89 import java.io.ByteArrayOutputStream JavaDoc;
90 import java.io.PrintStream JavaDoc;
91 import java.util.Iterator JavaDoc;
92 import java.util.StringTokenizer JavaDoc;
93
94
95 /**
96  * This controller handles errors in whatever way is appropriate
97  * as specified in it's parameters.
98  *
99  * @deprecated This is not used anymore due to stability issues
100  */

101 public class ErrorHandler
102         extends DBController {
103     private static Logger log = Logger.getLogger(ErrorHandler.class);
104
105     /**
106      * Our constructor "declares" what states we handle
107      */

108     public ErrorHandler() {
109         super();
110         State handle = new State("handle", "Handle an Error");
111         addState(handle);
112         setInitialState("handle");
113         this.setSchema(com.jcorporate.expresso.core.ExpressoSchema.class);
114     } /* ErrorHandler() */
115
116
117     private String JavaDoc getAttribString(String JavaDoc key, ControllerRequest params)
118             throws NonHandleableException {
119         StringUtil.assertNotBlank(key,
120                 "Cannot request a blank or null key here");
121
122         Object JavaDoc o = null;
123
124         try {
125             o = params.getSession().getPersistentAttribute(key);
126         } catch (ControllerException ce) {
127             throw new NonHandleableException(ce);
128         }
129         if (o == null) {
130             return null;
131         }
132         if (o instanceof SerializableString) {
133             SerializableString s = (SerializableString) o;
134
135             return StringUtil.notNull(s.toString());
136         }
137
138         throw new NonHandleableException("Value in session key '" + key +
139                 "' " +
140                 "was not a SerializableString - it was '" +
141                 o.getClass().getName() + "'");
142     }
143
144     private void handleState(ControllerResponse myResponse,
145                              ControllerRequest params)
146             throws ControllerException, NonHandleableException {
147         log.debug("Handling error begins");
148
149         Throwable JavaDoc t = null;
150         String JavaDoc callerType = "";
151
152         try {
153             log.debug("Getting caller type");
154             callerType = StringUtil.notNull(getAttribString("callerType",
155                     params));
156             log.debug("Getting exception");
157
158             Object JavaDoc o = params.getSession().getPersistentAttribute("exception");
159
160             if (o == null) {
161                 throw new NonHandleableException("No error in session");
162             }
163             if (o instanceof Throwable JavaDoc) {
164                 t = (Throwable JavaDoc) o;
165             } else {
166                 throw new NonHandleableException("The 'exception' object in the " +
167                         "session was not a 'Throwable'. It was '" +
168                         o.getClass().getName() + "'");
169             }
170             if (t == null) {
171                 throw new NonHandleableException("There was no attribute called " +
172                         "'exception' stored in the current session. Unable to handle error");
173             }
174
175             /* Stash the stackTrace, if available, in an output */
176             boolean showStack = true;
177
178             try {
179                 showStack = ConfigManager.getContext(params.getDataContext()).showStackTrace();
180             } catch (ConfigurationException ce) {
181                 throw new NonHandleableException(ce);
182             }
183             if (showStack) {
184                 if (t != null) {
185                     ByteArrayOutputStream JavaDoc bos = new ByteArrayOutputStream JavaDoc();
186                     t.printStackTrace(new PrintStream JavaDoc(bos));
187                     myResponse.addOutput(new Output("stackTrace",
188                             bos.toString()));
189                 } else {
190                     myResponse.addOutput(new Output("stackTrace",
191                             "No stack trace was available"));
192                 }
193             } else {
194                 myResponse.addOutput(new Output("stackTrace",
195                         "Stack trace display is not " + "enabled. To enable, add 'stackTrace=y' to the '" +
196                         params.getDataContext() +
197                         ".properties' file"));
198             }
199
200             myResponse.addOutput(new Output("exceptionMessage", t.getMessage()));
201
202             if (t instanceof ChainedException) {
203                 ChainedException c = (ChainedException) t;
204                 Throwable JavaDoc nestedException = c.getNested();
205
206                 if (nestedException != null) {
207                     myResponse.addOutput(new Output("nestedMessage",
208                             StringUtil.notNull(c.getNested().getMessage())));
209                 } else {
210                     myResponse.addOutput(new Output("nestedMessage", ""));
211                 }
212             } else {
213                 myResponse.addOutput(new Output("nestedMessage", ""));
214             }
215         } catch (Exception JavaDoc ex) {
216             log.error("Exception thrown after getting:", ex);
217             throw new NonHandleableException("Unable to handle exception", ex);
218         }
219
220         reportError(t, myResponse, params);
221
222         if (t instanceof SecurityException JavaDoc) {
223             displaySecurityException(myResponse, params);
224         } else if (t instanceof DBException) {
225             displayDBException((DBException) t, myResponse, params);
226         } else {
227             displayOtherException(myResponse, params);
228         }
229         if (callerType.equals("job")) {
230             try {
231                 User u = new User();
232                 u.setDataContext(params.getDataContext());
233                 u.setLoginName(params.getUser());
234
235                 StringBuffer JavaDoc bigString = new StringBuffer JavaDoc(getAttribString("message",
236                         params));
237                 bigString.append("\n");
238
239                 String JavaDoc dbDescrip = StringUtil.notNull(
240                         ConfigManager.getContext(params.getDataContext()).getDescription());
241
242                 if (!dbDescrip.equals("")) {
243                     dbDescrip = " (" + dbDescrip + ") ";
244                 }
245
246                 bigString.append("A " + t.getClass().getName() +
247                         "Error occurred in db/context '" +
248                         params.getDataContext() + "' " + dbDescrip + "\n");
249                 bigString.append("Server:" +
250                         Setup.getValueRequired(params.getDataContext(),
251                                 "HTTPServ") + "\n");
252                 bigString.append("Stack Trace:\n");
253                 bigString.append(myResponse.getOutput("stackTrace").getContent());
254
255                 if (u.find()) {
256                     String JavaDoc oneRecipient = u.getEmail();
257
258                     if (log.isDebugEnabled()) {
259                         log.debug("Notifying '" + oneRecipient +
260                                 "' of failure of " + "job");
261                     }
262
263                     EMailSender ems = new EMailSender();
264                     ems.setDBName(params.getDataContext());
265                     ems.send(oneRecipient, getAttribString("message", params),
266                             bigString.toString());
267                 }
268             } catch (Exception JavaDoc ie) {
269                 log.warn("Error sending mail", ie);
270             }
271         }
272     } /* handleState() */
273
274
275     /**
276      * Display a security exception. If "next" is non-blank
277      * then generate a series of outputs showing the error. If it
278      * is blank, then display them directly to the user if possible
279      *
280      * @param params the ControllerRequest object
281      * @param myResponse the ControllerResponse object
282      */

283     private void displaySecurityException(ControllerResponse myResponse,
284                                           ControllerRequest params)
285             throws NonHandleableException {
286         log.debug("Displaying security exception");
287
288         try {
289             myResponse.addOutput(new Output("errorType", "security"));
290             displayException(myResponse, params);
291         } catch (ControllerException ce) {
292             throw new NonHandleableException(ce);
293         }
294     } /* displaySecurityException() */
295
296
297     /**
298      * Display a db exception. If "next" is non-blank
299      * then generate a series of outputs showing the error. If it
300      * is blank, then display them directly to the user if possible
301      *
302      * @param params the ControllerRequest object
303      * @param myResponse the ControllerResponse object
304      * @param de the database exception
305      */

306     private void displayDBException(DBException de,
307                                     ControllerResponse myResponse,
308                                     ControllerRequest params)
309             throws NonHandleableException {
310         log.debug("Displaying db exception");
311
312         try {
313             myResponse.addOutput(new Output("errorType", "db"));
314
315             /* generate outputs */
316             genOutputErrorBody(getAttribString("message", params), myResponse);
317             genOutputErrorBodyDB(de.getDBMessage(), myResponse);
318         } catch (ControllerException ce) {
319             throw new NonHandleableException(ce);
320         }
321     } /* displayDBException(String, DBException) */
322
323
324     /**
325      * Display an exception which is not a security or db exception
326      * If "next" is non-blank
327      * then generate a series of outputs showing the error. If it
328      * is blank, then display them directly to the user if possible
329      *
330      * @param params the ControllerRequest object
331      * @param myResponse the ControllerResponse object
332      */

333     private void displayOtherException(ControllerResponse myResponse,
334                                        ControllerRequest params)
335             throws NonHandleableException {
336         log.debug("Displaying other exception");
337
338         try {
339             myResponse.addOutput(new Output("errorType", "other"));
340             displayException(myResponse, params);
341         } catch (ControllerException ce) {
342             throw new NonHandleableException(ce);
343         }
344     } /* displayOtherException(String) */
345
346
347     /**
348      * Handle the common function of displaying the exception - either
349      * to the user directly or via outputs as specified by the "next"
350      * parameter
351      *
352      * @param params the ControllerRequest object
353      * @param myResponse the ControllerResponse object
354      */

355     private void displayException(ControllerResponse myResponse,
356                                   ControllerRequest params)
357             throws NonHandleableException {
358         try {
359
360             /* generate outputs */
361             genOutputErrorBody(getAttribString("message", params), myResponse);
362         } catch (ControllerException ce) {
363             throw new NonHandleableException(ce);
364         }
365     } /* displayOtherException(String) */
366
367
368     /**
369      * Return the title of this Controller
370      *
371      * @return java.lang.String The Title of the controller
372      */

373     public String JavaDoc getTitle() {
374         return ("Error Handling");
375     } /* getTitle() */
376
377     /**
378      * Transition to a new state
379      *
380      * @param newState The new state to transition into
381      * @param params the ControllerRequest object
382      * @return a ControllerResponse object
383      * @throws ControllerException upon error
384      * @throws NonHandleableException upon fatal error
385      */

386     public ControllerResponse newState(String JavaDoc newState,
387                                        ControllerRequest params)
388             throws ControllerException,
389             NonHandleableException {
390         newState = "handle"; /* no matter what we were asked for! */
391
392         ControllerResponse myResponse = null;
393
394         try {
395             myResponse = super.newState(newState, params);
396             handleState(myResponse, params);
397         } catch (Exception JavaDoc ee) {
398             throw new NonHandleableException(ee);
399         }
400
401         log.debug("Error controller returning from newstate");
402
403         return myResponse;
404     } /* newState() */
405
406
407     /**
408      * Override the normal stateAllowed method to always allow
409      * access to this controller
410      *
411      * @param newState the state to execute
412      * @param params the ControllerRequest object
413      * @return true for this controller for all states
414      * @throws ControllerException upon error
415      */

416     public synchronized boolean stateAllowed(String JavaDoc newState,
417                                              ControllerRequest params)
418             throws ControllerException {
419         return true;
420     } /* stateAllowed(String) */
421
422
423     /**
424      * Method called for any kind of error to provide event notifications for
425      * errors.
426      *
427      * @param t the Throwable object
428      * @param params the ControllerRequest object
429      * @param myResponse the ControllerResponse object
430      * @throws NonHandleableException on fatal error
431      */

432     protected void reportError(Throwable JavaDoc t, ControllerResponse myResponse,
433                                ControllerRequest params)
434             throws NonHandleableException {
435         try {
436             StringBuffer JavaDoc theMessage = new StringBuffer JavaDoc();
437             theMessage.append("Error:\n");
438             theMessage.append("\tA " + t.getClass().getName() +
439                     " Error occurred at " +
440                     DateTime.getDateTimeForDB(params.getDataContext()) +
441                     " in database/context '" + params.getDataContext() +
442                     "' to user '" + params.getUser() + "'\n");
443             theMessage.append("\tThe requested URL was '" +
444                     getAttribString("RequestedURL", params) + "'\n");
445
446             if (getAttribString("QueryString", params) != null) {
447                 theMessage.append("?" +
448                         getAttribString("QueryString", params) +
449                         "'\n");
450             }
451
452             String JavaDoc errorMessage = getAttribString("message", params);
453
454             if (errorMessage != null) {
455                 theMessage.append("\t" + errorMessage);
456             } else {
457                 theMessage.append("No error message was available");
458             }
459
460             theMessage.append(myResponse.getOutput("stackTrace").getContent());
461             log.error(theMessage.toString(), t);
462
463             try {
464                 String JavaDoc servletEventFlag = StringUtil.notNull(Setup.getValue(params.getDataContext(),
465                         "ServletEvent"));
466
467                 if (servletEventFlag.equalsIgnoreCase("Y")) {
468                     EventHandler.Event(params.getDataContext(), "SYSERROR",
469                             theMessage.toString(), false);
470                 } else if (servletEventFlag.equalsIgnoreCase("E")) {
471                     if (!(t instanceof SecurityException JavaDoc)) {
472                         EventHandler.Event(params.getDataContext(), "SYSERROR",
473                                 theMessage.toString(), false);
474                     }
475                 } else {
476                     log.warn("Sending of errors via email is not enabled in " +
477                             "db/context '" + params.getDataContext() + "'");
478                 }
479             } catch (Exception JavaDoc e) {
480                 log.error("Unable to log error correctly:" +
481                         theMessage.toString(), e);
482             }
483         } catch (DBException dbe) {
484             throw new NonHandleableException(dbe);
485         } catch (ControllerException ce) {
486             throw new NonHandleableException(ce);
487         }
488     } /* reportError */
489
490
491     /**
492      * Generate outputs containing the various components
493      * of this error message for use by a custom display page,
494      * such as showerror.jsp
495      *
496      * @param errorMessage the error message
497      * @param myResponse the ControllerResponse object
498      * @throws ControllerException upon error
499      */

500     private void genOutputErrorBody(String JavaDoc errorMessage,
501                                     ControllerResponse myResponse)
502             throws ControllerException {
503         if (errorMessage == null) {
504             log.error("Error message was null");
505             errorMessage = ("Error message was null");
506         }
507
508         myResponse.addOutput(new Output("originalError", errorMessage));
509
510         StringTokenizer JavaDoc stk = new StringTokenizer JavaDoc(errorMessage, ":");
511         String JavaDoc objectName = null;
512
513         if (stk.hasMoreTokens()) {
514             objectName = stk.nextToken();
515         } else {
516             objectName = ("NONE");
517         }
518
519         String JavaDoc message = ("");
520         String JavaDoc errorText = ("");
521         String JavaDoc messageNumber = ("");
522
523         if (stk.hasMoreTokens()) {
524             while (stk.hasMoreTokens()) {
525                 message = message + stk.nextToken() + " ";
526             }
527             if (message.startsWith("[")) {
528
529                 /* message has a message number in it */
530                 StringTokenizer JavaDoc stk2 = new StringTokenizer JavaDoc(message, "]");
531                 messageNumber = stk2.nextToken().substring(1);
532
533                 while (stk2.hasMoreTokens()) {
534                     errorText = errorText + stk2.nextToken();
535                 }
536             } else { /* no number */
537                 errorText = message;
538                 messageNumber = ("None Assigned");
539             }
540         } else { /* if there is anything after the initial colon */
541             errorText = errorMessage;
542             objectName = ("Unknown");
543             messageNumber = ("None Assigned");
544         }
545
546         myResponse.addOutput(new Output("errorText", errorText));
547         myResponse.addOutput(new Output("messageNumber", messageNumber));
548         myResponse.addOutput(new Output("objectName", objectName));
549     } /* genOutputErrorBody(String) */
550
551
552     protected void genOutputErrorBodyDB(String JavaDoc dbErrorMessage,
553                                         ControllerResponse myResponse)
554             throws ControllerException {
555         String JavaDoc newMessage = dbErrorMessage;
556
557         try {
558             if (!StringUtil.notNull(dbErrorMessage).equals("")) {
559                 DBMessage dm = new DBMessage(SecuredDBObject.SYSTEM_ACCOUNT);
560                 DBMessage oneDm = null;
561
562                 for (Iterator JavaDoc dml = dm.searchAndRetrieveList().iterator();
563                      dml.hasNext();) {
564                     oneDm = (DBMessage) dml.next();
565
566                     if (dbErrorMessage.indexOf(oneDm.getField("InputString")) != -1) {
567                         newMessage = oneDm.getField("OutputString");
568                         break;
569                     }
570                 } /* for each message mapping registered */
571
572             }
573
574             myResponse.addOutput(new Output("dbErrorMessage", newMessage));
575         } catch (DBException de) {
576             log.error("Unable to lookup error message mappings", de);
577         }
578     } /* genOutputErrorBodyDB(String, String) */
579
580 } /* ErrorHandler */
581
Popular Tags