View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.project;
20  
21  import java.io.IOException;
22  import java.io.StringReader;
23  import java.util.Arrays;
24  import java.util.Collections;
25  import java.util.List;
26  import java.util.Map;
27  
28  import junit.framework.TestCase;
29  import org.apache.maven.model.Build;
30  import org.apache.maven.model.Dependency;
31  import org.apache.maven.model.Plugin;
32  import org.apache.maven.model.PluginContainer;
33  import org.apache.maven.model.PluginExecution;
34  import org.codehaus.plexus.util.xml.Xpp3Dom;
35  import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
36  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
37  
38  public class ModelUtilsTest extends TestCase {
39  
40      public void testShouldUseMainPluginDependencyVersionOverManagedDepVersion() {
41          Plugin mgtPlugin = createPlugin("group", "artifact", "1", Collections.EMPTY_MAP);
42          Dependency mgtDep = createDependency("g", "a", "2");
43          mgtPlugin.addDependency(mgtDep);
44  
45          Plugin plugin = createPlugin("group", "artifact", "1", Collections.EMPTY_MAP);
46          Dependency dep = createDependency("g", "a", "1");
47          plugin.addDependency(dep);
48  
49          ModelUtils.mergePluginDefinitions(plugin, mgtPlugin, false);
50  
51          assertEquals(dep.getVersion(), plugin.getDependencies().get(0).getVersion());
52      }
53  
54      private Dependency createDependency(String gid, String aid, String ver) {
55          Dependency dep = new Dependency();
56          dep.setGroupId(gid);
57          dep.setArtifactId(aid);
58          dep.setVersion(ver);
59  
60          return dep;
61      }
62  
63      public void testShouldNotInheritPluginWithInheritanceSetToFalse() {
64          PluginContainer parent = new PluginContainer();
65  
66          Plugin parentPlugin = createPlugin("group", "artifact", "1.0", Collections.EMPTY_MAP);
67          parentPlugin.setInherited("false");
68  
69          parent.addPlugin(parentPlugin);
70  
71          PluginContainer child = new PluginContainer();
72  
73          child.addPlugin(createPlugin("group3", "artifact3", "1.0", Collections.EMPTY_MAP));
74  
75          ModelUtils.mergePluginLists(child, parent, true);
76  
77          List results = child.getPlugins();
78  
79          assertEquals(1, results.size());
80  
81          Plugin result1 = (Plugin) results.get(0);
82          assertEquals("group3", result1.getGroupId());
83          assertEquals("artifact3", result1.getArtifactId());
84      }
85  
86      /**
87       * Test that this is the resulting ordering of plugins after merging:
88       * <p>
89       * Given:
90       * </p>
91       * <pre>
92       *   parent: X -&gt; A -&gt; B -&gt; D -&gt; E
93       *   child: Y -&gt; A -&gt; C -&gt; D -&gt; F
94       * </pre>
95       * <p>
96       * Result:
97       * </p>
98       * <pre>
99       *   X -&gt; Y -&gt; A -&gt; B -&gt; C -&gt; D -&gt; E -&gt; F
100      * </pre>
101      */
102     public void testShouldPreserveChildOrderingOfPluginsAfterParentMerge() {
103         PluginContainer parent = new PluginContainer();
104 
105         parent.addPlugin(createPlugin("group", "artifact", "1.0", Collections.EMPTY_MAP));
106         parent.addPlugin(createPlugin("group2", "artifact2", "1.0", Collections.singletonMap("key", "value")));
107 
108         PluginContainer child = new PluginContainer();
109 
110         child.addPlugin(createPlugin("group3", "artifact3", "1.0", Collections.EMPTY_MAP));
111         child.addPlugin(createPlugin("group2", "artifact2", "1.0", Collections.singletonMap("key2", "value2")));
112 
113         ModelUtils.mergePluginLists(child, parent, true);
114 
115         List results = child.getPlugins();
116 
117         assertEquals(3, results.size());
118 
119         Plugin result1 = (Plugin) results.get(0);
120 
121         assertEquals("group", result1.getGroupId());
122         assertEquals("artifact", result1.getArtifactId());
123 
124         Plugin result2 = (Plugin) results.get(1);
125 
126         assertEquals("group3", result2.getGroupId());
127         assertEquals("artifact3", result2.getArtifactId());
128 
129         Plugin result3 = (Plugin) results.get(2);
130 
131         assertEquals("group2", result3.getGroupId());
132         assertEquals("artifact2", result3.getArtifactId());
133 
134         Xpp3Dom result3Config = (Xpp3Dom) result3.getConfiguration();
135 
136         assertNotNull(result3Config);
137 
138         assertEquals("value", result3Config.getChild("key").getValue());
139         assertEquals("value2", result3Config.getChild("key2").getValue());
140     }
141 
142     private Plugin createPlugin(String groupId, String artifactId, String version, Map configuration) {
143         Plugin plugin = new Plugin();
144         plugin.setGroupId(groupId);
145         plugin.setArtifactId(artifactId);
146         plugin.setVersion(version);
147 
148         Xpp3Dom config = new Xpp3Dom("configuration");
149 
150         if (configuration != null) {
151             for (Object o : configuration.entrySet()) {
152                 Map.Entry entry = (Map.Entry) o;
153 
154                 Xpp3Dom param = new Xpp3Dom(String.valueOf(entry.getKey()));
155                 param.setValue(String.valueOf(entry.getValue()));
156 
157                 config.addChild(param);
158             }
159         }
160 
161         plugin.setConfiguration(config);
162 
163         return plugin;
164     }
165 
166     public void testShouldInheritOnePluginWithExecution() {
167         Plugin parent = new Plugin();
168         parent.setArtifactId("testArtifact");
169         parent.setGroupId("testGroup");
170         parent.setVersion("1.0");
171 
172         PluginExecution parentExecution = new PluginExecution();
173         parentExecution.setId("testExecution");
174 
175         parent.addExecution(parentExecution);
176 
177         Plugin child = new Plugin();
178         child.setArtifactId("testArtifact");
179         child.setGroupId("testGroup");
180         child.setVersion("1.0");
181 
182         ModelUtils.mergePluginDefinitions(child, parent, false);
183 
184         assertEquals(1, child.getExecutions().size());
185     }
186 
187     public void testShouldMergeInheritedPluginHavingExecutionWithLocalPlugin() {
188         Plugin parent = new Plugin();
189         parent.setArtifactId("testArtifact");
190         parent.setGroupId("testGroup");
191         parent.setVersion("1.0");
192 
193         PluginExecution parentExecution = new PluginExecution();
194         parentExecution.setId("testExecution");
195 
196         parent.addExecution(parentExecution);
197 
198         Plugin child = new Plugin();
199         child.setArtifactId("testArtifact");
200         child.setGroupId("testGroup");
201         child.setVersion("1.0");
202 
203         PluginExecution childExecution = new PluginExecution();
204         childExecution.setId("testExecution2");
205 
206         child.addExecution(childExecution);
207 
208         ModelUtils.mergePluginDefinitions(child, parent, false);
209 
210         assertEquals(2, child.getExecutions().size());
211     }
212 
213     public void testShouldMergeOnePluginWithInheritExecutionWithoutDuplicatingPluginInList() {
214         Plugin parent = new Plugin();
215         parent.setArtifactId("testArtifact");
216         parent.setGroupId("testGroup");
217         parent.setVersion("1.0");
218 
219         PluginExecution parentExecution = new PluginExecution();
220         parentExecution.setId("testExecution");
221 
222         parent.addExecution(parentExecution);
223 
224         Build parentContainer = new Build();
225         parentContainer.addPlugin(parent);
226 
227         Plugin child = new Plugin();
228         child.setArtifactId("testArtifact");
229         child.setGroupId("testGroup");
230         child.setVersion("1.0");
231 
232         Build childContainer = new Build();
233         childContainer.addPlugin(child);
234 
235         ModelUtils.mergePluginLists(childContainer, parentContainer, true);
236 
237         List plugins = childContainer.getPlugins();
238 
239         assertEquals(1, plugins.size());
240 
241         Plugin plugin = (Plugin) plugins.get(0);
242 
243         assertEquals(1, plugin.getExecutions().size());
244     }
245 
246     public void testShouldMergePluginWithDifferentExecutionFromParentWithoutDuplicatingPluginInList() {
247         Plugin parent = new Plugin();
248         parent.setArtifactId("testArtifact");
249         parent.setGroupId("testGroup");
250         parent.setVersion("1.0");
251 
252         PluginExecution parentExecution = new PluginExecution();
253         parentExecution.setId("testExecution");
254 
255         parent.addExecution(parentExecution);
256 
257         Build parentContainer = new Build();
258         parentContainer.addPlugin(parent);
259 
260         Plugin child = new Plugin();
261         child.setArtifactId("testArtifact");
262         child.setGroupId("testGroup");
263         child.setVersion("1.0");
264 
265         PluginExecution childExecution = new PluginExecution();
266         childExecution.setId("testExecution2");
267 
268         child.addExecution(childExecution);
269 
270         Build childContainer = new Build();
271         childContainer.addPlugin(child);
272 
273         ModelUtils.mergePluginLists(childContainer, parentContainer, true);
274 
275         List plugins = childContainer.getPlugins();
276 
277         assertEquals(1, plugins.size());
278 
279         Plugin plugin = (Plugin) plugins.get(0);
280 
281         assertEquals(2, plugin.getExecutions().size());
282     }
283 
284     public void testShouldNOTMergeInheritedPluginHavingInheritEqualFalse() {
285         Plugin parent = new Plugin();
286         parent.setArtifactId("testArtifact");
287         parent.setGroupId("testGroup");
288         parent.setVersion("1.0");
289         parent.setInherited("false");
290 
291         PluginExecution parentExecution = new PluginExecution();
292         parentExecution.setId("testExecution");
293 
294         parent.addExecution(parentExecution);
295 
296         Plugin child = new Plugin();
297         child.setArtifactId("testArtifact");
298         child.setGroupId("testGroup");
299         child.setVersion("1.0");
300 
301         ModelUtils.mergePluginDefinitions(child, parent, true);
302 
303         assertEquals(0, child.getExecutions().size());
304     }
305 
306     /**
307      * Verifies MNG-1499: The order of the merged list should be the plugins specified by the parent followed by the
308      * child list.
309      */
310     public void testShouldKeepOriginalPluginOrdering() {
311         Plugin parentPlugin1 = new Plugin();
312         parentPlugin1.setArtifactId("testArtifact");
313         parentPlugin1.setGroupId("zzz"); // This will put this plugin last in the sorted map
314         parentPlugin1.setVersion("1.0");
315 
316         PluginExecution parentExecution1 = new PluginExecution();
317         parentExecution1.setId("testExecution");
318 
319         parentPlugin1.addExecution(parentExecution1);
320 
321         Plugin parentPlugin2 = new Plugin();
322         parentPlugin2.setArtifactId("testArtifact");
323         parentPlugin2.setGroupId("yyy");
324         parentPlugin2.setVersion("1.0");
325 
326         PluginExecution parentExecution2 = new PluginExecution();
327         parentExecution2.setId("testExecution");
328 
329         parentPlugin2.addExecution(parentExecution2);
330 
331         PluginContainer parentContainer = new PluginContainer();
332         parentContainer.addPlugin(parentPlugin1);
333         parentContainer.addPlugin(parentPlugin2);
334 
335         Plugin childPlugin1 = new Plugin();
336         childPlugin1.setArtifactId("testArtifact");
337         childPlugin1.setGroupId("bbb");
338         childPlugin1.setVersion("1.0");
339 
340         PluginExecution childExecution1 = new PluginExecution();
341         childExecution1.setId("testExecution");
342 
343         childPlugin1.addExecution(childExecution1);
344 
345         Plugin childPlugin2 = new Plugin();
346         childPlugin2.setArtifactId("testArtifact");
347         childPlugin2.setGroupId("aaa");
348         childPlugin2.setVersion("1.0");
349 
350         PluginExecution childExecution2 = new PluginExecution();
351         childExecution2.setId("testExecution");
352 
353         childPlugin2.addExecution(childExecution2);
354 
355         PluginContainer childContainer = new PluginContainer();
356         childContainer.addPlugin(childPlugin1);
357         childContainer.addPlugin(childPlugin2);
358 
359         ModelUtils.mergePluginLists(childContainer, parentContainer, true);
360 
361         assertEquals(4, childContainer.getPlugins().size());
362         assertSame(parentPlugin1, childContainer.getPlugins().get(0));
363         assertSame(parentPlugin2, childContainer.getPlugins().get(1));
364         assertSame(childPlugin1, childContainer.getPlugins().get(2));
365         assertSame(childPlugin2, childContainer.getPlugins().get(3));
366     }
367 
368     /**
369      * Verifies MNG-1499: The ordering of plugin executions should also be in the specified order.
370      */
371     public void testShouldKeepOriginalPluginExecutionOrdering() {
372         Plugin parent = new Plugin();
373         parent.setArtifactId("testArtifact");
374         parent.setGroupId("testGroup");
375         parent.setVersion("1.0");
376 
377         PluginExecution parentExecution1 = new PluginExecution();
378         parentExecution1.setId("zzz"); // Will show up last in the sorted map
379         PluginExecution parentExecution2 = new PluginExecution();
380         parentExecution2.setId("yyy"); // Will show up last in the sorted map
381 
382         parent.addExecution(parentExecution1);
383         parent.addExecution(parentExecution2);
384 
385         // this block verifies MNG-1703
386         Dependency dep = new Dependency();
387         dep.setGroupId("depGroupId");
388         dep.setArtifactId("depArtifactId");
389         dep.setVersion("depVersion");
390         parent.setDependencies(Collections.singletonList(dep));
391 
392         Plugin child = new Plugin();
393         child.setArtifactId("testArtifact");
394         child.setGroupId("testGroup");
395         child.setVersion("1.0");
396 
397         PluginExecution childExecution1 = new PluginExecution();
398         childExecution1.setId("bbb");
399         PluginExecution childExecution2 = new PluginExecution();
400         childExecution2.setId("aaa");
401 
402         child.addExecution(childExecution1);
403         child.addExecution(childExecution2);
404 
405         ModelUtils.mergePluginDefinitions(child, parent, false);
406 
407         assertEquals(4, child.getExecutions().size());
408         assertSame(parentExecution1, child.getExecutions().get(0));
409         assertSame(parentExecution2, child.getExecutions().get(1));
410         assertSame(childExecution1, child.getExecutions().get(2));
411         assertSame(childExecution2, child.getExecutions().get(3));
412 
413         // this block prevents MNG-1703
414         assertEquals(1, child.getDependencies().size());
415         Dependency dep2 = child.getDependencies().get(0);
416         assertEquals(dep.getManagementKey(), dep2.getManagementKey());
417     }
418 
419     public void testShouldOverwritePluginConfigurationSubItemsByDefault() throws XmlPullParserException, IOException {
420         String parentConfigStr = "<configuration><items><item>one</item><item>two</item></items></configuration>";
421         Xpp3Dom parentConfig = Xpp3DomBuilder.build(new StringReader(parentConfigStr));
422 
423         Plugin parentPlugin = createPlugin("group", "artifact", "1", null);
424         parentPlugin.setConfiguration(parentConfig);
425 
426         String childConfigStr = "<configuration><items><item>three</item></items></configuration>";
427         Xpp3Dom childConfig = Xpp3DomBuilder.build(new StringReader(childConfigStr));
428 
429         Plugin childPlugin = createPlugin("group", "artifact", "1", null);
430         childPlugin.setConfiguration(childConfig);
431 
432         ModelUtils.mergePluginDefinitions(childPlugin, parentPlugin, true);
433 
434         Xpp3Dom result = (Xpp3Dom) childPlugin.getConfiguration();
435         Xpp3Dom items = result.getChild("items");
436 
437         assertEquals(1, items.getChildCount());
438 
439         Xpp3Dom item = items.getChild(0);
440         assertEquals("three", item.getValue());
441     }
442 
443     public void testShouldMergePluginConfigurationSubItemsWithMergeAttributeSet()
444             throws XmlPullParserException, IOException {
445         String parentConfigStr = "<configuration><items><item>one</item><item>two</item></items></configuration>";
446         Xpp3Dom parentConfig = Xpp3DomBuilder.build(new StringReader(parentConfigStr));
447 
448         Plugin parentPlugin = createPlugin("group", "artifact", "1", null);
449         parentPlugin.setConfiguration(parentConfig);
450 
451         String childConfigStr =
452                 "<configuration><items combine.children=\"append\"><item>three</item></items></configuration>";
453         Xpp3Dom childConfig = Xpp3DomBuilder.build(new StringReader(childConfigStr));
454 
455         Plugin childPlugin = createPlugin("group", "artifact", "1", null);
456         childPlugin.setConfiguration(childConfig);
457 
458         ModelUtils.mergePluginDefinitions(childPlugin, parentPlugin, true);
459 
460         Xpp3Dom result = (Xpp3Dom) childPlugin.getConfiguration();
461         Xpp3Dom items = result.getChild("items");
462 
463         assertEquals(3, items.getChildCount());
464 
465         Xpp3Dom[] item = items.getChildren();
466 
467         List<String> actual = Arrays.asList(item[0].getValue(), item[1].getValue(), item[2].getValue());
468         List<String> expected = Arrays.asList("one", "two", "three");
469         Collections.sort(actual);
470         Collections.sort(expected);
471         assertEquals(expected, actual);
472     }
473 
474     public void testShouldNotMergePluginExecutionWhenExecInheritedIsFalseAndTreatAsInheritanceIsTrue() {
475         String gid = "group";
476         String aid = "artifact";
477         String ver = "1";
478 
479         PluginContainer parent = new PluginContainer();
480         Plugin pParent = createPlugin(gid, aid, ver, Collections.EMPTY_MAP);
481 
482         pParent.setInherited(Boolean.toString(true));
483 
484         PluginExecution eParent = new PluginExecution();
485 
486         String testId = "test";
487 
488         eParent.setId(testId);
489         eParent.addGoal("run");
490         eParent.setPhase("initialize");
491         eParent.setInherited(Boolean.toString(false));
492 
493         pParent.addExecution(eParent);
494         parent.addPlugin(pParent);
495 
496         PluginContainer child = new PluginContainer();
497         Plugin pChild = createPlugin(gid, aid, ver, Collections.EMPTY_MAP);
498         PluginExecution eChild = new PluginExecution();
499 
500         eChild.setId("child-specified");
501         eChild.addGoal("child");
502         eChild.setPhase("compile");
503 
504         pChild.addExecution(eChild);
505         child.addPlugin(pChild);
506 
507         ModelUtils.mergePluginDefinitions(pChild, pParent, true);
508 
509         Map executionMap = pChild.getExecutionsAsMap();
510         assertNull("test execution should not be inherited from parent.", executionMap.get(testId));
511     }
512 
513     public void testShouldNotMergePluginExecutionWhenPluginInheritedIsFalseAndTreatAsInheritanceIsTrue() {
514         String gid = "group";
515         String aid = "artifact";
516         String ver = "1";
517 
518         PluginContainer parent = new PluginContainer();
519         Plugin pParent = createPlugin(gid, aid, ver, Collections.EMPTY_MAP);
520 
521         pParent.setInherited(Boolean.toString(false));
522 
523         PluginExecution eParent = new PluginExecution();
524 
525         String testId = "test";
526 
527         eParent.setId(testId);
528         eParent.addGoal("run");
529         eParent.setPhase("initialize");
530         eParent.setInherited(Boolean.toString(true));
531 
532         pParent.addExecution(eParent);
533         parent.addPlugin(pParent);
534 
535         PluginContainer child = new PluginContainer();
536         Plugin pChild = createPlugin(gid, aid, ver, Collections.EMPTY_MAP);
537         PluginExecution eChild = new PluginExecution();
538 
539         eChild.setId("child-specified");
540         eChild.addGoal("child");
541         eChild.setPhase("compile");
542 
543         pChild.addExecution(eChild);
544         child.addPlugin(pChild);
545 
546         ModelUtils.mergePluginDefinitions(pChild, pParent, true);
547 
548         Map executionMap = pChild.getExecutionsAsMap();
549         assertNull("test execution should not be inherited from parent.", executionMap.get(testId));
550     }
551 
552     public void testShouldMergePluginExecutionWhenExecInheritedIsTrueAndTreatAsInheritanceIsTrue() {
553         String gid = "group";
554         String aid = "artifact";
555         String ver = "1";
556 
557         PluginContainer parent = new PluginContainer();
558         Plugin pParent = createPlugin(gid, aid, ver, Collections.EMPTY_MAP);
559 
560         pParent.setInherited(Boolean.toString(true));
561 
562         PluginExecution eParent = new PluginExecution();
563 
564         String testId = "test";
565 
566         eParent.setId(testId);
567         eParent.addGoal("run");
568         eParent.setPhase("initialize");
569         eParent.setInherited(Boolean.toString(true));
570 
571         pParent.addExecution(eParent);
572         parent.addPlugin(pParent);
573 
574         PluginContainer child = new PluginContainer();
575         Plugin pChild = createPlugin(gid, aid, ver, Collections.EMPTY_MAP);
576         PluginExecution eChild = new PluginExecution();
577 
578         eChild.setId("child-specified");
579         eChild.addGoal("child");
580         eChild.setPhase("compile");
581 
582         pChild.addExecution(eChild);
583         child.addPlugin(pChild);
584 
585         ModelUtils.mergePluginDefinitions(pChild, pParent, true);
586 
587         Map executionMap = pChild.getExecutionsAsMap();
588         assertNotNull("test execution should be inherited from parent.", executionMap.get(testId));
589     }
590 }