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