1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.classic.spi;
15
16 import ch.qos.logback.core.CoreConstants;
17
18
19
20
21
22
23
24 public class ThrowableProxyUtil {
25
26 public static final int REGULAR_EXCEPTION_INDENT = 1;
27 public static final int SUPPRESSED_EXCEPTION_INDENT = 1;
28 private static final int BUILDER_CAPACITY = 2048;
29
30 public static void build(ThrowableProxy nestedTP, Throwable nestedThrowable, ThrowableProxy parentTP) {
31
32 StackTraceElement[] nestedSTE = nestedThrowable.getStackTrace();
33
34 int commonFramesCount = -1;
35 if (parentTP != null) {
36 commonFramesCount = findNumberOfCommonFrames(nestedSTE, parentTP.getStackTraceElementProxyArray());
37 }
38
39 nestedTP.commonFrames = commonFramesCount;
40 nestedTP.stackTraceElementProxyArray = steArrayToStepArray(nestedSTE);
41 }
42
43 static StackTraceElementProxy[] steArrayToStepArray(StackTraceElement[] stea) {
44 if (stea == null) {
45 return new StackTraceElementProxy[0];
46 }
47 StackTraceElementProxy[] stepa = new StackTraceElementProxy[stea.length];
48 for (int i = 0; i < stepa.length; i++) {
49 stepa[i] = new StackTraceElementProxy(stea[i]);
50 }
51 return stepa;
52 }
53
54 static int findNumberOfCommonFrames(StackTraceElement[] steArray, StackTraceElementProxy[] parentSTEPArray) {
55 if (parentSTEPArray == null || steArray == null) {
56 return 0;
57 }
58
59 int steIndex = steArray.length - 1;
60 int parentIndex = parentSTEPArray.length - 1;
61 int count = 0;
62 while (steIndex >= 0 && parentIndex >= 0) {
63 StackTraceElement ste = steArray[steIndex];
64 StackTraceElement otherSte = parentSTEPArray[parentIndex].ste;
65 if (ste.equals(otherSte)) {
66 count++;
67 } else {
68 break;
69 }
70 steIndex--;
71 parentIndex--;
72 }
73 return count;
74 }
75
76 public static void appendNominalFirstLine(StringBuilder buf, String classname, String message) {
77 buf.append(classname).append(": ").append(message);
78 }
79
80 public static String asString(IThrowableProxy tp) {
81 StringBuilder sb = new StringBuilder(BUILDER_CAPACITY);
82
83 recursiveAppend(sb, null, REGULAR_EXCEPTION_INDENT, tp);
84
85 return sb.toString();
86 }
87
88 private static void recursiveAppend(StringBuilder sb, String prefix, int indent, IThrowableProxy tp) {
89 if (tp == null)
90 return;
91 subjoinFirstLine(sb, prefix, indent, tp);
92 sb.append(CoreConstants.LINE_SEPARATOR);
93 subjoinSTEPArray(sb, indent, tp);
94 IThrowableProxy[] suppressed = tp.getSuppressed();
95 if (suppressed != null) {
96 for (IThrowableProxy current : suppressed) {
97 recursiveAppend(sb, CoreConstants.SUPPRESSED, indent + SUPPRESSED_EXCEPTION_INDENT, current);
98 }
99 }
100 recursiveAppend(sb, CoreConstants.CAUSED_BY, indent, tp.getCause());
101 }
102
103 public static void indent(StringBuilder buf, int indent) {
104 for (int j = 0; j < indent; j++) {
105 buf.append(CoreConstants.TAB);
106 }
107 }
108
109 private static void subjoinFirstLine(StringBuilder buf, String prefix, int indent, IThrowableProxy tp) {
110 indent(buf, indent - 1);
111 if (prefix != null) {
112 buf.append(prefix);
113 }
114 subjoinExceptionMessage(buf, tp);
115 }
116
117 public static void subjoinPackagingData(StringBuilder builder, StackTraceElementProxy step) {
118 if (step != null) {
119 ClassPackagingData cpd = step.getClassPackagingData();
120 if (cpd != null) {
121 if (!cpd.isExact()) {
122 builder.append(" ~[");
123 } else {
124 builder.append(" [");
125 }
126
127 builder.append(cpd.getCodeLocation()).append(':').append(cpd.getVersion()).append(']');
128 }
129 }
130 }
131
132 public static void subjoinSTEP(StringBuilder sb, StackTraceElementProxy step) {
133 sb.append(step.toString());
134 subjoinPackagingData(sb, step);
135 }
136
137
138
139
140
141
142
143 public static void subjoinSTEPArray(StringBuilder sb, IThrowableProxy tp) {
144
145 subjoinSTEPArray(sb, REGULAR_EXCEPTION_INDENT, tp);
146 }
147
148
149
150
151
152
153
154 public static void subjoinSTEPArray(StringBuilder sb, int indentLevel, IThrowableProxy tp) {
155 StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray();
156 int commonFrames = tp.getCommonFrames();
157
158 for (int i = 0; i < stepArray.length - commonFrames; i++) {
159 StackTraceElementProxy step = stepArray[i];
160 indent(sb, indentLevel);
161 subjoinSTEP(sb, step);
162 sb.append(CoreConstants.LINE_SEPARATOR);
163 }
164
165 if (commonFrames > 0) {
166 indent(sb, indentLevel);
167 sb.append("... ").append(commonFrames).append(" common frames omitted")
168 .append(CoreConstants.LINE_SEPARATOR);
169 }
170
171 }
172
173 public static void subjoinFirstLine(StringBuilder buf, IThrowableProxy tp) {
174 int commonFrames = tp.getCommonFrames();
175 if (commonFrames > 0) {
176 buf.append(CoreConstants.CAUSED_BY);
177 }
178 subjoinExceptionMessage(buf, tp);
179 }
180
181 public static void subjoinFirstLineRootCauseFirst(StringBuilder buf, IThrowableProxy tp) {
182 if (tp.getCause() != null) {
183 buf.append(CoreConstants.WRAPPED_BY);
184 }
185 subjoinExceptionMessage(buf, tp);
186 }
187
188 public static void subjoinExceptionMessage(StringBuilder stringBuilder, IThrowableProxy tp) {
189 if (tp.isCyclic()) {
190 stringBuilder.append("[CIRCULAR REFERENCE: ");
191 appendNominalOrOverridingMessage(stringBuilder, tp);
192 stringBuilder.append(']');
193 } else {
194 appendNominalOrOverridingMessage(stringBuilder, tp);
195 }
196 }
197
198 private static void appendNominalOrOverridingMessage(StringBuilder stringBuilder, IThrowableProxy tp) {
199 if(tp.getOverridingMessage() == null) {
200 appendNominalFirstLine(stringBuilder, tp.getClassName(), tp.getMessage());
201 } else {
202 stringBuilder.append(tp.getOverridingMessage());
203 }
204 }
205 }