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 java.text.DateFormat;
23  import java.text.SimpleDateFormat;
24  import java.util.Date;
25  import java.util.TimeZone;
26  
27  import org.apache.maven.execution.AbstractExecutionListener;
28  import org.apache.maven.execution.BuildFailure;
29  import org.apache.maven.execution.BuildSuccess;
30  import org.apache.maven.execution.BuildSummary;
31  import org.apache.maven.execution.ExecutionEvent;
32  import org.apache.maven.execution.MavenExecutionResult;
33  import org.apache.maven.execution.MavenSession;
34  import org.apache.maven.plugin.MojoExecution;
35  import org.apache.maven.project.MavenProject;
36  import org.codehaus.plexus.logging.Logger;
37  
38  /**
39   * Logs execution events to a user-supplied logger.
40   *
41   * @author Benjamin Bentmann
42   */
43  class ExecutionEventLogger
44      extends AbstractExecutionListener
45  {
46      private final Logger logger;
47  
48      private static final int LINE_LENGTH = 72;
49  
50      public ExecutionEventLogger( Logger logger )
51      {
52          if ( logger == null )
53          {
54              throw new IllegalArgumentException( "logger missing" );
55          }
56  
57          this.logger = logger;
58      }
59  
60      private static String chars( char c, int count )
61      {
62          StringBuilder buffer = new StringBuilder( count );
63  
64          for ( int i = count; i > 0; i-- )
65          {
66              buffer.append( c );
67          }
68  
69          return buffer.toString();
70      }
71  
72      private static String getFormattedTime( long time )
73      {
74          String pattern = "s.SSS's'";
75  
76          if ( time / 60000L > 0 )
77          {
78              pattern = "m:s" + pattern;
79  
80              if ( time / 3600000L > 0 )
81              {
82                  pattern = "H:m" + pattern;
83              }
84          }
85  
86          DateFormat fmt = new SimpleDateFormat( pattern );
87          fmt.setTimeZone( TimeZone.getTimeZone( "UTC" ) );
88  
89          return fmt.format( new Date( time ) );
90      }
91  
92      @Override
93      public void projectDiscoveryStarted( ExecutionEvent event )
94      {
95          if ( logger.isInfoEnabled() )
96          {
97              logger.info( "Scanning for projects..." );
98          }
99      }
100 
101     @Override
102     public void sessionStarted( ExecutionEvent event )
103     {
104         if ( logger.isInfoEnabled() && event.getSession().getProjects().size() > 1 )
105         {
106             logger.info( chars( '-', LINE_LENGTH ) );
107 
108             logger.info( "Reactor Build Order:" );
109 
110             logger.info( "" );
111 
112             for ( MavenProject project : event.getSession().getProjects() )
113             {
114                 logger.info( project.getName() );
115             }
116         }
117     }
118 
119     @Override
120     public void sessionEnded( ExecutionEvent event )
121     {
122         if ( logger.isInfoEnabled() )
123         {
124             if ( event.getSession().getProjects().size() > 1 )
125             {
126                 logReactorSummary( event.getSession() );
127             }
128 
129             logResult( event.getSession() );
130 
131             logStats( event.getSession() );
132 
133             logger.info( chars( '-', LINE_LENGTH ) );
134         }
135     }
136 
137     private void logReactorSummary( MavenSession session )
138     {
139         logger.info( chars( '-', LINE_LENGTH ) );
140 
141         logger.info( "Reactor Summary:" );
142 
143         logger.info( "" );
144 
145         MavenExecutionResult result = session.getResult();
146 
147         for ( MavenProject project : session.getProjects() )
148         {
149             StringBuilder buffer = new StringBuilder( 128 );
150 
151             buffer.append( project.getName() );
152 
153             buffer.append( ' ' );
154             while ( buffer.length() < LINE_LENGTH - 21 )
155             {
156                 buffer.append( '.' );
157             }
158             buffer.append( ' ' );
159 
160             BuildSummary buildSummary = result.getBuildSummary( project );
161 
162             if ( buildSummary == null )
163             {
164                 buffer.append( "SKIPPED" );
165             }
166             else if ( buildSummary instanceof BuildSuccess )
167             {
168                 buffer.append( "SUCCESS [" );
169                 buffer.append( getFormattedTime( buildSummary.getTime() ) );
170                 buffer.append( "]" );
171             }
172             else if ( buildSummary instanceof BuildFailure )
173             {
174                 buffer.append( "FAILURE [" );
175                 buffer.append( getFormattedTime( buildSummary.getTime() ) );
176                 buffer.append( "]" );
177             }
178 
179             logger.info( buffer.toString() );
180         }
181     }
182 
183     private void logResult( MavenSession session )
184     {
185         logger.info( chars( '-', LINE_LENGTH ) );
186 
187         if ( session.getResult().hasExceptions() )
188         {
189             logger.info( "BUILD FAILURE" );
190         }
191         else
192         {
193             logger.info( "BUILD SUCCESS" );
194         }
195     }
196 
197     private void logStats( MavenSession session )
198     {
199         logger.info( chars( '-', LINE_LENGTH ) );
200 
201         Date finish = new Date();
202 
203         long time = finish.getTime() - session.getRequest().getStartTime().getTime();
204 
205         String wallClock = session.getRequest().isThreadConfigurationPresent() ? " (Wall Clock)" : "";
206 
207         logger.info( "Total time: " + getFormattedTime( time ) + wallClock );
208 
209         logger.info( "Finished at: " + finish );
210 
211         System.gc();
212 
213         Runtime r = Runtime.getRuntime();
214 
215         long MB = 1024 * 1024;
216 
217         logger.info( "Final Memory: " + ( r.totalMemory() - r.freeMemory() ) / MB + "M/" + r.totalMemory() / MB + "M" );
218     }
219 
220     @Override
221     public void projectSkipped( ExecutionEvent event )
222     {
223         if ( logger.isInfoEnabled() )
224         {
225             logger.info( chars( ' ', LINE_LENGTH ) );
226             logger.info( chars( '-', LINE_LENGTH ) );
227 
228             logger.info( "Skipping " + event.getProject().getName() );
229             logger.info( "This project has been banned from the build due to previous failures." );
230 
231             logger.info( chars( '-', LINE_LENGTH ) );
232         }
233     }
234 
235     @Override
236     public void projectStarted( ExecutionEvent event )
237     {
238         if ( logger.isInfoEnabled() )
239         {
240             logger.info( chars( ' ', LINE_LENGTH ) );
241             logger.info( chars( '-', LINE_LENGTH ) );
242 
243             logger.info( "Building " + event.getProject().getName() + " " + event.getProject().getVersion() );
244 
245             logger.info( chars( '-', LINE_LENGTH ) );
246         }
247     }
248 
249     @Override
250     public void mojoSkipped( ExecutionEvent event )
251     {
252         if ( logger.isWarnEnabled() )
253         {
254             logger.warn( "Goal " + event.getMojoExecution().getGoal()
255                 + " requires online mode for execution but Maven is currently offline, skipping" );
256         }
257     }
258 
259     @Override
260     public void mojoStarted( ExecutionEvent event )
261     {
262         if ( logger.isInfoEnabled() )
263         {
264             StringBuilder buffer = new StringBuilder( 128 );
265 
266             buffer.append( "--- " );
267             append( buffer, event.getMojoExecution() );
268             append( buffer, event.getProject() );
269             buffer.append( " ---" );
270 
271             logger.info( "" );
272             logger.info( buffer.toString() );
273         }
274     }
275 
276     @Override
277     public void forkStarted( ExecutionEvent event )
278     {
279         if ( logger.isInfoEnabled() )
280         {
281             StringBuilder buffer = new StringBuilder( 128 );
282 
283             buffer.append( ">>> " );
284             append( buffer, event.getMojoExecution() );
285             append( buffer, event.getProject() );
286             buffer.append( " >>>" );
287 
288             logger.info( "" );
289             logger.info( buffer.toString() );
290         }
291     }
292 
293     @Override
294     public void forkSucceeded( ExecutionEvent event )
295     {
296         if ( logger.isInfoEnabled() )
297         {
298             StringBuilder buffer = new StringBuilder( 128 );
299 
300             buffer.append( "<<< " );
301             append( buffer, event.getMojoExecution() );
302             append( buffer, event.getProject() );
303             buffer.append( " <<<" );
304 
305             logger.info( "" );
306             logger.info( buffer.toString() );
307         }
308     }
309 
310     private void append( StringBuilder buffer, MojoExecution me )
311     {
312         buffer.append( me.getArtifactId() ).append( ':' ).append( me.getVersion() );
313         buffer.append( ':' ).append( me.getGoal() );
314         if ( me.getExecutionId() != null )
315         {
316             buffer.append( " (" ).append( me.getExecutionId() ).append( ')' );
317         }
318     }
319 
320     private void append( StringBuilder buffer, MavenProject project )
321     {
322         buffer.append( " @ " ).append( project.getArtifactId() );
323     }
324 
325     @Override
326     public void forkedProjectStarted( ExecutionEvent event )
327     {
328         if ( logger.isInfoEnabled() && event.getMojoExecution().getForkedExecutions().size() > 1 )
329         {
330             logger.info( chars( ' ', LINE_LENGTH ) );
331             logger.info( chars( '>', LINE_LENGTH ) );
332 
333             logger.info( "Forking " + event.getProject().getName() + " " + event.getProject().getVersion() );
334 
335             logger.info( chars( '>', LINE_LENGTH ) );
336         }
337     }
338 
339 }