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, MojoExecution.CLI_EXECUTION_ID ) ),
554 forkEntryPoints, session, 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, mojoExecution.getExecutionId() );
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, forkedExecution.getExecutionId() );
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 else
934 {
935 id = mojoExecution.getExecutionId();
936 }
937
938 MojoExecution reportExecution;
939 if ( id.startsWith( MojoExecution.DEFAULT_EXEC_ID_PREFIX ) )
940 {
941 reportExecution = new MojoExecution( mojoDescriptor );
942 }
943 else
944 {
945 reportExecution = new MojoExecution( mojoDescriptor, id );
946 }
947
948 reports.add( reportExecution );
949 }
950 }
951 return reports;
952 }
953
954 private List getReports( List reportExecutions, MavenProject project, MojoExecution mojoExecution, MavenSession session )
955 throws LifecycleExecutionException
956 {
957 List reports = new ArrayList();
958
959 for ( Iterator it = reportExecutions.iterator(); it.hasNext(); )
960 {
961 MojoExecution reportExecution = (MojoExecution) it.next();
962 PluginDescriptor pluginDescriptor = reportExecution.getMojoDescriptor().getPluginDescriptor();
963
964 try
965 {
966 MavenReport reportMojo = pluginManager.getReport( project, reportExecution, session );
967
968
969 if ( reportMojo != null )
970 {
971 reports.add( reportMojo );
972 mojoExecution.addMojoExecution( reportExecution );
973 }
974 }
975 catch ( PluginManagerException e )
976 {
977 throw new LifecycleExecutionException(
978 "Error getting reports from the plugin '" + pluginDescriptor.getId() + "': " + e.getMessage(), e );
979 }
980 catch ( PluginConfigurationException e )
981 {
982 throw new LifecycleExecutionException(
983 "Error getting reports from the plugin '" + pluginDescriptor.getId() + "'", e );
984 }
985 catch ( ArtifactNotFoundException e )
986 {
987 throw new LifecycleExecutionException( e.getMessage(), e );
988 }
989 catch ( ArtifactResolutionException e )
990 {
991 throw new LifecycleExecutionException( e.getMessage(), e );
992 }
993 }
994
995 return reports;
996 }
997
998 private void forkLifecycle( MojoDescriptor mojoDescriptor, Stack ancestorLifecycleForkers, MavenSession session,
999 MavenProject project, String executionId )
1000 throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
1001 {
1002 PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
1003 getLogger().info( "Preparing " + pluginDescriptor.getGoalPrefix() + ":" + mojoDescriptor.getGoal() );
1004
1005 if ( mojoDescriptor.isAggregator() )
1006 {
1007 for ( Iterator i = session.getSortedProjects().iterator(); i.hasNext(); )
1008 {
1009 MavenProject reactorProject = (MavenProject) i.next();
1010
1011 line();
1012
1013 getLogger().info( "Building " + reactorProject.getName() );
1014
1015 line();
1016
1017 forkProjectLifecycle( mojoDescriptor, ancestorLifecycleForkers, session, reactorProject, executionId );
1018 }
1019 }
1020 else
1021 {
1022 forkProjectLifecycle( mojoDescriptor, ancestorLifecycleForkers, session, project, executionId );
1023 }
1024 }
1025
1026 private void forkProjectLifecycle( MojoDescriptor mojoDescriptor, Stack forkEntryPoints, MavenSession session,
1027 MavenProject project, String executionId )
1028 throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
1029 {
1030 project = project.getExecutionProject();
1031
1032 forkEntryPoints.push( mojoDescriptor );
1033
1034 PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
1035
1036 String targetPhase = mojoDescriptor.getExecutePhase();
1037
1038 Map lifecycleMappings = null;
1039 if ( targetPhase != null )
1040 {
1041 Lifecycle lifecycle = getLifecycleForPhase( targetPhase );
1042
1043
1044 lifecycleMappings = constructLifecycleMappings( session, targetPhase, project, lifecycle );
1045
1046 String executeLifecycle = mojoDescriptor.getExecuteLifecycle();
1047 if ( executeLifecycle != null )
1048 {
1049 org.apache.maven.plugin.lifecycle.Lifecycle lifecycleOverlay;
1050 try
1051 {
1052 lifecycleOverlay = pluginDescriptor.getLifecycleMapping( executeLifecycle );
1053 }
1054 catch ( IOException e )
1055 {
1056 throw new LifecycleExecutionException( "Unable to read lifecycle mapping file: " + e.getMessage(),
1057 e );
1058 }
1059 catch ( XmlPullParserException e )
1060 {
1061 throw new LifecycleExecutionException( "Unable to parse lifecycle mapping file: " + e.getMessage(),
1062 e );
1063 }
1064
1065 if ( lifecycleOverlay == null )
1066 {
1067 throw new LifecycleExecutionException( "Lifecycle '" + executeLifecycle + "' not found in plugin" );
1068 }
1069
1070 for ( Iterator i = lifecycleOverlay.getPhases().iterator(); i.hasNext(); )
1071 {
1072 Phase phase = (Phase) i.next();
1073 for ( Iterator j = phase.getExecutions().iterator(); j.hasNext(); )
1074 {
1075 Execution exec = (Execution) j.next();
1076
1077 for ( Iterator k = exec.getGoals().iterator(); k.hasNext(); )
1078 {
1079 String goal = (String) k.next();
1080
1081 PluginDescriptor lifecyclePluginDescriptor;
1082 String lifecycleGoal;
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110 if ( goal.indexOf( ":" ) > 0 )
1111 {
1112 String[] s = StringUtils.split( goal, ":" );
1113
1114 String groupId = s[0];
1115 String artifactId = s[1];
1116 lifecycleGoal = s[2];
1117
1118 Plugin plugin = new Plugin();
1119 plugin.setGroupId( groupId );
1120 plugin.setArtifactId( artifactId );
1121 lifecyclePluginDescriptor = verifyPlugin( plugin, project, session.getSettings(),
1122 session.getLocalRepository() );
1123 if ( lifecyclePluginDescriptor == null )
1124 {
1125 throw new LifecycleExecutionException(
1126 "Unable to find plugin " + groupId + ":" + artifactId );
1127 }
1128 }
1129 else
1130 {
1131 lifecyclePluginDescriptor = pluginDescriptor;
1132 lifecycleGoal = goal;
1133 }
1134
1135 Xpp3Dom configuration = (Xpp3Dom) exec.getConfiguration();
1136
1137 if ( phase.getConfiguration() != null )
1138 {
1139 configuration = Xpp3Dom.mergeXpp3Dom( new Xpp3Dom( (Xpp3Dom) phase.getConfiguration() ),
1140 configuration );
1141 }
1142
1143 MojoDescriptor desc = getMojoDescriptor( lifecyclePluginDescriptor, lifecycleGoal );
1144 MojoExecution mojoExecution;
1145 if ( executionId.startsWith( MojoExecution.DEFAULT_EXEC_ID_PREFIX ) )
1146 {
1147 mojoExecution = new MojoExecution( desc, configuration );
1148 }
1149 else
1150 {
1151 mojoExecution = new MojoExecution( desc, configuration, executionId );
1152 }
1153
1154 addToLifecycleMappings( lifecycleMappings, phase.getId(), mojoExecution,
1155 session.getSettings() );
1156 }
1157 }
1158
1159 if ( phase.getConfiguration() != null )
1160 {
1161
1162
1163
1164 for ( Iterator j = lifecycleMappings.values().iterator(); j.hasNext(); )
1165 {
1166 List tasks = (List) j.next();
1167
1168 for ( Iterator k = tasks.iterator(); k.hasNext(); )
1169 {
1170 MojoExecution exec = (MojoExecution) k.next();
1171
1172 Xpp3Dom configuration = Xpp3Dom.mergeXpp3Dom(
1173 new Xpp3Dom( (Xpp3Dom) phase.getConfiguration() ), exec.getConfiguration() );
1174
1175 exec.setConfiguration( configuration );
1176 }
1177 }
1178 }
1179
1180 }
1181 }
1182
1183 removeFromLifecycle( forkEntryPoints, lifecycleMappings );
1184 }
1185
1186 if ( targetPhase != null )
1187 {
1188 Lifecycle lifecycle = getLifecycleForPhase( targetPhase );
1189
1190 executeGoalWithLifecycle( targetPhase, forkEntryPoints, session, lifecycleMappings, project, lifecycle );
1191 }
1192 else
1193 {
1194 String goal = mojoDescriptor.getExecuteGoal();
1195 MojoDescriptor desc = getMojoDescriptor( pluginDescriptor, goal );
1196 executeGoals( Collections.singletonList( new MojoExecution( desc, goal ) ), forkEntryPoints, session, project );
1197 }
1198 }
1199
1200 private Lifecycle getLifecycleForPhase( String phase )
1201 throws BuildFailureException, LifecycleExecutionException
1202 {
1203 Lifecycle lifecycle = (Lifecycle) getPhaseToLifecycleMap().get( phase );
1204
1205 if ( lifecycle == null )
1206 {
1207 throw new BuildFailureException( "Unable to find lifecycle for phase '" + phase + "'" );
1208 }
1209 return lifecycle;
1210 }
1211
1212 private MojoDescriptor getMojoDescriptor( PluginDescriptor pluginDescriptor, String goal )
1213 throws LifecycleExecutionException
1214 {
1215 MojoDescriptor desc = pluginDescriptor.getMojo( goal );
1216
1217 if ( desc == null )
1218 {
1219 String message =
1220 "Required goal '" + goal + "' not found in plugin '" + pluginDescriptor.getGoalPrefix() + "'";
1221 int index = goal.indexOf( ':' );
1222 if ( index >= 0 )
1223 {
1224 String prefix = goal.substring( index + 1 );
1225 if ( prefix.equals( pluginDescriptor.getGoalPrefix() ) )
1226 {
1227 message = message + " (goals should not be prefixed - try '" + prefix + "')";
1228 }
1229 }
1230 throw new LifecycleExecutionException( message );
1231 }
1232 return desc;
1233 }
1234
1235 private void removeFromLifecycle( Stack lifecycleForkers, Map lifecycleMappings )
1236 {
1237 for ( Iterator lifecycleIterator = lifecycleMappings.values().iterator(); lifecycleIterator.hasNext(); )
1238 {
1239 List tasks = (List) lifecycleIterator.next();
1240
1241 for ( Iterator taskIterator = tasks.iterator(); taskIterator.hasNext(); )
1242 {
1243 MojoExecution execution = (MojoExecution) taskIterator.next();
1244
1245 if ( lifecycleForkers.contains( execution.getMojoDescriptor() ) )
1246 {
1247 taskIterator.remove();
1248 getLogger().warn( "Removing: " + execution.getMojoDescriptor().getGoal()
1249 + " from forked lifecycle, to prevent recursive invocation." );
1250 }
1251 }
1252 }
1253 }
1254
1255 private Map constructLifecycleMappings( MavenSession session, String selectedPhase, MavenProject project,
1256 Lifecycle lifecycle )
1257 throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
1258 {
1259
1260 Map lifecycleMappings = bindLifecycleForPackaging( session, selectedPhase, project, lifecycle );
1261
1262
1263 for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext(); )
1264 {
1265 Plugin plugin = (Plugin) i.next();
1266
1267 bindPluginToLifecycle( plugin, session, lifecycleMappings, project );
1268 }
1269
1270 return lifecycleMappings;
1271 }
1272
1273 private Map bindLifecycleForPackaging( MavenSession session, String selectedPhase, MavenProject project,
1274 Lifecycle lifecycle )
1275 throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
1276 {
1277 Map mappings = findMappingsForLifecycle( session, project, lifecycle );
1278
1279 List optionalMojos = findOptionalMojosForLifecycle( session, project, lifecycle );
1280
1281 Map lifecycleMappings = new HashMap();
1282
1283 for ( Iterator i = lifecycle.getPhases().iterator(); i.hasNext(); )
1284 {
1285 String phase = (String) i.next();
1286
1287 String phaseTasks = (String) mappings.get( phase );
1288
1289 if ( phaseTasks != null )
1290 {
1291 for ( StringTokenizer tok = new StringTokenizer( phaseTasks, "," ); tok.hasMoreTokens(); )
1292 {
1293 String goal = tok.nextToken().trim();
1294
1295
1296 MojoDescriptor mojoDescriptor = getMojoDescriptor( goal, session, project, selectedPhase, false,
1297 optionalMojos.contains( goal ) );
1298
1299 if ( mojoDescriptor == null )
1300 {
1301 continue;
1302 }
1303
1304 if ( mojoDescriptor.isDirectInvocationOnly() )
1305 {
1306 throw new LifecycleExecutionException( "Mojo: \'" + goal +
1307 "\' requires direct invocation. It cannot be used as part of lifecycle: \'" +
1308 project.getPackaging() + "\'." );
1309 }
1310
1311 addToLifecycleMappings( lifecycleMappings, phase, new MojoExecution( mojoDescriptor ),
1312 session.getSettings() );
1313 }
1314 }
1315
1316 if ( phase.equals( selectedPhase ) )
1317 {
1318 break;
1319 }
1320 }
1321
1322 return lifecycleMappings;
1323 }
1324
1325 private Map findMappingsForLifecycle( MavenSession session, MavenProject project, Lifecycle lifecycle )
1326 throws LifecycleExecutionException, PluginNotFoundException
1327 {
1328 String packaging = project.getPackaging();
1329 Map mappings = null;
1330
1331 LifecycleMapping m = (LifecycleMapping) findExtension( project, LifecycleMapping.ROLE, packaging,
1332 session.getSettings(), session.getLocalRepository() );
1333 if ( m != null )
1334 {
1335 mappings = m.getPhases( lifecycle.getId() );
1336 }
1337
1338 Map defaultMappings = lifecycle.getDefaultPhases();
1339
1340 if ( mappings == null )
1341 {
1342 try
1343 {
1344 m = (LifecycleMapping) session.lookup( LifecycleMapping.ROLE, packaging );
1345 mappings = m.getPhases( lifecycle.getId() );
1346 }
1347 catch ( ComponentLookupException e )
1348 {
1349 if ( defaultMappings == null )
1350 {
1351 throw new LifecycleExecutionException(
1352 "Cannot find lifecycle mapping for packaging: \'" + packaging + "\'.", e );
1353 }
1354 }
1355 }
1356
1357 if ( mappings == null )
1358 {
1359 if ( defaultMappings == null )
1360 {
1361 throw new LifecycleExecutionException(
1362 "Cannot find lifecycle mapping for packaging: \'" + packaging + "\', and there is no default" );
1363 }
1364 else
1365 {
1366 mappings = defaultMappings;
1367 }
1368 }
1369
1370 return mappings;
1371 }
1372
1373 private List findOptionalMojosForLifecycle( MavenSession session, MavenProject project, Lifecycle lifecycle )
1374 throws LifecycleExecutionException, PluginNotFoundException
1375 {
1376 String packaging = project.getPackaging();
1377 List optionalMojos = null;
1378
1379 LifecycleMapping m = (LifecycleMapping) findExtension( project, LifecycleMapping.ROLE, packaging, session
1380 .getSettings(), session.getLocalRepository() );
1381
1382 if ( m != null )
1383 {
1384 optionalMojos = m.getOptionalMojos( lifecycle.getId() );
1385 }
1386
1387 if ( optionalMojos == null )
1388 {
1389 try
1390 {
1391 m = (LifecycleMapping) session.lookup( LifecycleMapping.ROLE, packaging );
1392 optionalMojos = m.getOptionalMojos( lifecycle.getId() );
1393 }
1394 catch ( ComponentLookupException e )
1395 {
1396 getLogger().debug( "Error looking up lifecycle mapping to retrieve optional mojos. Lifecycle ID: " +
1397 lifecycle.getId() + ". Error: " + e.getMessage(), e );
1398 }
1399 }
1400
1401 if ( optionalMojos == null )
1402 {
1403 optionalMojos = Collections.EMPTY_LIST;
1404 }
1405
1406 return optionalMojos;
1407 }
1408
1409 private Object findExtension( MavenProject project, String role, String roleHint, Settings settings,
1410 ArtifactRepository localRepository )
1411 throws LifecycleExecutionException, PluginNotFoundException
1412 {
1413 Object pluginComponent = null;
1414
1415 for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext() && pluginComponent == null; )
1416 {
1417 Plugin plugin = (Plugin) i.next();
1418
1419 if ( plugin.isExtensions() )
1420 {
1421 verifyPlugin( plugin, project, settings, localRepository );
1422
1423
1424 try
1425 {
1426 pluginComponent = pluginManager.getPluginComponent( plugin, role, roleHint );
1427 }
1428 catch ( ComponentLookupException e )
1429 {
1430 getLogger().debug( "Unable to find the lifecycle component in the extension", e );
1431 }
1432 catch ( PluginManagerException e )
1433 {
1434 throw new LifecycleExecutionException(
1435 "Error getting extensions from the plugin '" + plugin.getKey() + "': " + e.getMessage(), e );
1436 }
1437 }
1438 }
1439 return pluginComponent;
1440 }
1441
1442
1443
1444
1445
1446 private Map findArtifactTypeHandlers( MavenProject project, Settings settings, ArtifactRepository localRepository )
1447 throws LifecycleExecutionException, PluginNotFoundException
1448 {
1449 Map map = new HashMap();
1450 for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext(); )
1451 {
1452 Plugin plugin = (Plugin) i.next();
1453
1454 if ( plugin.isExtensions() )
1455 {
1456 verifyPlugin( plugin, project, settings, localRepository );
1457
1458
1459 try
1460 {
1461 Map components = pluginManager.getPluginComponents( plugin, ArtifactHandler.ROLE );
1462 map.putAll( components );
1463 }
1464 catch ( ComponentLookupException e )
1465 {
1466 getLogger().debug( "Unable to find the lifecycle component in the extension", e );
1467 }
1468 catch ( PluginManagerException e )
1469 {
1470 throw new LifecycleExecutionException( "Error looking up available components from plugin '" +
1471 plugin.getKey() + "': " + e.getMessage(), e );
1472 }
1473
1474
1475 for ( Iterator j = map.values().iterator(); j.hasNext(); )
1476 {
1477 ArtifactHandler handler = (ArtifactHandler) j.next();
1478 if ( project.getPackaging().equals( handler.getPackaging() ) )
1479 {
1480 project.getArtifact().setArtifactHandler( handler );
1481 }
1482 }
1483 }
1484 }
1485 return map;
1486 }
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496 private void bindPluginToLifecycle( Plugin plugin, MavenSession session, Map phaseMap, MavenProject project )
1497 throws LifecycleExecutionException, PluginNotFoundException
1498 {
1499 Settings settings = session.getSettings();
1500
1501 PluginDescriptor pluginDescriptor =
1502 verifyPlugin( plugin, project, session.getSettings(), session.getLocalRepository() );
1503
1504 if ( pluginDescriptor.getMojos() != null && !pluginDescriptor.getMojos().isEmpty() )
1505 {
1506
1507 if ( plugin.isInheritanceApplied() || pluginDescriptor.isInheritedByDefault() )
1508 {
1509 if ( plugin.getGoals() != null )
1510 {
1511 getLogger().error(
1512 "Plugin contains a <goals/> section: this is IGNORED - please use <executions/> instead." );
1513 }
1514
1515 List executions = plugin.getExecutions();
1516
1517 if ( executions != null )
1518 {
1519 for ( Iterator it = executions.iterator(); it.hasNext(); )
1520 {
1521 PluginExecution execution = (PluginExecution) it.next();
1522
1523 bindExecutionToLifecycle( pluginDescriptor, phaseMap, execution, settings );
1524 }
1525 }
1526 }
1527 }
1528 }
1529
1530 private PluginDescriptor verifyPlugin( Plugin plugin, MavenProject project, Settings settings,
1531 ArtifactRepository localRepository )
1532 throws LifecycleExecutionException, PluginNotFoundException
1533 {
1534 PluginDescriptor pluginDescriptor;
1535 try
1536 {
1537
1538
1539 pluginDescriptor = pluginManager.verifyPlugin( plugin, project, settings, localRepository );
1540 }
1541 catch ( PluginManagerException e )
1542 {
1543 throw new LifecycleExecutionException(
1544 "Internal error in the plugin manager getting plugin '" + plugin.getKey() + "': " + e.getMessage(), e );
1545 }
1546 catch ( PluginVersionResolutionException e )
1547 {
1548 throw new LifecycleExecutionException( e.getMessage(), e );
1549 }
1550 catch ( InvalidVersionSpecificationException e )
1551 {
1552 throw new LifecycleExecutionException( e.getMessage(), e );
1553 }
1554 catch ( InvalidPluginException e )
1555 {
1556 throw new LifecycleExecutionException( e.getMessage(), e );
1557 }
1558 catch ( ArtifactNotFoundException e )
1559 {
1560 throw new LifecycleExecutionException( e.getMessage(), e );
1561 }
1562 catch ( ArtifactResolutionException e )
1563 {
1564 throw new LifecycleExecutionException( e.getMessage(), e );
1565 }
1566 catch ( PluginVersionNotFoundException e )
1567 {
1568 throw new LifecycleExecutionException( e.getMessage(), e );
1569 }
1570 return pluginDescriptor;
1571 }
1572
1573 private PluginDescriptor verifyReportPlugin( ReportPlugin plugin, MavenProject project, MavenSession session )
1574 throws LifecycleExecutionException, PluginNotFoundException
1575 {
1576 PluginDescriptor pluginDescriptor;
1577 try
1578 {
1579 pluginDescriptor = pluginManager.verifyReportPlugin( plugin, project, session );
1580 }
1581 catch ( PluginManagerException e )
1582 {
1583 throw new LifecycleExecutionException(
1584 "Internal error in the plugin manager getting report '" + plugin.getKey() + "': " + e.getMessage(), e );
1585 }
1586 catch ( PluginVersionResolutionException e )
1587 {
1588 throw new LifecycleExecutionException( e.getMessage(), e );
1589 }
1590 catch ( InvalidVersionSpecificationException e )
1591 {
1592 throw new LifecycleExecutionException( e.getMessage(), e );
1593 }
1594 catch ( InvalidPluginException e )
1595 {
1596 throw new LifecycleExecutionException( e.getMessage(), e );
1597 }
1598 catch ( ArtifactNotFoundException e )
1599 {
1600 throw new LifecycleExecutionException( e.getMessage(), e );
1601 }
1602 catch ( ArtifactResolutionException e )
1603 {
1604 throw new LifecycleExecutionException( e.getMessage(), e );
1605 }
1606 catch ( PluginVersionNotFoundException e )
1607 {
1608 throw new LifecycleExecutionException( e.getMessage(), e );
1609 }
1610 return pluginDescriptor;
1611 }
1612
1613 private void bindExecutionToLifecycle( PluginDescriptor pluginDescriptor, Map phaseMap, PluginExecution execution,
1614 Settings settings )
1615 throws LifecycleExecutionException
1616 {
1617 for ( Iterator i = execution.getGoals().iterator(); i.hasNext(); )
1618 {
1619 String goal = (String) i.next();
1620
1621 MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( goal );
1622 if ( mojoDescriptor == null )
1623 {
1624 throw new LifecycleExecutionException(
1625 "'" + goal + "' was specified in an execution, but not found in the plugin" );
1626 }
1627
1628
1629 if ( execution.isInheritanceApplied() || mojoDescriptor.isInheritedByDefault() )
1630 {
1631 MojoExecution mojoExecution = new MojoExecution( mojoDescriptor, execution.getId() );
1632
1633 String phase = execution.getPhase();
1634
1635 if ( phase == null )
1636 {
1637
1638 phase = mojoDescriptor.getPhase();
1639 }
1640
1641 if ( phase != null )
1642 {
1643 if ( mojoDescriptor.isDirectInvocationOnly() )
1644 {
1645 throw new LifecycleExecutionException( "Mojo: \'" + goal +
1646 "\' requires direct invocation. It cannot be used as part of the lifecycle (it was included via the POM)." );
1647 }
1648
1649 addToLifecycleMappings( phaseMap, phase, mojoExecution, settings );
1650 }
1651 }
1652 }
1653 }
1654
1655 private void addToLifecycleMappings( Map lifecycleMappings, String phase, MojoExecution mojoExecution,
1656 Settings settings )
1657 {
1658 List goals = (List) lifecycleMappings.get( phase );
1659
1660 if ( goals == null )
1661 {
1662 goals = new ArrayList();
1663 lifecycleMappings.put( phase, goals );
1664 }
1665
1666 MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
1667 if ( settings.isOffline() && mojoDescriptor.isOnlineRequired() )
1668 {
1669 String goal = mojoDescriptor.getGoal();
1670 getLogger().warn( goal + " requires online mode, but maven is currently offline. Disabling " + goal + "." );
1671 }
1672 else
1673 {
1674 goals.add( mojoExecution );
1675 }
1676 }
1677
1678 private List processGoalChain( String task, Map phaseMap, Lifecycle lifecycle )
1679 {
1680 List goals = new ArrayList();
1681
1682
1683 int index = lifecycle.getPhases().indexOf( task );
1684
1685 for ( int i = 0; i <= index; i++ )
1686 {
1687 String p = (String) lifecycle.getPhases().get( i );
1688
1689 List phaseGoals = (List) phaseMap.get( p );
1690
1691 if ( phaseGoals != null )
1692 {
1693 goals.addAll( phaseGoals );
1694 }
1695 }
1696 return goals;
1697 }
1698
1699 private MojoDescriptor getMojoDescriptor( String task, MavenSession session, MavenProject project,
1700 String invokedVia, boolean canUsePrefix, boolean isOptionalMojo )
1701 throws BuildFailureException, LifecycleExecutionException, PluginNotFoundException
1702 {
1703 String goal;
1704 Plugin plugin = null;
1705
1706 PluginDescriptor pluginDescriptor = null;
1707
1708 try
1709 {
1710 StringTokenizer tok = new StringTokenizer( task, ":" );
1711 int numTokens = tok.countTokens();
1712
1713 if ( numTokens == 2 )
1714 {
1715 if ( !canUsePrefix )
1716 {
1717 String msg = "Mapped-prefix lookup of mojos are only supported from direct invocation. " +
1718 "Please use specification of the form groupId:artifactId[:version]:goal instead. " +
1719 "(Offending mojo: \'" + task + "\', invoked via: \'" + invokedVia + "\')";
1720 throw new LifecycleExecutionException( msg );
1721 }
1722
1723 String prefix = tok.nextToken();
1724 goal = tok.nextToken();
1725
1726
1727
1728 pluginDescriptor = pluginManager.getPluginDescriptorForPrefix( prefix );
1729 if ( pluginDescriptor != null )
1730 {
1731 plugin = new Plugin();
1732 plugin.setGroupId( pluginDescriptor.getGroupId() );
1733 plugin.setArtifactId( pluginDescriptor.getArtifactId() );
1734 plugin.setVersion( pluginDescriptor.getVersion() );
1735 }
1736
1737
1738 if ( plugin == null )
1739 {
1740 for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext(); )
1741 {
1742 Plugin buildPlugin = (Plugin) i.next();
1743
1744 PluginDescriptor desc =
1745 verifyPlugin( buildPlugin, project, session.getSettings(), session.getLocalRepository() );
1746 if ( prefix.equals( desc.getGoalPrefix() ) )
1747 {
1748 plugin = buildPlugin;
1749 pluginDescriptor = desc;
1750 break;
1751 }
1752 }
1753 }
1754
1755
1756 if ( plugin == null )
1757 {
1758 plugin = pluginManager.getPluginDefinitionForPrefix( prefix, session, project );
1759 }
1760
1761
1762 if ( plugin == null )
1763 {
1764 plugin = new Plugin();
1765 plugin.setGroupId( PluginDescriptor.getDefaultPluginGroupId() );
1766 plugin.setArtifactId( PluginDescriptor.getDefaultPluginArtifactId( prefix ) );
1767 }
1768 }
1769 else if ( numTokens == 3 || numTokens == 4 )
1770 {
1771 plugin = new Plugin();
1772
1773 plugin.setGroupId( tok.nextToken() );
1774 plugin.setArtifactId( tok.nextToken() );
1775
1776 if ( numTokens == 4 )
1777 {
1778 plugin.setVersion( tok.nextToken() );
1779 }
1780
1781 goal = tok.nextToken();
1782 }
1783 else
1784 {
1785 String message = "Invalid task '" + task + "': you must specify a valid lifecycle phase, or" +
1786 " a goal in the format plugin:goal or pluginGroupId:pluginArtifactId:pluginVersion:goal";
1787 throw new BuildFailureException( message );
1788 }
1789
1790 if ( plugin.getVersion() == null )
1791 {
1792 for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext(); )
1793 {
1794 Plugin buildPlugin = (Plugin) i.next();
1795
1796 if ( buildPlugin.getKey().equals( plugin.getKey() ) )
1797 {
1798 plugin = buildPlugin;
1799 break;
1800 }
1801 }
1802
1803 project.injectPluginManagementInfo( plugin );
1804 }
1805
1806 if ( pluginDescriptor == null )
1807 {
1808 pluginDescriptor = verifyPlugin( plugin, project, session.getSettings(), session.getLocalRepository() );
1809 }
1810
1811
1812
1813 project.addPlugin( plugin );
1814
1815 MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( goal );
1816 if ( mojoDescriptor == null )
1817 {
1818 if ( isOptionalMojo )
1819 {
1820 getLogger().info( "Skipping missing optional mojo: " + task );
1821 }
1822 else
1823 {
1824 throw new BuildFailureException( "Required goal not found: " + task + " in "
1825 + pluginDescriptor.getId() );
1826 }
1827 }
1828
1829 return mojoDescriptor;
1830 }
1831 catch ( PluginNotFoundException e )
1832 {
1833 if ( isOptionalMojo )
1834 {
1835 getLogger().info( "Skipping missing optional mojo: " + task );
1836 getLogger().debug( "Mojo: " + task + " could not be found. Reason: " + e.getMessage(), e );
1837 }
1838 else
1839 {
1840 throw e;
1841 }
1842 }
1843
1844 return null;
1845 }
1846
1847 protected void line()
1848 {
1849 getLogger().info( "------------------------------------------------------------------------" );
1850 }
1851
1852 public Map getPhaseToLifecycleMap()
1853 throws LifecycleExecutionException
1854 {
1855 if ( phaseToLifecycleMap == null )
1856 {
1857 phaseToLifecycleMap = new HashMap();
1858
1859 for ( Iterator i = lifecycles.iterator(); i.hasNext(); )
1860 {
1861 Lifecycle lifecycle = (Lifecycle) i.next();
1862
1863 for ( Iterator p = lifecycle.getPhases().iterator(); p.hasNext(); )
1864 {
1865 String phase = (String) p.next();
1866
1867 if ( phaseToLifecycleMap.containsKey( phase ) )
1868 {
1869 Lifecycle prevLifecycle = (Lifecycle) phaseToLifecycleMap.get( phase );
1870 throw new LifecycleExecutionException( "Phase '" + phase +
1871 "' is defined in more than one lifecycle: '" + lifecycle.getId() + "' and '" +
1872 prevLifecycle.getId() + "'" );
1873 }
1874 else
1875 {
1876 phaseToLifecycleMap.put( phase, lifecycle );
1877 }
1878 }
1879 }
1880 }
1881 return phaseToLifecycleMap;
1882 }
1883
1884 private static class TaskSegment
1885 {
1886 private boolean aggregate;
1887
1888 private List tasks = new ArrayList();
1889
1890 TaskSegment()
1891 {
1892
1893 }
1894
1895 TaskSegment( boolean aggregate )
1896 {
1897 this.aggregate = aggregate;
1898 }
1899
1900 public String toString()
1901 {
1902 StringBuffer message = new StringBuffer();
1903
1904 message.append( " task-segment: [" );
1905
1906 for ( Iterator it = tasks.iterator(); it.hasNext(); )
1907 {
1908 String task = (String) it.next();
1909
1910 message.append( task );
1911
1912 if ( it.hasNext() )
1913 {
1914 message.append( ", " );
1915 }
1916 }
1917
1918 message.append( "]" );
1919
1920 if ( aggregate )
1921 {
1922 message.append( " (aggregator-style)" );
1923 }
1924
1925 return message.toString();
1926 }
1927
1928 boolean aggregate()
1929 {
1930 return aggregate;
1931 }
1932
1933 void add( String task )
1934 {
1935 tasks.add( task );
1936 }
1937
1938 List getTasks()
1939 {
1940 return tasks;
1941 }
1942 }
1943
1944 public List getLifecycles()
1945 {
1946 return lifecycles;
1947 }
1948
1949
1950
1951
1952
1953
1954 public void initialize()
1955 throws InitializationException
1956 {
1957 if ( mavenProjectBuilder == null )
1958 {
1959 warnOfIncompleteComponentConfiguration( MavenProjectBuilder.ROLE );
1960 try
1961 {
1962 mavenProjectBuilder = (MavenProjectBuilder) container.lookup( MavenProjectBuilder.ROLE );
1963 }
1964 catch ( ComponentLookupException e )
1965 {
1966 throw new InitializationException( "Failed to lookup project builder after it was NOT injected via component requirement." );
1967 }
1968 }
1969
1970 if ( modelInterpolator == null )
1971 {
1972 warnOfIncompleteComponentConfiguration( ModelInterpolator.ROLE );
1973 try
1974 {
1975 modelInterpolator = (ModelInterpolator) container.lookup( ModelInterpolator.ROLE );
1976 }
1977 catch ( ComponentLookupException e )
1978 {
1979 throw new InitializationException( "Failed to lookup model interpolator after it was NOT injected via component requirement." );
1980 }
1981 }
1982
1983 if ( configInterpolator == null )
1984 {
1985 warnOfIncompleteComponentConfiguration( ConfigurationInterpolator.ROLE );
1986 try
1987 {
1988 configInterpolator = (ConfigurationInterpolator) container.lookup( ConfigurationInterpolator.ROLE );
1989 }
1990 catch ( ComponentLookupException e )
1991 {
1992 throw new InitializationException( "Failed to lookup plugin-configuration interpolator after it was NOT injected via component requirement." );
1993 }
1994 }
1995 }
1996
1997 private void warnOfIncompleteComponentConfiguration( String role )
1998 {
1999 StringBuffer buffer = new StringBuffer();
2000 buffer.append( "\n************ WARNING ************" );
2001 buffer.append( "\n\nThis Maven runtime contains a LifecycleExecutor component with an incomplete configuration." );
2002 buffer.append( "\n\nLifecycleExecutor class: " ).append( getClass().getName() );
2003 buffer.append( "\nMissing component requirement: " ).append( role );
2004 buffer.append( "\n" );
2005 buffer.append( "\nNOTE: This seems to be a third-party Maven derivative you are using. If so, please" );
2006 buffer.append( "\nnotify the developers for this derivative project of the problem. The Apache Maven team is not" );
2007 buffer.append( "\nresponsible for maintaining the integrity of third-party component overrides." );
2008 buffer.append( "\n\n" );
2009
2010 getLogger().warn( buffer.toString() );
2011 }
2012
2013 private PlexusContainer container;
2014
2015 public void contextualize( Context context )
2016 throws ContextException
2017 {
2018 container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
2019 }
2020 }