View Javadoc
1   package org.apache.maven.model.plugin;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.ArrayList;
23  import java.util.Collection;
24  import java.util.Collections;
25  import java.util.LinkedHashMap;
26  import java.util.List;
27  import java.util.Map;
28  
29  import org.apache.maven.lifecycle.LifeCyclePluginAnalyzer;
30  import org.apache.maven.model.Build;
31  import org.apache.maven.model.Model;
32  import org.apache.maven.model.Plugin;
33  import org.apache.maven.model.PluginContainer;
34  import org.apache.maven.model.PluginExecution;
35  import org.apache.maven.model.PluginManagement;
36  import org.apache.maven.model.building.ModelBuildingRequest;
37  import org.apache.maven.model.building.ModelProblemCollector;
38  import org.apache.maven.model.building.ModelProblem.Severity;
39  import org.apache.maven.model.building.ModelProblem.Version;
40  import org.apache.maven.model.building.ModelProblemCollectorRequest;
41  import org.apache.maven.model.merge.MavenModelMerger;
42  import org.codehaus.plexus.component.annotations.Component;
43  import org.codehaus.plexus.component.annotations.Requirement;
44  
45  /**
46   * Handles injection of plugin executions induced by the lifecycle bindings for a packaging.
47   *
48   * @author Benjamin Bentmann
49   */
50  @Component( role = LifecycleBindingsInjector.class )
51  public class DefaultLifecycleBindingsInjector
52      implements LifecycleBindingsInjector
53  {
54  
55      private LifecycleBindingsMerger merger = new LifecycleBindingsMerger();
56  
57      @Requirement
58      private LifeCyclePluginAnalyzer lifecycle;
59  
60      public void injectLifecycleBindings( Model model, ModelBuildingRequest request, ModelProblemCollector problems )
61      {
62          String packaging = model.getPackaging();
63  
64          Collection<Plugin> defaultPlugins = lifecycle.getPluginsBoundByDefaultToAllLifecycles( packaging );
65  
66          if ( defaultPlugins == null )
67          {
68              problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
69                      .setMessage( "Unknown packaging: " + packaging )
70                      .setLocation( model.getLocation( "packaging" ) ) );
71          }
72          else if ( !defaultPlugins.isEmpty() )
73          {
74              Model lifecycleModel = new Model();
75              lifecycleModel.setBuild( new Build() );
76              lifecycleModel.getBuild().getPlugins().addAll( defaultPlugins );
77  
78              merger.merge( model, lifecycleModel );
79          }
80      }
81  
82      /**
83       *  The domain-specific model merger for lifecycle bindings
84       */
85      protected static class LifecycleBindingsMerger
86          extends MavenModelMerger
87      {
88  
89          private static final String PLUGIN_MANAGEMENT = "plugin-management";
90  
91          public void merge( Model target, Model source )
92          {
93              if ( target.getBuild() == null )
94              {
95                  target.setBuild( new Build() );
96              }
97  
98              Map<Object, Object> context =
99                  Collections.<Object, Object>singletonMap( PLUGIN_MANAGEMENT, target.getBuild().getPluginManagement() );
100 
101             mergePluginContainer_Plugins( target.getBuild(), source.getBuild(), false, context );
102         }
103 
104         @SuppressWarnings( { "checkstyle:methodname" } )
105         @Override
106         protected void mergePluginContainer_Plugins( PluginContainer target, PluginContainer source,
107                                                      boolean sourceDominant, Map<Object, Object> context )
108         {
109             List<Plugin> src = source.getPlugins();
110             if ( !src.isEmpty() )
111             {
112                 List<Plugin> tgt = target.getPlugins();
113 
114                 Map<Object, Plugin> merged = new LinkedHashMap<>( ( src.size() + tgt.size() ) * 2 );
115 
116                 for ( Plugin element : tgt )
117                 {
118                     Object key = getPluginKey( element );
119                     merged.put( key, element );
120                 }
121 
122                 Map<Object, Plugin> added = new LinkedHashMap<>();
123 
124                 for ( Plugin element : src )
125                 {
126                     Object key = getPluginKey( element );
127                     Plugin existing = merged.get( key );
128                     if ( existing != null )
129                     {
130                         mergePlugin( existing, element, sourceDominant, context );
131                     }
132                     else
133                     {
134                         merged.put( key, element );
135                         added.put( key, element );
136                     }
137                 }
138 
139                 if ( !added.isEmpty() )
140                 {
141                     PluginManagement pluginMgmt = (PluginManagement) context.get( PLUGIN_MANAGEMENT );
142                     if ( pluginMgmt != null )
143                     {
144                         for ( Plugin managedPlugin : pluginMgmt.getPlugins() )
145                         {
146                             Object key = getPluginKey( managedPlugin );
147                             Plugin addedPlugin = added.get( key );
148                             if ( addedPlugin != null )
149                             {
150                                 Plugin plugin = managedPlugin.clone();
151                                 mergePlugin( plugin, addedPlugin, sourceDominant, Collections.emptyMap() );
152                                 merged.put( key, plugin );
153                             }
154                         }
155                     }
156                 }
157 
158                 List<Plugin> result = new ArrayList<>( merged.values() );
159 
160                 target.setPlugins( result );
161             }
162         }
163 
164         @Override
165         protected void mergePluginExecution( PluginExecution target, PluginExecution source, boolean sourceDominant,
166                                              Map<Object, Object> context )
167         {
168             super.mergePluginExecution( target, source, sourceDominant, context );
169 
170             target.setPriority( Math.min( target.getPriority(), source.getPriority() ) );
171         }
172 
173     }
174 
175 }