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