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.cling.utils;
20  
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.time.Duration;
24  import java.time.ZoneId;
25  import java.time.format.DateTimeFormatter;
26  import java.time.temporal.TemporalAccessor;
27  import java.util.Locale;
28  import java.util.Properties;
29  
30  import org.apache.maven.impl.util.Os;
31  import org.apache.maven.jline.MessageUtils;
32  import org.slf4j.Logger;
33  
34  /**
35   * Utility class used to report errors, statistics, application version info, etc.
36   *
37   */
38  public final class CLIReportingUtils {
39      // CHECKSTYLE_OFF: MagicNumber
40      public static final long MB = 1024 * 1024;
41  
42      private static final long ONE_SECOND = 1000L;
43  
44      private static final long ONE_MINUTE = 60 * ONE_SECOND;
45  
46      private static final long ONE_HOUR = 60 * ONE_MINUTE;
47  
48      private static final long ONE_DAY = 24 * ONE_HOUR;
49      // CHECKSTYLE_ON: MagicNumber
50  
51      public static final String BUILD_VERSION_PROPERTY = "version";
52  
53      public static String showVersion() {
54          return showVersion(null, null);
55      }
56  
57      public static String showVersion(String commandLine, String terminal) {
58          final String ls = System.lineSeparator();
59          Properties properties = getBuildProperties();
60          StringBuilder version = new StringBuilder(256);
61          version.append(MessageUtils.builder().strong(createMavenVersionString(properties)))
62                  .append(ls);
63          version.append(reduce(properties.getProperty("distributionShortName") + " home: "
64                          + System.getProperty("maven.home", "<unknown Maven " + "home>")))
65                  .append(ls);
66          version.append("Java version: ")
67                  .append(System.getProperty("java.version", "<unknown Java version>"))
68                  .append(", vendor: ")
69                  .append(System.getProperty("java.vendor", "<unknown vendor>"))
70                  .append(", runtime: ")
71                  .append(System.getProperty("java.home", "<unknown runtime>"))
72                  .append(ls);
73          version.append("Default locale: ")
74                  .append(Locale.getDefault())
75                  .append(", platform encoding: ")
76                  .append(System.getProperty("file.encoding", "<unknown encoding>"))
77                  .append(", time zone: ")
78                  .append(ZoneId.systemDefault().getId())
79                  .append(ls);
80          version.append("OS name: \"")
81                  .append(Os.OS_NAME)
82                  .append("\", version: \"")
83                  .append(Os.OS_VERSION)
84                  .append("\", arch: \"")
85                  .append(Os.OS_ARCH)
86                  .append("\", family: \"")
87                  .append(Os.OS_FAMILY)
88                  .append('\"');
89          // Add process information using modern Java API
90          if (commandLine != null) {
91              version.append(ls).append("Command line: ").append(commandLine);
92          }
93          if (terminal != null) {
94              version.append(ls).append("Terminal: ").append(terminal);
95          }
96          return version.toString();
97      }
98  
99      public static String showVersionMinimal() {
100         Properties properties = getBuildProperties();
101         String version = reduce(properties.getProperty(BUILD_VERSION_PROPERTY));
102         return (version != null ? version : "<version unknown>");
103     }
104 
105     /**
106      * Create a human-readable string containing the Maven version, buildnumber, and time of build
107      *
108      * @param buildProperties The build properties
109      * @return Readable build info
110      */
111     public static String createMavenVersionString(Properties buildProperties) {
112         String version = reduce(buildProperties.getProperty(BUILD_VERSION_PROPERTY));
113         String rev = reduce(buildProperties.getProperty("buildNumber"));
114         String distributionName = reduce(buildProperties.getProperty("distributionName"));
115 
116         return distributionName + " "
117                 + (version != null ? version : "<version unknown>")
118                 + (rev != null ? " (" + rev + ")" : "");
119     }
120 
121     private static String reduce(String s) {
122         return (s != null ? (s.startsWith("${") && s.endsWith("}") ? null : s) : null);
123     }
124 
125     public static Properties getBuildProperties() {
126         Properties properties = new Properties();
127 
128         try (InputStream resourceAsStream =
129                 CLIReportingUtils.class.getResourceAsStream("/org/apache/maven/messages/build.properties")) {
130 
131             if (resourceAsStream != null) {
132                 properties.load(resourceAsStream);
133             }
134         } catch (IOException e) {
135             System.err.println("Unable determine version from JAR file: " + e.getMessage());
136         }
137 
138         return properties;
139     }
140 
141     public static void showError(Logger logger, String message, Throwable e, boolean showStackTrace) {
142         if (logger == null) {
143             System.err.println(message);
144             if (showStackTrace && e != null) {
145                 e.printStackTrace(System.err);
146             }
147             return;
148         }
149         if (showStackTrace) {
150             logger.error(message, e);
151         } else {
152             logger.error(message);
153 
154             if (e != null) {
155                 logger.error(e.getMessage());
156 
157                 for (Throwable cause = e.getCause();
158                         cause != null && cause != cause.getCause();
159                         cause = cause.getCause()) {
160                     logger.error("Caused by: {}", cause.getMessage());
161                 }
162             }
163         }
164     }
165 
166     public static String formatTimestamp(TemporalAccessor instant) {
167         return DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(instant);
168     }
169 
170     public static String formatDuration(Duration duration) {
171         long days = duration.toDays();
172         long hours = duration.toHoursPart();
173         long minutes = duration.toMinutesPart();
174         long seconds = duration.toSecondsPart();
175         long millis = duration.toMillisPart();
176 
177         if (days > 0) {
178             return String.format("%d d %02d:%02d h", days, hours, minutes);
179         } else if (hours > 0) {
180             return String.format("%02d:%02d h", hours, minutes);
181         } else if (minutes > 0) {
182             return String.format("%02d:%02d min", minutes, seconds);
183         } else {
184             return String.format("%d.%03d s", seconds, millis);
185         }
186     }
187 }