View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.slf4j.simple;
20  
21  import java.io.PrintStream;
22  
23  import static org.apache.maven.jline.MessageUtils.builder;
24  
25  /**
26   * Logger for Maven, that support colorization of levels and stacktraces.
27   * This class implements 2 methods introduced in slf4j-simple provider local copy.
28   * @since 3.5.0
29   */
30  public class MavenSimpleLogger extends SimpleLogger {
31  
32      private String traceRenderedLevel;
33      private String debugRenderedLevel;
34      private String infoRenderedLevel;
35      private String warnRenderedLevel;
36      private String errorRenderedLevel;
37  
38      MavenSimpleLogger(String name) {
39          super(name);
40      }
41  
42      @Override
43      protected String renderLevel(int level) {
44          // lazy initialization at first use
45          // cannot be done in constructor because ansi terminals are not configured yet
46          if (traceRenderedLevel == null) {
47              traceRenderedLevel = builder().trace("TRACE").build();
48              debugRenderedLevel = builder().debug("DEBUG").build();
49              infoRenderedLevel = builder().info("INFO").build();
50              warnRenderedLevel = builder().warning("WARNING").build();
51              errorRenderedLevel = builder().error("ERROR").build();
52          }
53  
54          switch (level) {
55              case LOG_LEVEL_TRACE:
56                  return traceRenderedLevel;
57              case LOG_LEVEL_DEBUG:
58                  return debugRenderedLevel;
59              case LOG_LEVEL_INFO:
60                  return infoRenderedLevel;
61              case LOG_LEVEL_WARN:
62                  return warnRenderedLevel;
63              case LOG_LEVEL_ERROR:
64              default:
65                  return errorRenderedLevel;
66          }
67      }
68  
69      @Override
70      protected void writeThrowable(Throwable t, PrintStream stream) {
71          if (t == null) {
72              return;
73          }
74          stream.print(builder().failure(t.getClass().getName()));
75          if (t.getMessage() != null) {
76              stream.print(": ");
77              stream.print(builder().failure(t.getMessage()));
78          }
79          stream.println();
80  
81          printStackTrace(t, stream, "");
82      }
83  
84      private void printStackTrace(Throwable t, PrintStream stream, String prefix) {
85          for (StackTraceElement e : t.getStackTrace()) {
86              stream.print(prefix);
87              stream.print("    ");
88              stream.print(builder().strong("at"));
89              stream.print(" " + e.getClassName() + "." + e.getMethodName());
90              stream.print(builder().a(" (").strong(getLocation(e)).a(")"));
91              stream.println();
92          }
93          for (Throwable se : t.getSuppressed()) {
94              writeThrowable(se, stream, "Suppressed", prefix + "    ");
95          }
96          Throwable cause = t.getCause();
97          if (cause != null && t != cause) {
98              writeThrowable(cause, stream, "Caused by", prefix);
99          }
100     }
101 
102     private void writeThrowable(Throwable t, PrintStream stream, String caption, String prefix) {
103         stream.print(builder().a(prefix).strong(caption).a(": ").a(t.getClass().getName()));
104         if (t.getMessage() != null) {
105             stream.print(": ");
106             stream.print(builder().failure(t.getMessage()));
107         }
108         stream.println();
109 
110         printStackTrace(t, stream, prefix);
111     }
112 
113     protected String getLocation(final StackTraceElement e) {
114         assert e != null;
115 
116         if (e.isNativeMethod()) {
117             return "Native Method";
118         } else if (e.getFileName() == null) {
119             return "Unknown Source";
120         } else if (e.getLineNumber() >= 0) {
121             return String.format("%s:%s", e.getFileName(), e.getLineNumber());
122         } else {
123             return e.getFileName();
124         }
125     }
126 }