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