001    package org.apache.maven.model.plugin;
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.util.ArrayList;
023    import java.util.Collection;
024    import java.util.Collections;
025    import java.util.Iterator;
026    import java.util.LinkedHashMap;
027    import java.util.List;
028    import java.util.Map;
029    
030    import org.apache.maven.lifecycle.LifeCyclePluginAnalyzer;
031    import org.apache.maven.model.Build;
032    import org.apache.maven.model.Model;
033    import org.apache.maven.model.Plugin;
034    import org.apache.maven.model.PluginContainer;
035    import org.apache.maven.model.PluginExecution;
036    import org.apache.maven.model.PluginManagement;
037    import org.apache.maven.model.building.ModelBuildingRequest;
038    import org.apache.maven.model.building.ModelProblemCollector;
039    import org.apache.maven.model.building.ModelProblem.Severity;
040    import org.apache.maven.model.merge.MavenModelMerger;
041    import org.codehaus.plexus.component.annotations.Component;
042    import org.codehaus.plexus.component.annotations.Requirement;
043    
044    /**
045     * Handles injection of plugin executions induced by the lifecycle bindings for a packaging.
046     * 
047     * @author Benjamin Bentmann
048     */
049    @Component( role = LifecycleBindingsInjector.class )
050    public class DefaultLifecycleBindingsInjector
051        implements LifecycleBindingsInjector
052    {
053    
054        private LifecycleBindingsMerger merger = new LifecycleBindingsMerger();
055    
056        @Requirement
057        private LifeCyclePluginAnalyzer lifecycle;
058    
059        public void injectLifecycleBindings( Model model, ModelBuildingRequest request, ModelProblemCollector problems )
060        {
061            String packaging = model.getPackaging();
062    
063            Collection<Plugin> defaultPlugins = lifecycle.getPluginsBoundByDefaultToAllLifecycles( packaging );
064    
065            if ( defaultPlugins == null )
066            {
067                problems.add( Severity.ERROR, "Unknown packaging: " + packaging, model.getLocation( "packaging" ), null );
068            }
069            else if ( !defaultPlugins.isEmpty() )
070            {
071                Model lifecycleModel = new Model();
072                lifecycleModel.setBuild( new Build() );
073                lifecycleModel.getBuild().getPlugins().addAll( defaultPlugins );
074    
075                merger.merge( model, lifecycleModel );
076            }
077        }
078    
079        private static class LifecycleBindingsMerger
080            extends MavenModelMerger
081        {
082    
083            private static final String PLUGIN_MANAGEMENT = "plugin-management";
084    
085            public void merge( Model target, Model source )
086            {
087                if ( target.getBuild() == null )
088                {
089                    target.setBuild( new Build() );
090                }
091    
092                Map<Object, Object> context =
093                    Collections.<Object, Object> singletonMap( PLUGIN_MANAGEMENT, target.getBuild().getPluginManagement() );
094    
095                mergePluginContainer_Plugins( target.getBuild(), source.getBuild(), false, context );
096            }
097    
098            @Override
099            protected void mergePluginContainer_Plugins( PluginContainer target, PluginContainer source,
100                                                         boolean sourceDominant, Map<Object, Object> context )
101            {
102                List<Plugin> src = source.getPlugins();
103                if ( !src.isEmpty() )
104                {
105                    List<Plugin> tgt = target.getPlugins();
106    
107                    Map<Object, Plugin> merged = new LinkedHashMap<Object, Plugin>( ( src.size() + tgt.size() ) * 2 );
108    
109                    for ( Iterator<Plugin> it = tgt.iterator(); it.hasNext(); )
110                    {
111                        Plugin element = it.next();
112                        Object key = getPluginKey( element );
113                        merged.put( key, element );
114                    }
115    
116                    Map<Object, Plugin> unmanaged = new LinkedHashMap<Object, Plugin>();
117    
118                    for ( Iterator<Plugin> it = src.iterator(); it.hasNext(); )
119                    {
120                        Plugin element = it.next();
121                        Object key = getPluginKey( element );
122                        Plugin existing = merged.get( key );
123                        if ( existing != null )
124                        {
125                            mergePlugin( existing, element, sourceDominant, context );
126                        }
127                        else
128                        {
129                            merged.put( key, element );
130                            unmanaged.put( key, element );
131                        }
132                    }
133    
134                    if ( !unmanaged.isEmpty() )
135                    {
136                        PluginManagement pluginMgmt = (PluginManagement) context.get( PLUGIN_MANAGEMENT );
137                        if ( pluginMgmt != null )
138                        {
139                            for ( Iterator<Plugin> it = pluginMgmt.getPlugins().iterator(); it.hasNext(); )
140                            {
141                                Plugin managedPlugin = it.next();
142                                Object key = getPluginKey( managedPlugin );
143                                Plugin unmanagedPlugin = unmanaged.get( key );
144                                if ( unmanagedPlugin != null )
145                                {
146                                    Plugin plugin = managedPlugin.clone();
147                                    mergePlugin( plugin, unmanagedPlugin, sourceDominant, Collections.emptyMap() );
148                                    merged.put( key, plugin );
149                                }
150                            }
151                        }
152                    }
153    
154                    List<Plugin> result = new ArrayList<Plugin>( merged.values() );
155    
156                    target.setPlugins( result );
157                }
158            }
159    
160            @Override
161            protected void mergePluginExecution( PluginExecution target, PluginExecution source, boolean sourceDominant,
162                                                 Map<Object, Object> context )
163            {
164                super.mergePluginExecution( target, source, sourceDominant, context );
165    
166                target.setPriority( Math.min( target.getPriority(), source.getPriority() ) );
167            }
168    
169        }
170    
171    }