1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.slf4j;
20
21 import java.io.PrintStream;
22 import java.util.function.Consumer;
23
24 import org.apache.maven.api.services.MessageBuilder;
25
26 import static org.apache.maven.jline.MessageUtils.builder;
27
28
29
30
31
32
33
34 public class MavenSimpleLogger extends MavenBaseLogger {
35
36 private String traceRenderedLevel;
37 private String debugRenderedLevel;
38 private String infoRenderedLevel;
39 private String warnRenderedLevel;
40 private String errorRenderedLevel;
41
42 static Consumer<String> logSink;
43
44 public static final String DEFAULT_LOG_LEVEL_KEY = "org.slf4j.simpleLogger.defaultLogLevel";
45
46 public static void setLogSink(Consumer<String> logSink) {
47 MavenSimpleLogger.logSink = logSink;
48 }
49
50 MavenSimpleLogger(String name) {
51 super(name);
52 }
53
54 @Override
55 protected String renderLevel(int level) {
56 if (traceRenderedLevel == null) {
57 traceRenderedLevel = builder().trace("TRACE").build();
58 debugRenderedLevel = builder().debug("DEBUG").build();
59 infoRenderedLevel = builder().info("INFO").build();
60 warnRenderedLevel = builder().warning("WARNING").build();
61 errorRenderedLevel = builder().error("ERROR").build();
62 }
63 return switch (level) {
64 case LOG_LEVEL_TRACE -> traceRenderedLevel;
65 case LOG_LEVEL_DEBUG -> debugRenderedLevel;
66 case LOG_LEVEL_INFO -> infoRenderedLevel;
67 case LOG_LEVEL_WARN -> warnRenderedLevel;
68 default -> errorRenderedLevel;
69 };
70 }
71
72 @Override
73 protected void write(StringBuilder buf, Throwable t) {
74 Consumer<String> sink = logSink;
75 if (sink != null) {
76 sink.accept(buf.toString());
77 if (t != null) {
78 writeThrowable(t, sink);
79 }
80 } else {
81 super.write(buf, t);
82 }
83 }
84
85 @Override
86 protected void writeThrowable(Throwable t, PrintStream stream) {
87 writeThrowable(t, stream::println);
88 }
89
90 protected void writeThrowable(Throwable t, Consumer<String> stream) {
91 if (t == null) {
92 return;
93 }
94 MessageBuilder builder = builder().failure(t.getClass().getName());
95 if (t.getMessage() != null) {
96 builder.a(": ").failure(t.getMessage());
97 }
98 stream.accept(builder.toString());
99
100 printStackTrace(t, stream, "");
101 }
102
103 protected void printStackTrace(Throwable t, Consumer<String> stream, String prefix) {
104 MessageBuilder builder = builder();
105 for (StackTraceElement e : t.getStackTrace()) {
106 builder.a(prefix);
107 builder.a(" ");
108 builder.strong("at");
109 builder.a(" ");
110 builder.a(e.getClassName());
111 builder.a(".");
112 builder.a(e.getMethodName());
113 builder.a("(");
114 builder.strong(getLocation(e));
115 builder.a(")");
116 stream.accept(builder.toString());
117 builder.setLength(0);
118 }
119 for (Throwable se : t.getSuppressed()) {
120 writeThrowable(se, stream, "Suppressed", prefix + " ");
121 }
122 Throwable cause = t.getCause();
123 if (cause != null && t != cause) {
124 writeThrowable(cause, stream, "Caused by", prefix);
125 }
126 }
127
128 protected void writeThrowable(Throwable t, Consumer<String> stream, String caption, String prefix) {
129 MessageBuilder builder =
130 builder().a(prefix).strong(caption).a(": ").a(t.getClass().getName());
131 if (t.getMessage() != null) {
132 builder.a(": ").failure(t.getMessage());
133 }
134 stream.accept(builder.toString());
135
136 printStackTrace(t, stream, prefix);
137 }
138
139 protected String getLocation(final StackTraceElement e) {
140 assert e != null;
141
142 if (e.isNativeMethod()) {
143 return "Native Method";
144 } else if (e.getFileName() == null) {
145 return "Unknown Source";
146 } else if (e.getLineNumber() >= 0) {
147 return e.getFileName() + ":" + e.getLineNumber();
148 } else {
149 return e.getFileName();
150 }
151 }
152
153 public void configure(int defaultLogLevel) {
154 String levelString = recursivelyComputeLevelString();
155 if (levelString != null) {
156 this.currentLogLevel = SimpleLoggerConfiguration.stringToLevel(levelString);
157 } else {
158 this.currentLogLevel = defaultLogLevel;
159 }
160 traceRenderedLevel = builder().trace("TRACE").build();
161 debugRenderedLevel = builder().debug("DEBUG").build();
162 infoRenderedLevel = builder().info("INFO").build();
163 warnRenderedLevel = builder().warning("WARNING").build();
164 errorRenderedLevel = builder().error("ERROR").build();
165 }
166
167 public void setLogLevel(int logLevel) {
168 this.currentLogLevel = logLevel;
169 }
170 }