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