1 package org.apache.maven.lifecycle;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.BuildFailureException;
23 import org.apache.maven.ConfigurationInterpolationException;
24 import org.apache.maven.ConfigurationInterpolator;
25 import org.apache.maven.artifact.handler.ArtifactHandler;
26 import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
27 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
28 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
29 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
30 import org.apache.maven.execution.MavenSession;
31 import org.apache.maven.execution.ReactorManager;
32 import org.apache.maven.extension.ExtensionManager;
33 import org.apache.maven.lifecycle.mapping.LifecycleMapping;
34 import org.apache.maven.model.Extension;
35 import org.apache.maven.model.Plugin;
36 import org.apache.maven.model.PluginExecution;
37 import org.apache.maven.model.ReportPlugin;
38 import org.apache.maven.model.ReportSet;
39 import org.apache.maven.monitor.event.EventDispatcher;
40 import org.apache.maven.monitor.event.MavenEvents;
41 import org.apache.maven.plugin.InvalidPluginException;
42 import org.apache.maven.plugin.MojoExecution;
43 import org.apache.maven.plugin.MojoExecutionException;
44 import org.apache.maven.plugin.MojoFailureException;
45 import org.apache.maven.plugin.PluginConfigurationException;
46 import org.apache.maven.plugin.PluginManager;
47 import org.apache.maven.plugin.PluginManagerException;
48 import org.apache.maven.plugin.PluginNotFoundException;
49 import org.apache.maven.plugin.descriptor.MojoDescriptor;
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.version.PluginVersionNotFoundException;
54 import org.apache.maven.plugin.version.PluginVersionResolutionException;
55 import org.apache.maven.project.MavenProject;
56 import org.apache.maven.project.MavenProjectBuilder;
57 import org.apache.maven.project.artifact.InvalidDependencyVersionException;
58 import org.apache.maven.project.interpolation.ModelInterpolationException;
59 import org.apache.maven.project.interpolation.ModelInterpolator;
60 import org.apache.maven.reporting.MavenReport;
61 import org.apache.maven.settings.Settings;
62 import org.codehaus.plexus.PlexusConstants;
63 import org.codehaus.plexus.PlexusContainer;
64 import org.codehaus.plexus.PlexusContainerException;
65 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
66 import org.codehaus.plexus.configuration.PlexusConfiguration;
67 import org.codehaus.plexus.context.Context;
68 import org.codehaus.plexus.context.ContextException;
69 import org.codehaus.plexus.logging.AbstractLogEnabled;
70 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
71 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
72 import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
73 import org.codehaus.plexus.util.StringUtils;
74 import org.codehaus.plexus.util.xml.Xpp3Dom;
75 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
76
77 import java.io.IOException;
78 import java.util.ArrayList;
79 import java.util.Collections;
80 import java.util.HashMap;
81 import java.util.Iterator;
82 import java.util.List;
83 import java.util.Map;
84 import java.util.Stack;
85 import java.util.StringTokenizer;
86
87
88
89
90
91
92
93 public class DefaultLifecycleExecutor
94 extends AbstractLogEnabled
95 implements LifecycleExecutor, Initializable, Contextualizable
96 {
97
98
99
100
101 private PluginManager pluginManager;
102
103 private ExtensionManager extensionManager;
104
105 private List lifecycles;
106
107 private ArtifactHandlerManager artifactHandlerManager;
108
109 private List defaultReports;
110
111 private Map phaseToLifecycleMap;
112
113 private MavenProjectBuilder mavenProjectBuilder;
114
115 private ModelInterpolator modelInterpolator;
116
117 private ConfigurationInterpolator configInterpolator;
118
119
120
121
122
123
124
125
126
127
128
129
130
131 public void execute( final MavenSession session, final ReactorManager rm, final EventDispatcher dispatcher )
132 throws BuildFailureException, LifecycleExecutionException
133 {
134
135
136 MavenProject rootProject = rm.getTopLevelProject();
137
138 List goals = session.getGoals();
139
140 if ( goals.isEmpty() && rootProject != null )
141 {
142 String goal = rootProject.getDefaultGoal();
143
144 if ( goal != null )
145 {
146 goals = Collections.singletonList( goal );
147 }
148 }
149
150 if ( goals.isEmpty() )
151 {
152 StringBuffer buffer = new StringBuffer( 1024 );
153
154 buffer.append( "\n\n" );
155 buffer.append( "You must specify at least one goal or lifecycle phase to perform build steps.\n" );
156 buffer.append( "The following list illustrates some commonly used build commands:\n\n" );
157 buffer.append( " mvn clean\n" );
158 buffer.append( " Deletes any build output (e.g. class files or JARs).\n" );
159 buffer.append( " mvn test\n" );
160 buffer.append( " Runs the unit tests for the project.\n" );
161 buffer.append( " mvn install\n" );
162 buffer.append( " Copies the project artifacts into your local repository.\n" );
163 buffer.append( " mvn deploy\n" );
164 buffer.append( " Copies the project artifacts into the remote repository.\n" );
165 buffer.append( " mvn site\n" );
166 buffer.append( " Creates project documentation (e.g. reports or Javadoc).\n\n" );
167 buffer.append( "Please see\n" );
168 buffer.append( "http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html\n" );
169 buffer.append( "for a complete description of available lifecycle phases.\n\n" );
170 buffer.append( "Use \"mvn --help\" to show general usage information about Maven's command line.\n\n" );
171
172 throw new BuildFailureException( buffer.toString() );
173 }
174
175 List taskSegments = segmentTaskListByAggregationNeeds( goals, session, rootProject );
176
177
178 findExtensions( session );
179
180 executeTaskSegments( taskSegments, rm, session, rootProject, dispatcher );
181 }
182
183 private void findExtensions( final MavenSession session )
184 throws LifecycleExecutionException
185 {
186
187 Map<String, ArtifactHandler> handlers = new HashMap<String, ArtifactHandler>();
188 for ( MavenProject project : session.getSortedProjects() )
189 {
190 for ( Iterator j = project.getBuildExtensions().iterator(); j.hasNext(); )
191 {
192 Extension extension = (Extension) j.next();
193 try
194 {
195 getLogger().debug( "Adding extension: " + extension );
196 extensionManager.addExtension( extension, project, session.getLocalRepository() );
197 }
198 catch ( PlexusContainerException e )
199 {
200 throw new LifecycleExecutionException( "Unable to initialise extensions", e );
201 }
202 catch ( ArtifactResolutionException e )
203 {
204 throw new LifecycleExecutionException( e.getMessage(), e );
205 }
206 catch ( ArtifactNotFoundException e )
207 {
208 throw new LifecycleExecutionException( e.getMessage(), e );
209 }
210 }
211
212 }
213
214 extensionManager.registerWagons();
215
216 handlers.putAll( extensionManager.getArtifactTypeHandlers() );
217
218 for ( MavenProject project : session.getSortedProjects() )
219 {
220 try
221 {
222 handlers.putAll( findArtifactTypeHandlersInPlugins( project, session ) );
223
224
225 for ( ArtifactHandler handler : handlers.values() )
226 {
227 if ( project.getPackaging().equals( handler.getPackaging() ) )
228 {
229 project.getArtifact().setArtifactHandler( handler );
230
231
232 break;
233 }
234 }
235 }
236 catch ( PluginNotFoundException e )
237 {
238 throw new LifecycleExecutionException( e.getMessage(), e );
239 }
240 }
241
242 artifactHandlerManager.addHandlers( handlers );
243 }
244
245 private void executeTaskSegments( final List taskSegments, final ReactorManager rm, final MavenSession session,
246 final MavenProject rootProject, final EventDispatcher dispatcher )
247 throws LifecycleExecutionException, BuildFailureException
248 {
249 for ( Iterator it = taskSegments.iterator(); it.hasNext(); )
250 {
251 TaskSegment segment = (TaskSegment) it.next();
252
253 if ( segment.aggregate() )
254 {
255 if ( !rm.isBlackListed( rootProject ) )
256 {
257 line();
258
259 getLogger().info( "Building " + rootProject.getName() );
260
261 getLogger().info( " " + segment );
262
263 line();
264
265
266
267 String event = MavenEvents.PROJECT_EXECUTION;
268
269 long buildStartTime = System.currentTimeMillis();
270
271 String target = rootProject.getId() + " ( " + segment + " )";
272
273 dispatcher.dispatchStart( event, target );
274
275 try
276 {
277 session.setCurrentProject( rootProject );
278
279
280 for ( Iterator goalIterator = segment.getTasks().iterator(); goalIterator.hasNext(); )
281 {
282 String task = (String) goalIterator.next();
283
284 executeGoalAndHandleFailures( task, session, rootProject, dispatcher, event, rm, buildStartTime,
285 target );
286 }
287
288 rm.registerBuildSuccess( rootProject, System.currentTimeMillis() - buildStartTime );
289
290 }
291 finally
292 {
293 session.setCurrentProject( null );
294 }
295
296 dispatcher.dispatchEnd( event, target );
297 }
298 else
299 {
300 line();
301
302 getLogger().info( "SKIPPING " + rootProject.getName() );
303
304 getLogger().info( " " + segment );
305
306 getLogger().info(
307 "This project has been banned from further executions due to previous failures." );
308
309 line();
310 }
311 }
312 else
313 {
314 List sortedProjects = session.getSortedProjects();
315
316
317 for ( Iterator projectIterator = sortedProjects.iterator(); projectIterator.hasNext(); )
318 {
319 MavenProject currentProject = (MavenProject) projectIterator.next();
320
321 if ( !rm.isBlackListed( currentProject ) )
322 {
323 line();
324
325 getLogger().info( "Building " + currentProject.getName() );
326
327 getLogger().info( " " + segment );
328
329 line();
330
331
332
333 String event = MavenEvents.PROJECT_EXECUTION;
334
335 long buildStartTime = System.currentTimeMillis();
336
337 String target = currentProject.getId() + " ( " + segment + " )";
338 dispatcher.dispatchStart( event, target );
339
340 try
341 {
342 session.setCurrentProject( currentProject );
343
344 for ( Iterator goalIterator = segment.getTasks().iterator(); goalIterator.hasNext(); )
345 {
346 String task = (String) goalIterator.next();
347
348 executeGoalAndHandleFailures( task, session, currentProject, dispatcher, event, rm,
349 buildStartTime, target );
350 }
351
352 }
353 finally
354 {
355 session.setCurrentProject( null );
356 }
357
358 rm.registerBuildSuccess( currentProject, System.currentTimeMillis() - buildStartTime );
359
360 dispatcher.dispatchEnd( event, target );
361 }
362 else
363 {
364 line();
365
366 getLogger().info( "SKIPPING " + currentProject.getName() );
367
368 getLogger().info( " " + segment );
369
370 getLogger().info(
371 "This project has been banned from further executions due to previous failures." );
372
373 line();
374 }
375 }
376 }
377 }
378 }
379
380 private void executeGoalAndHandleFailures( final String task, final MavenSession session, final MavenProject project,
381 final EventDispatcher dispatcher, final String event, final ReactorManager rm,
382 final long buildStartTime, final String target )
383 throws BuildFailureException, LifecycleExecutionException
384 {
385 try
386 {
387 executeGoal( task, session, project );
388 }
389 catch ( LifecycleExecutionException e )
390 {
391 dispatcher.dispatchError( event, target, e );
392
393 if ( handleExecutionFailure( rm, project, e, task, buildStartTime ) )
394 {
395 throw e;
396 }
397 }
398 catch ( BuildFailureException e )
399 {
400 dispatcher.dispatchError( event, target, e );
401
402 if ( handleExecutionFailure( rm, project, e, task, buildStartTime ) )
403 {
404 throw e;
405 }
406 }
407 }
408
409 private boolean handleExecutionFailure( final ReactorManager rm, final MavenProject project, final Exception e, final String task,
410 final long buildStartTime )
411 {
412 rm.registerBuildFailure( project, e, task, System.currentTimeMillis() - buildStartTime );
413
414 if ( ReactorManager.FAIL_FAST.equals( rm.getFailureBehavior() ) )
415 {
416 return true;
417 }
418 else if ( ReactorManager.FAIL_AT_END.equals( rm.getFailureBehavior() ) )
419 {
420 rm.blackList( project );
421 }
422
423 return false;
424 }
425
426 private List segmentTaskListByAggregationNeeds( final List tasks, final MavenSession session, final MavenProject project )
427 throws LifecycleExecutionException, BuildFailureException
428 {
429 List segments = new ArrayList();
430
431 if ( project != null )
432 {
433
434 TaskSegment currentSegment = null;
435 for ( Iterator it = tasks.iterator(); it.hasNext(); )
436 {
437 String task = (String) it.next();
438
439
440
441 if ( getPhaseToLifecycleMap().containsKey( task ) )
442 {
443 if ( currentSegment != null && currentSegment.aggregate() )
444 {
445 segments.add( currentSegment );
446 currentSegment = null;
447 }
448
449 if ( currentSegment == null )
450 {
451 currentSegment = new TaskSegment();
452 }
453
454 currentSegment.add( task );
455 }
456 else
457 {
458 MojoDescriptor mojo = null;
459 try
460 {
461
462 mojo = getMojoDescriptor( task, session, project, task, true, false );
463 }
464 catch ( PluginNotFoundException e )
465 {
466
467 getLogger().info(
468 "Cannot find mojo descriptor for: \'" + task + "\' - Treating as non-aggregator." );
469 getLogger().debug( "", e );
470 }
471
472
473
474
475 if ( mojo != null && ( mojo.isAggregator() || !mojo.isProjectRequired() ) )
476 {
477 if ( currentSegment != null && !currentSegment.aggregate() )
478 {
479 segments.add( currentSegment );
480 currentSegment = null;
481 }
482
483 if ( currentSegment == null )
484 {
485 currentSegment = new TaskSegment( true );
486 }
487
488 currentSegment.add( task );
489 }
490 else
491 {
492 if ( currentSegment != null && currentSegment.aggregate() )
493 {
494 segments.add( currentSegment );
495 currentSegment = null;
496 }
497
498 if ( currentSegment == null )
499 {
500 currentSegment = new TaskSegment();
501 }
502
503 currentSegment.add( task );
504 }
505 }
506 }
507
508 segments.add( currentSegment );
509 }
510 else
511 {
512 TaskSegment segment = new TaskSegment( false );
513 for ( Iterator i = tasks.iterator(); i.hasNext(); )
514 {
515 segment.add( (String) i.next() );
516 }
517 segments.add( segment );
518 }
519
520 return segments;
521 }
522
523 private void executeGoal( final String task, final MavenSession session, final MavenProject project )
524 throws LifecycleExecutionException, BuildFailureException
525 {
526 try
527 {
528 Stack forkEntryPoints = new Stack();
529 if ( getPhaseToLifecycleMap().containsKey( task ) )
530 {
531 Lifecycle lifecycle = getLifecycleForPhase( task );
532
533
534 Map lifecycleMappings = constructLifecycleMappings( session, task, project, lifecycle );
535 executeGoalWithLifecycle( task, forkEntryPoints, session, lifecycleMappings, project, lifecycle );
536 }
537 else
538 {
539 executeStandaloneGoal( task, forkEntryPoints, session, project );
540 }
541 }
542 catch ( PluginNotFoundException e )
543 {
544 throw new BuildFailureException( "A required plugin was not found: " + e.getMessage(), e );
545 }
546 }
547
548 private void executeGoalWithLifecycle( final String task, final Stack forkEntryPoints, final MavenSession session,
549 final Map lifecycleMappings, final MavenProject project, final Lifecycle lifecycle )
550 throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
551 {
552 List goals = processGoalChain( task, lifecycleMappings, lifecycle );
553
554 if ( !goals.isEmpty() )
555 {
556 executeGoals( goals, forkEntryPoints, session, project );
557 }
558 else
559 {
560 getLogger().info( "No goals needed for project - skipping" );
561 }
562 }
563
564 private void executeStandaloneGoal( final String task, final Stack forkEntryPoints, final MavenSession session, final MavenProject project )
565 throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
566 {
567
568 MojoDescriptor mojoDescriptor = getMojoDescriptor( task, session, project, task, true, false );
569 executeGoals( Collections.singletonList( new MojoExecution( mojoDescriptor, MojoExecution.CLI_EXECUTION_ID ) ),
570 forkEntryPoints, session, project );
571 }
572
573 private void executeGoals( final List goals, final Stack forkEntryPoints, final MavenSession session, final MavenProject project )
574 throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
575 {
576 for ( Iterator i = goals.iterator(); i.hasNext(); )
577 {
578 MojoExecution mojoExecution = (MojoExecution) i.next();
579
580 MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
581
582 PlexusConfiguration configuration = mojoDescriptor.getMojoConfiguration();
583 boolean usesReactorProjects = mojoDescriptor.isAggregator() || usesSessionOrReactorProjects( configuration );
584
585 if ( usesReactorProjects )
586 {
587 calculateAllConcreteStates( session );
588 }
589 else
590 {
591 calculateConcreteState( project, session, true );
592 }
593
594 calculateConcreteConfiguration( mojoExecution, project, session );
595
596 List reportExecutions = null;
597 if ( mojoDescriptor.isRequiresReports() )
598 {
599 reportExecutions = getReportExecutions( project, forkEntryPoints, mojoExecution, session );
600 }
601
602 boolean hasFork = false;
603 if ( mojoDescriptor.getExecutePhase() != null || mojoDescriptor.getExecuteGoal() != null )
604 {
605 hasFork = true;
606 }
607 else if ( reportExecutions != null )
608 {
609 for ( Iterator it = reportExecutions.iterator(); it.hasNext(); )
610 {
611 MojoExecution reportExecution = (MojoExecution) it.next();
612 MojoDescriptor reportDescriptor = reportExecution.getMojoDescriptor();
613 if ( reportDescriptor.getExecutePhase() != null || reportDescriptor.getExecuteGoal() != null )
614 {
615 hasFork = true;
616 }
617 }
618 }
619
620 if ( hasFork )
621 {
622
623
624
625
626 createExecutionProject( project, session, true );
627
628 if ( usesReactorProjects )
629 {
630 List reactorProjects = session.getSortedProjects();
631 for ( Iterator it = reactorProjects.iterator(); it.hasNext(); )
632 {
633 MavenProject reactorProject = (MavenProject) it.next();
634 createExecutionProject( reactorProject, session, false );
635 }
636 }
637 }
638
639 if ( mojoDescriptor.getExecutePhase() != null || mojoDescriptor.getExecuteGoal() != null )
640 {
641 forkEntryPoints.push( mojoDescriptor );
642
643 forkLifecycle( mojoDescriptor, forkEntryPoints, session, project, mojoExecution.getExecutionId() );
644
645 forkEntryPoints.pop();
646 }
647
648 if ( mojoDescriptor.isRequiresReports() )
649 {
650 List reports = getReports( reportExecutions, project, mojoExecution, session );
651
652 mojoExecution.setReports( reports );
653
654 for ( Iterator j = mojoExecution.getForkedExecutions().iterator(); j.hasNext(); )
655 {
656 MojoExecution forkedExecution = (MojoExecution) j.next();
657 MojoDescriptor descriptor = forkedExecution.getMojoDescriptor();
658
659 if ( descriptor.getExecutePhase() != null )
660 {
661 forkEntryPoints.push( descriptor );
662
663 forkLifecycle( descriptor, forkEntryPoints, session, project, forkedExecution.getExecutionId() );
664
665 forkEntryPoints.pop();
666 }
667 }
668 }
669
670 if ( hasFork )
671 {
672
673
674
675
676 calculateConcreteState( project.getExecutionProject(), session, true );
677
678
679
680 if ( usesReactorProjects )
681 {
682 calculateAllConcreteStates( session );
683 List reactorProjects = session.getSortedProjects();
684 for ( Iterator it = reactorProjects.iterator(); it.hasNext(); )
685 {
686 MavenProject reactorProject = (MavenProject) it.next();
687 calculateConcreteState( reactorProject.getExecutionProject(), session, false );
688 }
689 }
690 }
691
692 try
693 {
694 pluginManager.executeMojo( project, mojoExecution, session );
695 }
696 catch ( PluginManagerException e )
697 {
698 throw new LifecycleExecutionException( "Internal error in the plugin manager executing goal '" +
699 mojoDescriptor.getId() + "': " + e.getMessage(), e );
700 }
701 catch ( ArtifactNotFoundException e )
702 {
703 throw new LifecycleExecutionException( e.getMessage(), e );
704 }
705 catch ( InvalidDependencyVersionException e )
706 {
707 throw new LifecycleExecutionException( e.getMessage(), e );
708 }
709 catch ( ArtifactResolutionException e )
710 {
711 throw new LifecycleExecutionException( e.getMessage(), e );
712 }
713 catch ( MojoFailureException e )
714 {
715 throw new BuildFailureException( e.getMessage(), e );
716 }
717 catch ( MojoExecutionException e )
718 {
719 throw new LifecycleExecutionException( e.getMessage(), e );
720 }
721 catch ( PluginConfigurationException e )
722 {
723 throw new LifecycleExecutionException( e.getMessage(), e );
724 }
725 }
726 }
727
728 private void createExecutionProject( final MavenProject project, final MavenSession session, final boolean processProjectReferences )
729 throws LifecycleExecutionException
730 {
731 MavenProject executionProject = new MavenProject( project );
732
733 calculateConcreteState( executionProject, session, processProjectReferences );
734
735 project.setExecutionProject( executionProject );
736 }
737
738 private boolean usesSessionOrReactorProjects( final PlexusConfiguration configuration )
739 {
740 String value = configuration != null ? String.valueOf( configuration ) : null;
741
742 if ( value != null )
743 {
744 if ( value.indexOf( "${session" ) > -1 || value.indexOf( "${reactorProjects}" ) > -1 )
745 {
746 return true;
747 }
748 }
749
750 return false;
751 }
752
753 private void calculateConcreteConfiguration( final MojoExecution mojoExecution, final MavenProject project, final MavenSession session )
754 throws LifecycleExecutionException
755 {
756 if ( mojoExecution.getConfiguration() == null )
757 {
758 return;
759 }
760
761 try
762 {
763 mojoExecution.setConfiguration( (Xpp3Dom) configInterpolator.interpolate(
764 mojoExecution.getConfiguration(),
765 project,
766 session.getProjectBuilderConfiguration() ) );
767 }
768 catch ( ConfigurationInterpolationException e )
769 {
770 throw new LifecycleExecutionException( "Error interpolating configuration for: '" + mojoExecution.getMojoDescriptor().getRoleHint() +
771 "' (execution: '" + mojoExecution.getExecutionId() + "')", e );
772 }
773 }
774
775 private void calculateAllConcreteStates( final MavenSession session )
776 throws LifecycleExecutionException
777 {
778 List projects = session.getSortedProjects();
779 if ( projects != null )
780 {
781 for ( Iterator it = projects.iterator(); it.hasNext(); )
782 {
783 calculateConcreteState( (MavenProject) it.next(), session, false );
784 }
785 }
786 }
787
788 private void calculateConcreteState( final MavenProject project, final MavenSession session, final boolean processReferences )
789 throws LifecycleExecutionException
790 {
791 if ( mavenProjectBuilder != null && project != null )
792 {
793 try
794 {
795 mavenProjectBuilder.calculateConcreteState( project, session.getProjectBuilderConfiguration(), processReferences );
796 }
797 catch ( ModelInterpolationException e )
798 {
799 throw new LifecycleExecutionException( "Failed to calculate concrete state for project: " + project,
800 e );
801 }
802 }
803 }
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832 private List getReportExecutions( final MavenProject project, final Stack forkEntryPoints, final MojoExecution mojoExecution, final MavenSession session )
833 throws LifecycleExecutionException, PluginNotFoundException
834 {
835 List reportPlugins = project.getReportPlugins();
836
837 if ( project.getModel().getReports() != null )
838 {
839 getLogger().error(
840 "Plugin contains a <reports/> section: this is IGNORED - please use <reporting/> instead." );
841 }
842
843 if ( project.getReporting() == null || !project.getReporting().isExcludeDefaults() )
844 {
845 if ( reportPlugins == null )
846 {
847 reportPlugins = new ArrayList();
848 }
849 else
850 {
851 reportPlugins = new ArrayList( reportPlugins );
852 }
853
854 for ( Iterator i = defaultReports.iterator(); i.hasNext(); )
855 {
856 String report = (String) i.next();
857
858 StringTokenizer tok = new StringTokenizer( report, ":" );
859 int count = tok.countTokens();
860 if ( count != 2 && count != 3 )
861 {
862 getLogger().warn( "Invalid default report ignored: '" + report + "' (must be groupId:artifactId[:version])" );
863 }
864 else
865 {
866 String groupId = tok.nextToken();
867 String artifactId = tok.nextToken();
868 String version = tok.hasMoreTokens() ? tok.nextToken() : null;
869
870 boolean found = false;
871 for ( Iterator j = reportPlugins.iterator(); j.hasNext() && !found; )
872 {
873 ReportPlugin reportPlugin = (ReportPlugin) j.next();
874 if ( reportPlugin.getGroupId().equals( groupId ) &&
875 reportPlugin.getArtifactId().equals( artifactId ) )
876 {
877 found = true;
878 }
879 }
880
881 if ( !found )
882 {
883 ReportPlugin reportPlugin = new ReportPlugin();
884 reportPlugin.setGroupId( groupId );
885 reportPlugin.setArtifactId( artifactId );
886 reportPlugin.setVersion( version );
887 reportPlugins.add( reportPlugin );
888 }
889 }
890 }
891 }
892
893 List reports = new ArrayList();
894 if ( reportPlugins != null )
895 {
896 for ( Iterator it = reportPlugins.iterator(); it.hasNext(); )
897 {
898 ReportPlugin reportPlugin = (ReportPlugin) it.next();
899
900 List reportSets = reportPlugin.getReportSets();
901
902 if ( reportSets == null || reportSets.isEmpty() )
903 {
904 reports.addAll( getReportExecutions( reportPlugin, forkEntryPoints, null, project, session, mojoExecution ) );
905 }
906 else
907 {
908 for ( Iterator j = reportSets.iterator(); j.hasNext(); )
909 {
910 ReportSet reportSet = (ReportSet) j.next();
911
912 reports.addAll( getReportExecutions( reportPlugin, forkEntryPoints, reportSet, project, session, mojoExecution ) );
913 }
914 }
915 }
916 }
917 return reports;
918 }
919
920 private List getReportExecutions( final ReportPlugin reportPlugin,
921 final Stack forkEntryPoints,
922 final ReportSet reportSet,
923 final MavenProject project,
924 final MavenSession session,
925 final MojoExecution mojoExecution )
926 throws LifecycleExecutionException, PluginNotFoundException
927 {
928 PluginDescriptor pluginDescriptor = verifyReportPlugin( reportPlugin, project, session );
929
930 List reports = new ArrayList();
931 for ( Iterator i = pluginDescriptor.getMojos().iterator(); i.hasNext(); )
932 {
933 MojoDescriptor mojoDescriptor = (MojoDescriptor) i.next();
934 if ( forkEntryPoints.contains( mojoDescriptor ) )
935 {
936 getLogger().debug( "Omitting report: " + mojoDescriptor.getFullGoalName() + " from reports list. It initiated part of the fork currently executing." );
937 continue;
938 }
939
940
941
942 if ( reportSet == null || reportSet.getReports().contains( mojoDescriptor.getGoal() ) )
943 {
944 String id = null;
945 if ( reportSet != null )
946 {
947 id = reportSet.getId();
948 }
949 else
950 {
951 id = mojoExecution.getExecutionId();
952 }
953
954 MojoExecution reportExecution;
955 if ( id.startsWith( MojoExecution.DEFAULT_EXEC_ID_PREFIX ) )
956 {
957 reportExecution = new MojoExecution( mojoDescriptor );
958 }
959 else
960 {
961 reportExecution = new MojoExecution( mojoDescriptor, id );
962 }
963
964 reports.add( reportExecution );
965 }
966 }
967 return reports;
968 }
969
970 private List getReports( final List reportExecutions, final MavenProject project, final MojoExecution mojoExecution, final MavenSession session )
971 throws LifecycleExecutionException
972 {
973 List reports = new ArrayList();
974
975 for ( Iterator it = reportExecutions.iterator(); it.hasNext(); )
976 {
977 MojoExecution reportExecution = (MojoExecution) it.next();
978 PluginDescriptor pluginDescriptor = reportExecution.getMojoDescriptor().getPluginDescriptor();
979
980 try
981 {
982 MavenReport reportMojo = pluginManager.getReport( project, reportExecution, session );
983
984
985 if ( reportMojo != null )
986 {
987 reports.add( reportMojo );
988 mojoExecution.addMojoExecution( reportExecution );
989 }
990 }
991 catch ( PluginManagerException e )
992 {
993 throw new LifecycleExecutionException(
994 "Error getting reports from the plugin '" + pluginDescriptor.getId() + "': " + e.getMessage(), e );
995 }
996 catch ( PluginConfigurationException e )
997 {
998 throw new LifecycleExecutionException(
999 "Error getting reports from the plugin '" + pluginDescriptor.getId() + "'", e );
1000 }
1001 catch ( ArtifactNotFoundException e )
1002 {
1003 throw new LifecycleExecutionException( e.getMessage(), e );
1004 }
1005 catch ( ArtifactResolutionException e )
1006 {
1007 throw new LifecycleExecutionException( e.getMessage(), e );
1008 }
1009 }
1010
1011 return reports;
1012 }
1013
1014 private void forkLifecycle( final MojoDescriptor mojoDescriptor, final Stack ancestorLifecycleForkers, final MavenSession session,
1015 final MavenProject project, final String executionId )
1016 throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
1017 {
1018 PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
1019 getLogger().info( "Preparing " + pluginDescriptor.getGoalPrefix() + ":" + mojoDescriptor.getGoal() );
1020
1021 if ( mojoDescriptor.isAggregator() )
1022 {
1023 for ( Iterator i = session.getSortedProjects().iterator(); i.hasNext(); )
1024 {
1025 MavenProject reactorProject = (MavenProject) i.next();
1026
1027 line();
1028
1029 getLogger().info( "Building " + reactorProject.getName() );
1030
1031 line();
1032
1033 forkProjectLifecycle( mojoDescriptor, ancestorLifecycleForkers, session, reactorProject, executionId );
1034 }
1035 }
1036 else
1037 {
1038 forkProjectLifecycle( mojoDescriptor, ancestorLifecycleForkers, session, project, executionId );
1039 }
1040 }
1041
1042 private void forkProjectLifecycle( final MojoDescriptor mojoDescriptor, final Stack forkEntryPoints, final MavenSession session,
1043 MavenProject project, final String executionId )
1044 throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
1045 {
1046 project = project.getExecutionProject();
1047
1048 forkEntryPoints.push( mojoDescriptor );
1049
1050 PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
1051
1052 String targetPhase = mojoDescriptor.getExecutePhase();
1053
1054 Map lifecycleMappings = null;
1055 if ( targetPhase != null )
1056 {
1057 Lifecycle lifecycle = getLifecycleForPhase( targetPhase );
1058
1059
1060 lifecycleMappings = constructLifecycleMappings( session, targetPhase, project, lifecycle );
1061
1062 String executeLifecycle = mojoDescriptor.getExecuteLifecycle();
1063 if ( executeLifecycle != null )
1064 {
1065 org.apache.maven.plugin.lifecycle.Lifecycle lifecycleOverlay;
1066 try
1067 {
1068 lifecycleOverlay = pluginDescriptor.getLifecycleMapping( executeLifecycle );
1069 }
1070 catch ( IOException e )
1071 {
1072 throw new LifecycleExecutionException( "Unable to read lifecycle mapping file: " + e.getMessage(),
1073 e );
1074 }
1075 catch ( XmlPullParserException e )
1076 {
1077 throw new LifecycleExecutionException( "Unable to parse lifecycle mapping file: " + e.getMessage(),
1078 e );
1079 }
1080
1081 if ( lifecycleOverlay == null )
1082 {
1083 throw new LifecycleExecutionException( "Lifecycle '" + executeLifecycle + "' not found in plugin" );
1084 }
1085
1086 for ( Iterator i = lifecycleOverlay.getPhases().iterator(); i.hasNext(); )
1087 {
1088 Phase phase = (Phase) i.next();
1089 for ( Iterator j = phase.getExecutions().iterator(); j.hasNext(); )
1090 {
1091 Execution exec = (Execution) j.next();
1092
1093 for ( Iterator k = exec.getGoals().iterator(); k.hasNext(); )
1094 {
1095 String goal = (String) k.next();
1096
1097 PluginDescriptor lifecyclePluginDescriptor;
1098 String lifecycleGoal;
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126 if ( goal.indexOf( ":" ) > 0 )
1127 {
1128 String[] s = StringUtils.split( goal, ":" );
1129
1130 String groupId = s[0];
1131 String artifactId = s[1];
1132 lifecycleGoal = s[2];
1133
1134 Plugin plugin = new Plugin();
1135 plugin.setGroupId( groupId );
1136 plugin.setArtifactId( artifactId );
1137 lifecyclePluginDescriptor = verifyPlugin( plugin, project, session );
1138 if ( lifecyclePluginDescriptor == null )
1139 {
1140 throw new LifecycleExecutionException(
1141 "Unable to find plugin " + groupId + ":" + artifactId );
1142 }
1143 }
1144 else
1145 {
1146 lifecyclePluginDescriptor = pluginDescriptor;
1147 lifecycleGoal = goal;
1148 }
1149
1150 Xpp3Dom configuration = (Xpp3Dom) exec.getConfiguration();
1151
1152 if ( phase.getConfiguration() != null )
1153 {
1154 configuration = Xpp3Dom.mergeXpp3Dom( new Xpp3Dom( (Xpp3Dom) phase.getConfiguration() ),
1155 configuration );
1156 }
1157
1158 MojoDescriptor desc = getMojoDescriptor( lifecyclePluginDescriptor, lifecycleGoal );
1159 MojoExecution mojoExecution;
1160 if ( executionId.startsWith( MojoExecution.DEFAULT_EXEC_ID_PREFIX ) )
1161 {
1162 mojoExecution = new MojoExecution( desc, configuration );
1163 }
1164 else
1165 {
1166 mojoExecution = new MojoExecution( desc, configuration, executionId );
1167 }
1168
1169 addToLifecycleMappings( lifecycleMappings, phase.getId(), mojoExecution,
1170 session.getSettings() );
1171 }
1172 }
1173
1174 if ( phase.getConfiguration() != null )
1175 {
1176
1177
1178
1179 for ( Iterator j = lifecycleMappings.values().iterator(); j.hasNext(); )
1180 {
1181 List tasks = (List) j.next();
1182
1183 for ( Iterator k = tasks.iterator(); k.hasNext(); )
1184 {
1185 MojoExecution exec = (MojoExecution) k.next();
1186
1187 Xpp3Dom configuration = Xpp3Dom.mergeXpp3Dom(
1188 new Xpp3Dom( (Xpp3Dom) phase.getConfiguration() ), exec.getConfiguration() );
1189
1190 exec.setConfiguration( configuration );
1191 }
1192 }
1193 }
1194
1195 }
1196 }
1197
1198 removeFromLifecycle( forkEntryPoints, lifecycleMappings );
1199 }
1200
1201 if ( targetPhase != null )
1202 {
1203 Lifecycle lifecycle = getLifecycleForPhase( targetPhase );
1204
1205 executeGoalWithLifecycle( targetPhase, forkEntryPoints, session, lifecycleMappings, project, lifecycle );
1206 }
1207 else
1208 {
1209 String goal = mojoDescriptor.getExecuteGoal();
1210 MojoDescriptor desc = getMojoDescriptor( pluginDescriptor, goal );
1211 executeGoals( Collections.singletonList( new MojoExecution( desc, goal ) ), forkEntryPoints, session, project );
1212 }
1213 }
1214
1215 private Lifecycle getLifecycleForPhase( final String phase )
1216 throws BuildFailureException, LifecycleExecutionException
1217 {
1218 Lifecycle lifecycle = (Lifecycle) getPhaseToLifecycleMap().get( phase );
1219
1220 if ( lifecycle == null )
1221 {
1222 throw new BuildFailureException( "Unable to find lifecycle for phase '" + phase + "'" );
1223 }
1224 return lifecycle;
1225 }
1226
1227 private MojoDescriptor getMojoDescriptor( final PluginDescriptor pluginDescriptor, final String goal )
1228 throws LifecycleExecutionException
1229 {
1230 MojoDescriptor desc = pluginDescriptor.getMojo( goal );
1231
1232 if ( desc == null )
1233 {
1234 String message =
1235 "Required goal '" + goal + "' not found in plugin '" + pluginDescriptor.getGoalPrefix() + "'";
1236 int index = goal.indexOf( ':' );
1237 if ( index >= 0 )
1238 {
1239 String prefix = goal.substring( index + 1 );
1240 if ( prefix.equals( pluginDescriptor.getGoalPrefix() ) )
1241 {
1242 message = message + " (goals should not be prefixed - try '" + prefix + "')";
1243 }
1244 }
1245 throw new LifecycleExecutionException( message );
1246 }
1247 return desc;
1248 }
1249
1250 private void removeFromLifecycle( final Stack lifecycleForkers, final Map lifecycleMappings )
1251 {
1252 for ( Iterator lifecycleIterator = lifecycleMappings.values().iterator(); lifecycleIterator.hasNext(); )
1253 {
1254 List tasks = (List) lifecycleIterator.next();
1255
1256 for ( Iterator taskIterator = tasks.iterator(); taskIterator.hasNext(); )
1257 {
1258 MojoExecution execution = (MojoExecution) taskIterator.next();
1259
1260 if ( lifecycleForkers.contains( execution.getMojoDescriptor() ) )
1261 {
1262 taskIterator.remove();
1263 getLogger().warn( "Removing: " + execution.getMojoDescriptor().getGoal()
1264 + " from forked lifecycle, to prevent recursive invocation." );
1265 }
1266 }
1267 }
1268 }
1269
1270 private Map constructLifecycleMappings( final MavenSession session, final String selectedPhase, final MavenProject project,
1271 final Lifecycle lifecycle )
1272 throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
1273 {
1274
1275 Map lifecycleMappings = bindLifecycleForPackaging( session, selectedPhase, project, lifecycle );
1276
1277
1278 for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext(); )
1279 {
1280 Plugin plugin = (Plugin) i.next();
1281
1282 bindPluginToLifecycle( plugin, session, lifecycleMappings, project );
1283 }
1284
1285 return lifecycleMappings;
1286 }
1287
1288 private Map bindLifecycleForPackaging( final MavenSession session, final String selectedPhase, final MavenProject project,
1289 final Lifecycle lifecycle )
1290 throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
1291 {
1292 Map mappings = findMappingsForLifecycle( session, project, lifecycle );
1293
1294 List optionalMojos = findOptionalMojosForLifecycle( session, project, lifecycle );
1295
1296 Map lifecycleMappings = new HashMap();
1297
1298 for ( Iterator i = lifecycle.getPhases().iterator(); i.hasNext(); )
1299 {
1300 String phase = (String) i.next();
1301
1302 String phaseTasks = (String) mappings.get( phase );
1303
1304 if ( phaseTasks != null )
1305 {
1306 for ( StringTokenizer tok = new StringTokenizer( phaseTasks, "," ); tok.hasMoreTokens(); )
1307 {
1308 String goal = tok.nextToken().trim();
1309
1310
1311 MojoDescriptor mojoDescriptor = getMojoDescriptor( goal, session, project, selectedPhase, false,
1312 optionalMojos.contains( goal ) );
1313
1314 if ( mojoDescriptor == null )
1315 {
1316 continue;
1317 }
1318
1319 if ( mojoDescriptor.isDirectInvocationOnly() )
1320 {
1321 throw new LifecycleExecutionException( "Mojo: \'" + goal +
1322 "\' requires direct invocation. It cannot be used as part of lifecycle: \'" +
1323 project.getPackaging() + "\'." );
1324 }
1325
1326 addToLifecycleMappings( lifecycleMappings, phase, new MojoExecution( mojoDescriptor ),
1327 session.getSettings() );
1328 }
1329 }
1330
1331 if ( phase.equals( selectedPhase ) )
1332 {
1333 break;
1334 }
1335 }
1336
1337 return lifecycleMappings;
1338 }
1339
1340 private Map findMappingsForLifecycle( final MavenSession session, final MavenProject project, final Lifecycle lifecycle )
1341 throws LifecycleExecutionException, PluginNotFoundException
1342 {
1343 String packaging = project.getPackaging();
1344 Map mappings = null;
1345
1346 LifecycleMapping m = (LifecycleMapping) findExtension( project, LifecycleMapping.ROLE, packaging, session );
1347 if ( m != null )
1348 {
1349 mappings = m.getPhases( lifecycle.getId() );
1350 }
1351
1352 Map defaultMappings = lifecycle.getDefaultPhases();
1353
1354 if ( mappings == null )
1355 {
1356 try
1357 {
1358 m = (LifecycleMapping) session.lookup( LifecycleMapping.ROLE, packaging );
1359 mappings = m.getPhases( lifecycle.getId() );
1360 }
1361 catch ( ComponentLookupException e )
1362 {
1363 if ( defaultMappings == null )
1364 {
1365 throw new LifecycleExecutionException(
1366 "Cannot find lifecycle mapping for packaging: \'" + packaging + "\'.", e );
1367 }
1368 }
1369 }
1370
1371 if ( mappings == null )
1372 {
1373 if ( defaultMappings == null )
1374 {
1375 throw new LifecycleExecutionException(
1376 "Cannot find lifecycle mapping for packaging: \'" + packaging + "\', and there is no default" );
1377 }
1378 else
1379 {
1380 mappings = defaultMappings;
1381 }
1382 }
1383
1384 return mappings;
1385 }
1386
1387 private List findOptionalMojosForLifecycle( final MavenSession session, final MavenProject project, final Lifecycle lifecycle )
1388 throws LifecycleExecutionException, PluginNotFoundException
1389 {
1390 String packaging = project.getPackaging();
1391 List optionalMojos = null;
1392
1393 LifecycleMapping m = (LifecycleMapping) findExtension( project, LifecycleMapping.ROLE, packaging, session );
1394
1395 if ( m != null )
1396 {
1397 optionalMojos = m.getOptionalMojos( lifecycle.getId() );
1398 }
1399
1400 if ( optionalMojos == null )
1401 {
1402 try
1403 {
1404 m = (LifecycleMapping) session.lookup( LifecycleMapping.ROLE, packaging );
1405 optionalMojos = m.getOptionalMojos( lifecycle.getId() );
1406 }
1407 catch ( ComponentLookupException e )
1408 {
1409 getLogger().debug( "Error looking up lifecycle mapping to retrieve optional mojos. Lifecycle ID: " +
1410 lifecycle.getId() + ". Error: " + e.getMessage(), e );
1411 }
1412 }
1413
1414 if ( optionalMojos == null )
1415 {
1416 optionalMojos = Collections.EMPTY_LIST;
1417 }
1418
1419 return optionalMojos;
1420 }
1421
1422 private Object findExtension( final MavenProject project, final String role, final String roleHint, final MavenSession session )
1423 throws LifecycleExecutionException, PluginNotFoundException
1424 {
1425 Object pluginComponent = null;
1426
1427 for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext() && pluginComponent == null; )
1428 {
1429 Plugin plugin = (Plugin) i.next();
1430
1431 if ( plugin.isExtensions() )
1432 {
1433 loadPluginFully( plugin, project, session );
1434
1435
1436 try
1437 {
1438 pluginComponent = pluginManager.getPluginComponent( plugin, role, roleHint );
1439 }
1440 catch ( ComponentLookupException e )
1441 {
1442 getLogger().debug( "Unable to find the lifecycle component in the extension", e );
1443 }
1444 catch ( PluginManagerException e )
1445 {
1446 throw new LifecycleExecutionException(
1447 "Error getting extensions from the plugin '" + plugin.getKey() + "': " + e.getMessage(), e );
1448 }
1449 }
1450 }
1451 return pluginComponent;
1452 }
1453
1454
1455
1456
1457
1458 private Map<String, ArtifactHandler> findArtifactTypeHandlersInPlugins( final MavenProject project, final MavenSession session )
1459 throws LifecycleExecutionException, PluginNotFoundException
1460 {
1461 Map<String, ArtifactHandler> map = new HashMap<String, ArtifactHandler>();
1462 for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext(); )
1463 {
1464 Plugin plugin = (Plugin) i.next();
1465
1466 if ( plugin.isExtensions() )
1467 {
1468 loadPluginFully( plugin, project, session );
1469
1470
1471 try
1472 {
1473 Map components = pluginManager.getPluginComponents( plugin, ArtifactHandler.ROLE );
1474 map.putAll( components );
1475 }
1476 catch ( ComponentLookupException e )
1477 {
1478 getLogger().debug( "Unable to find the lifecycle component in the extension", e );
1479 }
1480 catch ( PluginManagerException e )
1481 {
1482 throw new LifecycleExecutionException( "Error looking up available components from plugin '" +
1483 plugin.getKey() + "': " + e.getMessage(), e );
1484 }
1485 }
1486 }
1487 return map;
1488 }
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498 private void bindPluginToLifecycle( final Plugin plugin, final MavenSession session, final Map phaseMap, final MavenProject project )
1499 throws LifecycleExecutionException, PluginNotFoundException
1500 {
1501 Settings settings = session.getSettings();
1502
1503 PluginDescriptor pluginDescriptor =
1504 verifyPlugin( plugin, project, session );
1505
1506 if ( pluginDescriptor.getMojos() != null && !pluginDescriptor.getMojos().isEmpty() )
1507 {
1508
1509 if ( plugin.isInheritanceApplied() || pluginDescriptor.isInheritedByDefault() )
1510 {
1511 if ( plugin.getGoals() != null )
1512 {
1513 getLogger().error(
1514 "Plugin contains a <goals/> section: this is IGNORED - please use <executions/> instead." );
1515 }
1516
1517 List executions = plugin.getExecutions();
1518
1519 if ( executions != null )
1520 {
1521 for ( Iterator it = executions.iterator(); it.hasNext(); )
1522 {
1523 PluginExecution execution = (PluginExecution) it.next();
1524
1525 bindExecutionToLifecycle( pluginDescriptor, phaseMap, execution, settings );
1526 }
1527 }
1528 }
1529 }
1530 }
1531
1532 private PluginDescriptor verifyPlugin( final Plugin plugin, final MavenProject project, final MavenSession session )
1533 throws LifecycleExecutionException, PluginNotFoundException
1534 {
1535 PluginDescriptor pluginDescriptor;
1536 try
1537 {
1538
1539
1540 pluginDescriptor = pluginManager.loadPluginDescriptor( plugin, project, session );
1541 }
1542 catch ( PluginManagerException e )
1543 {
1544 throw new LifecycleExecutionException(
1545 "Internal error in the plugin manager getting plugin '" + plugin.getKey() + "': " + e.getMessage(), e );
1546 }
1547 catch ( PluginVersionResolutionException e )
1548 {
1549 throw new LifecycleExecutionException( e.getMessage(), e );
1550 }
1551 catch ( InvalidVersionSpecificationException e )
1552 {
1553 throw new LifecycleExecutionException( e.getMessage(), e );
1554 }
1555 catch ( InvalidPluginException e )
1556 {
1557 throw new LifecycleExecutionException( e.getMessage(), e );
1558 }
1559 catch ( ArtifactNotFoundException e )
1560 {
1561 throw new LifecycleExecutionException( e.getMessage(), e );
1562 }
1563 catch ( ArtifactResolutionException e )
1564 {
1565 throw new LifecycleExecutionException( e.getMessage(), e );
1566 }
1567 catch ( PluginVersionNotFoundException e )
1568 {
1569 throw new LifecycleExecutionException( e.getMessage(), e );
1570 }
1571 return pluginDescriptor;
1572 }
1573
1574 private PluginDescriptor loadPluginFully( final Plugin plugin, final MavenProject project, final MavenSession session )
1575 throws LifecycleExecutionException, PluginNotFoundException
1576 {
1577 PluginDescriptor pluginDescriptor;
1578 try
1579 {
1580
1581
1582 pluginDescriptor = pluginManager.loadPluginFully( plugin, project, session );
1583 }
1584 catch ( PluginManagerException e )
1585 {
1586 throw new LifecycleExecutionException(
1587 "Internal error in the plugin manager getting plugin '" + plugin.getKey() + "': " + e.getMessage(), e );
1588 }
1589 catch ( PluginVersionResolutionException e )
1590 {
1591 throw new LifecycleExecutionException( e.getMessage(), e );
1592 }
1593 catch ( InvalidVersionSpecificationException e )
1594 {
1595 throw new LifecycleExecutionException( e.getMessage(), e );
1596 }
1597 catch ( InvalidPluginException e )
1598 {
1599 throw new LifecycleExecutionException( e.getMessage(), e );
1600 }
1601 catch ( ArtifactNotFoundException e )
1602 {
1603 throw new LifecycleExecutionException( e.getMessage(), e );
1604 }
1605 catch ( ArtifactResolutionException e )
1606 {
1607 throw new LifecycleExecutionException( e.getMessage(), e );
1608 }
1609 catch ( PluginVersionNotFoundException e )
1610 {
1611 throw new LifecycleExecutionException( e.getMessage(), e );
1612 }
1613 return pluginDescriptor;
1614 }
1615
1616 private PluginDescriptor verifyReportPlugin( final ReportPlugin plugin, final MavenProject project, final MavenSession session )
1617 throws LifecycleExecutionException, PluginNotFoundException
1618 {
1619 PluginDescriptor pluginDescriptor;
1620 try
1621 {
1622 pluginDescriptor = pluginManager.verifyReportPlugin( plugin, project, session );
1623 }
1624 catch ( PluginManagerException e )
1625 {
1626 throw new LifecycleExecutionException(
1627 "Internal error in the plugin manager getting report '" + plugin.getKey() + "': " + e.getMessage(), e );
1628 }
1629 catch ( PluginVersionResolutionException e )
1630 {
1631 throw new LifecycleExecutionException( e.getMessage(), e );
1632 }
1633 catch ( InvalidVersionSpecificationException e )
1634 {
1635 throw new LifecycleExecutionException( e.getMessage(), e );
1636 }
1637 catch ( InvalidPluginException e )
1638 {
1639 throw new LifecycleExecutionException( e.getMessage(), e );
1640 }
1641 catch ( ArtifactNotFoundException e )
1642 {
1643 throw new LifecycleExecutionException( e.getMessage(), e );
1644 }
1645 catch ( ArtifactResolutionException e )
1646 {
1647 throw new LifecycleExecutionException( e.getMessage(), e );
1648 }
1649 catch ( PluginVersionNotFoundException e )
1650 {
1651 throw new LifecycleExecutionException( e.getMessage(), e );
1652 }
1653 return pluginDescriptor;
1654 }
1655
1656 private void bindExecutionToLifecycle( final PluginDescriptor pluginDescriptor, final Map phaseMap, final PluginExecution execution,
1657 final Settings settings )
1658 throws LifecycleExecutionException
1659 {
1660 for ( Iterator i = execution.getGoals().iterator(); i.hasNext(); )
1661 {
1662 String goal = (String) i.next();
1663
1664 MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( goal );
1665 if ( mojoDescriptor == null )
1666 {
1667 throw new LifecycleExecutionException(
1668 "'" + goal + "' was specified in an execution, but not found in the plugin" );
1669 }
1670
1671
1672 if ( execution.isInheritanceApplied() || mojoDescriptor.isInheritedByDefault() )
1673 {
1674 MojoExecution mojoExecution = new MojoExecution( mojoDescriptor, execution.getId() );
1675
1676 String phase = execution.getPhase();
1677
1678 if ( phase == null )
1679 {
1680
1681 phase = mojoDescriptor.getPhase();
1682 }
1683
1684 if ( phase != null )
1685 {
1686 if ( mojoDescriptor.isDirectInvocationOnly() )
1687 {
1688 throw new LifecycleExecutionException( "Mojo: \'" + goal +
1689 "\' requires direct invocation. It cannot be used as part of the lifecycle (it was included via the POM)." );
1690 }
1691
1692 addToLifecycleMappings( phaseMap, phase, mojoExecution, settings );
1693 }
1694 }
1695 }
1696 }
1697
1698 private void addToLifecycleMappings( final Map lifecycleMappings, final String phase, final MojoExecution mojoExecution,
1699 final Settings settings )
1700 {
1701 List goals = (List) lifecycleMappings.get( phase );
1702
1703 if ( goals == null )
1704 {
1705 goals = new ArrayList();
1706 lifecycleMappings.put( phase, goals );
1707 }
1708
1709 MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
1710 if ( settings.isOffline() && mojoDescriptor.isOnlineRequired() )
1711 {
1712 String goal = mojoDescriptor.getGoal();
1713 getLogger().warn( goal + " requires online mode, but maven is currently offline. Disabling " + goal + "." );
1714 }
1715 else
1716 {
1717 goals.add( mojoExecution );
1718 }
1719 }
1720
1721 private List processGoalChain( final String task, final Map phaseMap, final Lifecycle lifecycle )
1722 {
1723 List goals = new ArrayList();
1724
1725
1726 int index = lifecycle.getPhases().indexOf( task );
1727
1728 for ( int i = 0; i <= index; i++ )
1729 {
1730 String p = (String) lifecycle.getPhases().get( i );
1731
1732 List phaseGoals = (List) phaseMap.get( p );
1733
1734 if ( phaseGoals != null )
1735 {
1736 goals.addAll( phaseGoals );
1737 }
1738 }
1739 return goals;
1740 }
1741
1742 private MojoDescriptor getMojoDescriptor( final String task, final MavenSession session, final MavenProject project,
1743 final String invokedVia, final boolean canUsePrefix, final boolean isOptionalMojo )
1744 throws BuildFailureException, LifecycleExecutionException, PluginNotFoundException
1745 {
1746 String goal;
1747 Plugin plugin = null;
1748
1749 PluginDescriptor pluginDescriptor = null;
1750
1751 try
1752 {
1753 StringTokenizer tok = new StringTokenizer( task, ":" );
1754 int numTokens = tok.countTokens();
1755
1756 if ( numTokens == 2 )
1757 {
1758 if ( !canUsePrefix )
1759 {
1760 String msg = "Mapped-prefix lookup of mojos are only supported from direct invocation. " +
1761 "Please use specification of the form groupId:artifactId[:version]:goal instead. " +
1762 "(Offending mojo: \'" + task + "\', invoked via: \'" + invokedVia + "\')";
1763 throw new LifecycleExecutionException( msg );
1764 }
1765
1766 String prefix = tok.nextToken();
1767 goal = tok.nextToken();
1768
1769
1770
1771 pluginDescriptor = pluginManager.getPluginDescriptorForPrefix( prefix );
1772 if ( pluginDescriptor != null )
1773 {
1774 plugin = new Plugin();
1775 plugin.setGroupId( pluginDescriptor.getGroupId() );
1776 plugin.setArtifactId( pluginDescriptor.getArtifactId() );
1777 plugin.setVersion( pluginDescriptor.getVersion() );
1778 }
1779
1780
1781 if ( plugin == null )
1782 {
1783 for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext(); )
1784 {
1785 Plugin buildPlugin = (Plugin) i.next();
1786
1787 PluginDescriptor desc =
1788 verifyPlugin( buildPlugin, project, session );
1789 if ( prefix.equals( desc.getGoalPrefix() ) )
1790 {
1791 plugin = buildPlugin;
1792 pluginDescriptor = desc;
1793 break;
1794 }
1795 }
1796 }
1797
1798
1799 if ( plugin == null )
1800 {
1801 plugin = pluginManager.getPluginDefinitionForPrefix( prefix, session, project );
1802 }
1803
1804
1805 if ( plugin == null )
1806 {
1807 plugin = new Plugin();
1808 plugin.setGroupId( PluginDescriptor.getDefaultPluginGroupId() );
1809 plugin.setArtifactId( PluginDescriptor.getDefaultPluginArtifactId( prefix ) );
1810 }
1811 }
1812 else if ( numTokens == 3 || numTokens == 4 )
1813 {
1814 plugin = new Plugin();
1815
1816 plugin.setGroupId( tok.nextToken() );
1817 plugin.setArtifactId( tok.nextToken() );
1818
1819 if ( numTokens == 4 )
1820 {
1821 plugin.setVersion( tok.nextToken() );
1822 }
1823
1824 goal = tok.nextToken();
1825 }
1826 else
1827 {
1828 String message = "Invalid task '" + task + "': you must specify a valid lifecycle phase, or" +
1829 " a goal in the format plugin:goal or pluginGroupId:pluginArtifactId:pluginVersion:goal";
1830 throw new BuildFailureException( message );
1831 }
1832
1833 if ( plugin.getVersion() == null )
1834 {
1835 for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext(); )
1836 {
1837 Plugin buildPlugin = (Plugin) i.next();
1838
1839 if ( buildPlugin.getKey().equals( plugin.getKey() ) )
1840 {
1841 plugin = buildPlugin;
1842 break;
1843 }
1844 }
1845
1846 project.injectPluginManagementInfo( plugin );
1847 }
1848
1849 if ( pluginDescriptor == null )
1850 {
1851 pluginDescriptor = verifyPlugin( plugin, project, session );
1852 }
1853
1854
1855
1856 project.addPlugin( plugin );
1857
1858 MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( goal );
1859 if ( mojoDescriptor == null )
1860 {
1861 if ( isOptionalMojo )
1862 {
1863 getLogger().info( "Skipping missing optional mojo: " + task );
1864 }
1865 else
1866 {
1867 throw new BuildFailureException( "Required goal not found: " + task + " in "
1868 + pluginDescriptor.getId() );
1869 }
1870 }
1871
1872 return mojoDescriptor;
1873 }
1874 catch ( PluginNotFoundException e )
1875 {
1876 if ( isOptionalMojo )
1877 {
1878 getLogger().info( "Skipping missing optional mojo: " + task );
1879 getLogger().debug( "Mojo: " + task + " could not be found. Reason: " + e.getMessage(), e );
1880 }
1881 else
1882 {
1883 throw e;
1884 }
1885 }
1886
1887 return null;
1888 }
1889
1890 protected void line()
1891 {
1892 getLogger().info( "------------------------------------------------------------------------" );
1893 }
1894
1895 public Map getPhaseToLifecycleMap()
1896 throws LifecycleExecutionException
1897 {
1898 if ( phaseToLifecycleMap == null )
1899 {
1900 phaseToLifecycleMap = new HashMap();
1901
1902 for ( Iterator i = lifecycles.iterator(); i.hasNext(); )
1903 {
1904 Lifecycle lifecycle = (Lifecycle) i.next();
1905
1906 for ( Iterator p = lifecycle.getPhases().iterator(); p.hasNext(); )
1907 {
1908 String phase = (String) p.next();
1909
1910 if ( phaseToLifecycleMap.containsKey( phase ) )
1911 {
1912 Lifecycle prevLifecycle = (Lifecycle) phaseToLifecycleMap.get( phase );
1913 throw new LifecycleExecutionException( "Phase '" + phase +
1914 "' is defined in more than one lifecycle: '" + lifecycle.getId() + "' and '" +
1915 prevLifecycle.getId() + "'" );
1916 }
1917 else
1918 {
1919 phaseToLifecycleMap.put( phase, lifecycle );
1920 }
1921 }
1922 }
1923 }
1924 return phaseToLifecycleMap;
1925 }
1926
1927 private static class TaskSegment
1928 {
1929 private boolean aggregate;
1930
1931 private final List tasks = new ArrayList();
1932
1933 TaskSegment()
1934 {
1935
1936 }
1937
1938 TaskSegment( final boolean aggregate )
1939 {
1940 this.aggregate = aggregate;
1941 }
1942
1943 public String toString()
1944 {
1945 StringBuffer message = new StringBuffer();
1946
1947 message.append( " task-segment: [" );
1948
1949 for ( Iterator it = tasks.iterator(); it.hasNext(); )
1950 {
1951 String task = (String) it.next();
1952
1953 message.append( task );
1954
1955 if ( it.hasNext() )
1956 {
1957 message.append( ", " );
1958 }
1959 }
1960
1961 message.append( "]" );
1962
1963 if ( aggregate )
1964 {
1965 message.append( " (aggregator-style)" );
1966 }
1967
1968 return message.toString();
1969 }
1970
1971 boolean aggregate()
1972 {
1973 return aggregate;
1974 }
1975
1976 void add( final String task )
1977 {
1978 tasks.add( task );
1979 }
1980
1981 List getTasks()
1982 {
1983 return tasks;
1984 }
1985 }
1986
1987 public List getLifecycles()
1988 {
1989 return lifecycles;
1990 }
1991
1992
1993
1994
1995
1996
1997 public void initialize()
1998 throws InitializationException
1999 {
2000 if ( mavenProjectBuilder == null )
2001 {
2002 warnOfIncompleteComponentConfiguration( MavenProjectBuilder.ROLE );
2003 try
2004 {
2005 mavenProjectBuilder = (MavenProjectBuilder) container.lookup( MavenProjectBuilder.ROLE );
2006 }
2007 catch ( ComponentLookupException e )
2008 {
2009 throw new InitializationException( "Failed to lookup project builder after it was NOT injected via component requirement." );
2010 }
2011 }
2012
2013 if ( modelInterpolator == null )
2014 {
2015 warnOfIncompleteComponentConfiguration( ModelInterpolator.ROLE );
2016 try
2017 {
2018 modelInterpolator = (ModelInterpolator) container.lookup( ModelInterpolator.ROLE );
2019 }
2020 catch ( ComponentLookupException e )
2021 {
2022 throw new InitializationException( "Failed to lookup model interpolator after it was NOT injected via component requirement." );
2023 }
2024 }
2025
2026 if ( configInterpolator == null )
2027 {
2028 warnOfIncompleteComponentConfiguration( ConfigurationInterpolator.ROLE );
2029 try
2030 {
2031 configInterpolator = (ConfigurationInterpolator) container.lookup( ConfigurationInterpolator.ROLE );
2032 }
2033 catch ( ComponentLookupException e )
2034 {
2035 throw new InitializationException( "Failed to lookup plugin-configuration interpolator after it was NOT injected via component requirement." );
2036 }
2037 }
2038 }
2039
2040 private void warnOfIncompleteComponentConfiguration( final String role )
2041 {
2042 StringBuffer buffer = new StringBuffer();
2043 buffer.append( "\n************ WARNING ************" );
2044 buffer.append( "\n\nThis Maven runtime contains a LifecycleExecutor component with an incomplete configuration." );
2045 buffer.append( "\n\nLifecycleExecutor class: " ).append( getClass().getName() );
2046 buffer.append( "\nMissing component requirement: " ).append( role );
2047 buffer.append( "\n" );
2048 buffer.append( "\nNOTE: This seems to be a third-party Maven derivative you are using. If so, please" );
2049 buffer.append( "\nnotify the developers for this derivative project of the problem. The Apache Maven team is not" );
2050 buffer.append( "\nresponsible for maintaining the integrity of third-party component overrides." );
2051 buffer.append( "\n\n" );
2052
2053 getLogger().warn( buffer.toString() );
2054 }
2055
2056 private PlexusContainer container;
2057
2058 public void contextualize( final Context context )
2059 throws ContextException
2060 {
2061 container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
2062 }
2063 }