1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.pattern;
18
19 import java.io.PrintWriter;
20 import java.io.StringWriter;
21
22 import org.apache.logging.log4j.core.LogEvent;
23 import org.apache.logging.log4j.core.config.plugins.Plugin;
24 import org.apache.logging.log4j.core.helpers.Constants;
25 import org.apache.logging.log4j.core.impl.ThrowableFormatOptions;
26
27
28
29
30
31
32
33 @Plugin(name = "ThrowablePatternConverter", category = "Converter")
34 @ConverterKeys({"ex", "throwable", "exception" })
35 public class ThrowablePatternConverter extends LogEventPatternConverter {
36
37 private String rawOption;
38
39
40
41
42 protected final ThrowableFormatOptions options;
43
44
45
46
47
48
49
50 protected ThrowablePatternConverter(final String name, final String style, final String[] options) {
51 super(name, style);
52 this.options = ThrowableFormatOptions.newInstance(options);
53 if (options != null && options.length > 0) {
54 rawOption = options[0];
55 }
56 }
57
58
59
60
61
62
63
64
65 public static ThrowablePatternConverter newInstance(final String[] options) {
66 return new ThrowablePatternConverter("Throwable", "throwable", options);
67 }
68
69
70
71
72 @Override
73 public void format(final LogEvent event, final StringBuilder buffer) {
74 final Throwable t = event.getThrown();
75
76 if (isSubShortOption()) {
77 formatSubShortOption(t, buffer);
78 }
79 else if (t != null && options.anyLines()) {
80 formatOption(t, buffer);
81 }
82 }
83
84 private boolean isSubShortOption() {
85 return ThrowableFormatOptions.MESSAGE.equalsIgnoreCase(rawOption) ||
86 ThrowableFormatOptions.LOCALIZED_MESSAGE.equalsIgnoreCase(rawOption) ||
87 ThrowableFormatOptions.FILE_NAME.equalsIgnoreCase(rawOption) ||
88 ThrowableFormatOptions.LINE_NUMBER.equalsIgnoreCase(rawOption) ||
89 ThrowableFormatOptions.METHOD_NAME.equalsIgnoreCase(rawOption) ||
90 ThrowableFormatOptions.CLASS_NAME.equalsIgnoreCase(rawOption);
91 }
92
93 private void formatSubShortOption(final Throwable t, final StringBuilder buffer) {
94 StackTraceElement[] trace;
95 StackTraceElement throwingMethod = null;
96 int len;
97
98 if (t != null) {
99 trace = t.getStackTrace();
100 if (trace !=null && trace.length > 0) {
101 throwingMethod = trace[0];
102 }
103 }
104
105 if (t != null && throwingMethod != null) {
106 String toAppend = "";
107
108 if (ThrowableFormatOptions.CLASS_NAME.equalsIgnoreCase(rawOption)) {
109 toAppend = throwingMethod.getClassName();
110 }
111 else if (ThrowableFormatOptions.METHOD_NAME.equalsIgnoreCase(rawOption)) {
112 toAppend = throwingMethod.getMethodName();
113 }
114 else if (ThrowableFormatOptions.LINE_NUMBER.equalsIgnoreCase(rawOption)) {
115 toAppend = String.valueOf(throwingMethod.getLineNumber());
116 }
117 else if (ThrowableFormatOptions.MESSAGE.equalsIgnoreCase(rawOption)) {
118 toAppend = t.getMessage();
119 }
120 else if (ThrowableFormatOptions.LOCALIZED_MESSAGE.equalsIgnoreCase(rawOption)) {
121 toAppend = t.getLocalizedMessage();
122 }
123 else if (ThrowableFormatOptions.FILE_NAME.equalsIgnoreCase(rawOption)) {
124 toAppend = throwingMethod.getFileName();
125 }
126
127 len = buffer.length();
128 if (len > 0 && !Character.isWhitespace(buffer.charAt(len - 1))) {
129 buffer.append(" ");
130 }
131 buffer.append(toAppend);
132 }
133 }
134
135 private void formatOption(final Throwable throwable, final StringBuilder buffer) {
136 final StringWriter w = new StringWriter();
137
138 throwable.printStackTrace(new PrintWriter(w));
139 final int len = buffer.length();
140 if (len > 0 && !Character.isWhitespace(buffer.charAt(len - 1))) {
141 buffer.append(' ');
142 }
143 if (!options.allLines() || !Constants.LINE_SEP.equals(options.getSeparator())) {
144 final StringBuilder sb = new StringBuilder();
145 final String[] array = w.toString().split(Constants.LINE_SEP);
146 final int limit = options.minLines(array.length) - 1;
147 for (int i = 0; i <= limit; ++i) {
148 sb.append(array[i]);
149 if (i < limit) {
150 sb.append(options.getSeparator());
151 }
152 }
153 buffer.append(sb.toString());
154
155 } else {
156 buffer.append(w.toString());
157 }
158 }
159
160
161
162
163
164
165 @Override
166 public boolean handlesThrowable() {
167 return true;
168 }
169 }