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.Iterator;
26  import java.util.LinkedHashMap;
27  import java.util.List;
28  import java.util.Map;
29  
30  import org.apache.maven.lifecycle.LifeCyclePluginAnalyzer;
31  import org.apache.maven.model.Build;
32  import org.apache.maven.model.Model;
33  import org.apache.maven.model.Plugin;
34  import org.apache.maven.model.PluginContainer;
35  import org.apache.maven.model.PluginExecution;
36  import org.apache.maven.model.PluginManagement;
37  import org.apache.maven.model.building.ModelBuildingRequest;
38  import org.apache.maven.model.building.ModelProblemCollector;
39  import org.apache.maven.model.building.ModelProblem.Severity;
40  import org.apache.maven.model.merge.MavenModelMerger;
41  import org.codehaus.plexus.component.annotations.Component;
42  import org.codehaus.plexus.component.annotations.Requirement;
43  
44  /**
45   * Handles injection of plugin executions induced by the lifecycle bindings for a packaging.
46   * 
47   * @author Benjamin Bentmann
48   */
49  @Component( role = LifecycleBindingsInjector.class )
50  public class DefaultLifecycleBindingsInjector
51      implements LifecycleBindingsInjector
52  {
53  
54      private LifecycleBindingsMerger merger = new LifecycleBindingsMerger();
55  
56      @Requirement
57      private LifeCyclePluginAnalyzer lifecycle;
58  
59      public void injectLifecycleBindings( Model model, ModelBuildingRequest request, ModelProblemCollector problems )
60      {
61          String packaging = model.getPackaging();
62  
63          Collection<Plugin> defaultPlugins = lifecycle.getPluginsBoundByDefaultToAllLifecycles( packaging );
64  
65          if ( defaultPlugins == null )
66          {
67              problems.add( Severity.ERROR, "Unknown packaging: " + packaging, model.getLocation( "packaging" ), null );
68          }
69          else if ( !defaultPlugins.isEmpty() )
70          {
71              Model lifecycleModel = new Model();
72              lifecycleModel.setBuild( new Build() );
73              lifecycleModel.getBuild().getPlugins().addAll( defaultPlugins );
74  
75              merger.merge( model, lifecycleModel );
76          }
77      }
78  
79      private static class LifecycleBindingsMerger
80          extends MavenModelMerger
81      {
82  
83          private static final String PLUGIN_MANAGEMENT = "plugin-management";
84  
85          public void merge( Model target, Model source )
86          {
87              if ( target.getBuild() == null )
88              {
89                  target.setBuild( new Build() );
90              }
91  
92              Map<Object, Object> context =
93                  Collections.<Object, Object> singletonMap( PLUGIN_MANAGEMENT, target.getBuild().getPluginManagement() );
94  
95              mergePluginContainer_Plugins( target.getBuild(), source.getBuild(), false, context );
96          }
97  
98          @Override
99          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 }