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.cli;
20  
21  import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
22  
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.text.SimpleDateFormat;
26  import java.util.Date;
27  import java.util.Locale;
28  import java.util.Properties;
29  import org.apache.commons.lang3.StringUtils;
30  import org.codehaus.plexus.util.Os;
31  import org.slf4j.Logger;
32  
33  /**
34   * Utility class used to report errors, statistics, application version info, etc.
35   *
36   * @author jdcasey
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          final String ls = System.lineSeparator();
55          Properties properties = getBuildProperties();
56          StringBuilder version = new StringBuilder(256);
57          version.append(buffer().strong(createMavenVersionString(properties))).append(ls);
58          version.append(reduce(properties.getProperty("distributionShortName") + " home: "
59                          + System.getProperty("maven.home", "<unknown Maven " + "home>")))
60                  .append(ls);
61          version.append("Java version: ")
62                  .append(System.getProperty("java.version", "<unknown Java version>"))
63                  .append(", vendor: ")
64                  .append(System.getProperty("java.vendor", "<unknown vendor>"))
65                  .append(", runtime: ")
66                  .append(System.getProperty("java.home", "<unknown runtime>"))
67                  .append(ls);
68          version.append("Default locale: ")
69                  .append(Locale.getDefault())
70                  .append(", platform encoding: ")
71                  .append(System.getProperty("file.encoding", "<unknown encoding>"))
72                  .append(ls);
73          version.append("OS name: \"")
74                  .append(Os.OS_NAME)
75                  .append("\", version: \"")
76                  .append(Os.OS_VERSION)
77                  .append("\", arch: \"")
78                  .append(Os.OS_ARCH)
79                  .append("\", family: \"")
80                  .append(Os.OS_FAMILY)
81                  .append('\"');
82          return version.toString();
83      }
84  
85      public static String showVersionMinimal() {
86          Properties properties = getBuildProperties();
87          String version = reduce(properties.getProperty(BUILD_VERSION_PROPERTY));
88          return (version != null ? version : "<version unknown>");
89      }
90  
91      /**
92       * Create a human-readable string containing the Maven version, buildnumber, and time of build
93       *
94       * @param buildProperties The build properties
95       * @return Readable build info
96       */
97      static String createMavenVersionString(Properties buildProperties) {
98          String timestamp = reduce(buildProperties.getProperty("timestamp"));
99          String version = reduce(buildProperties.getProperty(BUILD_VERSION_PROPERTY));
100         String rev = reduce(buildProperties.getProperty("buildNumber"));
101         String distributionName = reduce(buildProperties.getProperty("distributionName"));
102 
103         String msg = distributionName + " ";
104         msg += (version != null ? version : "<version unknown>");
105         if (rev != null || timestamp != null) {
106             msg += " (";
107             msg += (rev != null ? rev : "");
108             if (StringUtils.isNotBlank(timestamp)) {
109                 String ts = formatTimestamp(Long.parseLong(timestamp));
110                 msg += (rev != null ? "; " : "") + ts;
111             }
112             msg += ")";
113         }
114         return msg;
115     }
116 
117     private static String reduce(String s) {
118         return (s != null ? (s.startsWith("${") && s.endsWith("}") ? null : s) : null);
119     }
120 
121     static Properties getBuildProperties() {
122         Properties properties = new Properties();
123 
124         try (InputStream resourceAsStream =
125                 MavenCli.class.getResourceAsStream("/org/apache/maven/messages/build.properties")) {
126 
127             if (resourceAsStream != null) {
128                 properties.load(resourceAsStream);
129             }
130         } catch (IOException e) {
131             System.err.println("Unable determine version from JAR file: " + e.getMessage());
132         }
133 
134         return properties;
135     }
136 
137     public static void showError(Logger logger, String message, Throwable e, boolean showStackTrace) {
138         if (showStackTrace) {
139             logger.error(message, e);
140         } else {
141             logger.error(message);
142 
143             if (e != null) {
144                 logger.error(e.getMessage());
145 
146                 for (Throwable cause = e.getCause(); cause != null; cause = cause.getCause()) {
147                     logger.error("Caused by: {}", cause.getMessage());
148                 }
149             }
150         }
151     }
152 
153     public static String formatTimestamp(long timestamp) {
154         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
155         return sdf.format(new Date(timestamp));
156     }
157 
158     public static String formatDuration(long duration) {
159         // CHECKSTYLE_OFF: MagicNumber
160         long ms = duration % 1000;
161         long s = (duration / ONE_SECOND) % 60;
162         long m = (duration / ONE_MINUTE) % 60;
163         long h = (duration / ONE_HOUR) % 24;
164         long d = duration / ONE_DAY;
165         // CHECKSTYLE_ON: MagicNumber
166 
167         String format;
168         if (d > 0) {
169             // Length 11+ chars
170             format = "%d d %02d:%02d h";
171         } else if (h > 0) {
172             // Length 7 chars
173             format = "%2$02d:%3$02d h";
174         } else if (m > 0) {
175             // Length 9 chars
176             format = "%3$02d:%4$02d min";
177         } else {
178             // Length 7-8 chars
179             format = "%4$d.%5$03d s";
180         }
181 
182         return String.format(format, d, h, m, s, ms);
183     }
184 }