View Javadoc
1   package org.apache.maven.cli;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.codehaus.plexus.util.Os;
23  import org.slf4j.Logger;
24  
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.util.Date;
28  import java.util.Locale;
29  import java.util.Properties;
30  import java.util.TimeZone;
31  
32  /**
33   * Utility class used to report errors, statistics, application version info, etc.
34   *
35   * @author jdcasey
36   */
37  public final class CLIReportingUtils
38  {
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      {
55          final String ls = System.getProperty( "line.separator" );
56          Properties properties = getBuildProperties();
57          StringBuilder version = new StringBuilder();
58          version.append( createMavenVersionString( properties ) ).append( ls );
59          version.append( reduce(
60              properties.getProperty( "distributionShortName" ) + " home: " + System.getProperty( "maven.home",
61                                                                                                  "<unknown Maven "
62                                                                                                      + "home>" ) ) )
63              .append(
64              ls );
65          version.append( "Java version: " ).append(
66              System.getProperty( "java.version", "<unknown Java version>" ) ).append( ", vendor: " ).append(
67              System.getProperty( "java.vendor", "<unknown vendor>" ) ).append( ls );
68          version.append( "Java home: " ).append( System.getProperty( "java.home", "<unknown Java home>" ) ).append( ls );
69          version.append( "Default locale: " ).append( Locale.getDefault() ).append( ", platform encoding: " ).append(
70              System.getProperty( "file.encoding", "<unknown encoding>" ) ).append( ls );
71          version.append( "OS name: \"" ).append( Os.OS_NAME ).append( "\", version: \"" ).append( Os.OS_VERSION ).append(
72              "\", arch: \"" ).append( Os.OS_ARCH ).append( "\", family: \"" ).append( Os.OS_FAMILY ).append( "\"" );
73          return version.toString();
74      }
75  
76      /**
77       * Create a human readable string containing the Maven version, buildnumber, and time of build
78       *
79       * @param buildProperties The build properties
80       * @return Readable build info
81       */
82      static String createMavenVersionString( Properties buildProperties )
83      {
84          String timestamp = reduce( buildProperties.getProperty( "timestamp" ) );
85          String version = reduce( buildProperties.getProperty( BUILD_VERSION_PROPERTY ) );
86          String rev = reduce( buildProperties.getProperty( "buildNumber" ) );
87          String distributionName = reduce( buildProperties.getProperty( "distributionName" ) );
88  
89          String msg = distributionName + " ";
90          msg += ( version != null ? version : "<version unknown>" );
91          if ( rev != null || timestamp != null )
92          {
93              msg += " (";
94              msg += ( rev != null ? rev : "" );
95              if ( timestamp != null )
96              {
97                  String ts = formatTimestamp( Long.valueOf( timestamp ) );
98                  msg += ( rev != null ? "; " : "" ) + ts;
99              }
100             msg += ")";
101         }
102         return msg;
103     }
104 
105     private static String reduce( String s )
106     {
107         return ( s != null ? ( s.startsWith( "${" ) && s.endsWith( "}" ) ? null : s ) : null );
108     }
109 
110     static Properties getBuildProperties()
111     {
112         Properties properties = new Properties();
113 
114         try ( InputStream resourceAsStream = MavenCli.class.getResourceAsStream(
115             "/org/apache/maven/messages/build.properties" ) )
116         {
117 
118             if ( resourceAsStream != null )
119             {
120                 properties.load( resourceAsStream );
121             }
122         }
123         catch ( IOException e )
124         {
125             System.err.println( "Unable determine version from JAR file: " + e.getMessage() );
126         }
127 
128         return properties;
129     }
130 
131     public static void showError( Logger logger, String message, Throwable e, boolean showStackTrace )
132     {
133         if ( showStackTrace )
134         {
135             logger.error( message, e );
136         }
137         else
138         {
139             logger.error( message );
140 
141             if ( e != null )
142             {
143                 logger.error( e.getMessage() );
144 
145                 for ( Throwable cause = e.getCause(); cause != null; cause = cause.getCause() )
146                 {
147                     logger.error( "Caused by: " + cause.getMessage() );
148                 }
149             }
150         }
151     }
152 
153     public static String formatTimestamp( long timestamp )
154     {
155         // Manual construction of the tz offset because only Java 7 is aware of ISO 8601 time zones
156         TimeZone tz = TimeZone.getDefault();
157         int offset = tz.getRawOffset();
158 
159         // Raw offset ignores DST, so check if we are in DST now and add the offset
160         if ( tz.inDaylightTime( new Date( timestamp ) ) )
161         {
162             offset += tz.getDSTSavings();
163         }
164 
165         // CHECKSTYLE_OFF: MagicNumber
166         long m = Math.abs( ( offset / ONE_MINUTE ) % 60 );
167         long h = Math.abs( ( offset / ONE_HOUR ) % 24 );
168         // CHECKSTYLE_ON: MagicNumber
169 
170         int offsetDir = (int) Math.signum( (float) offset );
171         char offsetSign = offsetDir >= 0 ? '+' : '-';
172         return String.format( "%tFT%<tT%s%02d:%02d", timestamp, offsetSign, h, m );
173     }
174 
175     public static String formatDuration( long duration )
176     {
177         // CHECKSTYLE_OFF: MagicNumber
178         long ms = duration % 1000;
179         long s = ( duration / ONE_SECOND ) % 60;
180         long m = ( duration / ONE_MINUTE ) % 60;
181         long h = ( duration / ONE_HOUR ) % 24;
182         long d = duration / ONE_DAY;
183         // CHECKSTYLE_ON: MagicNumber
184 
185         String format;
186         if ( d > 0 )
187         {
188             format = "%d d %02d:%02d h";
189         }
190         else if ( h > 0 )
191         {
192             format = "%2$02d:%3$02d h";
193         }
194         else if ( m > 0 )
195         {
196             format = "%3$02d:%4$02d min";
197         }
198         else
199         {
200             format = "%4$d.%5$03d s";
201         }
202 
203         return String.format( format, d, h, m, s, ms );
204     }
205 
206 }