View Javadoc

1   /*
2    * Copyright 2001-2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.jdiagnose.message;
17  
18  import java.io.PrintWriter;
19  import java.io.StringWriter;
20  import java.lang.reflect.Method;
21  
22  import org.jdiagnose.DefaultDiagnosticMessage;
23  import org.jdiagnose.DiagnosticMessage;
24  import org.jdiagnose.MessageFactory;
25  import org.jdiagnose.exception.NestableRuntimeException;
26  
27  /***
28   * Creates diagnostic messages from exceptions. The exception message
29   * is used as the summary and the stacktrace as the body. Will use the 
30   * root exception by default and can optionally suppress the stack trace.
31   * Uses reflection to find the root cause so that it can be backwards
32   * compatible with Java 1.3
33   * 
34   * @author jmccrindle
35   */
36  public class ExceptionMessageFactory implements MessageFactory {
37      
38      public static final ExceptionMessageFactory DEFAULT_EXCEPTION_MESSAGE_FACTORY = new ExceptionMessageFactory();
39  
40      private boolean suppressStackTrace = false;
41      private boolean rootExceptionOnly = true;
42      
43      /***
44       * @param suppressStackTrace whether the stackTrace should be used for the 
45       *        message body
46       * @param rootExceptionOnly whether the root exception should be used or the 
47       *        whole exception.
48       */
49      public ExceptionMessageFactory(boolean suppressStackTrace,
50              boolean rootExceptionOnly) {
51          super();
52          this.suppressStackTrace = suppressStackTrace;
53          this.rootExceptionOnly = rootExceptionOnly;
54      }
55      
56      /***
57       * Default Constructor 
58       */
59      public ExceptionMessageFactory() {
60          super();
61      }
62  
63      /***
64       * Finds the root cause given an exception. Uses reflection to make it
65       * compatible with Java 1.3
66       * 
67       * @param t
68       * @return
69       */
70      protected Throwable getRootCause(Throwable t) {
71          if(t == null) return t;
72          try {
73              Method method = t.getClass().getMethod("getCause", null);
74              Throwable cause = (Throwable) method.invoke(t, null);
75              if(cause == null) {
76                  return t;
77              } else {
78                  return getRootCause(cause);
79              }
80          } catch (NoSuchMethodException e) {
81              // just return null...
82              return null;
83          } catch (Throwable e) {
84              throw new NestableRuntimeException(e);
85          }
86      }
87      
88      /***
89       * @see org.jdiagnose.MessageFactory#getMessage(java.lang.Object)
90       */
91      public DiagnosticMessage getMessage(Object object) {
92          // if(object == null) return null;
93          if (object instanceof Throwable) {
94              Throwable throwable = (Throwable) object;
95              if(rootExceptionOnly) {
96                  throwable = getRootCause(throwable);
97              }
98              String body = null;
99              if(!suppressStackTrace) {
100                 StringWriter stringWriter = new StringWriter();
101                 PrintWriter printer = new PrintWriter(stringWriter);
102                 throwable.printStackTrace(printer);
103                 body = stringWriter.toString();
104             }
105             return new DefaultDiagnosticMessage(throwable.getMessage(), body);
106         }
107         return null;
108     }
109     
110     /***
111      * @param rootExceptionOnly whether the root exception should be used or the 
112      *        whole exception.
113      */
114     public void setRootExceptionOnly(boolean rootExceptionOnly) {
115         this.rootExceptionOnly = rootExceptionOnly;
116     }
117     
118     /***
119      * @param suppressStackTrace whether the stackTrace should be used for the 
120      *        message body
121      */
122     public void setSuppressStackTrace(boolean suppressStackTrace) {
123         this.suppressStackTrace = suppressStackTrace;
124     }
125 }