View Javadoc

1   package org.apache.maven.lifecycle.internal;
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 java.io.IOException;
23  import java.util.ArrayList;
24  import java.util.Collection;
25  import java.util.Collections;
26  import java.util.HashSet;
27  import java.util.LinkedHashMap;
28  import java.util.List;
29  import java.util.Map;
30  import java.util.TreeMap;
31  
32  import org.apache.maven.execution.MavenSession;
33  import org.apache.maven.lifecycle.DefaultLifecycles;
34  import org.apache.maven.lifecycle.DefaultSchedules;
35  import org.apache.maven.lifecycle.Lifecycle;
36  import org.apache.maven.lifecycle.LifecycleNotFoundException;
37  import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
38  import org.apache.maven.lifecycle.MavenExecutionPlan;
39  import org.apache.maven.model.Plugin;
40  import org.apache.maven.model.PluginExecution;
41  import org.apache.maven.plugin.BuildPluginManager;
42  import org.apache.maven.plugin.InvalidPluginDescriptorException;
43  import org.apache.maven.plugin.MojoExecution;
44  import org.apache.maven.plugin.MojoNotFoundException;
45  import org.apache.maven.plugin.PluginDescriptorParsingException;
46  import org.apache.maven.plugin.PluginNotFoundException;
47  import org.apache.maven.plugin.PluginResolutionException;
48  import org.apache.maven.plugin.descriptor.MojoDescriptor;
49  import org.apache.maven.plugin.descriptor.Parameter;
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.prefix.NoPluginFoundForPrefixException;
54  import org.apache.maven.plugin.version.PluginVersionResolutionException;
55  import org.apache.maven.plugin.version.PluginVersionResolver;
56  import org.apache.maven.project.MavenProject;
57  import org.codehaus.plexus.component.annotations.Component;
58  import org.codehaus.plexus.component.annotations.Requirement;
59  import org.codehaus.plexus.util.StringUtils;
60  import org.codehaus.plexus.util.xml.Xpp3Dom;
61  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
62  
63  /**
64   * @since 3.0
65   * @author Benjamin Bentmann
66   * @author Kristian Rosenvold (Extract class)
67   *         <p/>
68   *         NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
69   */
70  @Component( role = LifecycleExecutionPlanCalculator.class )
71  public class DefaultLifecycleExecutionPlanCalculator
72      implements LifecycleExecutionPlanCalculator
73  {
74      @Requirement
75      private PluginVersionResolver pluginVersionResolver;
76  
77      @Requirement
78      private BuildPluginManager pluginManager;
79  
80      @Requirement
81      private DefaultLifecycles defaultLifeCycles;
82  
83      @Requirement
84      private DefaultSchedules defaultSchedules;
85  
86      @Requirement
87      private MojoDescriptorCreator mojoDescriptorCreator;
88  
89      @Requirement
90      private LifecyclePluginResolver lifecyclePluginResolver;
91  
92      @SuppressWarnings( { "UnusedDeclaration" } )
93      public DefaultLifecycleExecutionPlanCalculator()
94      {
95      }
96  
97      public DefaultLifecycleExecutionPlanCalculator( BuildPluginManager pluginManager,
98                                                      DefaultLifecycles defaultLifeCycles,
99                                                      MojoDescriptorCreator mojoDescriptorCreator,
100                                                     LifecyclePluginResolver lifecyclePluginResolver,
101                                                     DefaultSchedules defaultSchedules )
102     {
103         this.pluginManager = pluginManager;
104         this.defaultLifeCycles = defaultLifeCycles;
105         this.mojoDescriptorCreator = mojoDescriptorCreator;
106         this.lifecyclePluginResolver = lifecyclePluginResolver;
107         this.defaultSchedules = defaultSchedules;
108     }
109 
110     public MavenExecutionPlan calculateExecutionPlan( MavenSession session, MavenProject project, List<Object> tasks, boolean setup )
111         throws PluginNotFoundException, PluginResolutionException, LifecyclePhaseNotFoundException,
112         PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException,
113         NoPluginFoundForPrefixException, LifecycleNotFoundException, PluginVersionResolutionException
114     {
115         lifecyclePluginResolver.resolveMissingPluginVersions( project, session );
116 
117         final List<MojoExecution> executions = calculateMojoExecutions( session, project, tasks );
118 
119         if ( setup )
120         {
121             setupMojoExecutions( session, project, executions );
122         }
123 
124         final List<ExecutionPlanItem> planItem = defaultSchedules.createExecutionPlanItem( project, executions );
125 
126         return new MavenExecutionPlan( planItem, defaultLifeCycles );
127     }
128 
129     public MavenExecutionPlan calculateExecutionPlan( MavenSession session, MavenProject project, List<Object> tasks )
130         throws PluginNotFoundException, PluginResolutionException, LifecyclePhaseNotFoundException,
131         PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException,
132         NoPluginFoundForPrefixException, LifecycleNotFoundException, PluginVersionResolutionException
133     {
134         return calculateExecutionPlan( session, project, tasks, true );
135     }
136 
137     private void setupMojoExecutions( MavenSession session, MavenProject project, List<MojoExecution> mojoExecutions )
138         throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
139         MojoNotFoundException, InvalidPluginDescriptorException, NoPluginFoundForPrefixException,
140         LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException
141     {
142         for ( MojoExecution mojoExecution : mojoExecutions )
143         {
144             setupMojoExecution( session, project, mojoExecution );
145         }
146     }
147 
148     public void setupMojoExecution( MavenSession session, MavenProject project, MojoExecution mojoExecution )
149         throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
150         MojoNotFoundException, InvalidPluginDescriptorException, NoPluginFoundForPrefixException,
151         LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException
152     {
153         MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
154 
155         if ( mojoDescriptor == null )
156         {
157             mojoDescriptor =
158                 pluginManager.getMojoDescriptor( mojoExecution.getPlugin(), mojoExecution.getGoal(),
159                                                  project.getRemotePluginRepositories(),
160                                                  session.getRepositorySession() );
161 
162             mojoExecution.setMojoDescriptor( mojoDescriptor );
163         }
164 
165         populateMojoExecutionConfiguration( project, mojoExecution,
166                                             MojoExecution.Source.CLI.equals( mojoExecution.getSource() ) );
167 
168         finalizeMojoConfiguration( mojoExecution );
169 
170         calculateForkedExecutions( mojoExecution, session, project, new HashSet<MojoDescriptor>() );
171     }
172     
173     public List<MojoExecution> calculateMojoExecutions( MavenSession session, MavenProject project,
174                                                          List<Object> tasks )
175         throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
176         MojoNotFoundException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
177         PluginVersionResolutionException, LifecyclePhaseNotFoundException
178     {
179         final List<MojoExecution> mojoExecutions = new ArrayList<MojoExecution>();
180 
181         for ( Object task : tasks )
182         {
183             if ( task instanceof GoalTask )
184             {
185                 String pluginGoal = ( (GoalTask) task ).pluginGoal;
186 
187                 MojoDescriptor mojoDescriptor = mojoDescriptorCreator.getMojoDescriptor( pluginGoal, session, project );
188 
189                 MojoExecution mojoExecution =
190                     new MojoExecution( mojoDescriptor, "default-cli", MojoExecution.Source.CLI );
191 
192                 mojoExecutions.add( mojoExecution );
193             }
194             else if ( task instanceof LifecycleTask )
195             {
196                 String lifecyclePhase = ( (LifecycleTask) task ).getLifecyclePhase();
197 
198                 Map<String, List<MojoExecution>> phaseToMojoMapping =
199                     calculateLifecycleMappings( session, project, lifecyclePhase );
200 
201                 for ( List<MojoExecution> mojoExecutionsFromLifecycle : phaseToMojoMapping.values() )
202                 {
203                     mojoExecutions.addAll( mojoExecutionsFromLifecycle );
204                 }
205             }
206             else
207             {
208                 throw new IllegalStateException( "unexpected task " + task );
209             }
210         }
211         return mojoExecutions;
212     }
213 
214     private Map<String, List<MojoExecution>> calculateLifecycleMappings( MavenSession session, MavenProject project,
215                                                                          String lifecyclePhase )
216         throws LifecyclePhaseNotFoundException, PluginNotFoundException, PluginResolutionException,
217         PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException
218     {
219         /*
220          * Determine the lifecycle that corresponds to the given phase.
221          */
222 
223         Lifecycle lifecycle = defaultLifeCycles.get( lifecyclePhase );
224 
225         if ( lifecycle == null )
226         {
227             throw new LifecyclePhaseNotFoundException( "Unknown lifecycle phase \"" + lifecyclePhase
228                 + "\". You must specify a valid lifecycle phase" + " or a goal in the format <plugin-prefix>:<goal> or"
229                 + " <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: "
230                 + defaultLifeCycles.getLifecyclePhaseList() + ".", lifecyclePhase );
231         }
232 
233         /*
234          * Initialize mapping from lifecycle phase to bound mojos. The key set of this map denotes the phases the caller
235          * is interested in, i.e. all phases up to and including the specified phase.
236          */
237 
238         Map<String, Map<Integer, List<MojoExecution>>> mappings =
239             new LinkedHashMap<String, Map<Integer, List<MojoExecution>>>();
240 
241         for ( String phase : lifecycle.getPhases() )
242         {
243             Map<Integer, List<MojoExecution>> phaseBindings = new TreeMap<Integer, List<MojoExecution>>();
244 
245             mappings.put( phase, phaseBindings );
246 
247             if ( phase.equals( lifecyclePhase ) )
248             {
249                 break;
250             }
251         }
252 
253         /*
254          * Grab plugin executions that are bound to the selected lifecycle phases from project. The effective model of
255          * the project already contains the plugin executions induced by the project's packaging type. Remember, all
256          * phases of interest and only those are in the lifecyle mapping, if a phase has no value in the map, we are not
257          * interested in any of the executions bound to it.
258          */
259 
260         for ( Plugin plugin : project.getBuild().getPlugins() )
261         {
262             for ( PluginExecution execution : plugin.getExecutions() )
263             {
264                 // if the phase is specified then I don't have to go fetch the plugin yet and pull it down
265                 // to examine the phase it is associated to.
266                 if ( execution.getPhase() != null )
267                 {
268                     Map<Integer, List<MojoExecution>> phaseBindings = mappings.get( execution.getPhase() );
269                     if ( phaseBindings != null )
270                     {
271                         for ( String goal : execution.getGoals() )
272                         {
273                             MojoExecution mojoExecution = new MojoExecution( plugin, goal, execution.getId() );
274                             mojoExecution.setLifecyclePhase( execution.getPhase() );
275                             addMojoExecution( phaseBindings, mojoExecution, execution.getPriority() );
276                         }
277                     }
278                 }
279                 // if not then i need to grab the mojo descriptor and look at the phase that is specified
280                 else
281                 {
282                     for ( String goal : execution.getGoals() )
283                     {
284                         MojoDescriptor mojoDescriptor =
285                             pluginManager.getMojoDescriptor( plugin, goal, project.getRemotePluginRepositories(),
286                                                              session.getRepositorySession() );
287 
288                         Map<Integer, List<MojoExecution>> phaseBindings = mappings.get( mojoDescriptor.getPhase() );
289                         if ( phaseBindings != null )
290                         {
291                             MojoExecution mojoExecution = new MojoExecution( mojoDescriptor, execution.getId() );
292                             mojoExecution.setLifecyclePhase( mojoDescriptor.getPhase() );
293                             addMojoExecution( phaseBindings, mojoExecution, execution.getPriority() );
294                         }
295                     }
296                 }
297             }
298         }
299 
300         Map<String, List<MojoExecution>> lifecycleMappings = new LinkedHashMap<String, List<MojoExecution>>();
301 
302         for ( Map.Entry<String, Map<Integer, List<MojoExecution>>> entry : mappings.entrySet() )
303         {
304             List<MojoExecution> mojoExecutions = new ArrayList<MojoExecution>();
305 
306             for ( List<MojoExecution> executions : entry.getValue().values() )
307             {
308                 mojoExecutions.addAll( executions );
309             }
310 
311             lifecycleMappings.put( entry.getKey(), mojoExecutions );
312         }
313 
314         return lifecycleMappings;
315     }
316 
317     private void addMojoExecution( Map<Integer, List<MojoExecution>> phaseBindings, MojoExecution mojoExecution,
318                                    int priority )
319     {
320         List<MojoExecution> mojoExecutions = phaseBindings.get( priority );
321 
322         if ( mojoExecutions == null )
323         {
324             mojoExecutions = new ArrayList<MojoExecution>();
325             phaseBindings.put( priority, mojoExecutions );
326         }
327 
328         mojoExecutions.add( mojoExecution );
329     }
330 
331     private void populateMojoExecutionConfiguration( MavenProject project, MojoExecution mojoExecution,
332                                                      boolean allowPluginLevelConfig )
333     {
334         String g = mojoExecution.getGroupId();
335 
336         String a = mojoExecution.getArtifactId();
337 
338         Plugin plugin = findPlugin( g, a, project.getBuildPlugins() );
339 
340         if ( plugin == null && project.getPluginManagement() != null )
341         {
342             plugin = findPlugin( g, a, project.getPluginManagement().getPlugins() );
343         }
344 
345         if ( plugin != null )
346         {
347             PluginExecution pluginExecution =
348                 findPluginExecution( mojoExecution.getExecutionId(), plugin.getExecutions() );
349 
350             Xpp3Dom pomConfiguration = null;
351 
352             if ( pluginExecution != null )
353             {
354                 pomConfiguration = (Xpp3Dom) pluginExecution.getConfiguration();
355             }
356             else if ( allowPluginLevelConfig )
357             {
358                 pomConfiguration = (Xpp3Dom) plugin.getConfiguration();
359             }
360 
361             Xpp3Dom mojoConfiguration = ( pomConfiguration != null ) ? new Xpp3Dom( pomConfiguration ) : null;
362 
363             mojoConfiguration = Xpp3Dom.mergeXpp3Dom( mojoExecution.getConfiguration(), mojoConfiguration );
364 
365             mojoExecution.setConfiguration( mojoConfiguration );
366         }
367     }
368 
369     private Plugin findPlugin( String groupId, String artifactId, Collection<Plugin> plugins )
370     {
371         for ( Plugin plugin : plugins )
372         {
373             if ( artifactId.equals( plugin.getArtifactId() ) && groupId.equals( plugin.getGroupId() ) )
374             {
375                 return plugin;
376             }
377         }
378 
379         return null;
380     }
381 
382     private PluginExecution findPluginExecution( String executionId, Collection<PluginExecution> executions )
383     {
384         if ( StringUtils.isNotEmpty( executionId ) )
385         {
386             for ( PluginExecution execution : executions )
387             {
388                 if ( executionId.equals( execution.getId() ) )
389                 {
390                     return execution;
391                 }
392             }
393         }
394 
395         return null;
396     }
397 
398     /**
399      * Post-processes the effective configuration for the specified mojo execution. This step discards all parameters
400      * from the configuration that are not applicable to the mojo and injects the default values for any missing
401      * parameters.
402      *
403      * @param mojoExecution The mojo execution whose configuration should be finalized, must not be {@code null}.
404      */
405     private void finalizeMojoConfiguration( MojoExecution mojoExecution )
406     {
407         MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
408 
409         Xpp3Dom executionConfiguration = mojoExecution.getConfiguration();
410         if ( executionConfiguration == null )
411         {
412             executionConfiguration = new Xpp3Dom( "configuration" );
413         }
414 
415         Xpp3Dom defaultConfiguration = getMojoConfiguration( mojoDescriptor );
416 
417         Xpp3Dom finalConfiguration = new Xpp3Dom( "configuration" );
418 
419         if ( mojoDescriptor.getParameters() != null )
420         {
421             for ( Parameter parameter : mojoDescriptor.getParameters() )
422             {
423                 Xpp3Dom parameterConfiguration = executionConfiguration.getChild( parameter.getName() );
424 
425                 if ( parameterConfiguration == null )
426                 {
427                     parameterConfiguration = executionConfiguration.getChild( parameter.getAlias() );
428                 }
429 
430                 Xpp3Dom parameterDefaults = defaultConfiguration.getChild( parameter.getName() );
431 
432                 parameterConfiguration =
433                     Xpp3Dom.mergeXpp3Dom( parameterConfiguration, parameterDefaults, Boolean.TRUE );
434 
435                 if ( parameterConfiguration != null )
436                 {
437                     parameterConfiguration = new Xpp3Dom( parameterConfiguration, parameter.getName() );
438 
439                     if ( StringUtils.isEmpty( parameterConfiguration.getAttribute( "implementation" ) )
440                         && StringUtils.isNotEmpty( parameter.getImplementation() ) )
441                     {
442                         parameterConfiguration.setAttribute( "implementation", parameter.getImplementation() );
443                     }
444 
445                     finalConfiguration.addChild( parameterConfiguration );
446                 }
447             }
448         }
449 
450         mojoExecution.setConfiguration( finalConfiguration );
451     }
452 
453     private Xpp3Dom getMojoConfiguration( MojoDescriptor mojoDescriptor )
454     {
455         return MojoDescriptorCreator.convert( mojoDescriptor );
456     }
457 
458     public void calculateForkedExecutions( MojoExecution mojoExecution, MavenSession session )
459         throws MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
460         PluginDescriptorParsingException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
461         LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException
462     {
463         calculateForkedExecutions( mojoExecution, session, session.getCurrentProject(), new HashSet<MojoDescriptor>() );
464     }
465 
466     private void calculateForkedExecutions( MojoExecution mojoExecution, MavenSession session, MavenProject project,
467                                             Collection<MojoDescriptor> alreadyForkedExecutions )
468         throws MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
469         PluginDescriptorParsingException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
470         LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException
471     {
472         MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
473 
474         if ( !mojoDescriptor.isForking() )
475         {
476             return;
477         }
478 
479         if ( !alreadyForkedExecutions.add( mojoDescriptor ) )
480         {
481             return;
482         }
483 
484         List<MavenProject> forkedProjects =
485             LifecycleDependencyResolver.getProjects( project, session, mojoDescriptor.isAggregator() );
486 
487         for ( MavenProject forkedProject : forkedProjects )
488         {
489             if ( forkedProject != project )
490             {
491                 lifecyclePluginResolver.resolveMissingPluginVersions( forkedProject, session );
492             }
493 
494             List<MojoExecution> forkedExecutions;
495 
496             if ( StringUtils.isNotEmpty( mojoDescriptor.getExecutePhase() ) )
497             {
498                 forkedExecutions =
499                     calculateForkedLifecycle( mojoExecution, session, forkedProject, alreadyForkedExecutions );
500             }
501             else
502             {
503                 forkedExecutions =
504                     calculateForkedGoal( mojoExecution, session, forkedProject, alreadyForkedExecutions );
505             }
506 
507             mojoExecution.setForkedExecutions( BuilderCommon.getKey( forkedProject ), forkedExecutions );
508         }
509 
510         alreadyForkedExecutions.remove( mojoDescriptor );
511     }
512 
513     private List<MojoExecution> calculateForkedLifecycle( MojoExecution mojoExecution, MavenSession session,
514                                                           MavenProject project,
515                                                           Collection<MojoDescriptor> alreadyForkedExecutions )
516         throws MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
517         PluginDescriptorParsingException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
518         LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException
519     {
520         MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
521 
522         String forkedPhase = mojoDescriptor.getExecutePhase();
523 
524         Map<String, List<MojoExecution>> lifecycleMappings =
525             calculateLifecycleMappings( session, project, forkedPhase );
526 
527         for ( List<MojoExecution> forkedExecutions : lifecycleMappings.values() )
528         {
529             for ( MojoExecution forkedExecution : forkedExecutions )
530             {
531                 if ( forkedExecution.getMojoDescriptor() == null )
532                 {
533                     MojoDescriptor forkedMojoDescriptor =
534                         pluginManager.getMojoDescriptor( forkedExecution.getPlugin(), forkedExecution.getGoal(),
535                                                          project.getRemotePluginRepositories(),
536                                                          session.getRepositorySession() );
537 
538                     forkedExecution.setMojoDescriptor( forkedMojoDescriptor );
539                 }
540 
541                 populateMojoExecutionConfiguration( project, forkedExecution, false );
542             }
543         }
544 
545         injectLifecycleOverlay( lifecycleMappings, mojoExecution, session, project );
546 
547         List<MojoExecution> mojoExecutions = new ArrayList<MojoExecution>();
548 
549         for ( List<MojoExecution> forkedExecutions : lifecycleMappings.values() )
550         {
551             for ( MojoExecution forkedExecution : forkedExecutions )
552             {
553                 if ( !alreadyForkedExecutions.contains( forkedExecution.getMojoDescriptor() ) )
554                 {
555                     finalizeMojoConfiguration( forkedExecution );
556 
557                     calculateForkedExecutions( forkedExecution, session, project, alreadyForkedExecutions );
558 
559                     mojoExecutions.add( forkedExecution );
560                 }
561             }
562         }
563 
564         return mojoExecutions;
565     }
566 
567     private void injectLifecycleOverlay( Map<String, List<MojoExecution>> lifecycleMappings,
568                                          MojoExecution mojoExecution, MavenSession session, MavenProject project )
569         throws PluginDescriptorParsingException, LifecycleNotFoundException, MojoNotFoundException,
570         PluginNotFoundException, PluginResolutionException, NoPluginFoundForPrefixException,
571         InvalidPluginDescriptorException, PluginVersionResolutionException
572     {
573         MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
574 
575         PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
576 
577         String forkedLifecycle = mojoDescriptor.getExecuteLifecycle();
578 
579         if ( StringUtils.isEmpty( forkedLifecycle ) )
580         {
581             return;
582         }
583 
584         org.apache.maven.plugin.lifecycle.Lifecycle lifecycleOverlay;
585 
586         try
587         {
588             lifecycleOverlay = pluginDescriptor.getLifecycleMapping( forkedLifecycle );
589         }
590         catch ( IOException e )
591         {
592             throw new PluginDescriptorParsingException( pluginDescriptor.getPlugin(), pluginDescriptor.getSource(), e );
593         }
594         catch ( XmlPullParserException e )
595         {
596             throw new PluginDescriptorParsingException( pluginDescriptor.getPlugin(), pluginDescriptor.getSource(), e );
597         }
598 
599         if ( lifecycleOverlay == null )
600         {
601             throw new LifecycleNotFoundException( forkedLifecycle );
602         }
603 
604         for ( Phase phase : lifecycleOverlay.getPhases() )
605         {
606             List<MojoExecution> forkedExecutions = lifecycleMappings.get( phase.getId() );
607 
608             if ( forkedExecutions != null )
609             {
610                 for ( Execution execution : phase.getExecutions() )
611                 {
612                     for ( String goal : execution.getGoals() )
613                     {
614                         MojoDescriptor forkedMojoDescriptor;
615 
616                         if ( goal.indexOf( ':' ) < 0 )
617                         {
618                             forkedMojoDescriptor = pluginDescriptor.getMojo( goal );
619                             if ( forkedMojoDescriptor == null )
620                             {
621                                 throw new MojoNotFoundException( goal, pluginDescriptor );
622                             }
623                         }
624                         else
625                         {
626                             forkedMojoDescriptor = mojoDescriptorCreator.getMojoDescriptor( goal, session, project );
627                         }
628 
629                         MojoExecution forkedExecution =
630                             new MojoExecution( forkedMojoDescriptor, mojoExecution.getExecutionId() );
631 
632                         Xpp3Dom forkedConfiguration = (Xpp3Dom) execution.getConfiguration();
633 
634                         forkedExecution.setConfiguration( forkedConfiguration );
635 
636                         populateMojoExecutionConfiguration( project, forkedExecution, true );
637 
638                         forkedExecutions.add( forkedExecution );
639                     }
640                 }
641 
642                 Xpp3Dom phaseConfiguration = (Xpp3Dom) phase.getConfiguration();
643 
644                 if ( phaseConfiguration != null )
645                 {
646                     for ( MojoExecution forkedExecution : forkedExecutions )
647                     {
648                         Xpp3Dom forkedConfiguration = forkedExecution.getConfiguration();
649 
650                         forkedConfiguration = Xpp3Dom.mergeXpp3Dom( phaseConfiguration, forkedConfiguration );
651 
652                         forkedExecution.setConfiguration( forkedConfiguration );
653                     }
654                 }
655             }
656         }
657     }
658     // org.apache.maven.plugins:maven-remote-resources-plugin:1.0:process
659     //TODO: take repo mans into account as one may be aggregating prefixes of many
660     //TODO: collect at the root of the repository, read the one at the root, and fetch remote if something is missing
661     //      or the user forces the issue
662 
663     private List<MojoExecution> calculateForkedGoal( MojoExecution mojoExecution, MavenSession session,
664                                                      MavenProject project,
665                                                      Collection<MojoDescriptor> alreadyForkedExecutions )
666         throws MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
667         PluginDescriptorParsingException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
668         LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException
669     {
670         MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
671 
672         PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
673 
674         String forkedGoal = mojoDescriptor.getExecuteGoal();
675 
676         MojoDescriptor forkedMojoDescriptor = pluginDescriptor.getMojo( forkedGoal );
677         if ( forkedMojoDescriptor == null )
678         {
679             throw new MojoNotFoundException( forkedGoal, pluginDescriptor );
680         }
681 
682         if ( alreadyForkedExecutions.contains( forkedMojoDescriptor ) )
683         {
684             return Collections.emptyList();
685         }
686 
687         MojoExecution forkedExecution = new MojoExecution( forkedMojoDescriptor, forkedGoal );
688 
689         populateMojoExecutionConfiguration( project, forkedExecution, true );
690 
691         finalizeMojoConfiguration( forkedExecution );
692 
693         calculateForkedExecutions( forkedExecution, session, project, alreadyForkedExecutions );
694 
695         return Collections.singletonList( forkedExecution );
696     }
697 
698 
699 }