1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.classic.pattern;
15
16 import java.util.ArrayList;
17 import java.util.List;
18 import java.util.Map;
19
20 import ch.qos.logback.classic.spi.ILoggingEvent;
21 import ch.qos.logback.classic.spi.IThrowableProxy;
22 import ch.qos.logback.classic.spi.StackTraceElementProxy;
23 import ch.qos.logback.classic.spi.ThrowableProxyUtil;
24 import ch.qos.logback.core.Context;
25 import ch.qos.logback.core.CoreConstants;
26 import ch.qos.logback.core.boolex.EvaluationException;
27 import ch.qos.logback.core.boolex.EventEvaluator;
28 import ch.qos.logback.core.status.ErrorStatus;
29
30
31
32
33
34
35 public class ThrowableProxyConverter extends ThrowableHandlingConverter {
36
37 int lengthOption;
38 List<EventEvaluator<ILoggingEvent>> evaluatorList = null;
39
40 int errorCount = 0;
41
42 @SuppressWarnings("unchecked")
43 public void start() {
44
45 String lengthStr = getFirstOption();
46
47 if (lengthStr == null) {
48 lengthOption = Integer.MAX_VALUE;
49 } else {
50 lengthStr = lengthStr.toLowerCase();
51 if ("full".equals(lengthStr)) {
52 lengthOption = Integer.MAX_VALUE;
53 } else if ("short".equals(lengthStr)) {
54 lengthOption = 2;
55 } else {
56 try {
57
58 lengthOption = Integer.parseInt(lengthStr) + 1;
59 } catch (NumberFormatException nfe) {
60 addError("Could not parser [" + lengthStr + " as an integer");
61 lengthOption = Integer.MAX_VALUE;
62 }
63 }
64 }
65
66 final List optionList = getOptionList();
67
68 if (optionList != null && optionList.size() > 1) {
69 final int optionListSize = optionList.size();
70 for (int i = 1; i < optionListSize; i++) {
71 String evaluatorStr = (String) optionList.get(i);
72 Context context = getContext();
73 Map evaluatorMap = (Map) context.getObject(CoreConstants.EVALUATOR_MAP);
74 EventEvaluator<ILoggingEvent> ee = (EventEvaluator<ILoggingEvent>) evaluatorMap
75 .get(evaluatorStr);
76 addEvaluator(ee);
77 }
78 }
79 super.start();
80 }
81
82 private void addEvaluator(EventEvaluator<ILoggingEvent> ee) {
83 if (evaluatorList == null) {
84 evaluatorList = new ArrayList<EventEvaluator<ILoggingEvent>>();
85 }
86 evaluatorList.add(ee);
87 }
88
89 public void stop() {
90 evaluatorList = null;
91 super.stop();
92 }
93
94 protected void extraData(StringBuilder builder, StackTraceElementProxy step) {
95
96 }
97
98 public String convert(ILoggingEvent event) {
99
100 IThrowableProxy tp = event.getThrowableProxy();
101 if (tp == null) {
102 return CoreConstants.EMPTY_STRING;
103 }
104
105
106 if (evaluatorList != null) {
107 boolean printStack = true;
108 for (int i = 0; i < evaluatorList.size(); i++) {
109 EventEvaluator<ILoggingEvent> ee = evaluatorList.get(i);
110 try {
111 if (ee.evaluate(event)) {
112 printStack = false;
113 break;
114 }
115 } catch (EvaluationException eex) {
116 errorCount++;
117 if (errorCount < CoreConstants.MAX_ERROR_COUNT) {
118 addError("Exception thrown for evaluator named [" + ee.getName()
119 + "]", eex);
120 } else if (errorCount == CoreConstants.MAX_ERROR_COUNT) {
121 ErrorStatus errorStatus = new ErrorStatus(
122 "Exception thrown for evaluator named [" + ee.getName() + "].",
123 this, eex);
124 errorStatus.add(new ErrorStatus(
125 "This was the last warning about this evaluator's errors."
126 + "We don't want the StatusManager to get flooded.", this));
127 addStatus(errorStatus);
128 }
129 }
130 }
131
132 if (!printStack) {
133 return CoreConstants.EMPTY_STRING;
134 }
135 }
136
137 return throwableProxyToString(tp);
138 }
139
140 protected String throwableProxyToString(IThrowableProxy tp) {
141 StringBuilder buf = new StringBuilder(32);
142 IThrowableProxy currentThrowable = tp;
143 while (currentThrowable != null) {
144 subjoinThrowableProxy(buf, currentThrowable);
145 currentThrowable = currentThrowable.getCause();
146 }
147 return buf.toString();
148 }
149
150 void subjoinThrowableProxy(StringBuilder buf, IThrowableProxy tp) {
151 ThrowableProxyUtil.subjoinFirstLine(buf, tp);
152 buf.append(CoreConstants.LINE_SEPARATOR);
153 StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray();
154 int commonFrames = tp.getCommonFrames();
155
156 boolean unrestrictedPrinting = lengthOption > stepArray.length;
157
158
159 int maxIndex = (unrestrictedPrinting) ? stepArray.length : lengthOption;
160 if (commonFrames > 0 && unrestrictedPrinting) {
161 maxIndex -= commonFrames;
162 }
163
164 for (int i = 0; i < maxIndex; i++) {
165 String string = stepArray[i].toString();
166 buf.append(CoreConstants.TAB);
167 buf.append(string);
168 extraData(buf, stepArray[i]);
169 buf.append(CoreConstants.LINE_SEPARATOR);
170 }
171
172 if (commonFrames > 0 && unrestrictedPrinting) {
173 buf.append("\t... ").append(tp.getCommonFrames()).append(
174 " common frames omitted").append(CoreConstants.LINE_SEPARATOR);
175 }
176 }
177 }