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