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