View Javadoc

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