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.apache.maven.slf4j;
20  
21  import java.io.PrintStream;
22  
23  import org.apache.maven.api.services.MessageBuilder;
24  import org.slf4j.simple.SimpleLogger;
25  
26  import static org.apache.maven.cli.jline.MessageUtils.builder;
27  
28  /**
29   * Logger for Maven, that support colorization of levels and stacktraces. This class implements 2 methods introduced in
30   * slf4j-simple provider local copy.
31   *
32   * @since 3.5.0
33   */
34  public class MavenSimpleLogger extends SimpleLogger {
35  
36      private final String traceRenderedLevel = builder().trace("TRACE").build();
37      private final String debugRenderedLevel = builder().debug("DEBUG").build();
38      private final String infoRenderedLevel = builder().info("INFO").build();
39      private final String warnRenderedLevel = builder().warning("WARNING").build();
40      private final String errorRenderedLevel = builder().error("ERROR").build();
41  
42      MavenSimpleLogger(String name) {
43          super(name);
44      }
45  
46      @Override
47      protected String renderLevel(int level) {
48          switch (level) {
49              case LOG_LEVEL_TRACE:
50                  return traceRenderedLevel;
51              case LOG_LEVEL_DEBUG:
52                  return debugRenderedLevel;
53              case LOG_LEVEL_INFO:
54                  return infoRenderedLevel;
55              case LOG_LEVEL_WARN:
56                  return warnRenderedLevel;
57              case LOG_LEVEL_ERROR:
58              default:
59                  return errorRenderedLevel;
60          }
61      }
62  
63      @Override
64      protected void writeThrowable(Throwable t, PrintStream stream) {
65          if (t == null) {
66              return;
67          }
68          MessageBuilder builder = builder().failure(t.getClass().getName());
69          if (t.getMessage() != null) {
70              builder.a(": ").failure(t.getMessage());
71          }
72          stream.println(builder);
73  
74          printStackTrace(t, stream, "");
75      }
76  
77      private void printStackTrace(Throwable t, PrintStream stream, String prefix) {
78          MessageBuilder builder = builder();
79          for (StackTraceElement e : t.getStackTrace()) {
80              builder.a(prefix);
81              builder.a("    ");
82              builder.strong("at");
83              builder.a(" ");
84              builder.a(e.getClassName());
85              builder.a(".");
86              builder.a(e.getMethodName());
87              builder.a("(");
88              builder.strong(getLocation(e));
89              builder.a(")");
90              stream.println(builder);
91              builder.setLength(0);
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         MessageBuilder builder =
104                 builder().a(prefix).strong(caption).a(": ").a(t.getClass().getName());
105         if (t.getMessage() != null) {
106             builder.a(": ").failure(t.getMessage());
107         }
108         stream.println(builder);
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 e.getFileName() + ":" + e.getLineNumber();
122         } else {
123             return e.getFileName();
124         }
125     }
126 }