View Javadoc

1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2011, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.classic.spi;
15  
16  import ch.qos.logback.core.CoreConstants;
17  
18  import java.lang.reflect.InvocationTargetException;
19  import java.lang.reflect.Method;
20  
21  public class ThrowableProxy implements IThrowableProxy {
22  
23    private Throwable throwable;
24    private String className;
25    private String message;
26    // package-private because of ThrowableProxyUtil
27    StackTraceElementProxy[] stackTraceElementProxyArray;
28    // package-private because of ThrowableProxyUtil
29    int commonFrames;
30    private ThrowableProxy cause;
31    private ThrowableProxy[] suppressed=NO_SUPPRESSED;
32  
33    private transient PackagingDataCalculator packagingDataCalculator;
34    private boolean calculatedPackageData = false;
35  
36    private static final Method GET_SUPPRESSED_METHOD;
37  
38    static {
39      Method method = null;
40      try {
41        method = Throwable.class.getMethod("getSuppressed");
42      } catch (NoSuchMethodException e) {
43        // ignore, will get thrown in Java < 7
44      }
45      GET_SUPPRESSED_METHOD = method;
46    }
47  
48    private static final ThrowableProxy[] NO_SUPPRESSED=new ThrowableProxy[0];
49  
50    public ThrowableProxy(Throwable throwable) {
51     
52      this.throwable = throwable;
53      this.className = throwable.getClass().getName();
54      this.message = throwable.getMessage();
55      this.stackTraceElementProxyArray = ThrowableProxyUtil.steArrayToStepArray(throwable
56          .getStackTrace());
57      
58      Throwable nested = throwable.getCause();
59      
60      if (nested != null) {
61        this.cause = new ThrowableProxy(nested);
62        this.cause.commonFrames = ThrowableProxyUtil
63            .findNumberOfCommonFrames(nested.getStackTrace(),
64                stackTraceElementProxyArray);
65      }
66      if(GET_SUPPRESSED_METHOD != null) {
67        // this will only execute on Java 7
68        try {
69          Object obj = GET_SUPPRESSED_METHOD.invoke(throwable);
70          if(obj instanceof Throwable[]) {
71            Throwable[] throwableSuppressed = (Throwable[]) obj;
72            if(throwableSuppressed.length > 0) {
73              suppressed = new ThrowableProxy[throwableSuppressed.length];
74              for(int i=0;i<throwableSuppressed.length;i++) {
75                this.suppressed[i] = new ThrowableProxy(throwableSuppressed[i]);
76                this.suppressed[i].commonFrames = ThrowableProxyUtil
77                    .findNumberOfCommonFrames(throwableSuppressed[i].getStackTrace(),
78                        stackTraceElementProxyArray);
79              }
80            }
81          }
82        } catch (IllegalAccessException e) {
83          // ignore
84        } catch (InvocationTargetException e) {
85          // ignore
86        }
87      }
88  
89    }
90  
91  
92    public Throwable getThrowable() {
93      return throwable;
94    }
95  
96    public String getMessage() {
97      return message;
98    }
99  
100   /*
101    * (non-Javadoc)
102    * 
103    * @see ch.qos.logback.classic.spi.IThrowableProxy#getClassName()
104    */
105   public String getClassName() {
106     return className;
107   }
108 
109   public StackTraceElementProxy[] getStackTraceElementProxyArray() {
110     return stackTraceElementProxyArray;
111   }
112 
113   public int getCommonFrames() {
114     return commonFrames;
115   }
116 
117   /*
118    * (non-Javadoc)
119    * 
120    * @see ch.qos.logback.classic.spi.IThrowableProxy#getCause()
121    */
122   public IThrowableProxy getCause() {
123     return cause;
124   }
125 
126   public IThrowableProxy[] getSuppressed() {
127     return suppressed;
128   }
129 
130   public PackagingDataCalculator getPackagingDataCalculator() {
131     // if original instance (non-deserialized), and packagingDataCalculator
132     // is not already initialized, then create an instance.
133     // here we assume that (throwable == null) for deserialized instances
134     if (throwable != null && packagingDataCalculator == null) {
135       packagingDataCalculator = new PackagingDataCalculator();
136     }
137     return packagingDataCalculator;
138   }
139 
140   public void calculatePackagingData() {
141     if (calculatedPackageData) {
142       return;
143     }
144     PackagingDataCalculator pdc = this.getPackagingDataCalculator();
145     if (pdc != null) {
146       calculatedPackageData = true;
147       pdc.calculate(this);
148     }
149   }
150 
151 
152 
153   public void fullDump() {
154     StringBuilder builder = new StringBuilder();
155     for (StackTraceElementProxy step : stackTraceElementProxyArray) {
156       String string = step.toString();
157       builder.append(CoreConstants.TAB).append(string);
158       ThrowableProxyUtil.subjoinPackagingData(builder, step);
159       builder.append(CoreConstants.LINE_SEPARATOR);
160     }
161     System.out.println(builder.toString());
162   }
163 
164 
165 }