1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.lifecycle.internal;
20
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.HashSet;
27 import java.util.List;
28 import java.util.Map;
29
30 import org.apache.maven.execution.MavenSession;
31 import org.apache.maven.lifecycle.DefaultLifecycles;
32 import org.apache.maven.lifecycle.Lifecycle;
33 import org.apache.maven.lifecycle.LifecycleMappingDelegate;
34 import org.apache.maven.lifecycle.LifecycleNotFoundException;
35 import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
36 import org.apache.maven.lifecycle.MavenExecutionPlan;
37 import org.apache.maven.lifecycle.MojoExecutionConfigurator;
38 import org.apache.maven.lifecycle.internal.builder.BuilderCommon;
39 import org.apache.maven.plugin.BuildPluginManager;
40 import org.apache.maven.plugin.InvalidPluginDescriptorException;
41 import org.apache.maven.plugin.MojoExecution;
42 import org.apache.maven.plugin.MojoNotFoundException;
43 import org.apache.maven.plugin.PluginDescriptorParsingException;
44 import org.apache.maven.plugin.PluginNotFoundException;
45 import org.apache.maven.plugin.PluginResolutionException;
46 import org.apache.maven.plugin.descriptor.MojoDescriptor;
47 import org.apache.maven.plugin.descriptor.Parameter;
48 import org.apache.maven.plugin.descriptor.PluginDescriptor;
49 import org.apache.maven.plugin.lifecycle.Execution;
50 import org.apache.maven.plugin.lifecycle.Phase;
51 import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
52 import org.apache.maven.plugin.version.PluginVersionResolutionException;
53 import org.apache.maven.plugin.version.PluginVersionResolver;
54 import org.apache.maven.project.MavenProject;
55 import org.codehaus.plexus.component.annotations.Component;
56 import org.codehaus.plexus.component.annotations.Requirement;
57 import org.codehaus.plexus.util.StringUtils;
58 import org.codehaus.plexus.util.xml.Xpp3Dom;
59 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
60
61
62
63
64
65
66
67
68 @Component(role = LifecycleExecutionPlanCalculator.class)
69 public class DefaultLifecycleExecutionPlanCalculator implements LifecycleExecutionPlanCalculator {
70 @Requirement
71 private PluginVersionResolver pluginVersionResolver;
72
73 @Requirement
74 private BuildPluginManager pluginManager;
75
76 @Requirement
77 private DefaultLifecycles defaultLifeCycles;
78
79 @Requirement
80 private MojoDescriptorCreator mojoDescriptorCreator;
81
82 @Requirement
83 private LifecyclePluginResolver lifecyclePluginResolver;
84
85 @Requirement(hint = DefaultLifecycleMappingDelegate.HINT)
86 private LifecycleMappingDelegate standardDelegate;
87
88 @Requirement
89 private Map<String, LifecycleMappingDelegate> delegates;
90
91 @Requirement
92 private Map<String, MojoExecutionConfigurator> mojoExecutionConfigurators;
93
94 @SuppressWarnings({"UnusedDeclaration"})
95 public DefaultLifecycleExecutionPlanCalculator() {}
96
97
98 public DefaultLifecycleExecutionPlanCalculator(
99 BuildPluginManager pluginManager,
100 DefaultLifecycles defaultLifeCycles,
101 MojoDescriptorCreator mojoDescriptorCreator,
102 LifecyclePluginResolver lifecyclePluginResolver) {
103 this.pluginManager = pluginManager;
104 this.defaultLifeCycles = defaultLifeCycles;
105 this.mojoDescriptorCreator = mojoDescriptorCreator;
106 this.lifecyclePluginResolver = lifecyclePluginResolver;
107 this.mojoExecutionConfigurators =
108 Collections.singletonMap("default", (MojoExecutionConfigurator) new DefaultMojoExecutionConfigurator());
109 }
110
111 @Override
112 public MavenExecutionPlan calculateExecutionPlan(
113 MavenSession session, MavenProject project, List<Object> tasks, boolean setup)
114 throws PluginNotFoundException, PluginResolutionException, LifecyclePhaseNotFoundException,
115 PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException,
116 NoPluginFoundForPrefixException, LifecycleNotFoundException, PluginVersionResolutionException {
117 lifecyclePluginResolver.resolveMissingPluginVersions(project, session);
118
119 final List<MojoExecution> executions = calculateMojoExecutions(session, project, tasks);
120
121 if (setup) {
122 setupMojoExecutions(session, project, executions);
123 }
124
125 final List<ExecutionPlanItem> planItem = ExecutionPlanItem.createExecutionPlanItems(project, executions);
126
127 return new MavenExecutionPlan(planItem, defaultLifeCycles);
128 }
129
130 @Override
131 public MavenExecutionPlan calculateExecutionPlan(MavenSession session, MavenProject project, List<Object> tasks)
132 throws PluginNotFoundException, PluginResolutionException, LifecyclePhaseNotFoundException,
133 PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException,
134 NoPluginFoundForPrefixException, LifecycleNotFoundException, PluginVersionResolutionException {
135 return calculateExecutionPlan(session, project, tasks, true);
136 }
137
138 private void setupMojoExecutions(MavenSession session, MavenProject project, List<MojoExecution> mojoExecutions)
139 throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
140 MojoNotFoundException, InvalidPluginDescriptorException, NoPluginFoundForPrefixException,
141 LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException {
142 for (MojoExecution mojoExecution : mojoExecutions) {
143 setupMojoExecution(session, project, mojoExecution);
144 }
145 }
146
147 @Override
148 public void setupMojoExecution(MavenSession session, MavenProject project, MojoExecution mojoExecution)
149 throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
150 MojoNotFoundException, InvalidPluginDescriptorException, NoPluginFoundForPrefixException,
151 LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException {
152 MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
153
154 if (mojoDescriptor == null) {
155 mojoDescriptor = pluginManager.getMojoDescriptor(
156 mojoExecution.getPlugin(),
157 mojoExecution.getGoal(),
158 project.getRemotePluginRepositories(),
159 session.getRepositorySession());
160
161 mojoExecution.setMojoDescriptor(mojoDescriptor);
162 }
163
164 mojoExecutionConfigurator(mojoExecution)
165 .configure(project, mojoExecution, MojoExecution.Source.CLI.equals(mojoExecution.getSource()));
166
167 finalizeMojoConfiguration(mojoExecution);
168
169 calculateForkedExecutions(mojoExecution, session, project, new HashSet<MojoDescriptor>());
170 }
171
172 public List<MojoExecution> calculateMojoExecutions(MavenSession session, MavenProject project, List<Object> tasks)
173 throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
174 MojoNotFoundException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
175 PluginVersionResolutionException, LifecyclePhaseNotFoundException {
176 final List<MojoExecution> mojoExecutions = new ArrayList<>();
177
178 for (Object task : tasks) {
179 if (task instanceof GoalTask) {
180 String pluginGoal = ((GoalTask) task).pluginGoal;
181
182 String executionId = "default-cli";
183 int executionIdx = pluginGoal.indexOf('@');
184 if (executionIdx > 0) {
185 executionId = pluginGoal.substring(executionIdx + 1);
186 }
187
188 MojoDescriptor mojoDescriptor = mojoDescriptorCreator.getMojoDescriptor(pluginGoal, session, project);
189
190 MojoExecution mojoExecution = new MojoExecution(mojoDescriptor, executionId, MojoExecution.Source.CLI);
191
192 mojoExecutions.add(mojoExecution);
193 } else if (task instanceof LifecycleTask) {
194 String lifecyclePhase = ((LifecycleTask) task).getLifecyclePhase();
195
196 Map<String, List<MojoExecution>> phaseToMojoMapping =
197 calculateLifecycleMappings(session, project, lifecyclePhase);
198
199 for (List<MojoExecution> mojoExecutionsFromLifecycle : phaseToMojoMapping.values()) {
200 mojoExecutions.addAll(mojoExecutionsFromLifecycle);
201 }
202 } else {
203 throw new IllegalStateException("unexpected task " + task);
204 }
205 }
206 return mojoExecutions;
207 }
208
209 private Map<String, List<MojoExecution>> calculateLifecycleMappings(
210 MavenSession session, MavenProject project, String lifecyclePhase)
211 throws LifecyclePhaseNotFoundException, PluginNotFoundException, PluginResolutionException,
212 PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException {
213
214
215
216
217 Lifecycle lifecycle = defaultLifeCycles.get(lifecyclePhase);
218
219 if (lifecycle == null) {
220 throw new LifecyclePhaseNotFoundException(
221 "Unknown lifecycle phase \"" + lifecyclePhase
222 + "\". You must specify a valid lifecycle phase"
223 + " or a goal in the format <plugin-prefix>:<goal> or"
224 + " <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: "
225 + defaultLifeCycles.getLifecyclePhaseList() + ".",
226 lifecyclePhase);
227 }
228
229 LifecycleMappingDelegate delegate;
230 if (Arrays.binarySearch(DefaultLifecycles.STANDARD_LIFECYCLES, lifecycle.getId()) >= 0) {
231 delegate = standardDelegate;
232 } else {
233 delegate = delegates.get(lifecycle.getId());
234 if (delegate == null) {
235 delegate = standardDelegate;
236 }
237 }
238
239 return delegate.calculateLifecycleMappings(session, project, lifecycle, lifecyclePhase);
240 }
241
242
243
244
245
246
247
248
249 private void finalizeMojoConfiguration(MojoExecution mojoExecution) {
250 MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
251
252 Xpp3Dom executionConfiguration = mojoExecution.getConfiguration();
253 if (executionConfiguration == null) {
254 executionConfiguration = new Xpp3Dom("configuration");
255 }
256
257 Xpp3Dom defaultConfiguration = getMojoConfiguration(mojoDescriptor);
258
259 Xpp3Dom finalConfiguration = new Xpp3Dom("configuration");
260
261 if (mojoDescriptor.getParameters() != null) {
262 for (Parameter parameter : mojoDescriptor.getParameters()) {
263 Xpp3Dom parameterConfiguration = executionConfiguration.getChild(parameter.getName());
264
265 if (parameterConfiguration == null) {
266 parameterConfiguration = executionConfiguration.getChild(parameter.getAlias());
267 }
268
269 Xpp3Dom parameterDefaults = defaultConfiguration.getChild(parameter.getName());
270
271 parameterConfiguration = Xpp3Dom.mergeXpp3Dom(parameterConfiguration, parameterDefaults, Boolean.TRUE);
272
273 if (parameterConfiguration != null) {
274 parameterConfiguration = new Xpp3Dom(parameterConfiguration, parameter.getName());
275
276 if (StringUtils.isEmpty(parameterConfiguration.getAttribute("implementation"))
277 && StringUtils.isNotEmpty(parameter.getImplementation())) {
278 parameterConfiguration.setAttribute("implementation", parameter.getImplementation());
279 }
280
281 finalConfiguration.addChild(parameterConfiguration);
282 }
283 }
284 }
285
286 mojoExecution.setConfiguration(finalConfiguration);
287 }
288
289 private Xpp3Dom getMojoConfiguration(MojoDescriptor mojoDescriptor) {
290 return MojoDescriptorCreator.convert(mojoDescriptor);
291 }
292
293 @Override
294 public void calculateForkedExecutions(MojoExecution mojoExecution, MavenSession session)
295 throws MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
296 PluginDescriptorParsingException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
297 LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException {
298 calculateForkedExecutions(mojoExecution, session, session.getCurrentProject(), new HashSet<MojoDescriptor>());
299 }
300
301 private void calculateForkedExecutions(
302 MojoExecution mojoExecution,
303 MavenSession session,
304 MavenProject project,
305 Collection<MojoDescriptor> alreadyForkedExecutions)
306 throws MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
307 PluginDescriptorParsingException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
308 LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException {
309 MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
310
311 if (!mojoDescriptor.isForking()) {
312 return;
313 }
314
315 if (!alreadyForkedExecutions.add(mojoDescriptor)) {
316 return;
317 }
318
319 List<MavenProject> forkedProjects =
320 LifecycleDependencyResolver.getProjects(project, session, mojoDescriptor.isAggregator());
321
322 for (MavenProject forkedProject : forkedProjects) {
323 if (forkedProject != project) {
324 lifecyclePluginResolver.resolveMissingPluginVersions(forkedProject, session);
325 }
326
327 List<MojoExecution> forkedExecutions;
328
329 if (StringUtils.isNotEmpty(mojoDescriptor.getExecutePhase())) {
330 forkedExecutions =
331 calculateForkedLifecycle(mojoExecution, session, forkedProject, alreadyForkedExecutions);
332 } else {
333 forkedExecutions = calculateForkedGoal(mojoExecution, session, forkedProject, alreadyForkedExecutions);
334 }
335
336 mojoExecution.setForkedExecutions(BuilderCommon.getKey(forkedProject), forkedExecutions);
337 }
338
339 alreadyForkedExecutions.remove(mojoDescriptor);
340 }
341
342 private List<MojoExecution> calculateForkedLifecycle(
343 MojoExecution mojoExecution,
344 MavenSession session,
345 MavenProject project,
346 Collection<MojoDescriptor> alreadyForkedExecutions)
347 throws MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
348 PluginDescriptorParsingException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
349 LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException {
350 MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
351
352 String forkedPhase = mojoDescriptor.getExecutePhase();
353
354 Map<String, List<MojoExecution>> lifecycleMappings = calculateLifecycleMappings(session, project, forkedPhase);
355
356 for (List<MojoExecution> forkedExecutions : lifecycleMappings.values()) {
357 for (MojoExecution forkedExecution : forkedExecutions) {
358 if (forkedExecution.getMojoDescriptor() == null) {
359 MojoDescriptor forkedMojoDescriptor = pluginManager.getMojoDescriptor(
360 forkedExecution.getPlugin(),
361 forkedExecution.getGoal(),
362 project.getRemotePluginRepositories(),
363 session.getRepositorySession());
364
365 forkedExecution.setMojoDescriptor(forkedMojoDescriptor);
366 }
367
368 mojoExecutionConfigurator(forkedExecution).configure(project, forkedExecution, false);
369 }
370 }
371
372 injectLifecycleOverlay(lifecycleMappings, mojoExecution, session, project);
373
374 List<MojoExecution> mojoExecutions = new ArrayList<>();
375
376 for (List<MojoExecution> forkedExecutions : lifecycleMappings.values()) {
377 for (MojoExecution forkedExecution : forkedExecutions) {
378 if (!alreadyForkedExecutions.contains(forkedExecution.getMojoDescriptor())) {
379 finalizeMojoConfiguration(forkedExecution);
380
381 calculateForkedExecutions(forkedExecution, session, project, alreadyForkedExecutions);
382
383 mojoExecutions.add(forkedExecution);
384 }
385 }
386 }
387
388 return mojoExecutions;
389 }
390
391 private void injectLifecycleOverlay(
392 Map<String, List<MojoExecution>> lifecycleMappings,
393 MojoExecution mojoExecution,
394 MavenSession session,
395 MavenProject project)
396 throws PluginDescriptorParsingException, LifecycleNotFoundException, MojoNotFoundException,
397 PluginNotFoundException, PluginResolutionException, NoPluginFoundForPrefixException,
398 InvalidPluginDescriptorException, PluginVersionResolutionException {
399 MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
400
401 PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
402
403 String forkedLifecycle = mojoDescriptor.getExecuteLifecycle();
404
405 if (StringUtils.isEmpty(forkedLifecycle)) {
406 return;
407 }
408
409 org.apache.maven.plugin.lifecycle.Lifecycle lifecycleOverlay;
410
411 try {
412 lifecycleOverlay = pluginDescriptor.getLifecycleMapping(forkedLifecycle);
413 } catch (IOException | XmlPullParserException e) {
414 throw new PluginDescriptorParsingException(pluginDescriptor.getPlugin(), pluginDescriptor.getSource(), e);
415 }
416
417 if (lifecycleOverlay == null) {
418 throw new LifecycleNotFoundException(forkedLifecycle);
419 }
420
421 for (Phase phase : lifecycleOverlay.getPhases()) {
422 List<MojoExecution> forkedExecutions = lifecycleMappings.get(phase.getId());
423
424 if (forkedExecutions != null) {
425 for (Execution execution : phase.getExecutions()) {
426 for (String goal : execution.getGoals()) {
427 MojoDescriptor forkedMojoDescriptor;
428
429 if (goal.indexOf(':') < 0) {
430 forkedMojoDescriptor = pluginDescriptor.getMojo(goal);
431 if (forkedMojoDescriptor == null) {
432 throw new MojoNotFoundException(goal, pluginDescriptor);
433 }
434 } else {
435 forkedMojoDescriptor = mojoDescriptorCreator.getMojoDescriptor(goal, session, project);
436 }
437
438 MojoExecution forkedExecution =
439 new MojoExecution(forkedMojoDescriptor, mojoExecution.getExecutionId());
440
441 Xpp3Dom forkedConfiguration = (Xpp3Dom) execution.getConfiguration();
442
443 forkedExecution.setConfiguration(forkedConfiguration);
444
445 mojoExecutionConfigurator(forkedExecution).configure(project, forkedExecution, true);
446
447 forkedExecutions.add(forkedExecution);
448 }
449 }
450
451 Xpp3Dom phaseConfiguration = (Xpp3Dom) phase.getConfiguration();
452
453 if (phaseConfiguration != null) {
454 for (MojoExecution forkedExecution : forkedExecutions) {
455 Xpp3Dom forkedConfiguration = forkedExecution.getConfiguration();
456
457 forkedConfiguration = Xpp3Dom.mergeXpp3Dom(phaseConfiguration, forkedConfiguration);
458
459 forkedExecution.setConfiguration(forkedConfiguration);
460 }
461 }
462 }
463 }
464 }
465
466
467
468
469
470
471 private List<MojoExecution> calculateForkedGoal(
472 MojoExecution mojoExecution,
473 MavenSession session,
474 MavenProject project,
475 Collection<MojoDescriptor> alreadyForkedExecutions)
476 throws MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
477 PluginDescriptorParsingException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
478 LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException {
479 MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
480
481 PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
482
483 String forkedGoal = mojoDescriptor.getExecuteGoal();
484
485 MojoDescriptor forkedMojoDescriptor = pluginDescriptor.getMojo(forkedGoal);
486 if (forkedMojoDescriptor == null) {
487 throw new MojoNotFoundException(forkedGoal, pluginDescriptor);
488 }
489
490 if (alreadyForkedExecutions.contains(forkedMojoDescriptor)) {
491 return Collections.emptyList();
492 }
493
494 MojoExecution forkedExecution = new MojoExecution(forkedMojoDescriptor, forkedGoal);
495
496 mojoExecutionConfigurator(forkedExecution).configure(project, forkedExecution, true);
497
498 finalizeMojoConfiguration(forkedExecution);
499
500 calculateForkedExecutions(forkedExecution, session, project, alreadyForkedExecutions);
501
502 return Collections.singletonList(forkedExecution);
503 }
504
505 private MojoExecutionConfigurator mojoExecutionConfigurator(MojoExecution mojoExecution) {
506 String configuratorId = mojoExecution.getMojoDescriptor().getComponentConfigurator();
507 if (configuratorId == null) {
508 configuratorId = "default";
509 }
510
511 MojoExecutionConfigurator mojoExecutionConfigurator = mojoExecutionConfigurators.get(configuratorId);
512
513 if (mojoExecutionConfigurator == null) {
514
515
516
517
518 mojoExecutionConfigurator = mojoExecutionConfigurators.get("default");
519 }
520 return mojoExecutionConfigurator;
521 }
522 }