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