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.util.ArrayList;
023import java.util.LinkedHashMap;
024import java.util.List;
025import java.util.Map;
026import java.util.TreeMap;
027
028import org.apache.maven.execution.MavenSession;
029import org.apache.maven.lifecycle.Lifecycle;
030import org.apache.maven.lifecycle.LifecycleMappingDelegate;
031import org.apache.maven.model.Plugin;
032import org.apache.maven.model.PluginExecution;
033import org.apache.maven.plugin.BuildPluginManager;
034import org.apache.maven.plugin.InvalidPluginDescriptorException;
035import org.apache.maven.plugin.MojoExecution;
036import org.apache.maven.plugin.MojoNotFoundException;
037import org.apache.maven.plugin.PluginDescriptorParsingException;
038import org.apache.maven.plugin.PluginNotFoundException;
039import org.apache.maven.plugin.PluginResolutionException;
040import org.apache.maven.plugin.descriptor.MojoDescriptor;
041import org.apache.maven.project.MavenProject;
042import org.codehaus.plexus.component.annotations.Component;
043import org.codehaus.plexus.component.annotations.Requirement;
044
045@Component( role = LifecycleMappingDelegate.class, hint = DefaultLifecycleMappingDelegate.HINT )
046public class DefaultLifecycleMappingDelegate
047    implements LifecycleMappingDelegate
048{
049    public static final String HINT = "default";
050
051    @Requirement
052    private BuildPluginManager pluginManager;
053
054    public Map<String, List<MojoExecution>> calculateLifecycleMappings( MavenSession session, MavenProject project,
055                                                                        Lifecycle lifecycle, String lifecyclePhase )
056        throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
057        MojoNotFoundException, InvalidPluginDescriptorException
058    {
059        /*
060         * Initialize mapping from lifecycle phase to bound mojos. The key set of this map denotes the phases the caller
061         * is interested in, i.e. all phases up to and including the specified phase.
062         */
063
064        Map<String, Map<Integer, List<MojoExecution>>> mappings =
065            new LinkedHashMap<>();
066
067        for ( String phase : lifecycle.getPhases() )
068        {
069            Map<Integer, List<MojoExecution>> phaseBindings = new TreeMap<>();
070
071            mappings.put( phase, phaseBindings );
072
073            if ( phase.equals( lifecyclePhase ) )
074            {
075                break;
076            }
077        }
078
079        /*
080         * Grab plugin executions that are bound to the selected lifecycle phases from project. The effective model of
081         * the project already contains the plugin executions induced by the project's packaging type. Remember, all
082         * phases of interest and only those are in the lifecyle mapping, if a phase has no value in the map, we are not
083         * interested in any of the executions bound to it.
084         */
085
086        for ( Plugin plugin : project.getBuild().getPlugins() )
087        {
088            for ( PluginExecution execution : plugin.getExecutions() )
089            {
090                // if the phase is specified then I don't have to go fetch the plugin yet and pull it down
091                // to examine the phase it is associated to.
092                if ( execution.getPhase() != null )
093                {
094                    Map<Integer, List<MojoExecution>> phaseBindings = mappings.get( execution.getPhase() );
095                    if ( phaseBindings != null )
096                    {
097                        for ( String goal : execution.getGoals() )
098                        {
099                            MojoExecution mojoExecution = new MojoExecution( plugin, goal, execution.getId() );
100                            mojoExecution.setLifecyclePhase( execution.getPhase() );
101                            addMojoExecution( phaseBindings, mojoExecution, execution.getPriority() );
102                        }
103                    }
104                }
105                // if not then i need to grab the mojo descriptor and look at the phase that is specified
106                else
107                {
108                    for ( String goal : execution.getGoals() )
109                    {
110                        MojoDescriptor mojoDescriptor =
111                            pluginManager.getMojoDescriptor( plugin, goal, project.getRemotePluginRepositories(),
112                                                             session.getRepositorySession() );
113
114                        Map<Integer, List<MojoExecution>> phaseBindings = mappings.get( mojoDescriptor.getPhase() );
115                        if ( phaseBindings != null )
116                        {
117                            MojoExecution mojoExecution = new MojoExecution( mojoDescriptor, execution.getId() );
118                            mojoExecution.setLifecyclePhase( mojoDescriptor.getPhase() );
119                            addMojoExecution( phaseBindings, mojoExecution, execution.getPriority() );
120                        }
121                    }
122                }
123            }
124        }
125
126        Map<String, List<MojoExecution>> lifecycleMappings = new LinkedHashMap<>();
127
128        for ( Map.Entry<String, Map<Integer, List<MojoExecution>>> entry : mappings.entrySet() )
129        {
130            List<MojoExecution> mojoExecutions = new ArrayList<>();
131
132            for ( List<MojoExecution> executions : entry.getValue().values() )
133            {
134                mojoExecutions.addAll( executions );
135            }
136
137            lifecycleMappings.put( entry.getKey(), mojoExecutions );
138        }
139
140        return lifecycleMappings;
141
142    }
143
144    private void addMojoExecution( Map<Integer, List<MojoExecution>> phaseBindings, MojoExecution mojoExecution,
145                                   int priority )
146    {
147        List<MojoExecution> mojoExecutions = phaseBindings.get( priority );
148
149        if ( mojoExecutions == null )
150        {
151            mojoExecutions = new ArrayList<>();
152            phaseBindings.put( priority, mojoExecutions );
153        }
154
155        mojoExecutions.add( mojoExecution );
156    }
157
158}