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