001    package 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    
022    import java.io.IOException;
023    import java.util.ArrayList;
024    import java.util.Collection;
025    import java.util.Collections;
026    import java.util.HashSet;
027    import java.util.LinkedHashMap;
028    import java.util.List;
029    import java.util.Map;
030    import java.util.TreeMap;
031    
032    import org.apache.maven.execution.MavenSession;
033    import org.apache.maven.lifecycle.DefaultLifecycles;
034    import org.apache.maven.lifecycle.DefaultSchedules;
035    import org.apache.maven.lifecycle.Lifecycle;
036    import org.apache.maven.lifecycle.LifecycleNotFoundException;
037    import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
038    import org.apache.maven.lifecycle.MavenExecutionPlan;
039    import org.apache.maven.model.Plugin;
040    import org.apache.maven.model.PluginExecution;
041    import org.apache.maven.plugin.BuildPluginManager;
042    import org.apache.maven.plugin.InvalidPluginDescriptorException;
043    import org.apache.maven.plugin.MojoExecution;
044    import org.apache.maven.plugin.MojoNotFoundException;
045    import org.apache.maven.plugin.PluginDescriptorParsingException;
046    import org.apache.maven.plugin.PluginNotFoundException;
047    import org.apache.maven.plugin.PluginResolutionException;
048    import org.apache.maven.plugin.descriptor.MojoDescriptor;
049    import org.apache.maven.plugin.descriptor.Parameter;
050    import org.apache.maven.plugin.descriptor.PluginDescriptor;
051    import org.apache.maven.plugin.lifecycle.Execution;
052    import org.apache.maven.plugin.lifecycle.Phase;
053    import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
054    import org.apache.maven.plugin.version.PluginVersionResolutionException;
055    import org.apache.maven.plugin.version.PluginVersionResolver;
056    import org.apache.maven.project.MavenProject;
057    import org.codehaus.plexus.component.annotations.Component;
058    import org.codehaus.plexus.component.annotations.Requirement;
059    import org.codehaus.plexus.util.StringUtils;
060    import org.codehaus.plexus.util.xml.Xpp3Dom;
061    import 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 )
071    public 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    }