View Javadoc

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