View Javadoc
1   package org.apache.maven.project;
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.Iterator;
24  import java.util.LinkedHashMap;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.TreeMap;
28  
29  import org.apache.maven.model.Dependency;
30  import org.apache.maven.model.Plugin;
31  import org.apache.maven.model.PluginContainer;
32  import org.apache.maven.model.PluginExecution;
33  import org.apache.maven.model.Repository;
34  import org.codehaus.plexus.util.xml.Xpp3Dom;
35  
36  /** @deprecated */
37  @Deprecated
38  public final class ModelUtils
39  {
40  
41      /**
42       * This should be the resulting ordering of plugins after merging:
43       * <p>
44       * Given:
45       * <pre>
46       * parent: X -&gt; A -&gt; B -&gt; D -&gt; E
47       * child: Y -&gt; A -&gt; C -&gt; D -&gt; F
48       * </pre>
49       * Result:
50       * <pre>
51       * X -&gt; Y -&gt; A -&gt; B -&gt; C -&gt; D -&gt; E -&gt; F
52       * </pre>
53       */
54      public static void mergePluginLists( PluginContainer childContainer, PluginContainer parentContainer,
55                                           boolean handleAsInheritance )
56      {
57          if ( ( childContainer == null ) || ( parentContainer == null ) )
58          {
59              // nothing to do.
60              return;
61          }
62  
63          List<Plugin> parentPlugins = parentContainer.getPlugins();
64  
65          if ( ( parentPlugins != null ) && !parentPlugins.isEmpty() )
66          {
67              parentPlugins = new ArrayList<>( parentPlugins );
68  
69              // If we're processing this merge as an inheritance, we have to build up a list of
70              // plugins that were considered for inheritance.
71              if ( handleAsInheritance )
72              {
73                  for ( Iterator<Plugin> it = parentPlugins.iterator(); it.hasNext(); )
74                  {
75                      Plugin plugin = it.next();
76  
77                      String inherited = plugin.getInherited();
78  
79                      if ( ( inherited != null ) && !Boolean.valueOf( inherited ) )
80                      {
81                          it.remove();
82                      }
83                  }
84              }
85  
86              List<Plugin> assembledPlugins = new ArrayList<>();
87  
88              Map<String, Plugin> childPlugins = childContainer.getPluginsAsMap();
89  
90              for ( Plugin parentPlugin : parentPlugins )
91              {
92                  String parentInherited = parentPlugin.getInherited();
93  
94                  // only merge plugin definition from the parent if at least one
95                  // of these is true:
96                  // 1. we're not processing the plugins in an inheritance-based merge
97                  // 2. the parent's <inherited/> flag is not set
98                  // 3. the parent's <inherited/> flag is set to true
99                  if ( !handleAsInheritance || ( parentInherited == null )
100                     || Boolean.valueOf( parentInherited ) )
101                 {
102                     Plugin childPlugin = childPlugins.get( parentPlugin.getKey() );
103 
104                     if ( ( childPlugin != null ) && !assembledPlugins.contains( childPlugin ) )
105                     {
106                         Plugin assembledPlugin = childPlugin;
107 
108                         mergePluginDefinitions( childPlugin, parentPlugin, handleAsInheritance );
109 
110                         // fix for MNG-2221 (assembly cache was not being populated for later reference):
111                         assembledPlugins.add( assembledPlugin );
112                     }
113 
114                     // if we're processing this as an inheritance-based merge, and
115                     // the parent's <inherited/> flag is not set, then we need to
116                     // clear the inherited flag in the merge result.
117                     if ( handleAsInheritance && ( parentInherited == null ) )
118                     {
119                         parentPlugin.unsetInheritanceApplied();
120                     }
121                 }
122 
123                 // very important to use the parentPlugins List, rather than parentContainer.getPlugins()
124                 // since this list is a local one, and may have been modified during processing.
125                 List<Plugin> results =
126                     ModelUtils.orderAfterMerge( assembledPlugins, parentPlugins, childContainer.getPlugins() );
127 
128                 childContainer.setPlugins( results );
129 
130                 childContainer.flushPluginMap();
131             }
132         }
133     }
134 
135     public static List<Plugin> orderAfterMerge( List<Plugin> merged, List<Plugin> highPrioritySource,
136                                                 List<Plugin> lowPrioritySource )
137     {
138         List<Plugin> results = new ArrayList<>();
139 
140         if ( !merged.isEmpty() )
141         {
142             results.addAll( merged );
143         }
144 
145         List<Plugin> missingFromResults = new ArrayList<>();
146 
147         List<List<Plugin>> sources = new ArrayList<>();
148 
149         sources.add( highPrioritySource );
150         sources.add( lowPrioritySource );
151 
152         for ( List<Plugin> source : sources )
153         {
154             for ( Plugin item : source )
155             {
156                 if ( results.contains( item ) )
157                 {
158                     if ( !missingFromResults.isEmpty() )
159                     {
160                         int idx = results.indexOf( item );
161 
162                         if ( idx < 0 )
163                         {
164                             idx = 0;
165                         }
166 
167                         results.addAll( idx, missingFromResults );
168 
169                         missingFromResults.clear();
170                     }
171                 }
172                 else
173                 {
174                     missingFromResults.add( item );
175                 }
176             }
177 
178             if ( !missingFromResults.isEmpty() )
179             {
180                 results.addAll( missingFromResults );
181 
182                 missingFromResults.clear();
183             }
184         }
185 
186         return results;
187     }
188 
189 
190     public static void mergePluginDefinitions( Plugin child, Plugin parent, boolean handleAsInheritance )
191     {
192         if ( ( child == null ) || ( parent == null ) )
193         {
194             // nothing to do.
195             return;
196         }
197 
198         if ( parent.isExtensions() )
199         {
200             child.setExtensions( true );
201         }
202 
203         if ( ( child.getVersion() == null ) && ( parent.getVersion() != null ) )
204         {
205             child.setVersion( parent.getVersion() );
206         }
207 
208         Xpp3Dom childConfiguration = (Xpp3Dom) child.getConfiguration();
209         Xpp3Dom parentConfiguration = (Xpp3Dom) parent.getConfiguration();
210 
211         childConfiguration = Xpp3Dom.mergeXpp3Dom( childConfiguration, parentConfiguration );
212 
213         child.setConfiguration( childConfiguration );
214 
215         child.setDependencies( mergeDependencyList( child.getDependencies(), parent.getDependencies() ) );
216 
217         // from here to the end of the method is dealing with merging of the <executions/> section.
218         String parentInherited = parent.getInherited();
219 
220         boolean parentIsInherited = ( parentInherited == null ) || Boolean.valueOf( parentInherited );
221 
222         List<PluginExecution> parentExecutions = parent.getExecutions();
223 
224         if ( ( parentExecutions != null ) && !parentExecutions.isEmpty() )
225         {
226             List<PluginExecution> mergedExecutions = new ArrayList<>();
227 
228             Map<String, PluginExecution> assembledExecutions = new TreeMap<>();
229 
230             Map<String, PluginExecution> childExecutions = child.getExecutionsAsMap();
231 
232             for ( PluginExecution parentExecution : parentExecutions )
233             {
234                 String inherited = parentExecution.getInherited();
235 
236                 boolean parentExecInherited =
237                     parentIsInherited && ( ( inherited == null ) || Boolean.valueOf( inherited ) );
238 
239                 if ( !handleAsInheritance || parentExecInherited )
240                 {
241                     PluginExecution assembled = parentExecution;
242 
243                     PluginExecution childExecution = childExecutions.get( parentExecution.getId() );
244 
245                     if ( childExecution != null )
246                     {
247                         mergePluginExecutionDefinitions( childExecution, parentExecution );
248 
249                         assembled = childExecution;
250                     }
251                     else if ( handleAsInheritance && ( parentInherited == null ) )
252                     {
253                         parentExecution.unsetInheritanceApplied();
254                     }
255 
256                     assembledExecutions.put( assembled.getId(), assembled );
257                     mergedExecutions.add( assembled );
258                 }
259             }
260 
261             for ( PluginExecution childExecution : child.getExecutions() )
262             {
263                 if ( !assembledExecutions.containsKey( childExecution.getId() ) )
264                 {
265                     mergedExecutions.add( childExecution );
266                 }
267             }
268 
269             child.setExecutions( mergedExecutions );
270 
271             child.flushExecutionMap();
272         }
273 
274     }
275 
276     private static void mergePluginExecutionDefinitions( PluginExecution child, PluginExecution parent )
277     {
278         if ( child.getPhase() == null )
279         {
280             child.setPhase( parent.getPhase() );
281         }
282 
283         List<String> parentGoals = parent.getGoals();
284         List<String> childGoals = child.getGoals();
285 
286         List<String> goals = new ArrayList<>();
287 
288         if ( ( childGoals != null ) && !childGoals.isEmpty() )
289         {
290             goals.addAll( childGoals );
291         }
292 
293         if ( parentGoals != null )
294         {
295             for (  String goal : parentGoals )
296             {
297                 if ( !goals.contains( goal ) )
298                 {
299                     goals.add( goal );
300                 }
301             }
302         }
303 
304         child.setGoals( goals );
305 
306         Xpp3Dom childConfiguration = (Xpp3Dom) child.getConfiguration();
307         Xpp3Dom parentConfiguration = (Xpp3Dom) parent.getConfiguration();
308 
309         childConfiguration = Xpp3Dom.mergeXpp3Dom( childConfiguration, parentConfiguration );
310 
311         child.setConfiguration( childConfiguration );
312     }
313 
314     public static List<Repository> mergeRepositoryLists( List<Repository> dominant, List<Repository> recessive )
315     {
316 
317         List<Repository> repositories = new ArrayList<>( dominant );
318 
319         for ( Repository repository : recessive )
320         {
321             if ( !repositories.contains( repository ) )
322             {
323                 repositories.add( repository );
324             }
325         }
326 
327         return repositories;
328     }
329 
330     public static void mergeFilterLists( List<String> childFilters, List<String> parentFilters )
331     {
332         for ( String f : parentFilters )
333         {
334             if ( !childFilters.contains( f ) )
335             {
336                 childFilters.add( f );
337             }
338         }
339     }
340 
341     private static List<Dependency> mergeDependencyList( List<Dependency> child, List<Dependency> parent )
342     {
343         Map<String, Dependency> depsMap = new LinkedHashMap<>();
344 
345         if ( parent != null )
346         {
347             for ( Dependency dependency : parent )
348             {
349                 depsMap.put( dependency.getManagementKey(), dependency );
350             }
351         }
352 
353         if ( child != null )
354         {
355             for ( Dependency dependency : child )
356             {
357                 depsMap.put( dependency.getManagementKey(), dependency );
358             }
359         }
360 
361         return new ArrayList<>( depsMap.values() );
362     }
363 
364 }