1 package org.apache.maven;
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
23 import org.apache.maven.artifact.manager.WagonManager;
24 import org.apache.maven.artifact.repository.ArtifactRepository;
25 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
26 import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
27 import org.apache.maven.execution.BuildFailure;
28 import org.apache.maven.execution.DefaultMavenExecutionRequest;
29 import org.apache.maven.execution.MavenExecutionRequest;
30 import org.apache.maven.execution.MavenSession;
31 import org.apache.maven.execution.ReactorManager;
32 import org.apache.maven.execution.RuntimeInformation;
33 import org.apache.maven.lifecycle.LifecycleExecutionException;
34 import org.apache.maven.lifecycle.LifecycleExecutor;
35 import org.apache.maven.monitor.event.DefaultEventDispatcher;
36 import org.apache.maven.monitor.event.EventDispatcher;
37 import org.apache.maven.monitor.event.MavenEvents;
38 import org.apache.maven.profiles.ProfileManager;
39 import org.apache.maven.profiles.activation.ProfileActivationException;
40 import org.apache.maven.project.DefaultProjectBuilderConfiguration;
41 import org.apache.maven.project.DuplicateProjectException;
42 import org.apache.maven.project.MavenProject;
43 import org.apache.maven.project.MavenProjectBuilder;
44 import org.apache.maven.project.ProjectBuilderConfiguration;
45 import org.apache.maven.project.ProjectBuildingException;
46 import org.apache.maven.reactor.MavenExecutionException;
47 import org.apache.maven.settings.Mirror;
48 import org.apache.maven.settings.Proxy;
49 import org.apache.maven.settings.Server;
50 import org.apache.maven.settings.Settings;
51 import org.apache.maven.usability.SystemWarnings;
52 import org.apache.maven.usability.diagnostics.ErrorDiagnostics;
53 import org.apache.maven.wagon.repository.RepositoryPermissions;
54 import org.codehaus.plexus.PlexusConstants;
55 import org.codehaus.plexus.PlexusContainer;
56 import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
57 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
58 import org.codehaus.plexus.context.Context;
59 import org.codehaus.plexus.context.ContextException;
60 import org.codehaus.plexus.logging.AbstractLogEnabled;
61 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
62 import org.codehaus.plexus.util.FileUtils;
63 import org.codehaus.plexus.util.Os;
64 import org.codehaus.plexus.util.StringUtils;
65 import org.codehaus.plexus.util.dag.CycleDetectedException;
66 import org.codehaus.plexus.util.xml.Xpp3Dom;
67
68 import java.io.File;
69 import java.io.IOException;
70 import java.text.DateFormat;
71 import java.text.SimpleDateFormat;
72 import java.util.ArrayList;
73 import java.util.Collections;
74 import java.util.Date;
75 import java.util.Iterator;
76 import java.util.List;
77 import java.util.Properties;
78 import java.util.TimeZone;
79
80 /**
81 * @author <a href="mailto:jason@maven.org">Jason van Zyl </a>
82 * @version $Id: DefaultMaven.java 642024 2008-03-27 23:30:59Z jdcasey $
83 */
84 public class DefaultMaven
85 extends AbstractLogEnabled
86 implements Maven, Contextualizable
87 {
88 // ----------------------------------------------------------------------
89 // Components
90 // ----------------------------------------------------------------------
91
92 protected MavenProjectBuilder projectBuilder;
93
94 protected LifecycleExecutor lifecycleExecutor;
95
96 protected PlexusContainer container;
97
98 protected ErrorDiagnostics errorDiagnostics;
99
100 protected RuntimeInformation runtimeInformation;
101
102 private static final long MB = 1024 * 1024;
103
104 private static final int MS_PER_SEC = 1000;
105
106 private static final int SEC_PER_MIN = 60;
107
108 // ----------------------------------------------------------------------
109 // Project execution
110 // ----------------------------------------------------------------------
111
112 public void execute( MavenExecutionRequest request )
113 throws MavenExecutionException
114 {
115 // if ( request.getLocalRepository() == null )
116 // {
117 // request.setLocalRepository( mavenTools.createLocalRepository( request.getLocalRepositoryPath() ) );
118 // }
119
120 EventDispatcher dispatcher = request.getEventDispatcher();
121
122 String event = MavenEvents.REACTOR_EXECUTION;
123
124 dispatcher.dispatchStart( event, request.getBaseDirectory() );
125
126 ReactorManager rm;
127 try
128 {
129 rm = doExecute( request, dispatcher );
130 }
131 catch ( LifecycleExecutionException e )
132 {
133 dispatcher.dispatchError( event, request.getBaseDirectory(), e );
134
135 logError( e, request.isShowErrors() );
136
137 stats( request.getStartTime() );
138
139 line();
140
141 throw new MavenExecutionException( e.getMessage(), e );
142 }
143 catch ( BuildFailureException e )
144 {
145 dispatcher.dispatchError( event, request.getBaseDirectory(), e );
146
147 logFailure( e, request.isShowErrors() );
148
149 stats( request.getStartTime() );
150
151 line();
152
153 throw new MavenExecutionException( e.getMessage(), e );
154 }
155 catch ( Throwable t )
156 {
157 dispatcher.dispatchError( event, request.getBaseDirectory(), t );
158
159 logFatal( t );
160
161 stats( request.getStartTime() );
162
163 line();
164
165 throw new MavenExecutionException( "Error executing project within the reactor", t );
166 }
167
168 // Either the build was successful, or it was a fail_at_end/fail_never reactor build
169
170 // TODO: should all the logging be left to the CLI?
171 logReactorSummary( rm );
172
173 if ( rm.hasBuildFailures() )
174 {
175 logErrors( rm, request.isShowErrors() );
176
177 if ( !ReactorManager.FAIL_NEVER.equals( rm.getFailureBehavior() ) )
178 {
179 dispatcher.dispatchError( event, request.getBaseDirectory(), null );
180
181 getLogger().info( "BUILD ERRORS" );
182
183 line();
184
185 stats( request.getStartTime() );
186
187 line();
188
189 throw new MavenExecutionException( "Some builds failed" );
190 }
191 else
192 {
193 getLogger().info( " + Ignoring failures" );
194 }
195 }
196
197 logSuccess( rm );
198
199 stats( request.getStartTime() );
200
201 line();
202
203 dispatcher.dispatchEnd( event, request.getBaseDirectory() );
204 }
205
206 private void logErrors( ReactorManager rm, boolean showErrors )
207 {
208 for ( Iterator it = rm.getSortedProjects().iterator(); it.hasNext(); )
209 {
210 MavenProject project = (MavenProject) it.next();
211
212 if ( rm.hasBuildFailure( project ) )
213 {
214 BuildFailure buildFailure = rm.getBuildFailure( project );
215
216 getLogger().info(
217 "Error for project: " + project.getName() + " (during " + buildFailure.getTask() + ")" );
218
219 line();
220
221 logDiagnostics( buildFailure.getCause() );
222
223 logTrace( buildFailure.getCause(), showErrors );
224 }
225 }
226
227 if ( !showErrors )
228 {
229 getLogger().info( "For more information, run Maven with the -e switch" );
230
231 line();
232 }
233
234 }
235
236 private ReactorManager doExecute( MavenExecutionRequest request, EventDispatcher dispatcher )
237 throws MavenExecutionException, BuildFailureException, LifecycleExecutionException
238 {
239 if ( request.getSettings().isOffline() )
240 {
241 getLogger().info( SystemWarnings.getOfflineWarning() );
242
243 WagonManager wagonManager = null;
244
245 try
246 {
247 wagonManager = (WagonManager) container.lookup( WagonManager.ROLE );
248
249 wagonManager.setOnline( false );
250 }
251 catch ( ComponentLookupException e )
252 {
253 throw new MavenExecutionException( "Cannot retrieve WagonManager in order to set offline mode.", e );
254 }
255 finally
256 {
257 try
258 {
259 container.release( wagonManager );
260 }
261 catch ( ComponentLifecycleException e )
262 {
263 getLogger().warn( "Cannot release WagonManager.", e );
264 }
265 }
266 }
267
268 try
269 {
270 resolveParameters( request.getSettings() );
271 }
272 catch ( ComponentLookupException e )
273 {
274 throw new MavenExecutionException( "Unable to configure Maven for execution", e );
275 }
276 catch ( ComponentLifecycleException e )
277 {
278 throw new MavenExecutionException( "Unable to configure Maven for execution", e );
279 }
280 catch ( SettingsConfigurationException e )
281 {
282 throw new MavenExecutionException( "Unable to configure Maven for execution", e );
283 }
284
285 ProfileManager globalProfileManager = request.getGlobalProfileManager();
286
287 globalProfileManager.loadSettingsProfiles( request.getSettings() );
288
289 getLogger().info( "Scanning for projects..." );
290
291 boolean foundProjects = true;
292 List projects = getProjects( request );
293 if ( projects.isEmpty() )
294 {
295 projects.add( getSuperProject( request ) );
296 foundProjects = false;
297 }
298
299 ReactorManager rm;
300 try
301 {
302 rm = new ReactorManager( projects );
303
304 String requestFailureBehavior = request.getFailureBehavior();
305
306 if ( requestFailureBehavior != null )
307 {
308 rm.setFailureBehavior( requestFailureBehavior );
309 }
310 }
311 catch ( CycleDetectedException e )
312 {
313 throw new BuildFailureException(
314 "The projects in the reactor contain a cyclic reference: " + e.getMessage(), e );
315 }
316 catch ( DuplicateProjectException e )
317 {
318 throw new BuildFailureException( e.getMessage(), e );
319 }
320
321 if ( rm.hasMultipleProjects() )
322 {
323 getLogger().info( "Reactor build order: " );
324
325 for ( Iterator i = rm.getSortedProjects().iterator(); i.hasNext(); )
326 {
327 MavenProject project = (MavenProject) i.next();
328 getLogger().info( " " + project.getName() );
329 }
330 }
331
332 MavenSession session = createSession( request, rm );
333
334 session.setUsingPOMsFromFilesystem( foundProjects );
335
336 lifecycleExecutor.execute( session, rm, dispatcher );
337
338 return rm;
339 }
340
341 private MavenProject getSuperProject( MavenExecutionRequest request )
342 throws MavenExecutionException
343 {
344 MavenProject superProject;
345 try
346 {
347 superProject = projectBuilder.buildStandaloneSuperProject( request.getLocalRepository(), request.getGlobalProfileManager() );
348
349 }
350 catch ( ProjectBuildingException e )
351 {
352 throw new MavenExecutionException( e.getMessage(), e );
353 }
354 return superProject;
355 }
356
357 private List getProjects( MavenExecutionRequest request )
358 throws MavenExecutionException, BuildFailureException
359 {
360 List projects;
361 try
362 {
363 List files = getProjectFiles( request );
364
365 projects = collectProjects( files, request, !request.isReactorActive() );
366
367 }
368 catch ( IOException e )
369 {
370 throw new MavenExecutionException( "Error processing projects for the reactor: " + e.getMessage(), e );
371 }
372 catch ( ArtifactResolutionException e )
373 {
374 throw new MavenExecutionException( e.getMessage(), e );
375 }
376 catch ( ProjectBuildingException e )
377 {
378 throw new MavenExecutionException( e.getMessage(), e );
379 }
380 catch ( ProfileActivationException e )
381 {
382 throw new MavenExecutionException( e.getMessage(), e );
383 }
384 return projects;
385 }
386
387 private void logReactorSummaryLine( String name, String status )
388 {
389 logReactorSummaryLine( name, status, -1 );
390 }
391
392 private void logReactorSummaryLine( String name, String status, long time )
393 {
394 StringBuffer messageBuffer = new StringBuffer();
395
396 messageBuffer.append( name );
397
398 int dotCount = 54;
399
400 dotCount -= name.length();
401
402 messageBuffer.append( " " );
403
404 for ( int i = 0; i < dotCount; i++ )
405 {
406 messageBuffer.append( '.' );
407 }
408
409 messageBuffer.append( " " );
410
411 messageBuffer.append( status );
412
413 if ( time >= 0 )
414 {
415 messageBuffer.append( " [" );
416
417 messageBuffer.append( getFormattedTime( time ) );
418
419 messageBuffer.append( "]" );
420 }
421
422 getLogger().info( messageBuffer.toString() );
423 }
424
425 private static String getFormattedTime( long time )
426 {
427 String pattern = "s.SSS's'";
428 if ( time / 60000L > 0 )
429 {
430 pattern = "m:s" + pattern;
431 if ( time / 3600000L > 0 )
432 {
433 pattern = "H:m" + pattern;
434 }
435 }
436 DateFormat fmt = new SimpleDateFormat( pattern );
437 fmt.setTimeZone( TimeZone.getTimeZone( "UTC" ) );
438 return fmt.format( new Date( time ) );
439 }
440
441 private List collectProjects( List files, MavenExecutionRequest request, boolean isRoot )
442 throws ArtifactResolutionException, ProjectBuildingException, ProfileActivationException,
443 MavenExecutionException, BuildFailureException
444 {
445 // .getLocalRepository(), request.isRecursive(),
446 // request.getSettings(), request.getUserProperties(), requ, !request.isReactorActive()
447 List projects = new ArrayList( files.size() );
448
449 for ( Iterator iterator = files.iterator(); iterator.hasNext(); )
450 {
451 File file = (File) iterator.next();
452
453 boolean usingReleasePom = false;
454
455 if ( RELEASE_POMv4.equals( file.getName() ) )
456 {
457 getLogger().info( "NOTE: Using release-pom: " + file + " in reactor build." );
458 usingReleasePom = true;
459 }
460
461 MavenProject project = getProject( file, request );
462
463 if ( isRoot )
464 {
465 project.setExecutionRoot( true );
466 }
467
468 if ( ( project.getPrerequisites() != null ) && ( project.getPrerequisites().getMaven() != null ) )
469 {
470 DefaultArtifactVersion version = new DefaultArtifactVersion( project.getPrerequisites().getMaven() );
471 if ( runtimeInformation.getApplicationVersion().compareTo( version ) < 0 )
472 {
473 throw new BuildFailureException( "Unable to build project '" + project.getFile() +
474 "; it requires Maven version " + version.toString() );
475 }
476 }
477
478 if ( ( project.getModules() != null ) && !project.getModules().isEmpty() && request.isRecursive() )
479 {
480 // TODO: Really should fail if it was not? What if it is aggregating - eg "ear"?
481 project.setPackaging( "pom" );
482
483 File basedir = file.getParentFile();
484
485 // Initial ordering is as declared in the modules section
486 List moduleFiles = new ArrayList( project.getModules().size() );
487 for ( Iterator i = project.getModules().iterator(); i.hasNext(); )
488 {
489 String name = (String) i.next();
490
491 if ( StringUtils.isEmpty( StringUtils.trim( name ) ) )
492 {
493 getLogger().warn(
494 "Empty module detected. Please check you don't have any empty module definitions in your POM." );
495
496 continue;
497 }
498
499 File moduleFile = new File( basedir, name );
500
501 if ( moduleFile.exists() && moduleFile.isDirectory() )
502 {
503 if ( usingReleasePom )
504 {
505 moduleFile = new File( basedir, name + "/" + Maven.RELEASE_POMv4 );
506 }
507 else
508 {
509 moduleFile = new File( basedir, name + "/" + Maven.POMv4 );
510 }
511 }
512
513 if ( Os.isFamily( "windows" ) )
514 {
515 // we don't canonicalize on unix to avoid interfering with symlinks
516
517 try
518 {
519 moduleFile = moduleFile.getCanonicalFile();
520 }
521 catch ( IOException e )
522 {
523 throw new MavenExecutionException( "Unable to canonicalize file name " + moduleFile, e );
524 }
525 }
526 else
527 {
528 moduleFile = new File( moduleFile.toURI().normalize() );
529 }
530
531 moduleFiles.add( moduleFile );
532 }
533
534 List collectedProjects =
535 collectProjects( moduleFiles, request, false );
536 projects.addAll( collectedProjects );
537 project.setCollectedProjects( collectedProjects );
538 }
539 projects.add( project );
540 }
541
542 return projects;
543 }
544
545 /**
546 * @deprecated Use {@link DefaultMaven#getProject(File, MavenExecutionRequest)} instead.
547 */
548 public MavenProject getProject( File pom, ArtifactRepository localRepository, Settings settings,
549 Properties userProperties, ProfileManager globalProfileManager )
550 throws ProjectBuildingException, ArtifactResolutionException, ProfileActivationException
551 {
552 MavenExecutionRequest request = new DefaultMavenExecutionRequest(
553 localRepository,
554 settings,
555 new DefaultEventDispatcher(),
556 Collections.EMPTY_LIST,
557 pom.getParentFile()
558 .getAbsolutePath(),
559 globalProfileManager,
560 globalProfileManager.getRequestProperties(),
561 new Properties(), false );
562
563 return getProject( pom, request );
564 }
565
566 public MavenProject getProject( File pom, MavenExecutionRequest request )
567 throws ProjectBuildingException, ArtifactResolutionException, ProfileActivationException
568 {
569 if ( pom.exists() )
570 {
571 if ( pom.length() == 0 )
572 {
573 throw new ProjectBuildingException( "unknown", "The file " + pom.getAbsolutePath() +
574 " you specified has zero length." );
575 }
576 }
577
578 ProjectBuilderConfiguration config = new DefaultProjectBuilderConfiguration();
579 config.setLocalRepository( request.getLocalRepository() )
580 .setGlobalProfileManager( request.getGlobalProfileManager() )
581 .setUserProperties( request.getUserProperties() );
582
583 return projectBuilder.build( pom, config );
584 }
585
586 // ----------------------------------------------------------------------
587 // Methods used by all execution request handlers
588 // ----------------------------------------------------------------------
589
590 //!! We should probably have the execution request handler create the
591 // session as
592 // the session type would be specific to the request i.e. having a project
593 // or not.
594
595 protected MavenSession createSession( MavenExecutionRequest request,
596 ReactorManager rpm )
597 {
598 return new MavenSession( container, request.getSettings(), request.getLocalRepository(),
599 request.getEventDispatcher(), rpm, request.getGoals(), request.getBaseDirectory(),
600 request.getExecutionProperties(), request.getStartTime() );
601 }
602
603 /**
604 * @todo [BP] this might not be required if there is a better way to pass
605 * them in. It doesn't feel quite right.
606 * @todo [JC] we should at least provide a mapping of protocol-to-proxy for
607 * the wagons, shouldn't we?
608 */
609 private void resolveParameters( Settings settings )
610 throws ComponentLookupException, ComponentLifecycleException, SettingsConfigurationException
611 {
612 WagonManager wagonManager = (WagonManager) container.lookup( WagonManager.ROLE );
613
614 try
615 {
616 Proxy proxy = settings.getActiveProxy();
617
618 if ( proxy != null )
619 {
620 if ( proxy.getHost() == null )
621 {
622 throw new SettingsConfigurationException( "Proxy in settings.xml has no host" );
623 }
624
625 wagonManager.addProxy( proxy.getProtocol(), proxy.getHost(), proxy.getPort(), proxy.getUsername(),
626 proxy.getPassword(), proxy.getNonProxyHosts() );
627 }
628
629 for ( Iterator i = settings.getServers().iterator(); i.hasNext(); )
630 {
631 Server server = (Server) i.next();
632
633 wagonManager.addAuthenticationInfo( server.getId(), server.getUsername(), server.getPassword(),
634 server.getPrivateKey(), server.getPassphrase() );
635
636 wagonManager.addPermissionInfo( server.getId(), server.getFilePermissions(),
637 server.getDirectoryPermissions() );
638
639 if ( server.getConfiguration() != null )
640 {
641 wagonManager.addConfiguration( server.getId(), (Xpp3Dom) server.getConfiguration() );
642 }
643 }
644
645 RepositoryPermissions defaultPermissions = new RepositoryPermissions();
646
647 defaultPermissions.setDirectoryMode( "775" );
648
649 defaultPermissions.setFileMode( "664" );
650
651 wagonManager.setDefaultRepositoryPermissions( defaultPermissions );
652
653 for ( Iterator i = settings.getMirrors().iterator(); i.hasNext(); )
654 {
655 Mirror mirror = (Mirror) i.next();
656
657 wagonManager.addMirror( mirror.getId(), mirror.getMirrorOf(), mirror.getUrl() );
658 }
659 }
660 finally
661 {
662 container.release( wagonManager );
663 }
664 }
665
666 // ----------------------------------------------------------------------
667 // Lifecylce Management
668 // ----------------------------------------------------------------------
669
670 public void contextualize( Context context )
671 throws ContextException
672 {
673 container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
674 }
675
676 // ----------------------------------------------------------------------
677 // Reporting / Logging
678 // ----------------------------------------------------------------------
679
680 protected void logFatal( Throwable error )
681 {
682 line();
683
684 getLogger().error( "FATAL ERROR" );
685
686 line();
687
688 logDiagnostics( error );
689
690 logTrace( error, true );
691 }
692
693 protected void logError( Exception e, boolean showErrors )
694 {
695 line();
696
697 getLogger().error( "BUILD ERROR" );
698
699 line();
700
701 logDiagnostics( e );
702
703 logTrace( e, showErrors );
704
705 if ( !showErrors )
706 {
707 getLogger().info( "For more information, run Maven with the -e switch" );
708
709 line();
710 }
711 }
712
713 protected void logFailure( BuildFailureException e, boolean showErrors )
714 {
715 line();
716
717 getLogger().error( "BUILD FAILURE" );
718
719 line();
720
721 logDiagnostics( e );
722
723 logTrace( e, showErrors );
724
725 if ( !showErrors )
726 {
727 getLogger().info( "For more information, run Maven with the -e switch" );
728
729 line();
730 }
731 }
732
733 private void logTrace( Throwable t, boolean showErrors )
734 {
735 if ( getLogger().isDebugEnabled() )
736 {
737 getLogger().debug( "Trace", t );
738
739 line();
740 }
741 else if ( showErrors )
742 {
743 getLogger().info( "Trace", t );
744
745 line();
746 }
747 }
748
749 private void logDiagnostics( Throwable t )
750 {
751 String message = null;
752 if ( errorDiagnostics != null )
753 {
754 message = errorDiagnostics.diagnose( t );
755 }
756
757 if ( message == null )
758 {
759 message = t.getMessage();
760 }
761
762 getLogger().info( message );
763
764 line();
765 }
766
767 protected void logSuccess( ReactorManager rm )
768 {
769 line();
770
771 getLogger().info( "BUILD SUCCESSFUL" );
772
773 line();
774 }
775
776 private void logReactorSummary( ReactorManager rm )
777 {
778 if ( rm.hasMultipleProjects() && rm.executedMultipleProjects() )
779 {
780 getLogger().info( "" );
781 getLogger().info( "" );
782
783 // -------------------------
784 // Reactor Summary:
785 // -------------------------
786 // o project-name...........FAILED
787 // o project2-name..........SKIPPED (dependency build failed or was skipped)
788 // o project-3-name.........SUCCESS
789
790 line();
791 getLogger().info( "Reactor Summary:" );
792 line();
793
794 for ( Iterator it = rm.getSortedProjects().iterator(); it.hasNext(); )
795 {
796 MavenProject project = (MavenProject) it.next();
797
798 if ( rm.hasBuildFailure( project ) )
799 {
800 logReactorSummaryLine( project.getName(), "FAILED", rm.getBuildFailure( project ).getTime() );
801 }
802 else if ( rm.isBlackListed( project ) )
803 {
804 logReactorSummaryLine( project.getName(), "SKIPPED (dependency build failed or was skipped)" );
805 }
806 else if ( rm.hasBuildSuccess( project ) )
807 {
808 logReactorSummaryLine( project.getName(), "SUCCESS", rm.getBuildSuccess( project ).getTime() );
809 }
810 else
811 {
812 logReactorSummaryLine( project.getName(), "NOT BUILT" );
813 }
814 }
815 line();
816 }
817 }
818
819 protected void stats( Date start )
820 {
821 Date finish = new Date();
822
823 long time = finish.getTime() - start.getTime();
824
825 getLogger().info( "Total time: " + formatTime( time ) );
826
827 getLogger().info( "Finished at: " + finish );
828
829 //noinspection CallToSystemGC
830 System.gc();
831
832 Runtime r = Runtime.getRuntime();
833
834 getLogger().info(
835 "Final Memory: " + ( r.totalMemory() - r.freeMemory() ) / MB + "M/" + r.totalMemory() / MB + "M" );
836 }
837
838 protected void line()
839 {
840 getLogger().info( "------------------------------------------------------------------------" );
841 }
842
843 protected static String formatTime( long ms )
844 {
845 long secs = ms / MS_PER_SEC;
846
847 long min = secs / SEC_PER_MIN;
848
849 secs = secs % SEC_PER_MIN;
850
851 String msg = "";
852
853 if ( min > 1 )
854 {
855 msg = min + " minutes ";
856 }
857 else if ( min == 1 )
858 {
859 msg = "1 minute ";
860 }
861
862 if ( secs > 1 )
863 {
864 msg += secs + " seconds";
865 }
866 else if ( secs == 1 )
867 {
868 msg += "1 second";
869 }
870 else if ( min == 0 )
871 {
872 msg += "< 1 second";
873 }
874 return msg;
875 }
876
877 private List getProjectFiles( MavenExecutionRequest request )
878 throws IOException
879 {
880 List files = Collections.EMPTY_LIST;
881
882 File userDir = new File( System.getProperty( "user.dir" ) );
883 if ( request.isReactorActive() )
884 {
885 // TODO: should we now include the pom.xml in the current directory?
886 // String includes = System.getProperty( "maven.reactor.includes", "**/" + POMv4 );
887 // String excludes = System.getProperty( "maven.reactor.excludes", POMv4 );
888
889 String includes = System.getProperty( "maven.reactor.includes", "**/" + POMv4 + ",**/" + RELEASE_POMv4 );
890 String excludes = System.getProperty( "maven.reactor.excludes", POMv4 + "," + RELEASE_POMv4 );
891
892 files = FileUtils.getFiles( userDir, includes, excludes );
893
894 filterOneProjectFilePerDirectory( files );
895
896 // make sure there is consistent ordering on all platforms, rather than using the filesystem ordering
897 Collections.sort( files );
898 }
899 else if ( request.getPomFile() != null )
900 {
901 File projectFile = new File( request.getPomFile() ).getAbsoluteFile();
902
903 if ( projectFile.exists() )
904 {
905 files = Collections.singletonList( projectFile );
906 }
907 }
908 else
909 {
910 File projectFile = new File( userDir, RELEASE_POMv4 );
911
912 if ( !projectFile.exists() )
913 {
914 projectFile = new File( userDir, POMv4 );
915 }
916
917 if ( projectFile.exists() )
918 {
919 files = Collections.singletonList( projectFile );
920 }
921 }
922
923 return files;
924 }
925
926 private void filterOneProjectFilePerDirectory( List files )
927 {
928 List releaseDirs = new ArrayList();
929
930 for ( Iterator it = files.iterator(); it.hasNext(); )
931 {
932 File projectFile = (File) it.next();
933
934 if ( RELEASE_POMv4.equals( projectFile.getName() ) )
935 {
936 releaseDirs.add( projectFile.getParentFile() );
937 }
938 }
939
940 for ( Iterator it = files.iterator(); it.hasNext(); )
941 {
942 File projectFile = (File) it.next();
943
944 // remove pom.xml files where there is a sibling release-pom.xml file...
945 if ( !RELEASE_POMv4.equals( projectFile.getName() ) && releaseDirs.contains( projectFile.getParentFile() ) )
946 {
947 it.remove();
948 }
949 }
950 }
951 }