001package org.apache.maven.lifecycle.internal;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.io.IOException;
023import java.util.ArrayList;
024import java.util.Collection;
025import java.util.Collections;
026import java.util.HashSet;
027import java.util.LinkedHashMap;
028import java.util.List;
029import java.util.Map;
030import java.util.TreeMap;
031
032import org.apache.maven.execution.MavenSession;
033import org.apache.maven.lifecycle.DefaultLifecycles;
034import org.apache.maven.lifecycle.DefaultSchedules;
035import org.apache.maven.lifecycle.Lifecycle;
036import org.apache.maven.lifecycle.LifecycleNotFoundException;
037import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
038import org.apache.maven.lifecycle.MavenExecutionPlan;
039import org.apache.maven.model.Plugin;
040import org.apache.maven.model.PluginExecution;
041import org.apache.maven.plugin.BuildPluginManager;
042import org.apache.maven.plugin.InvalidPluginDescriptorException;
043import org.apache.maven.plugin.MojoExecution;
044import org.apache.maven.plugin.MojoNotFoundException;
045import org.apache.maven.plugin.PluginDescriptorParsingException;
046import org.apache.maven.plugin.PluginNotFoundException;
047import org.apache.maven.plugin.PluginResolutionException;
048import org.apache.maven.plugin.descriptor.MojoDescriptor;
049import org.apache.maven.plugin.descriptor.Parameter;
050import org.apache.maven.plugin.descriptor.PluginDescriptor;
051import org.apache.maven.plugin.lifecycle.Execution;
052import org.apache.maven.plugin.lifecycle.Phase;
053import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
054import org.apache.maven.plugin.version.PluginVersionResolutionException;
055import org.apache.maven.plugin.version.PluginVersionResolver;
056import org.apache.maven.project.MavenProject;
057import org.codehaus.plexus.component.annotations.Component;
058import org.codehaus.plexus.component.annotations.Requirement;
059import org.codehaus.plexus.util.StringUtils;
060import org.codehaus.plexus.util.xml.Xpp3Dom;
061import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
062
063/**
064 * @since 3.0
065 * @author Benjamin Bentmann
066 * @author Kristian Rosenvold (Extract class)
067 *         <p/>
068 *         NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
069 */
070@Component( role = LifecycleExecutionPlanCalculator.class )
071public class DefaultLifecycleExecutionPlanCalculator
072    implements LifecycleExecutionPlanCalculator
073{
074    @Requirement
075    private PluginVersionResolver pluginVersionResolver;
076
077    @Requirement
078    private BuildPluginManager pluginManager;
079
080    @Requirement
081    private DefaultLifecycles defaultLifeCycles;
082
083    @Requirement
084    private DefaultSchedules defaultSchedules;
085
086    @Requirement
087    private MojoDescriptorCreator mojoDescriptorCreator;
088
089    @Requirement
090    private LifecyclePluginResolver lifecyclePluginResolver;
091
092    @SuppressWarnings( { "UnusedDeclaration" } )
093    public DefaultLifecycleExecutionPlanCalculator()
094    {
095    }
096
097    public DefaultLifecycleExecutionPlanCalculator( BuildPluginManager pluginManager,
098                                                    DefaultLifecycles defaultLifeCycles,
099                                                    MojoDescriptorCreator mojoDescriptorCreator,
100                                                    LifecyclePluginResolver lifecyclePluginResolver,
101                                                    DefaultSchedules defaultSchedules )
102    {
103        this.pluginManager = pluginManager;
104        this.defaultLifeCycles = defaultLifeCycles;
105        this.mojoDescriptorCreator = mojoDescriptorCreator;
106        this.lifecyclePluginResolver = lifecyclePluginResolver;
107        this.defaultSchedules = defaultSchedules;
108    }
109
110    public MavenExecutionPlan calculateExecutionPlan( MavenSession session, MavenProject project, List<Object> tasks, boolean setup )
111        throws PluginNotFoundException, PluginResolutionException, LifecyclePhaseNotFoundException,
112        PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException,
113        NoPluginFoundForPrefixException, LifecycleNotFoundException, PluginVersionResolutionException
114    {
115        lifecyclePluginResolver.resolveMissingPluginVersions( project, session );
116
117        final List<MojoExecution> executions = calculateMojoExecutions( session, project, tasks );
118
119        if ( setup )
120        {
121            setupMojoExecutions( session, project, executions );
122        }
123
124        final List<ExecutionPlanItem> planItem = defaultSchedules.createExecutionPlanItem( project, executions );
125
126        return new MavenExecutionPlan( planItem, defaultLifeCycles );
127    }
128
129    public MavenExecutionPlan calculateExecutionPlan( MavenSession session, MavenProject project, List<Object> tasks )
130        throws PluginNotFoundException, PluginResolutionException, LifecyclePhaseNotFoundException,
131        PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException,
132        NoPluginFoundForPrefixException, LifecycleNotFoundException, PluginVersionResolutionException
133    {
134        return calculateExecutionPlan( session, project, tasks, true );
135    }
136
137    private void setupMojoExecutions( MavenSession session, MavenProject project, List<MojoExecution> mojoExecutions )
138        throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
139        MojoNotFoundException, InvalidPluginDescriptorException, NoPluginFoundForPrefixException,
140        LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException
141    {
142        for ( MojoExecution mojoExecution : mojoExecutions )
143        {
144            setupMojoExecution( session, project, mojoExecution );
145        }
146    }
147
148    public void setupMojoExecution( MavenSession session, MavenProject project, MojoExecution mojoExecution )
149        throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
150        MojoNotFoundException, InvalidPluginDescriptorException, NoPluginFoundForPrefixException,
151        LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException
152    {
153        MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
154
155        if ( mojoDescriptor == null )
156        {
157            mojoDescriptor =
158                pluginManager.getMojoDescriptor( mojoExecution.getPlugin(), mojoExecution.getGoal(),
159                                                 project.getRemotePluginRepositories(),
160                                                 session.getRepositorySession() );
161
162            mojoExecution.setMojoDescriptor( mojoDescriptor );
163        }
164
165        populateMojoExecutionConfiguration( project, mojoExecution,
166                                            MojoExecution.Source.CLI.equals( mojoExecution.getSource() ) );
167
168        finalizeMojoConfiguration( mojoExecution );
169
170        calculateForkedExecutions( mojoExecution, session, project, new HashSet<MojoDescriptor>() );
171    }
172    
173    public List<MojoExecution> calculateMojoExecutions( MavenSession session, MavenProject project,
174                                                         List<Object> tasks )
175        throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
176        MojoNotFoundException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
177        PluginVersionResolutionException, LifecyclePhaseNotFoundException
178    {
179        final List<MojoExecution> mojoExecutions = new ArrayList<MojoExecution>();
180
181        for ( Object task : tasks )
182        {
183            if ( task instanceof GoalTask )
184            {
185                String pluginGoal = ( (GoalTask) task ).pluginGoal;
186
187                MojoDescriptor mojoDescriptor = mojoDescriptorCreator.getMojoDescriptor( pluginGoal, session, project );
188
189                MojoExecution mojoExecution =
190                    new MojoExecution( mojoDescriptor, "default-cli", MojoExecution.Source.CLI );
191
192                mojoExecutions.add( mojoExecution );
193            }
194            else if ( task instanceof LifecycleTask )
195            {
196                String lifecyclePhase = ( (LifecycleTask) task ).getLifecyclePhase();
197
198                Map<String, List<MojoExecution>> phaseToMojoMapping =
199                    calculateLifecycleMappings( session, project, lifecyclePhase );
200
201                for ( List<MojoExecution> mojoExecutionsFromLifecycle : phaseToMojoMapping.values() )
202                {
203                    mojoExecutions.addAll( mojoExecutionsFromLifecycle );
204                }
205            }
206            else
207            {
208                throw new IllegalStateException( "unexpected task " + task );
209            }
210        }
211        return mojoExecutions;
212    }
213
214    private Map<String, List<MojoExecution>> calculateLifecycleMappings( MavenSession session, MavenProject project,
215                                                                         String lifecyclePhase )
216        throws LifecyclePhaseNotFoundException, PluginNotFoundException, PluginResolutionException,
217        PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException
218    {
219        /*
220         * Determine the lifecycle that corresponds to the given phase.
221         */
222
223        Lifecycle lifecycle = defaultLifeCycles.get( lifecyclePhase );
224
225        if ( lifecycle == null )
226        {
227            throw new LifecyclePhaseNotFoundException( "Unknown lifecycle phase \"" + lifecyclePhase
228                + "\". You must specify a valid lifecycle phase" + " or a goal in the format <plugin-prefix>:<goal> or"
229                + " <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: "
230                + defaultLifeCycles.getLifecyclePhaseList() + ".", lifecyclePhase );
231        }
232
233        /*
234         * Initialize mapping from lifecycle phase to bound mojos. The key set of this map denotes the phases the caller
235         * is interested in, i.e. all phases up to and including the specified phase.
236         */
237
238        Map<String, Map<Integer, List<MojoExecution>>> mappings =
239            new LinkedHashMap<String, Map<Integer, List<MojoExecution>>>();
240
241        for ( String phase : lifecycle.getPhases() )
242        {
243            Map<Integer, List<MojoExecution>> phaseBindings = new TreeMap<Integer, List<MojoExecution>>();
244
245            mappings.put( phase, phaseBindings );
246
247            if ( phase.equals( lifecyclePhase ) )
248            {
249                break;
250            }
251        }
252
253        /*
254         * Grab plugin executions that are bound to the selected lifecycle phases from project. The effective model of
255         * the project already contains the plugin executions induced by the project's packaging type. Remember, all
256         * phases of interest and only those are in the lifecyle mapping, if a phase has no value in the map, we are not
257         * interested in any of the executions bound to it.
258         */
259
260        for ( Plugin plugin : project.getBuild().getPlugins() )
261        {
262            for ( PluginExecution execution : plugin.getExecutions() )
263            {
264                // if the phase is specified then I don't have to go fetch the plugin yet and pull it down
265                // to examine the phase it is associated to.
266                if ( execution.getPhase() != null )
267                {
268                    Map<Integer, List<MojoExecution>> phaseBindings = mappings.get( execution.getPhase() );
269                    if ( phaseBindings != null )
270                    {
271                        for ( String goal : execution.getGoals() )
272                        {
273                            MojoExecution mojoExecution = new MojoExecution( plugin, goal, execution.getId() );
274                            mojoExecution.setLifecyclePhase( execution.getPhase() );
275                            addMojoExecution( phaseBindings, mojoExecution, execution.getPriority() );
276                        }
277                    }
278                }
279                // if not then i need to grab the mojo descriptor and look at the phase that is specified
280                else
281                {
282                    for ( String goal : execution.getGoals() )
283                    {
284                        MojoDescriptor mojoDescriptor =
285                            pluginManager.getMojoDescriptor( plugin, goal, project.getRemotePluginRepositories(),
286                                                             session.getRepositorySession() );
287
288                        Map<Integer, List<MojoExecution>> phaseBindings = mappings.get( mojoDescriptor.getPhase() );
289                        if ( phaseBindings != null )
290                        {
291                            MojoExecution mojoExecution = new MojoExecution( mojoDescriptor, execution.getId() );
292                            mojoExecution.setLifecyclePhase( mojoDescriptor.getPhase() );
293                            addMojoExecution( phaseBindings, mojoExecution, execution.getPriority() );
294                        }
295                    }
296                }
297            }
298        }
299
300        Map<String, List<MojoExecution>> lifecycleMappings = new LinkedHashMap<String, List<MojoExecution>>();
301
302        for ( Map.Entry<String, Map<Integer, List<MojoExecution>>> entry : mappings.entrySet() )
303        {
304            List<MojoExecution> mojoExecutions = new ArrayList<MojoExecution>();
305
306            for ( List<MojoExecution> executions : entry.getValue().values() )
307            {
308                mojoExecutions.addAll( executions );
309            }
310
311            lifecycleMappings.put( entry.getKey(), mojoExecutions );
312        }
313
314        return lifecycleMappings;
315    }
316
317    private void addMojoExecution( Map<Integer, List<MojoExecution>> phaseBindings, MojoExecution mojoExecution,
318                                   int priority )
319    {
320        List<MojoExecution> mojoExecutions = phaseBindings.get( priority );
321
322        if ( mojoExecutions == null )
323        {
324            mojoExecutions = new ArrayList<MojoExecution>();
325            phaseBindings.put( priority, mojoExecutions );
326        }
327
328        mojoExecutions.add( mojoExecution );
329    }
330
331    private void populateMojoExecutionConfiguration( MavenProject project, MojoExecution mojoExecution,
332                                                     boolean allowPluginLevelConfig )
333    {
334        String g = mojoExecution.getGroupId();
335
336        String a = mojoExecution.getArtifactId();
337
338        Plugin plugin = findPlugin( g, a, project.getBuildPlugins() );
339
340        if ( plugin == null && project.getPluginManagement() != null )
341        {
342            plugin = findPlugin( g, a, project.getPluginManagement().getPlugins() );
343        }
344
345        if ( plugin != null )
346        {
347            PluginExecution pluginExecution =
348                findPluginExecution( mojoExecution.getExecutionId(), plugin.getExecutions() );
349
350            Xpp3Dom pomConfiguration = null;
351
352            if ( pluginExecution != null )
353            {
354                pomConfiguration = (Xpp3Dom) pluginExecution.getConfiguration();
355            }
356            else if ( allowPluginLevelConfig )
357            {
358                pomConfiguration = (Xpp3Dom) plugin.getConfiguration();
359            }
360
361            Xpp3Dom mojoConfiguration = ( pomConfiguration != null ) ? new Xpp3Dom( pomConfiguration ) : null;
362
363            mojoConfiguration = Xpp3Dom.mergeXpp3Dom( mojoExecution.getConfiguration(), mojoConfiguration );
364
365            mojoExecution.setConfiguration( mojoConfiguration );
366        }
367    }
368
369    private Plugin findPlugin( String groupId, String artifactId, Collection<Plugin> plugins )
370    {
371        for ( Plugin plugin : plugins )
372        {
373            if ( artifactId.equals( plugin.getArtifactId() ) && groupId.equals( plugin.getGroupId() ) )
374            {
375                return plugin;
376            }
377        }
378
379        return null;
380    }
381
382    private PluginExecution findPluginExecution( String executionId, Collection<PluginExecution> executions )
383    {
384        if ( StringUtils.isNotEmpty( executionId ) )
385        {
386            for ( PluginExecution execution : executions )
387            {
388                if ( executionId.equals( execution.getId() ) )
389                {
390                    return execution;
391                }
392            }
393        }
394
395        return null;
396    }
397
398    /**
399     * Post-processes the effective configuration for the specified mojo execution. This step discards all parameters
400     * from the configuration that are not applicable to the mojo and injects the default values for any missing
401     * parameters.
402     *
403     * @param mojoExecution The mojo execution whose configuration should be finalized, must not be {@code null}.
404     */
405    private void finalizeMojoConfiguration( MojoExecution mojoExecution )
406    {
407        MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
408
409        Xpp3Dom executionConfiguration = mojoExecution.getConfiguration();
410        if ( executionConfiguration == null )
411        {
412            executionConfiguration = new Xpp3Dom( "configuration" );
413        }
414
415        Xpp3Dom defaultConfiguration = getMojoConfiguration( mojoDescriptor );
416
417        Xpp3Dom finalConfiguration = new Xpp3Dom( "configuration" );
418
419        if ( mojoDescriptor.getParameters() != null )
420        {
421            for ( Parameter parameter : mojoDescriptor.getParameters() )
422            {
423                Xpp3Dom parameterConfiguration = executionConfiguration.getChild( parameter.getName() );
424
425                if ( parameterConfiguration == null )
426                {
427                    parameterConfiguration = executionConfiguration.getChild( parameter.getAlias() );
428                }
429
430                Xpp3Dom parameterDefaults = defaultConfiguration.getChild( parameter.getName() );
431
432                parameterConfiguration =
433                    Xpp3Dom.mergeXpp3Dom( parameterConfiguration, parameterDefaults, Boolean.TRUE );
434
435                if ( parameterConfiguration != null )
436                {
437                    parameterConfiguration = new Xpp3Dom( parameterConfiguration, parameter.getName() );
438
439                    if ( StringUtils.isEmpty( parameterConfiguration.getAttribute( "implementation" ) )
440                        && StringUtils.isNotEmpty( parameter.getImplementation() ) )
441                    {
442                        parameterConfiguration.setAttribute( "implementation", parameter.getImplementation() );
443                    }
444
445                    finalConfiguration.addChild( parameterConfiguration );
446                }
447            }
448        }
449
450        mojoExecution.setConfiguration( finalConfiguration );
451    }
452
453    private Xpp3Dom getMojoConfiguration( MojoDescriptor mojoDescriptor )
454    {
455        return MojoDescriptorCreator.convert( mojoDescriptor );
456    }
457
458    public void calculateForkedExecutions( MojoExecution mojoExecution, MavenSession session )
459        throws MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
460        PluginDescriptorParsingException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
461        LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException
462    {
463        calculateForkedExecutions( mojoExecution, session, session.getCurrentProject(), new HashSet<MojoDescriptor>() );
464    }
465
466    private void calculateForkedExecutions( MojoExecution mojoExecution, MavenSession session, MavenProject project,
467                                            Collection<MojoDescriptor> alreadyForkedExecutions )
468        throws MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
469        PluginDescriptorParsingException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
470        LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException
471    {
472        MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
473
474        if ( !mojoDescriptor.isForking() )
475        {
476            return;
477        }
478
479        if ( !alreadyForkedExecutions.add( mojoDescriptor ) )
480        {
481            return;
482        }
483
484        List<MavenProject> forkedProjects =
485            LifecycleDependencyResolver.getProjects( project, session, mojoDescriptor.isAggregator() );
486
487        for ( MavenProject forkedProject : forkedProjects )
488        {
489            if ( forkedProject != project )
490            {
491                lifecyclePluginResolver.resolveMissingPluginVersions( forkedProject, session );
492            }
493
494            List<MojoExecution> forkedExecutions;
495
496            if ( StringUtils.isNotEmpty( mojoDescriptor.getExecutePhase() ) )
497            {
498                forkedExecutions =
499                    calculateForkedLifecycle( mojoExecution, session, forkedProject, alreadyForkedExecutions );
500            }
501            else
502            {
503                forkedExecutions =
504                    calculateForkedGoal( mojoExecution, session, forkedProject, alreadyForkedExecutions );
505            }
506
507            mojoExecution.setForkedExecutions( BuilderCommon.getKey( forkedProject ), forkedExecutions );
508        }
509
510        alreadyForkedExecutions.remove( mojoDescriptor );
511    }
512
513    private List<MojoExecution> calculateForkedLifecycle( MojoExecution mojoExecution, MavenSession session,
514                                                          MavenProject project,
515                                                          Collection<MojoDescriptor> alreadyForkedExecutions )
516        throws MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
517        PluginDescriptorParsingException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
518        LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException
519    {
520        MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
521
522        String forkedPhase = mojoDescriptor.getExecutePhase();
523
524        Map<String, List<MojoExecution>> lifecycleMappings =
525            calculateLifecycleMappings( session, project, forkedPhase );
526
527        for ( List<MojoExecution> forkedExecutions : lifecycleMappings.values() )
528        {
529            for ( MojoExecution forkedExecution : forkedExecutions )
530            {
531                if ( forkedExecution.getMojoDescriptor() == null )
532                {
533                    MojoDescriptor forkedMojoDescriptor =
534                        pluginManager.getMojoDescriptor( forkedExecution.getPlugin(), forkedExecution.getGoal(),
535                                                         project.getRemotePluginRepositories(),
536                                                         session.getRepositorySession() );
537
538                    forkedExecution.setMojoDescriptor( forkedMojoDescriptor );
539                }
540
541                populateMojoExecutionConfiguration( project, forkedExecution, false );
542            }
543        }
544
545        injectLifecycleOverlay( lifecycleMappings, mojoExecution, session, project );
546
547        List<MojoExecution> mojoExecutions = new ArrayList<MojoExecution>();
548
549        for ( List<MojoExecution> forkedExecutions : lifecycleMappings.values() )
550        {
551            for ( MojoExecution forkedExecution : forkedExecutions )
552            {
553                if ( !alreadyForkedExecutions.contains( forkedExecution.getMojoDescriptor() ) )
554                {
555                    finalizeMojoConfiguration( forkedExecution );
556
557                    calculateForkedExecutions( forkedExecution, session, project, alreadyForkedExecutions );
558
559                    mojoExecutions.add( forkedExecution );
560                }
561            }
562        }
563
564        return mojoExecutions;
565    }
566
567    private void injectLifecycleOverlay( Map<String, List<MojoExecution>> lifecycleMappings,
568                                         MojoExecution mojoExecution, MavenSession session, MavenProject project )
569        throws PluginDescriptorParsingException, LifecycleNotFoundException, MojoNotFoundException,
570        PluginNotFoundException, PluginResolutionException, NoPluginFoundForPrefixException,
571        InvalidPluginDescriptorException, PluginVersionResolutionException
572    {
573        MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
574
575        PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
576
577        String forkedLifecycle = mojoDescriptor.getExecuteLifecycle();
578
579        if ( StringUtils.isEmpty( forkedLifecycle ) )
580        {
581            return;
582        }
583
584        org.apache.maven.plugin.lifecycle.Lifecycle lifecycleOverlay;
585
586        try
587        {
588            lifecycleOverlay = pluginDescriptor.getLifecycleMapping( forkedLifecycle );
589        }
590        catch ( IOException e )
591        {
592            throw new PluginDescriptorParsingException( pluginDescriptor.getPlugin(), pluginDescriptor.getSource(), e );
593        }
594        catch ( XmlPullParserException e )
595        {
596            throw new PluginDescriptorParsingException( pluginDescriptor.getPlugin(), pluginDescriptor.getSource(), e );
597        }
598
599        if ( lifecycleOverlay == null )
600        {
601            throw new LifecycleNotFoundException( forkedLifecycle );
602        }
603
604        for ( Phase phase : lifecycleOverlay.getPhases() )
605        {
606            List<MojoExecution> forkedExecutions = lifecycleMappings.get( phase.getId() );
607
608            if ( forkedExecutions != null )
609            {
610                for ( Execution execution : phase.getExecutions() )
611                {
612                    for ( String goal : execution.getGoals() )
613                    {
614                        MojoDescriptor forkedMojoDescriptor;
615
616                        if ( goal.indexOf( ':' ) < 0 )
617                        {
618                            forkedMojoDescriptor = pluginDescriptor.getMojo( goal );
619                            if ( forkedMojoDescriptor == null )
620                            {
621                                throw new MojoNotFoundException( goal, pluginDescriptor );
622                            }
623                        }
624                        else
625                        {
626                            forkedMojoDescriptor = mojoDescriptorCreator.getMojoDescriptor( goal, session, project );
627                        }
628
629                        MojoExecution forkedExecution =
630                            new MojoExecution( forkedMojoDescriptor, mojoExecution.getExecutionId() );
631
632                        Xpp3Dom forkedConfiguration = (Xpp3Dom) execution.getConfiguration();
633
634                        forkedExecution.setConfiguration( forkedConfiguration );
635
636                        populateMojoExecutionConfiguration( project, forkedExecution, true );
637
638                        forkedExecutions.add( forkedExecution );
639                    }
640                }
641
642                Xpp3Dom phaseConfiguration = (Xpp3Dom) phase.getConfiguration();
643
644                if ( phaseConfiguration != null )
645                {
646                    for ( MojoExecution forkedExecution : forkedExecutions )
647                    {
648                        Xpp3Dom forkedConfiguration = forkedExecution.getConfiguration();
649
650                        forkedConfiguration = Xpp3Dom.mergeXpp3Dom( phaseConfiguration, forkedConfiguration );
651
652                        forkedExecution.setConfiguration( forkedConfiguration );
653                    }
654                }
655            }
656        }
657    }
658    // org.apache.maven.plugins:maven-remote-resources-plugin:1.0:process
659    //TODO: take repo mans into account as one may be aggregating prefixes of many
660    //TODO: collect at the root of the repository, read the one at the root, and fetch remote if something is missing
661    //      or the user forces the issue
662
663    private List<MojoExecution> calculateForkedGoal( MojoExecution mojoExecution, MavenSession session,
664                                                     MavenProject project,
665                                                     Collection<MojoDescriptor> alreadyForkedExecutions )
666        throws MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
667        PluginDescriptorParsingException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
668        LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException
669    {
670        MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
671
672        PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
673
674        String forkedGoal = mojoDescriptor.getExecuteGoal();
675
676        MojoDescriptor forkedMojoDescriptor = pluginDescriptor.getMojo( forkedGoal );
677        if ( forkedMojoDescriptor == null )
678        {
679            throw new MojoNotFoundException( forkedGoal, pluginDescriptor );
680        }
681
682        if ( alreadyForkedExecutions.contains( forkedMojoDescriptor ) )
683        {
684            return Collections.emptyList();
685        }
686
687        MojoExecution forkedExecution = new MojoExecution( forkedMojoDescriptor, forkedGoal );
688
689        populateMojoExecutionConfiguration( project, forkedExecution, true );
690
691        finalizeMojoConfiguration( forkedExecution );
692
693        calculateForkedExecutions( forkedExecution, session, project, alreadyForkedExecutions );
694
695        return Collections.singletonList( forkedExecution );
696    }
697
698
699}