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 @Override
263 public void mojoStarted( ExecutionEvent event )
264 {
265 if ( logger.isInfoEnabled() )
266 {
267 StringBuilder buffer = new StringBuilder( 128 );
268
269 buffer.append( "--- " );
270 append( buffer, event.getMojoExecution() );
271 append( buffer, event.getProject() );
272 buffer.append( " ---" );
273
274 logger.info( "" );
275 logger.info( buffer.toString() );
276 }
277 }
278
279 @Override
280 public void forkStarted( ExecutionEvent event )
281 {
282 if ( logger.isInfoEnabled() )
283 {
284 StringBuilder buffer = new StringBuilder( 128 );
285
286 buffer.append( ">>> " );
287 append( buffer, event.getMojoExecution() );
288 append( buffer, event.getProject() );
289 buffer.append( " >>>" );
290
291 logger.info( "" );
292 logger.info( buffer.toString() );
293 }
294 }
295
296 @Override
297 public void forkSucceeded( ExecutionEvent event )
298 {
299 if ( logger.isInfoEnabled() )
300 {
301 StringBuilder buffer = new StringBuilder( 128 );
302
303 buffer.append( "<<< " );
304 append( buffer, event.getMojoExecution() );
305 append( buffer, event.getProject() );
306 buffer.append( " <<<" );
307
308 logger.info( "" );
309 logger.info( buffer.toString() );
310 }
311 }
312
313 private void append( StringBuilder buffer, MojoExecution me )
314 {
315 buffer.append( me.getArtifactId() ).append( ':' ).append( me.getVersion() );
316 buffer.append( ':' ).append( me.getGoal() );
317 if ( me.getExecutionId() != null )
318 {
319 buffer.append( " (" ).append( me.getExecutionId() ).append( ')' );
320 }
321 }
322
323 private void append( StringBuilder buffer, MavenProject project )
324 {
325 buffer.append( " @ " ).append( project.getArtifactId() );
326 }
327
328 @Override
329 public void forkedProjectStarted( ExecutionEvent event )
330 {
331 if ( logger.isInfoEnabled() && event.getMojoExecution().getForkedExecutions().size() > 1 )
332 {
333 logger.info( chars( ' ', LINE_LENGTH ) );
334 logger.info( chars( '>', LINE_LENGTH ) );
335
336 logger.info( "Forking " + event.getProject().getName() + " " + event.getProject().getVersion() );
337
338 logger.info( chars( '>', LINE_LENGTH ) );
339 }
340 }
341
342 }