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.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
40
41
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 }