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      protected static class LifecycleBindingsMerger
83          extends MavenModelMerger
84      {
85  
86          private static final String PLUGIN_MANAGEMENT = "plugin-management";
87  
88          public void merge( Model target, Model source )
89          {
90              if ( target.getBuild() == null )
91              {
92                  target.setBuild( new Build() );
93              }
94  
95              Map<Object, Object> context =
96                  Collections.<Object, Object>singletonMap( PLUGIN_MANAGEMENT, target.getBuild().getPluginManagement() );
97  
98              mergePluginContainer_Plugins( target.getBuild(), source.getBuild(), false, context );
99          }
100 
101         @Override
102         protected void mergePluginContainer_Plugins( PluginContainer target, PluginContainer source,
103                                                      boolean sourceDominant, Map<Object, Object> context )
104         {
105             List<Plugin> src = source.getPlugins();
106             if ( !src.isEmpty() )
107             {
108                 List<Plugin> tgt = target.getPlugins();
109 
110                 Map<Object, Plugin> merged = new LinkedHashMap<>( ( src.size() + tgt.size() ) * 2 );
111 
112                 for ( Plugin element : tgt )
113                 {
114                     Object key = getPluginKey( element );
115                     merged.put( key, element );
116                 }
117 
118                 Map<Object, Plugin> unmanaged = new LinkedHashMap<>();
119 
120                 for ( Plugin element : src )
121                 {
122                     Object key = getPluginKey( element );
123                     Plugin existing = merged.get( key );
124                     if ( existing != null )
125                     {
126                         mergePlugin( existing, element, sourceDominant, context );
127                     }
128                     else
129                     {
130                         merged.put( key, element );
131                         unmanaged.put( key, element );
132                     }
133                 }
134 
135                 if ( !unmanaged.isEmpty() )
136                 {
137                     PluginManagement pluginMgmt = (PluginManagement) context.get( PLUGIN_MANAGEMENT );
138                     if ( pluginMgmt != null )
139                     {
140                         for ( Plugin managedPlugin : pluginMgmt.getPlugins() )
141                         {
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<>( 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 }