View Javadoc

1   package org.apache.maven.lifecycle;
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  import org.apache.maven.BuildFailureException;
23  import org.apache.maven.ConfigurationInterpolationException;
24  import org.apache.maven.ConfigurationInterpolator;
25  import org.apache.maven.artifact.handler.ArtifactHandler;
26  import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
27  import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
28  import org.apache.maven.artifact.resolver.ArtifactResolutionException;
29  import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
30  import org.apache.maven.execution.MavenSession;
31  import org.apache.maven.execution.ReactorManager;
32  import org.apache.maven.extension.ExtensionManager;
33  import org.apache.maven.lifecycle.mapping.LifecycleMapping;
34  import org.apache.maven.model.Extension;
35  import org.apache.maven.model.Plugin;
36  import org.apache.maven.model.PluginExecution;
37  import org.apache.maven.model.ReportPlugin;
38  import org.apache.maven.model.ReportSet;
39  import org.apache.maven.monitor.event.EventDispatcher;
40  import org.apache.maven.monitor.event.MavenEvents;
41  import org.apache.maven.plugin.InvalidPluginException;
42  import org.apache.maven.plugin.MojoExecution;
43  import org.apache.maven.plugin.MojoExecutionException;
44  import org.apache.maven.plugin.MojoFailureException;
45  import org.apache.maven.plugin.PluginConfigurationException;
46  import org.apache.maven.plugin.PluginManager;
47  import org.apache.maven.plugin.PluginManagerException;
48  import org.apache.maven.plugin.PluginNotFoundException;
49  import org.apache.maven.plugin.descriptor.MojoDescriptor;
50  import org.apache.maven.plugin.descriptor.PluginDescriptor;
51  import org.apache.maven.plugin.lifecycle.Execution;
52  import org.apache.maven.plugin.lifecycle.Phase;
53  import org.apache.maven.plugin.version.PluginVersionNotFoundException;
54  import org.apache.maven.plugin.version.PluginVersionResolutionException;
55  import org.apache.maven.project.MavenProject;
56  import org.apache.maven.project.MavenProjectBuilder;
57  import org.apache.maven.project.artifact.InvalidDependencyVersionException;
58  import org.apache.maven.project.interpolation.ModelInterpolationException;
59  import org.apache.maven.project.interpolation.ModelInterpolator;
60  import org.apache.maven.reporting.MavenReport;
61  import org.apache.maven.settings.Settings;
62  import org.codehaus.plexus.PlexusConstants;
63  import org.codehaus.plexus.PlexusContainer;
64  import org.codehaus.plexus.PlexusContainerException;
65  import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
66  import org.codehaus.plexus.configuration.PlexusConfiguration;
67  import org.codehaus.plexus.context.Context;
68  import org.codehaus.plexus.context.ContextException;
69  import org.codehaus.plexus.logging.AbstractLogEnabled;
70  import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
71  import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
72  import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
73  import org.codehaus.plexus.util.StringUtils;
74  import org.codehaus.plexus.util.xml.Xpp3Dom;
75  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
76  
77  import java.io.IOException;
78  import java.util.ArrayList;
79  import java.util.Collections;
80  import java.util.HashMap;
81  import java.util.Iterator;
82  import java.util.List;
83  import java.util.Map;
84  import java.util.Stack;
85  import java.util.StringTokenizer;
86  
87  /**
88   * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
89   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
90   * @version $Id: DefaultLifecycleExecutor.java 799759 2009-07-31 22:19:49Z jdcasey $
91   * @todo because of aggregation, we ended up with cli-ish stuff in here (like line() and the project logging, without much of the event handling)
92   */
93  public class DefaultLifecycleExecutor
94      extends AbstractLogEnabled
95      implements LifecycleExecutor, Initializable, Contextualizable
96  {
97      // ----------------------------------------------------------------------
98      // Components
99      // ----------------------------------------------------------------------
100 
101     private PluginManager pluginManager;
102 
103     private ExtensionManager extensionManager;
104 
105     private List lifecycles;
106 
107     private ArtifactHandlerManager artifactHandlerManager;
108 
109     private List defaultReports;
110 
111     private Map phaseToLifecycleMap;
112 
113     private MavenProjectBuilder mavenProjectBuilder;
114 
115     private ModelInterpolator modelInterpolator;
116     
117     private ConfigurationInterpolator configInterpolator;
118 
119     // ----------------------------------------------------------------------
120     //
121     // ----------------------------------------------------------------------
122 
123     /**
124      * Execute a task. Each task may be a phase in the lifecycle or the
125      * execution of a mojo.
126      *
127      * @param session
128      * @param rm
129      * @param dispatcher
130      */
131     public void execute( final MavenSession session, final ReactorManager rm, final EventDispatcher dispatcher )
132         throws BuildFailureException, LifecycleExecutionException
133     {
134         // TODO: This is dangerous, particularly when it's just a collection of loose-leaf projects being built
135         // within the same reactor (using an inclusion pattern to gather them up)...
136         MavenProject rootProject = rm.getTopLevelProject();
137 
138         List goals = session.getGoals();
139 
140         if ( goals.isEmpty() && rootProject != null )
141         {
142             String goal = rootProject.getDefaultGoal();
143 
144             if ( goal != null )
145             {
146                 goals = Collections.singletonList( goal );
147             }
148         }
149 
150         if ( goals.isEmpty() )
151         {
152             StringBuffer buffer = new StringBuffer( 1024 );
153 
154             buffer.append( "\n\n" );
155             buffer.append( "You must specify at least one goal or lifecycle phase to perform build steps.\n" );
156             buffer.append( "The following list illustrates some commonly used build commands:\n\n" );
157             buffer.append( "  mvn clean\n" );
158             buffer.append( "    Deletes any build output (e.g. class files or JARs).\n" );
159             buffer.append( "  mvn test\n" );
160             buffer.append( "    Runs the unit tests for the project.\n" );
161             buffer.append( "  mvn install\n" );
162             buffer.append( "    Copies the project artifacts into your local repository.\n" );
163             buffer.append( "  mvn deploy\n" );
164             buffer.append( "    Copies the project artifacts into the remote repository.\n" );
165             buffer.append( "  mvn site\n" );
166             buffer.append( "    Creates project documentation (e.g. reports or Javadoc).\n\n" );
167             buffer.append( "Please see\n" );
168             buffer.append( "http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html\n" );
169             buffer.append( "for a complete description of available lifecycle phases.\n\n" );
170             buffer.append( "Use \"mvn --help\" to show general usage information about Maven's command line.\n\n" );
171 
172             throw new BuildFailureException( buffer.toString() );
173         }
174 
175         List taskSegments = segmentTaskListByAggregationNeeds( goals, session, rootProject );
176 
177         // TODO: probably don't want to do all this up front
178         findExtensions( session );
179 
180         executeTaskSegments( taskSegments, rm, session, rootProject, dispatcher );
181     }
182 
183     private void findExtensions( final MavenSession session )
184         throws LifecycleExecutionException
185     {
186         // TODO: MNG-4081. What about extensions within the current reactor??
187         Map<String, ArtifactHandler> handlers = new HashMap<String, ArtifactHandler>();
188         for ( MavenProject project : session.getSortedProjects() )
189         {
190             for ( Iterator j = project.getBuildExtensions().iterator(); j.hasNext(); )
191             {
192                 Extension extension = (Extension) j.next();
193                 try
194                 {
195                     getLogger().debug( "Adding extension: " + extension );
196                     extensionManager.addExtension( extension, project, session.getLocalRepository() );
197                 }
198                 catch ( PlexusContainerException e )
199                 {
200                     throw new LifecycleExecutionException( "Unable to initialise extensions", e );
201                 }
202                 catch ( ArtifactResolutionException e )
203                 {
204                     throw new LifecycleExecutionException( e.getMessage(), e );
205                 }
206                 catch ( ArtifactNotFoundException e )
207                 {
208                     throw new LifecycleExecutionException( e.getMessage(), e );
209                 }
210             }
211 
212         }
213         
214         extensionManager.registerWagons();
215         
216         handlers.putAll( extensionManager.getArtifactTypeHandlers() );
217 
218         for ( MavenProject project : session.getSortedProjects() )
219         {
220             try
221             {
222                 handlers.putAll( findArtifactTypeHandlersInPlugins( project, session ) );
223 
224                 // shudder...
225                 for ( ArtifactHandler handler : handlers.values() )
226                 {
227                     if ( project.getPackaging().equals( handler.getPackaging() ) )
228                     {
229                         project.getArtifact().setArtifactHandler( handler );
230                         
231                         // NOTE: Adding this (maven 2.2.1) to short-circuit things. This means first match is used, NOT LAST.
232                         break;
233                     }
234                 }
235             }
236             catch ( PluginNotFoundException e )
237             {
238                 throw new LifecycleExecutionException( e.getMessage(), e );
239             }
240         }
241         
242         artifactHandlerManager.addHandlers( handlers );
243     }
244 
245     private void executeTaskSegments( final List taskSegments, final ReactorManager rm, final MavenSession session,
246                                       final MavenProject rootProject, final EventDispatcher dispatcher )
247         throws LifecycleExecutionException, BuildFailureException
248     {
249         for ( Iterator it = taskSegments.iterator(); it.hasNext(); )
250         {
251             TaskSegment segment = (TaskSegment) it.next();
252 
253             if ( segment.aggregate() )
254             {
255                 if ( !rm.isBlackListed( rootProject ) )
256                 {
257                     line();
258 
259                     getLogger().info( "Building " + rootProject.getName() );
260 
261                     getLogger().info( "  " + segment );
262 
263                     line();
264 
265                     // !! This is ripe for refactoring to an aspect.
266                     // Event monitoring.
267                     String event = MavenEvents.PROJECT_EXECUTION;
268 
269                     long buildStartTime = System.currentTimeMillis();
270 
271                     String target = rootProject.getId() + " ( " + segment + " )";
272 
273                     dispatcher.dispatchStart( event, target );
274 
275                     try
276                     {
277                         session.setCurrentProject( rootProject );
278 
279                         // only call once, with the top-level project (assumed to be provided as a parameter)...
280                         for ( Iterator goalIterator = segment.getTasks().iterator(); goalIterator.hasNext(); )
281                         {
282                             String task = (String) goalIterator.next();
283 
284                             executeGoalAndHandleFailures( task, session, rootProject, dispatcher, event, rm, buildStartTime,
285                                                           target );
286                         }
287 
288                         rm.registerBuildSuccess( rootProject, System.currentTimeMillis() - buildStartTime );
289 
290                     }
291                     finally
292                     {
293                         session.setCurrentProject( null );
294                     }
295 
296                     dispatcher.dispatchEnd( event, target );
297                 }
298                 else
299                 {
300                     line();
301 
302                     getLogger().info( "SKIPPING " + rootProject.getName() );
303 
304                     getLogger().info( "  " + segment );
305 
306                     getLogger().info(
307                         "This project has been banned from further executions due to previous failures." );
308 
309                     line();
310                 }
311             }
312             else
313             {
314                 List sortedProjects = session.getSortedProjects();
315 
316                 // iterate over projects, and execute on each...
317                 for ( Iterator projectIterator = sortedProjects.iterator(); projectIterator.hasNext(); )
318                 {
319                     MavenProject currentProject = (MavenProject) projectIterator.next();
320 
321                     if ( !rm.isBlackListed( currentProject ) )
322                     {
323                         line();
324 
325                         getLogger().info( "Building " + currentProject.getName() );
326 
327                         getLogger().info( "  " + segment );
328 
329                         line();
330 
331                         // !! This is ripe for refactoring to an aspect.
332                         // Event monitoring.
333                         String event = MavenEvents.PROJECT_EXECUTION;
334 
335                         long buildStartTime = System.currentTimeMillis();
336 
337                         String target = currentProject.getId() + " ( " + segment + " )";
338                         dispatcher.dispatchStart( event, target );
339 
340                         try
341                         {
342                             session.setCurrentProject( currentProject );
343 
344                             for ( Iterator goalIterator = segment.getTasks().iterator(); goalIterator.hasNext(); )
345                             {
346                                 String task = (String) goalIterator.next();
347 
348                                 executeGoalAndHandleFailures( task, session, currentProject, dispatcher, event, rm,
349                                                               buildStartTime, target );
350                             }
351 
352                         }
353                         finally
354                         {
355                             session.setCurrentProject( null );
356                         }
357 
358                         rm.registerBuildSuccess( currentProject, System.currentTimeMillis() - buildStartTime );
359 
360                         dispatcher.dispatchEnd( event, target );
361                     }
362                     else
363                     {
364                         line();
365 
366                         getLogger().info( "SKIPPING " + currentProject.getName() );
367 
368                         getLogger().info( "  " + segment );
369 
370                         getLogger().info(
371                             "This project has been banned from further executions due to previous failures." );
372 
373                         line();
374                     }
375                 }
376             }
377         }
378     }
379 
380     private void executeGoalAndHandleFailures( final String task, final MavenSession session, final MavenProject project,
381                                                final EventDispatcher dispatcher, final String event, final ReactorManager rm,
382                                                final long buildStartTime, final String target )
383         throws BuildFailureException, LifecycleExecutionException
384     {
385         try
386         {
387             executeGoal( task, session, project );
388         }
389         catch ( LifecycleExecutionException e )
390         {
391             dispatcher.dispatchError( event, target, e );
392 
393             if ( handleExecutionFailure( rm, project, e, task, buildStartTime ) )
394             {
395                 throw e;
396             }
397         }
398         catch ( BuildFailureException e )
399         {
400             dispatcher.dispatchError( event, target, e );
401 
402             if ( handleExecutionFailure( rm, project, e, task, buildStartTime ) )
403             {
404                 throw e;
405             }
406         }
407     }
408 
409     private boolean handleExecutionFailure( final ReactorManager rm, final MavenProject project, final Exception e, final String task,
410                                             final long buildStartTime )
411     {
412         rm.registerBuildFailure( project, e, task, System.currentTimeMillis() - buildStartTime );
413 
414         if ( ReactorManager.FAIL_FAST.equals( rm.getFailureBehavior() ) )
415         {
416             return true;
417         }
418         else if ( ReactorManager.FAIL_AT_END.equals( rm.getFailureBehavior() ) )
419         {
420             rm.blackList( project );
421         }
422         // if NEVER, don't blacklist
423         return false;
424     }
425 
426     private List segmentTaskListByAggregationNeeds( final List tasks, final MavenSession session, final MavenProject project )
427         throws LifecycleExecutionException, BuildFailureException
428     {
429         List segments = new ArrayList();
430 
431         if ( project != null )
432         {
433 
434             TaskSegment currentSegment = null;
435             for ( Iterator it = tasks.iterator(); it.hasNext(); )
436             {
437                 String task = (String) it.next();
438 
439                 // if it's a phase, then we don't need to check whether it's an aggregator.
440                 // simply add it to the current task partition.
441                 if ( getPhaseToLifecycleMap().containsKey( task ) )
442                 {
443                     if ( currentSegment != null && currentSegment.aggregate() )
444                     {
445                         segments.add( currentSegment );
446                         currentSegment = null;
447                     }
448 
449                     if ( currentSegment == null )
450                     {
451                         currentSegment = new TaskSegment();
452                     }
453 
454                     currentSegment.add( task );
455                 }
456                 else
457                 {
458                     MojoDescriptor mojo = null;
459                     try
460                     {
461                         // definitely a CLI goal, can use prefix
462                         mojo = getMojoDescriptor( task, session, project, task, true, false );
463                     }
464                     catch ( PluginNotFoundException e )
465                     {
466                         // TODO: shouldn't hit this, investigate using the same resolution logic as otheres for plugins in the reactor
467                         getLogger().info(
468                             "Cannot find mojo descriptor for: \'" + task + "\' - Treating as non-aggregator." );
469                         getLogger().debug( "", e );
470                     }
471 
472                     // if the mojo descriptor was found, determine aggregator status according to:
473                     // 1. whether the mojo declares itself an aggregator
474                     // 2. whether the mojo DOES NOT require a project to function (implicitly avoid reactor)
475                     if ( mojo != null && ( mojo.isAggregator() || !mojo.isProjectRequired() ) )
476                     {
477                         if ( currentSegment != null && !currentSegment.aggregate() )
478                         {
479                             segments.add( currentSegment );
480                             currentSegment = null;
481                         }
482 
483                         if ( currentSegment == null )
484                         {
485                             currentSegment = new TaskSegment( true );
486                         }
487 
488                         currentSegment.add( task );
489                     }
490                     else
491                     {
492                         if ( currentSegment != null && currentSegment.aggregate() )
493                         {
494                             segments.add( currentSegment );
495                             currentSegment = null;
496                         }
497 
498                         if ( currentSegment == null )
499                         {
500                             currentSegment = new TaskSegment();
501                         }
502 
503                         currentSegment.add( task );
504                     }
505                 }
506             }
507 
508             segments.add( currentSegment );
509         }
510         else
511         {
512             TaskSegment segment = new TaskSegment( false );
513             for ( Iterator i = tasks.iterator(); i.hasNext(); )
514             {
515                 segment.add( (String) i.next() );
516             }
517             segments.add( segment );
518         }
519 
520         return segments;
521     }
522 
523     private void executeGoal( final String task, final MavenSession session, final MavenProject project )
524         throws LifecycleExecutionException, BuildFailureException
525     {
526         try
527         {
528             Stack forkEntryPoints = new Stack();
529             if ( getPhaseToLifecycleMap().containsKey( task ) )
530             {
531                 Lifecycle lifecycle = getLifecycleForPhase( task );
532 
533                 // we have a lifecycle phase, so lets bind all the necessary goals
534                 Map lifecycleMappings = constructLifecycleMappings( session, task, project, lifecycle );
535                 executeGoalWithLifecycle( task, forkEntryPoints, session, lifecycleMappings, project, lifecycle );
536             }
537             else
538             {
539                 executeStandaloneGoal( task, forkEntryPoints, session, project );
540             }
541         }
542         catch ( PluginNotFoundException e )
543         {
544             throw new BuildFailureException( "A required plugin was not found: " + e.getMessage(), e );
545         }
546     }
547 
548     private void executeGoalWithLifecycle( final String task, final Stack forkEntryPoints, final MavenSession session,
549                                            final Map lifecycleMappings, final MavenProject project, final Lifecycle lifecycle )
550         throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
551     {
552         List goals = processGoalChain( task, lifecycleMappings, lifecycle );
553 
554         if ( !goals.isEmpty() )
555         {
556             executeGoals( goals, forkEntryPoints, session, project );
557         }
558         else
559         {
560             getLogger().info( "No goals needed for project - skipping" );
561         }
562     }
563 
564     private void executeStandaloneGoal( final String task, final Stack forkEntryPoints, final MavenSession session, final MavenProject project )
565         throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
566     {
567         // guaranteed to come from the CLI and not be part of a phase
568         MojoDescriptor mojoDescriptor = getMojoDescriptor( task, session, project, task, true, false );
569         executeGoals( Collections.singletonList( new MojoExecution( mojoDescriptor, MojoExecution.CLI_EXECUTION_ID ) ),
570                       forkEntryPoints, session, project );
571     }
572 
573     private void executeGoals( final List goals, final Stack forkEntryPoints, final MavenSession session, final MavenProject project )
574         throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
575     {
576         for ( Iterator i = goals.iterator(); i.hasNext(); )
577         {
578             MojoExecution mojoExecution = (MojoExecution) i.next();
579 
580             MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
581             
582             PlexusConfiguration configuration = mojoDescriptor.getMojoConfiguration();
583             boolean usesReactorProjects = mojoDescriptor.isAggregator() || usesSessionOrReactorProjects( configuration );
584             
585             if ( usesReactorProjects )
586             {
587                 calculateAllConcreteStates( session );
588             }
589             else
590             {
591                 calculateConcreteState( project, session, true );
592             }
593             
594             calculateConcreteConfiguration( mojoExecution, project, session );
595             
596             List reportExecutions = null;
597             if ( mojoDescriptor.isRequiresReports() )
598             {
599                 reportExecutions = getReportExecutions( project, forkEntryPoints, mojoExecution, session );
600             }
601             
602             boolean hasFork = false;
603             if ( mojoDescriptor.getExecutePhase() != null || mojoDescriptor.getExecuteGoal() != null )
604             {
605                 hasFork = true;
606             }
607             else if ( reportExecutions != null )
608             {
609                 for ( Iterator it = reportExecutions.iterator(); it.hasNext(); )
610                 {
611                     MojoExecution reportExecution = (MojoExecution) it.next();
612                     MojoDescriptor reportDescriptor = reportExecution.getMojoDescriptor();
613                     if ( reportDescriptor.getExecutePhase() != null || reportDescriptor.getExecuteGoal() != null )
614                     {
615                         hasFork = true;
616                     }
617                 }
618             }
619             
620             if ( hasFork )
621             {
622                 // NOTE: This must always happen, regardless of treatment of reactorProjects below, because
623                 // if we're in a forked execution right now, the current project will itself be an execution project of
624                 // something in the reactorProjects list, and won't have a next-stage executionProject created
625                 // for it otherwise, which leaves the project == null for the upcoming forked execution.
626                 createExecutionProject( project, session, true );
627                 
628                 if ( usesReactorProjects )
629                 {
630                     List reactorProjects = session.getSortedProjects();
631                     for ( Iterator it = reactorProjects.iterator(); it.hasNext(); )
632                     {
633                         MavenProject reactorProject = (MavenProject) it.next();
634                         createExecutionProject( reactorProject, session, false );
635                     }
636                 }
637             }
638 
639             if ( mojoDescriptor.getExecutePhase() != null || mojoDescriptor.getExecuteGoal() != null )
640             {
641                 forkEntryPoints.push( mojoDescriptor );
642 
643                 forkLifecycle( mojoDescriptor, forkEntryPoints, session, project, mojoExecution.getExecutionId() );
644 
645                 forkEntryPoints.pop();
646             }
647             
648             if ( mojoDescriptor.isRequiresReports() )
649             {
650                 List reports = getReports( reportExecutions, project, mojoExecution, session );
651 
652                 mojoExecution.setReports( reports );
653 
654                 for ( Iterator j = mojoExecution.getForkedExecutions().iterator(); j.hasNext(); )
655                 {
656                     MojoExecution forkedExecution = (MojoExecution) j.next();
657                     MojoDescriptor descriptor = forkedExecution.getMojoDescriptor();
658 
659                     if ( descriptor.getExecutePhase() != null )
660                     {
661                         forkEntryPoints.push( descriptor );
662 
663                         forkLifecycle( descriptor, forkEntryPoints, session, project, forkedExecution.getExecutionId() );
664 
665                         forkEntryPoints.pop();
666                     }
667                 }
668             }
669             
670             if ( hasFork )
671             {
672                 // NOTE: This must always happen, regardless of treatment of reactorProjects below, because
673                 // if we're in a forked execution right now, the current project will itself be an execution project of
674                 // something in the reactorProjects list, and may not have had its own executionProject instance reset to 
675                 // a concrete state again after the previous forked executions.
676                 calculateConcreteState( project.getExecutionProject(), session, true );
677                 
678                 // FIXME: Would be nice to find a way to cause the execution project to stay in a concrete state...
679                 // TODO: Test this! It should be fixed, but I don't want to destabilize until I have the issue I'm working on fixed.
680                 if ( usesReactorProjects )
681                 {
682                     calculateAllConcreteStates( session );
683                     List reactorProjects = session.getSortedProjects();
684                     for ( Iterator it = reactorProjects.iterator(); it.hasNext(); )
685                     {
686                         MavenProject reactorProject = (MavenProject) it.next();
687                         calculateConcreteState( reactorProject.getExecutionProject(), session, false );
688                     }
689                 }
690             }
691 
692             try
693             {
694                 pluginManager.executeMojo( project, mojoExecution, session );
695             }
696             catch ( PluginManagerException e )
697             {
698                 throw new LifecycleExecutionException( "Internal error in the plugin manager executing goal '" +
699                     mojoDescriptor.getId() + "': " + e.getMessage(), e );
700             }
701             catch ( ArtifactNotFoundException e )
702             {
703                 throw new LifecycleExecutionException( e.getMessage(), e );
704             }
705             catch ( InvalidDependencyVersionException e )
706             {
707                 throw new LifecycleExecutionException( e.getMessage(), e );
708             }
709             catch ( ArtifactResolutionException e )
710             {
711                 throw new LifecycleExecutionException( e.getMessage(), e );
712             }
713             catch ( MojoFailureException e )
714             {
715                 throw new BuildFailureException( e.getMessage(), e );
716             }
717             catch ( MojoExecutionException e )
718             {
719                 throw new LifecycleExecutionException( e.getMessage(), e );
720             }
721             catch ( PluginConfigurationException e )
722             {
723                 throw new LifecycleExecutionException( e.getMessage(), e );
724             }
725         }
726     }
727     
728     private void createExecutionProject( final MavenProject project, final MavenSession session, final boolean processProjectReferences )
729         throws LifecycleExecutionException
730     {
731         MavenProject executionProject = new MavenProject( project );
732         
733         calculateConcreteState( executionProject, session, processProjectReferences );
734         
735         project.setExecutionProject( executionProject );
736     }
737 
738     private boolean usesSessionOrReactorProjects( final PlexusConfiguration configuration )
739     {
740         String value = configuration != null ? String.valueOf( configuration ) : null;
741         
742         if ( value != null )
743         {
744             if ( value.indexOf( "${session" ) > -1 || value.indexOf( "${reactorProjects}" ) > -1 )
745             {
746                 return true;
747             }
748         }
749         
750         return false;
751     }
752 
753     private void calculateConcreteConfiguration( final MojoExecution mojoExecution, final MavenProject project, final MavenSession session )
754         throws LifecycleExecutionException
755     {
756         if ( mojoExecution.getConfiguration() == null )
757         {
758             return;
759         }
760         
761         try
762         {
763             mojoExecution.setConfiguration( (Xpp3Dom) configInterpolator.interpolate(
764                                                                                       mojoExecution.getConfiguration(),
765                                                                                       project,
766                                                                                       session.getProjectBuilderConfiguration() ) );
767         }
768         catch ( ConfigurationInterpolationException e )
769         {
770             throw new LifecycleExecutionException( "Error interpolating configuration for: '" + mojoExecution.getMojoDescriptor().getRoleHint() +
771                                                    "' (execution: '" + mojoExecution.getExecutionId() + "')", e );
772         }
773     }
774     
775     private void calculateAllConcreteStates( final MavenSession session )
776         throws LifecycleExecutionException
777     {
778         List projects = session.getSortedProjects();
779         if ( projects != null )
780         {
781             for ( Iterator it = projects.iterator(); it.hasNext(); )
782             {
783                 calculateConcreteState( (MavenProject) it.next(), session, false );
784             }
785         }
786     }
787 
788     private void calculateConcreteState( final MavenProject project, final MavenSession session, final boolean processReferences )
789         throws LifecycleExecutionException
790     {
791         if ( mavenProjectBuilder != null && project != null )
792         {
793             try
794             {
795                 mavenProjectBuilder.calculateConcreteState( project, session.getProjectBuilderConfiguration(), processReferences );
796             }
797             catch ( ModelInterpolationException e )
798             {
799                 throw new LifecycleExecutionException( "Failed to calculate concrete state for project: " + project,
800                                                          e );
801             }
802         }
803     }
804     
805 //    private void restoreAllDynamicStates( MavenSession session )
806 //        throws LifecycleExecutionException
807 //    {
808 //        List reactorProjects = session.getSortedProjects();
809 //        if ( reactorProjects != null )
810 //        {
811 //            for ( Iterator it = reactorProjects.iterator(); it.hasNext(); )
812 //            {
813 //                MavenProject project = (MavenProject) it.next();
814 //                restoreDynamicState( project, session, false );
815 //            }
816 //        }
817 //    }
818 //
819 //    private void restoreDynamicState( MavenProject project, MavenSession session, boolean processReferences )
820 //        throws LifecycleExecutionException
821 //    {
822 //        try
823 //        {
824 //            mavenProjectBuilder.restoreDynamicState( project, session.getProjectBuilderConfiguration(), processReferences );
825 //        }
826 //        catch ( ModelInterpolationException e )
827 //        {
828 //            throw new LifecycleExecutionException( "Failed to restore dynamic state for project: " + project, e );
829 //        }
830 //    }
831 
832     private List getReportExecutions( final MavenProject project, final Stack forkEntryPoints, final MojoExecution mojoExecution, final MavenSession session )
833         throws LifecycleExecutionException, PluginNotFoundException
834     {
835         List reportPlugins = project.getReportPlugins();
836 
837         if ( project.getModel().getReports() != null )
838         {
839             getLogger().error(
840                 "Plugin contains a <reports/> section: this is IGNORED - please use <reporting/> instead." );
841         }
842 
843         if ( project.getReporting() == null || !project.getReporting().isExcludeDefaults() )
844         {
845             if ( reportPlugins == null )
846             {
847                 reportPlugins = new ArrayList();
848             }
849             else
850             {
851                 reportPlugins = new ArrayList( reportPlugins );
852             }
853 
854             for ( Iterator i = defaultReports.iterator(); i.hasNext(); )
855             {
856                 String report = (String) i.next();
857 
858                 StringTokenizer tok = new StringTokenizer( report, ":" );
859                 int count = tok.countTokens();
860                 if ( count != 2 && count != 3 )
861                 {
862                     getLogger().warn( "Invalid default report ignored: '" + report + "' (must be groupId:artifactId[:version])" );
863                 }
864                 else
865                 {
866                     String groupId = tok.nextToken();
867                     String artifactId = tok.nextToken();
868                     String version = tok.hasMoreTokens() ? tok.nextToken() : null;
869 
870                     boolean found = false;
871                     for ( Iterator j = reportPlugins.iterator(); j.hasNext() && !found; )
872                     {
873                         ReportPlugin reportPlugin = (ReportPlugin) j.next();
874                         if ( reportPlugin.getGroupId().equals( groupId ) &&
875                             reportPlugin.getArtifactId().equals( artifactId ) )
876                         {
877                             found = true;
878                         }
879                     }
880 
881                     if ( !found )
882                     {
883                         ReportPlugin reportPlugin = new ReportPlugin();
884                         reportPlugin.setGroupId( groupId );
885                         reportPlugin.setArtifactId( artifactId );
886                         reportPlugin.setVersion( version );
887                         reportPlugins.add( reportPlugin );
888                     }
889                 }
890             }
891         }
892 
893         List reports = new ArrayList();
894         if ( reportPlugins != null )
895         {
896             for ( Iterator it = reportPlugins.iterator(); it.hasNext(); )
897             {
898                 ReportPlugin reportPlugin = (ReportPlugin) it.next();
899 
900                 List reportSets = reportPlugin.getReportSets();
901 
902                 if ( reportSets == null || reportSets.isEmpty() )
903                 {
904                     reports.addAll( getReportExecutions( reportPlugin, forkEntryPoints, null, project, session, mojoExecution ) );
905                 }
906                 else
907                 {
908                     for ( Iterator j = reportSets.iterator(); j.hasNext(); )
909                     {
910                         ReportSet reportSet = (ReportSet) j.next();
911 
912                         reports.addAll( getReportExecutions( reportPlugin, forkEntryPoints, reportSet, project, session, mojoExecution ) );
913                     }
914                 }
915             }
916         }
917         return reports;
918     }
919     
920     private List getReportExecutions( final ReportPlugin reportPlugin,
921                              final Stack forkEntryPoints,
922                              final ReportSet reportSet,
923                              final MavenProject project,
924                              final MavenSession session,
925                              final MojoExecution mojoExecution )
926         throws LifecycleExecutionException, PluginNotFoundException
927     {
928         PluginDescriptor pluginDescriptor = verifyReportPlugin( reportPlugin, project, session );
929 
930         List reports = new ArrayList();
931         for ( Iterator i = pluginDescriptor.getMojos().iterator(); i.hasNext(); )
932         {
933             MojoDescriptor mojoDescriptor = (MojoDescriptor) i.next();
934             if ( forkEntryPoints.contains( mojoDescriptor ) )
935             {
936                 getLogger().debug( "Omitting report: " + mojoDescriptor.getFullGoalName() + " from reports list. It initiated part of the fork currently executing." );
937                 continue;
938             }
939 
940             // TODO: check ID is correct for reports
941             // if the POM configured no reports, give all from plugin
942             if ( reportSet == null || reportSet.getReports().contains( mojoDescriptor.getGoal() ) )
943             {
944                 String id = null;
945                 if ( reportSet != null )
946                 {
947                     id = reportSet.getId();
948                 }
949                 else
950                 {
951                     id = mojoExecution.getExecutionId();
952                 }
953                 
954                 MojoExecution reportExecution;
955                 if ( id.startsWith( MojoExecution.DEFAULT_EXEC_ID_PREFIX ) )
956                 {
957                     reportExecution = new MojoExecution( mojoDescriptor );
958                 }
959                 else
960                 {
961                     reportExecution = new MojoExecution( mojoDescriptor, id );
962                 }
963 
964                 reports.add( reportExecution );
965             }
966         }
967         return reports;
968     }
969 
970     private List getReports( final List reportExecutions, final MavenProject project, final MojoExecution mojoExecution, final MavenSession session )
971         throws LifecycleExecutionException
972     {
973         List reports = new ArrayList();
974         
975         for ( Iterator it = reportExecutions.iterator(); it.hasNext(); )
976         {
977             MojoExecution reportExecution = (MojoExecution) it.next();
978             PluginDescriptor pluginDescriptor = reportExecution.getMojoDescriptor().getPluginDescriptor();
979             
980             try
981             {
982                 MavenReport reportMojo = pluginManager.getReport( project, reportExecution, session );
983 
984                 // Comes back null if it was a plugin, not a report - these are mojos in the reporting plugins that are not reports
985                 if ( reportMojo != null )
986                 {
987                     reports.add( reportMojo );
988                     mojoExecution.addMojoExecution( reportExecution );
989                 }
990             }
991             catch ( PluginManagerException e )
992             {
993                 throw new LifecycleExecutionException(
994                     "Error getting reports from the plugin '" + pluginDescriptor.getId() + "': " + e.getMessage(), e );
995             }
996             catch ( PluginConfigurationException e )
997             {
998                 throw new LifecycleExecutionException(
999                     "Error getting reports from the plugin '" + pluginDescriptor.getId() + "'", e );
1000             }
1001             catch ( ArtifactNotFoundException e )
1002             {
1003                 throw new LifecycleExecutionException( e.getMessage(), e );
1004             }
1005             catch ( ArtifactResolutionException e )
1006             {
1007                 throw new LifecycleExecutionException( e.getMessage(), e );
1008             }
1009         }
1010         
1011         return reports;
1012     }
1013 
1014     private void forkLifecycle( final MojoDescriptor mojoDescriptor, final Stack ancestorLifecycleForkers, final MavenSession session,
1015                                 final MavenProject project, final String executionId )
1016         throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
1017     {
1018         PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
1019         getLogger().info( "Preparing " + pluginDescriptor.getGoalPrefix() + ":" + mojoDescriptor.getGoal() );
1020 
1021         if ( mojoDescriptor.isAggregator() )
1022         {
1023             for ( Iterator i = session.getSortedProjects().iterator(); i.hasNext(); )
1024             {
1025                 MavenProject reactorProject = (MavenProject) i.next();
1026                 
1027                 line();
1028 
1029                 getLogger().info( "Building " + reactorProject.getName() );
1030 
1031                 line();
1032 
1033                 forkProjectLifecycle( mojoDescriptor, ancestorLifecycleForkers, session, reactorProject, executionId );
1034             }
1035         }
1036         else
1037         {
1038             forkProjectLifecycle( mojoDescriptor, ancestorLifecycleForkers, session, project, executionId );
1039         }
1040     }
1041 
1042     private void forkProjectLifecycle( final MojoDescriptor mojoDescriptor, final Stack forkEntryPoints, final MavenSession session,
1043                                        MavenProject project, final String executionId )
1044         throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
1045     {
1046         project = project.getExecutionProject();
1047         
1048         forkEntryPoints.push( mojoDescriptor );
1049 
1050         PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
1051 
1052         String targetPhase = mojoDescriptor.getExecutePhase();
1053 
1054         Map lifecycleMappings = null;
1055         if ( targetPhase != null )
1056         {
1057             Lifecycle lifecycle = getLifecycleForPhase( targetPhase );
1058 
1059             // Create new lifecycle
1060             lifecycleMappings = constructLifecycleMappings( session, targetPhase, project, lifecycle );
1061 
1062             String executeLifecycle = mojoDescriptor.getExecuteLifecycle();
1063             if ( executeLifecycle != null )
1064             {
1065                 org.apache.maven.plugin.lifecycle.Lifecycle lifecycleOverlay;
1066                 try
1067                 {
1068                     lifecycleOverlay = pluginDescriptor.getLifecycleMapping( executeLifecycle );
1069                 }
1070                 catch ( IOException e )
1071                 {
1072                     throw new LifecycleExecutionException( "Unable to read lifecycle mapping file: " + e.getMessage(),
1073                                                            e );
1074                 }
1075                 catch ( XmlPullParserException e )
1076                 {
1077                     throw new LifecycleExecutionException( "Unable to parse lifecycle mapping file: " + e.getMessage(),
1078                                                            e );
1079                 }
1080 
1081                 if ( lifecycleOverlay == null )
1082                 {
1083                     throw new LifecycleExecutionException( "Lifecycle '" + executeLifecycle + "' not found in plugin" );
1084                 }
1085 
1086                 for ( Iterator i = lifecycleOverlay.getPhases().iterator(); i.hasNext(); )
1087                 {
1088                     Phase phase = (Phase) i.next();
1089                     for ( Iterator j = phase.getExecutions().iterator(); j.hasNext(); )
1090                     {
1091                         Execution exec = (Execution) j.next();
1092 
1093                         for ( Iterator k = exec.getGoals().iterator(); k.hasNext(); )
1094                         {
1095                             String goal = (String) k.next();
1096 
1097                             PluginDescriptor lifecyclePluginDescriptor;
1098                             String lifecycleGoal;
1099 
1100                             // Here we are looking to see if we have a mojo from an external plugin.
1101                             // If we do then we need to lookup the plugin descriptor for the externally
1102                             // referenced plugin so that we can overly the execution into the lifecycle.
1103                             // An example of this is the corbertura plugin that needs to call the surefire
1104                             // plugin in forking mode.
1105                             //
1106                             //<phase>
1107                             //  <id>test</id>
1108                             //  <executions>
1109                             //    <execution>
1110                             //      <goals>
1111                             //        <goal>org.apache.maven.plugins:maven-surefire-plugin:test</goal>
1112                             //      </goals>
1113                             //      <configuration>
1114                             //        <classesDirectory>${project.build.directory}/generated-classes/cobertura</classesDirectory>
1115                             //        <ignoreFailures>true</ignoreFailures>
1116                             //        <forkMode>once</forkMode>
1117                             //      </configuration>
1118                             //    </execution>
1119                             //  </executions>
1120                             //</phase>
1121 
1122                             // ----------------------------------------------------------------------
1123                             //
1124                             // ----------------------------------------------------------------------
1125 
1126                             if ( goal.indexOf( ":" ) > 0 )
1127                             {
1128                                 String[] s = StringUtils.split( goal, ":" );
1129 
1130                                 String groupId = s[0];
1131                                 String artifactId = s[1];
1132                                 lifecycleGoal = s[2];
1133 
1134                                 Plugin plugin = new Plugin();
1135                                 plugin.setGroupId( groupId );
1136                                 plugin.setArtifactId( artifactId );
1137                                 lifecyclePluginDescriptor = verifyPlugin( plugin, project, session );
1138                                 if ( lifecyclePluginDescriptor == null )
1139                                 {
1140                                     throw new LifecycleExecutionException(
1141                                         "Unable to find plugin " + groupId + ":" + artifactId );
1142                                 }
1143                             }
1144                             else
1145                             {
1146                                 lifecyclePluginDescriptor = pluginDescriptor;
1147                                 lifecycleGoal = goal;
1148                             }
1149 
1150                             Xpp3Dom configuration = (Xpp3Dom) exec.getConfiguration();
1151                             // NOTE: This seems to be duplicated below. Why??
1152                             if ( phase.getConfiguration() != null )
1153                             {
1154                                 configuration = Xpp3Dom.mergeXpp3Dom( new Xpp3Dom( (Xpp3Dom) phase.getConfiguration() ),
1155                                                                       configuration );
1156                             }
1157 
1158                             MojoDescriptor desc = getMojoDescriptor( lifecyclePluginDescriptor, lifecycleGoal );
1159                             MojoExecution mojoExecution;
1160                             if ( executionId.startsWith( MojoExecution.DEFAULT_EXEC_ID_PREFIX ) )
1161                             {
1162                                 mojoExecution = new MojoExecution( desc, configuration );
1163                             }
1164                             else
1165                             {
1166                                 mojoExecution = new MojoExecution( desc, configuration, executionId );
1167                             }
1168                             
1169                             addToLifecycleMappings( lifecycleMappings, phase.getId(), mojoExecution,
1170                                                     session.getSettings() );
1171                         }
1172                     }
1173 
1174                     if ( phase.getConfiguration() != null )
1175                     {
1176                         // Merge in general configuration for a phase.
1177                         // TODO: this is all kind of backwards from the POMM. Let's align it all under 2.1.
1178                         //   We should create a new lifecycle executor for modelVersion >5.0.0
1179                         for ( Iterator j = lifecycleMappings.values().iterator(); j.hasNext(); )
1180                         {
1181                             List tasks = (List) j.next();
1182 
1183                             for ( Iterator k = tasks.iterator(); k.hasNext(); )
1184                             {
1185                                 MojoExecution exec = (MojoExecution) k.next();
1186 
1187                                 Xpp3Dom configuration = Xpp3Dom.mergeXpp3Dom(
1188                                     new Xpp3Dom( (Xpp3Dom) phase.getConfiguration() ), exec.getConfiguration() );
1189 
1190                                 exec.setConfiguration( configuration );
1191                             }
1192                         }
1193                     }
1194 
1195                 }
1196             }
1197 
1198             removeFromLifecycle( forkEntryPoints, lifecycleMappings );
1199         }
1200 
1201         if ( targetPhase != null )
1202         {
1203             Lifecycle lifecycle = getLifecycleForPhase( targetPhase );
1204 
1205             executeGoalWithLifecycle( targetPhase, forkEntryPoints, session, lifecycleMappings, project, lifecycle );
1206         }
1207         else
1208         {
1209             String goal = mojoDescriptor.getExecuteGoal();
1210             MojoDescriptor desc = getMojoDescriptor( pluginDescriptor, goal );
1211             executeGoals( Collections.singletonList( new MojoExecution( desc, goal ) ), forkEntryPoints, session, project );
1212         }
1213     }
1214 
1215     private Lifecycle getLifecycleForPhase( final String phase )
1216         throws BuildFailureException, LifecycleExecutionException
1217     {
1218         Lifecycle lifecycle = (Lifecycle) getPhaseToLifecycleMap().get( phase );
1219 
1220         if ( lifecycle == null )
1221         {
1222             throw new BuildFailureException( "Unable to find lifecycle for phase '" + phase + "'" );
1223         }
1224         return lifecycle;
1225     }
1226 
1227     private MojoDescriptor getMojoDescriptor( final PluginDescriptor pluginDescriptor, final String goal )
1228         throws LifecycleExecutionException
1229     {
1230         MojoDescriptor desc = pluginDescriptor.getMojo( goal );
1231 
1232         if ( desc == null )
1233         {
1234             String message =
1235                 "Required goal '" + goal + "' not found in plugin '" + pluginDescriptor.getGoalPrefix() + "'";
1236             int index = goal.indexOf( ':' );
1237             if ( index >= 0 )
1238             {
1239                 String prefix = goal.substring( index + 1 );
1240                 if ( prefix.equals( pluginDescriptor.getGoalPrefix() ) )
1241                 {
1242                     message = message + " (goals should not be prefixed - try '" + prefix + "')";
1243                 }
1244             }
1245             throw new LifecycleExecutionException( message );
1246         }
1247         return desc;
1248     }
1249 
1250     private void removeFromLifecycle( final Stack lifecycleForkers, final Map lifecycleMappings )
1251     {
1252         for ( Iterator lifecycleIterator = lifecycleMappings.values().iterator(); lifecycleIterator.hasNext(); )
1253         {
1254             List tasks = (List) lifecycleIterator.next();
1255 
1256             for ( Iterator taskIterator = tasks.iterator(); taskIterator.hasNext(); )
1257             {
1258                 MojoExecution execution = (MojoExecution) taskIterator.next();
1259 
1260                 if ( lifecycleForkers.contains( execution.getMojoDescriptor() ) )
1261                 {
1262                     taskIterator.remove();
1263                     getLogger().warn( "Removing: " + execution.getMojoDescriptor().getGoal()
1264                                       + " from forked lifecycle, to prevent recursive invocation." );
1265                 }
1266             }
1267         }
1268     }
1269 
1270     private Map constructLifecycleMappings( final MavenSession session, final String selectedPhase, final MavenProject project,
1271                                             final Lifecycle lifecycle )
1272         throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
1273     {
1274         // first, bind those associated with the packaging
1275         Map lifecycleMappings = bindLifecycleForPackaging( session, selectedPhase, project, lifecycle );
1276 
1277         // next, loop over plugins and for any that have a phase, bind it
1278         for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext(); )
1279         {
1280             Plugin plugin = (Plugin) i.next();
1281 
1282             bindPluginToLifecycle( plugin, session, lifecycleMappings, project );
1283         }
1284 
1285         return lifecycleMappings;
1286     }
1287 
1288     private Map bindLifecycleForPackaging( final MavenSession session, final String selectedPhase, final MavenProject project,
1289                                            final Lifecycle lifecycle )
1290         throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
1291     {
1292         Map mappings = findMappingsForLifecycle( session, project, lifecycle );
1293 
1294         List optionalMojos = findOptionalMojosForLifecycle( session, project, lifecycle );
1295 
1296         Map lifecycleMappings = new HashMap();
1297 
1298         for ( Iterator i = lifecycle.getPhases().iterator(); i.hasNext(); )
1299         {
1300             String phase = (String) i.next();
1301 
1302             String phaseTasks = (String) mappings.get( phase );
1303 
1304             if ( phaseTasks != null )
1305             {
1306                 for ( StringTokenizer tok = new StringTokenizer( phaseTasks, "," ); tok.hasMoreTokens(); )
1307                 {
1308                     String goal = tok.nextToken().trim();
1309 
1310                     // Not from the CLI, don't use prefix
1311                     MojoDescriptor mojoDescriptor = getMojoDescriptor( goal, session, project, selectedPhase, false,
1312                                                                        optionalMojos.contains( goal ) );
1313 
1314                     if ( mojoDescriptor == null )
1315                     {
1316                         continue;
1317                     }
1318 
1319                     if ( mojoDescriptor.isDirectInvocationOnly() )
1320                     {
1321                         throw new LifecycleExecutionException( "Mojo: \'" + goal +
1322                             "\' requires direct invocation. It cannot be used as part of lifecycle: \'" +
1323                             project.getPackaging() + "\'." );
1324                     }
1325 
1326                     addToLifecycleMappings( lifecycleMappings, phase, new MojoExecution( mojoDescriptor ),
1327                                             session.getSettings() );
1328                 }
1329             }
1330 
1331             if ( phase.equals( selectedPhase ) )
1332             {
1333                 break;
1334             }
1335         }
1336 
1337         return lifecycleMappings;
1338     }
1339 
1340     private Map findMappingsForLifecycle( final MavenSession session, final MavenProject project, final Lifecycle lifecycle )
1341         throws LifecycleExecutionException, PluginNotFoundException
1342     {
1343         String packaging = project.getPackaging();
1344         Map mappings = null;
1345 
1346         LifecycleMapping m = (LifecycleMapping) findExtension( project, LifecycleMapping.ROLE, packaging, session );
1347         if ( m != null )
1348         {
1349             mappings = m.getPhases( lifecycle.getId() );
1350         }
1351 
1352         Map defaultMappings = lifecycle.getDefaultPhases();
1353 
1354         if ( mappings == null )
1355         {
1356             try
1357             {
1358                 m = (LifecycleMapping) session.lookup( LifecycleMapping.ROLE, packaging );
1359                 mappings = m.getPhases( lifecycle.getId() );
1360             }
1361             catch ( ComponentLookupException e )
1362             {
1363                 if ( defaultMappings == null )
1364                 {
1365                     throw new LifecycleExecutionException(
1366                         "Cannot find lifecycle mapping for packaging: \'" + packaging + "\'.", e );
1367                 }
1368             }
1369         }
1370 
1371         if ( mappings == null )
1372         {
1373             if ( defaultMappings == null )
1374             {
1375                 throw new LifecycleExecutionException(
1376                     "Cannot find lifecycle mapping for packaging: \'" + packaging + "\', and there is no default" );
1377             }
1378             else
1379             {
1380                 mappings = defaultMappings;
1381             }
1382         }
1383 
1384         return mappings;
1385     }
1386 
1387     private List findOptionalMojosForLifecycle( final MavenSession session, final MavenProject project, final Lifecycle lifecycle )
1388         throws LifecycleExecutionException, PluginNotFoundException
1389     {
1390         String packaging = project.getPackaging();
1391         List optionalMojos = null;
1392 
1393         LifecycleMapping m = (LifecycleMapping) findExtension( project, LifecycleMapping.ROLE, packaging, session );
1394 
1395         if ( m != null )
1396         {
1397             optionalMojos = m.getOptionalMojos( lifecycle.getId() );
1398         }
1399 
1400         if ( optionalMojos == null )
1401         {
1402             try
1403             {
1404                 m = (LifecycleMapping) session.lookup( LifecycleMapping.ROLE, packaging );
1405                 optionalMojos = m.getOptionalMojos( lifecycle.getId() );
1406             }
1407             catch ( ComponentLookupException e )
1408             {
1409                 getLogger().debug( "Error looking up lifecycle mapping to retrieve optional mojos. Lifecycle ID: " +
1410                     lifecycle.getId() + ". Error: " + e.getMessage(), e );
1411             }
1412         }
1413 
1414         if ( optionalMojos == null )
1415         {
1416             optionalMojos = Collections.EMPTY_LIST;
1417         }
1418 
1419         return optionalMojos;
1420     }
1421 
1422     private Object findExtension( final MavenProject project, final String role, final String roleHint, final MavenSession session )
1423         throws LifecycleExecutionException, PluginNotFoundException
1424     {
1425         Object pluginComponent = null;
1426 
1427         for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext() && pluginComponent == null; )
1428         {
1429             Plugin plugin = (Plugin) i.next();
1430 
1431             if ( plugin.isExtensions() )
1432             {
1433                 loadPluginFully( plugin, project, session );
1434 
1435                 // TODO: if moved to the plugin manager we already have the descriptor from above and so do can lookup the container directly
1436                 try
1437                 {
1438                     pluginComponent = pluginManager.getPluginComponent( plugin, role, roleHint );
1439                 }
1440                 catch ( ComponentLookupException e )
1441                 {
1442                     getLogger().debug( "Unable to find the lifecycle component in the extension", e );
1443                 }
1444                 catch ( PluginManagerException e )
1445                 {
1446                     throw new LifecycleExecutionException(
1447                         "Error getting extensions from the plugin '" + plugin.getKey() + "': " + e.getMessage(), e );
1448                 }
1449             }
1450         }
1451         return pluginComponent;
1452     }
1453 
1454     /**
1455      * @todo Not particularly happy about this. Would like WagonManager and ArtifactTypeHandlerManager to be able to
1456      * lookup directly, or have them passed in
1457      */
1458     private Map<String, ArtifactHandler> findArtifactTypeHandlersInPlugins( final MavenProject project, final MavenSession session )
1459         throws LifecycleExecutionException, PluginNotFoundException
1460     {
1461         Map<String, ArtifactHandler> map = new HashMap<String, ArtifactHandler>();
1462         for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext(); )
1463         {
1464             Plugin plugin = (Plugin) i.next();
1465 
1466             if ( plugin.isExtensions() )
1467             {
1468                 loadPluginFully( plugin, project, session );
1469 
1470                 // TODO: if moved to the plugin manager we already have the descriptor from above and so do can lookup the container directly
1471                 try
1472                 {
1473                     Map components = pluginManager.getPluginComponents( plugin, ArtifactHandler.ROLE );
1474                     map.putAll( components );
1475                 }
1476                 catch ( ComponentLookupException e )
1477                 {
1478                     getLogger().debug( "Unable to find the lifecycle component in the extension", e );
1479                 }
1480                 catch ( PluginManagerException e )
1481                 {
1482                     throw new LifecycleExecutionException( "Error looking up available components from plugin '" +
1483                         plugin.getKey() + "': " + e.getMessage(), e );
1484                 }
1485             }
1486         }
1487         return map;
1488     }
1489 
1490     /**
1491      * Take each mojo contained with a plugin, look to see whether it contributes to a
1492      * phase in the lifecycle and if it does place it at the end of the list of goals
1493      * to execute for that given phase.
1494      *
1495      * @param project
1496      * @param session
1497      */
1498     private void bindPluginToLifecycle( final Plugin plugin, final MavenSession session, final Map phaseMap, final MavenProject project )
1499         throws LifecycleExecutionException, PluginNotFoundException
1500     {
1501         Settings settings = session.getSettings();
1502 
1503         PluginDescriptor pluginDescriptor =
1504             verifyPlugin( plugin, project, session );
1505 
1506         if ( pluginDescriptor.getMojos() != null && !pluginDescriptor.getMojos().isEmpty() )
1507         {
1508             // use the plugin if inherit was true in a base class, or it is in the current POM, otherwise use the default inheritence setting
1509             if ( plugin.isInheritanceApplied() || pluginDescriptor.isInheritedByDefault() )
1510             {
1511                 if ( plugin.getGoals() != null )
1512                 {
1513                     getLogger().error(
1514                         "Plugin contains a <goals/> section: this is IGNORED - please use <executions/> instead." );
1515                 }
1516 
1517                 List executions = plugin.getExecutions();
1518 
1519                 if ( executions != null )
1520                 {
1521                     for ( Iterator it = executions.iterator(); it.hasNext(); )
1522                     {
1523                         PluginExecution execution = (PluginExecution) it.next();
1524 
1525                         bindExecutionToLifecycle( pluginDescriptor, phaseMap, execution, settings );
1526                     }
1527                 }
1528             }
1529         }
1530     }
1531 
1532     private PluginDescriptor verifyPlugin( final Plugin plugin, final MavenProject project, final MavenSession session )
1533         throws LifecycleExecutionException, PluginNotFoundException
1534     {
1535         PluginDescriptor pluginDescriptor;
1536         try
1537         {
1538             // TODO: MNG-4081...need to flush this plugin once we look at it, to avoid using an external
1539             // version of a plugin when a newer version will be created in the current reactor...
1540             pluginDescriptor = pluginManager.loadPluginDescriptor( plugin, project, session );
1541         }
1542         catch ( PluginManagerException e )
1543         {
1544             throw new LifecycleExecutionException(
1545                 "Internal error in the plugin manager getting plugin '" + plugin.getKey() + "': " + e.getMessage(), e );
1546         }
1547         catch ( PluginVersionResolutionException e )
1548         {
1549             throw new LifecycleExecutionException( e.getMessage(), e );
1550         }
1551         catch ( InvalidVersionSpecificationException e )
1552         {
1553             throw new LifecycleExecutionException( e.getMessage(), e );
1554         }
1555         catch ( InvalidPluginException e )
1556         {
1557             throw new LifecycleExecutionException( e.getMessage(), e );
1558         }
1559         catch ( ArtifactNotFoundException e )
1560         {
1561             throw new LifecycleExecutionException( e.getMessage(), e );
1562         }
1563         catch ( ArtifactResolutionException e )
1564         {
1565             throw new LifecycleExecutionException( e.getMessage(), e );
1566         }
1567         catch ( PluginVersionNotFoundException e )
1568         {
1569             throw new LifecycleExecutionException( e.getMessage(), e );
1570         }
1571         return pluginDescriptor;
1572     }
1573 
1574     private PluginDescriptor loadPluginFully( final Plugin plugin, final MavenProject project, final MavenSession session )
1575         throws LifecycleExecutionException, PluginNotFoundException
1576     {
1577         PluginDescriptor pluginDescriptor;
1578         try
1579         {
1580             // TODO: MNG-4081...need to flush this plugin once we look at it, to avoid using an external
1581             // version of a plugin when a newer version will be created in the current reactor...
1582             pluginDescriptor = pluginManager.loadPluginFully( plugin, project, session );
1583         }
1584         catch ( PluginManagerException e )
1585         {
1586             throw new LifecycleExecutionException(
1587                 "Internal error in the plugin manager getting plugin '" + plugin.getKey() + "': " + e.getMessage(), e );
1588         }
1589         catch ( PluginVersionResolutionException e )
1590         {
1591             throw new LifecycleExecutionException( e.getMessage(), e );
1592         }
1593         catch ( InvalidVersionSpecificationException e )
1594         {
1595             throw new LifecycleExecutionException( e.getMessage(), e );
1596         }
1597         catch ( InvalidPluginException e )
1598         {
1599             throw new LifecycleExecutionException( e.getMessage(), e );
1600         }
1601         catch ( ArtifactNotFoundException e )
1602         {
1603             throw new LifecycleExecutionException( e.getMessage(), e );
1604         }
1605         catch ( ArtifactResolutionException e )
1606         {
1607             throw new LifecycleExecutionException( e.getMessage(), e );
1608         }
1609         catch ( PluginVersionNotFoundException e )
1610         {
1611             throw new LifecycleExecutionException( e.getMessage(), e );
1612         }
1613         return pluginDescriptor;
1614     }
1615 
1616     private PluginDescriptor verifyReportPlugin( final ReportPlugin plugin, final MavenProject project, final MavenSession session )
1617         throws LifecycleExecutionException, PluginNotFoundException
1618     {
1619         PluginDescriptor pluginDescriptor;
1620         try
1621         {
1622             pluginDescriptor = pluginManager.verifyReportPlugin( plugin, project, session );
1623         }
1624         catch ( PluginManagerException e )
1625         {
1626             throw new LifecycleExecutionException(
1627                 "Internal error in the plugin manager getting report '" + plugin.getKey() + "': " + e.getMessage(), e );
1628         }
1629         catch ( PluginVersionResolutionException e )
1630         {
1631             throw new LifecycleExecutionException( e.getMessage(), e );
1632         }
1633         catch ( InvalidVersionSpecificationException e )
1634         {
1635             throw new LifecycleExecutionException( e.getMessage(), e );
1636         }
1637         catch ( InvalidPluginException e )
1638         {
1639             throw new LifecycleExecutionException( e.getMessage(), e );
1640         }
1641         catch ( ArtifactNotFoundException e )
1642         {
1643             throw new LifecycleExecutionException( e.getMessage(), e );
1644         }
1645         catch ( ArtifactResolutionException e )
1646         {
1647             throw new LifecycleExecutionException( e.getMessage(), e );
1648         }
1649         catch ( PluginVersionNotFoundException e )
1650         {
1651             throw new LifecycleExecutionException( e.getMessage(), e );
1652         }
1653         return pluginDescriptor;
1654     }
1655 
1656     private void bindExecutionToLifecycle( final PluginDescriptor pluginDescriptor, final Map phaseMap, final PluginExecution execution,
1657                                            final Settings settings )
1658         throws LifecycleExecutionException
1659     {
1660         for ( Iterator i = execution.getGoals().iterator(); i.hasNext(); )
1661         {
1662             String goal = (String) i.next();
1663 
1664             MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( goal );
1665             if ( mojoDescriptor == null )
1666             {
1667                 throw new LifecycleExecutionException(
1668                     "'" + goal + "' was specified in an execution, but not found in the plugin" );
1669             }
1670 
1671             // We have to check to see that the inheritance rules have been applied before binding this mojo.
1672             if ( execution.isInheritanceApplied() || mojoDescriptor.isInheritedByDefault() )
1673             {
1674                 MojoExecution mojoExecution = new MojoExecution( mojoDescriptor, execution.getId() );
1675 
1676                 String phase = execution.getPhase();
1677 
1678                 if ( phase == null )
1679                 {
1680                     // if the phase was not in the configuration, use the phase in the descriptor
1681                     phase = mojoDescriptor.getPhase();
1682                 }
1683 
1684                 if ( phase != null )
1685                 {
1686                     if ( mojoDescriptor.isDirectInvocationOnly() )
1687                     {
1688                         throw new LifecycleExecutionException( "Mojo: \'" + goal +
1689                             "\' requires direct invocation. It cannot be used as part of the lifecycle (it was included via the POM)." );
1690                     }
1691 
1692                     addToLifecycleMappings( phaseMap, phase, mojoExecution, settings );
1693                 }
1694             }
1695         }
1696     }
1697 
1698     private void addToLifecycleMappings( final Map lifecycleMappings, final String phase, final MojoExecution mojoExecution,
1699                                          final Settings settings )
1700     {
1701         List goals = (List) lifecycleMappings.get( phase );
1702 
1703         if ( goals == null )
1704         {
1705             goals = new ArrayList();
1706             lifecycleMappings.put( phase, goals );
1707         }
1708 
1709         MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
1710         if ( settings.isOffline() && mojoDescriptor.isOnlineRequired() )
1711         {
1712             String goal = mojoDescriptor.getGoal();
1713             getLogger().warn( goal + " requires online mode, but maven is currently offline. Disabling " + goal + "." );
1714         }
1715         else
1716         {
1717             goals.add( mojoExecution );
1718         }
1719     }
1720 
1721     private List processGoalChain( final String task, final Map phaseMap, final Lifecycle lifecycle )
1722     {
1723         List goals = new ArrayList();
1724 
1725         // only execute up to the given phase
1726         int index = lifecycle.getPhases().indexOf( task );
1727 
1728         for ( int i = 0; i <= index; i++ )
1729         {
1730             String p = (String) lifecycle.getPhases().get( i );
1731 
1732             List phaseGoals = (List) phaseMap.get( p );
1733 
1734             if ( phaseGoals != null )
1735             {
1736                 goals.addAll( phaseGoals );
1737             }
1738         }
1739         return goals;
1740     }
1741 
1742     private MojoDescriptor getMojoDescriptor( final String task, final MavenSession session, final MavenProject project,
1743                                               final String invokedVia, final boolean canUsePrefix, final boolean isOptionalMojo )
1744         throws BuildFailureException, LifecycleExecutionException, PluginNotFoundException
1745     {
1746         String goal;
1747         Plugin plugin = null;
1748 
1749         PluginDescriptor pluginDescriptor = null;
1750 
1751         try
1752         {
1753             StringTokenizer tok = new StringTokenizer( task, ":" );
1754             int numTokens = tok.countTokens();
1755 
1756             if ( numTokens == 2 )
1757             {
1758                 if ( !canUsePrefix )
1759                 {
1760                     String msg = "Mapped-prefix lookup of mojos are only supported from direct invocation. " +
1761                         "Please use specification of the form groupId:artifactId[:version]:goal instead. " +
1762                         "(Offending mojo: \'" + task + "\', invoked via: \'" + invokedVia + "\')";
1763                     throw new LifecycleExecutionException( msg );
1764                 }
1765 
1766                 String prefix = tok.nextToken();
1767                 goal = tok.nextToken();
1768 
1769                 // Steps for retrieving the plugin model instance:
1770                 // 1. request directly from the plugin collector by prefix
1771                 pluginDescriptor = pluginManager.getPluginDescriptorForPrefix( prefix );
1772                 if ( pluginDescriptor != null )
1773                 {
1774                     plugin = new Plugin();
1775                     plugin.setGroupId( pluginDescriptor.getGroupId() );
1776                     plugin.setArtifactId( pluginDescriptor.getArtifactId() );
1777                     plugin.setVersion( pluginDescriptor.getVersion() );
1778                 }
1779 
1780                 // 2. search plugins in the current POM
1781                 if ( plugin == null )
1782                 {
1783                     for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext(); )
1784                     {
1785                         Plugin buildPlugin = (Plugin) i.next();
1786 
1787                         PluginDescriptor desc =
1788                             verifyPlugin( buildPlugin, project, session );
1789                         if ( prefix.equals( desc.getGoalPrefix() ) )
1790                         {
1791                             plugin = buildPlugin;
1792                             pluginDescriptor = desc;
1793                             break;
1794                         }
1795                     }
1796                 }
1797 
1798                 // 3. look in the repository via search groups
1799                 if ( plugin == null )
1800                 {
1801                     plugin = pluginManager.getPluginDefinitionForPrefix( prefix, session, project );
1802                 }
1803 
1804                 // 4. default to o.a.m.plugins and maven-<prefix>-plugin
1805                 if ( plugin == null )
1806                 {
1807                     plugin = new Plugin();
1808                     plugin.setGroupId( PluginDescriptor.getDefaultPluginGroupId() );
1809                     plugin.setArtifactId( PluginDescriptor.getDefaultPluginArtifactId( prefix ) );
1810                 }
1811             }
1812             else if ( numTokens == 3 || numTokens == 4 )
1813             {
1814                 plugin = new Plugin();
1815 
1816                 plugin.setGroupId( tok.nextToken() );
1817                 plugin.setArtifactId( tok.nextToken() );
1818 
1819                 if ( numTokens == 4 )
1820                 {
1821                     plugin.setVersion( tok.nextToken() );
1822                 }
1823 
1824                 goal = tok.nextToken();
1825             }
1826             else
1827             {
1828                 String message = "Invalid task '" + task + "': you must specify a valid lifecycle phase, or" +
1829                     " a goal in the format plugin:goal or pluginGroupId:pluginArtifactId:pluginVersion:goal";
1830                 throw new BuildFailureException( message );
1831             }
1832 
1833             if ( plugin.getVersion() == null )
1834             {
1835                 for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext(); )
1836                 {
1837                     Plugin buildPlugin = (Plugin) i.next();
1838 
1839                     if ( buildPlugin.getKey().equals( plugin.getKey() ) )
1840                     {
1841                         plugin = buildPlugin;
1842                         break;
1843                     }
1844                 }
1845 
1846                 project.injectPluginManagementInfo( plugin );
1847             }
1848 
1849             if ( pluginDescriptor == null )
1850             {
1851                 pluginDescriptor = verifyPlugin( plugin, project, session );
1852             }
1853 
1854             // this has been simplified from the old code that injected the plugin management stuff, since
1855             // pluginManagement injection is now handled by the project method.
1856             project.addPlugin( plugin );
1857 
1858             MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( goal );
1859             if ( mojoDescriptor == null )
1860             {
1861                 if ( isOptionalMojo )
1862                 {
1863                     getLogger().info( "Skipping missing optional mojo: " + task );
1864                 }
1865                 else
1866                 {
1867                     throw new BuildFailureException( "Required goal not found: " + task + " in "
1868                         + pluginDescriptor.getId() );
1869                 }
1870             }
1871 
1872             return mojoDescriptor;
1873         }
1874         catch ( PluginNotFoundException e )
1875         {
1876             if ( isOptionalMojo )
1877             {
1878                 getLogger().info( "Skipping missing optional mojo: " + task );
1879                 getLogger().debug( "Mojo: " + task + " could not be found. Reason: " + e.getMessage(), e );
1880             }
1881             else
1882             {
1883                 throw e;
1884             }
1885         }
1886 
1887         return null;
1888     }
1889 
1890     protected void line()
1891     {
1892         getLogger().info( "------------------------------------------------------------------------" );
1893     }
1894 
1895     public Map getPhaseToLifecycleMap()
1896         throws LifecycleExecutionException
1897     {
1898         if ( phaseToLifecycleMap == null )
1899         {
1900             phaseToLifecycleMap = new HashMap();
1901 
1902             for ( Iterator i = lifecycles.iterator(); i.hasNext(); )
1903             {
1904                 Lifecycle lifecycle = (Lifecycle) i.next();
1905 
1906                 for ( Iterator p = lifecycle.getPhases().iterator(); p.hasNext(); )
1907                 {
1908                     String phase = (String) p.next();
1909 
1910                     if ( phaseToLifecycleMap.containsKey( phase ) )
1911                     {
1912                         Lifecycle prevLifecycle = (Lifecycle) phaseToLifecycleMap.get( phase );
1913                         throw new LifecycleExecutionException( "Phase '" + phase +
1914                             "' is defined in more than one lifecycle: '" + lifecycle.getId() + "' and '" +
1915                             prevLifecycle.getId() + "'" );
1916                     }
1917                     else
1918                     {
1919                         phaseToLifecycleMap.put( phase, lifecycle );
1920                     }
1921                 }
1922             }
1923         }
1924         return phaseToLifecycleMap;
1925     }
1926 
1927     private static class TaskSegment
1928     {
1929         private boolean aggregate;
1930 
1931         private final List tasks = new ArrayList();
1932 
1933         TaskSegment()
1934         {
1935 
1936         }
1937 
1938         TaskSegment( final boolean aggregate )
1939         {
1940             this.aggregate = aggregate;
1941         }
1942 
1943         public String toString()
1944         {
1945             StringBuffer message = new StringBuffer();
1946 
1947             message.append( " task-segment: [" );
1948 
1949             for ( Iterator it = tasks.iterator(); it.hasNext(); )
1950             {
1951                 String task = (String) it.next();
1952 
1953                 message.append( task );
1954 
1955                 if ( it.hasNext() )
1956                 {
1957                     message.append( ", " );
1958                 }
1959             }
1960 
1961             message.append( "]" );
1962 
1963             if ( aggregate )
1964             {
1965                 message.append( " (aggregator-style)" );
1966             }
1967 
1968             return message.toString();
1969         }
1970 
1971         boolean aggregate()
1972         {
1973             return aggregate;
1974         }
1975 
1976         void add( final String task )
1977         {
1978             tasks.add( task );
1979         }
1980 
1981         List getTasks()
1982         {
1983             return tasks;
1984         }
1985     }
1986     
1987     public List getLifecycles()
1988     {
1989         return lifecycles;
1990     }
1991 
1992     // -------------------------------------------------------------------------
1993     // TODO: The methods and fields below are only needed for products like Hudson,
1994     // that provide their own LifecycleExecutor and component configuration that extend
1995     // default implementation, and which may become out-of-date as component requirements
1996     // are updated within Maven itself.
1997     public void initialize()
1998         throws InitializationException
1999     {
2000         if ( mavenProjectBuilder == null )
2001         {
2002             warnOfIncompleteComponentConfiguration( MavenProjectBuilder.ROLE );
2003             try
2004             {
2005                 mavenProjectBuilder = (MavenProjectBuilder) container.lookup( MavenProjectBuilder.ROLE );
2006             }
2007             catch ( ComponentLookupException e )
2008             {
2009                 throw new InitializationException( "Failed to lookup project builder after it was NOT injected via component requirement." );
2010             }
2011         }
2012         
2013         if ( modelInterpolator == null )
2014         {
2015             warnOfIncompleteComponentConfiguration( ModelInterpolator.ROLE );
2016             try
2017             {
2018                 modelInterpolator = (ModelInterpolator) container.lookup( ModelInterpolator.ROLE );
2019             }
2020             catch ( ComponentLookupException e )
2021             {
2022                 throw new InitializationException( "Failed to lookup model interpolator after it was NOT injected via component requirement." );
2023             }
2024         }
2025         
2026         if ( configInterpolator == null )
2027         {
2028             warnOfIncompleteComponentConfiguration( ConfigurationInterpolator.ROLE );
2029             try
2030             {
2031                 configInterpolator = (ConfigurationInterpolator) container.lookup( ConfigurationInterpolator.ROLE );
2032             }
2033             catch ( ComponentLookupException e )
2034             {
2035                 throw new InitializationException( "Failed to lookup plugin-configuration interpolator after it was NOT injected via component requirement." );
2036             }
2037         }
2038     }
2039     
2040     private void warnOfIncompleteComponentConfiguration( final String role )
2041     {
2042         StringBuffer buffer = new StringBuffer();
2043         buffer.append( "\n************ WARNING ************" );
2044         buffer.append( "\n\nThis Maven runtime contains a LifecycleExecutor component with an incomplete configuration." );
2045         buffer.append( "\n\nLifecycleExecutor class: " ).append( getClass().getName() );
2046         buffer.append( "\nMissing component requirement: " ).append( role );
2047         buffer.append( "\n" );
2048         buffer.append( "\nNOTE: This seems to be a third-party Maven derivative you are using. If so, please" );
2049         buffer.append( "\nnotify the developers for this derivative project of the problem. The Apache Maven team is not" );
2050         buffer.append( "\nresponsible for maintaining the integrity of third-party component overrides." );
2051         buffer.append( "\n\n" );
2052         
2053         getLogger().warn( buffer.toString() );
2054     }
2055 
2056     private PlexusContainer container;
2057 
2058     public void contextualize( final Context context )
2059         throws ContextException
2060     {
2061         container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
2062     }
2063 }