001    package org.apache.maven.project;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *  http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import java.io.IOException;
023    import java.io.StringReader;
024    import java.util.Arrays;
025    import java.util.Collections;
026    import java.util.Iterator;
027    import java.util.List;
028    import java.util.Map;
029    
030    import junit.framework.TestCase;
031    
032    import org.apache.maven.model.Build;
033    import org.apache.maven.model.Dependency;
034    import org.apache.maven.model.Plugin;
035    import org.apache.maven.model.PluginContainer;
036    import org.apache.maven.model.PluginExecution;
037    import org.codehaus.plexus.util.xml.Xpp3Dom;
038    import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
039    import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
040    
041    public class ModelUtilsTest
042        extends TestCase
043    {
044    
045        public void testShouldUseMainPluginDependencyVersionOverManagedDepVersion()
046        {
047            Plugin mgtPlugin = createPlugin( "group", "artifact", "1", Collections.EMPTY_MAP );
048            Dependency mgtDep = createDependency( "g", "a", "2" );
049            mgtPlugin.addDependency( mgtDep );
050    
051            Plugin plugin = createPlugin( "group", "artifact", "1", Collections.EMPTY_MAP );
052            Dependency dep = createDependency( "g", "a", "1" );
053            plugin.addDependency( dep );
054    
055            ModelUtils.mergePluginDefinitions( plugin, mgtPlugin, false );
056    
057            assertEquals( dep.getVersion(), ((Dependency) plugin.getDependencies().get( 0 ) ).getVersion() );
058        }
059    
060        private Dependency createDependency( String gid,
061                                             String aid,
062                                             String ver )
063        {
064            Dependency dep = new Dependency();
065            dep.setGroupId( gid );
066            dep.setArtifactId( aid );
067            dep.setVersion( ver );
068    
069            return dep;
070        }
071    
072        public void testShouldNotInheritPluginWithInheritanceSetToFalse()
073        {
074            PluginContainer parent = new PluginContainer();
075    
076            Plugin parentPlugin = createPlugin( "group", "artifact", "1.0", Collections.EMPTY_MAP );
077            parentPlugin.setInherited( "false" );
078    
079            parent.addPlugin( parentPlugin );
080    
081            PluginContainer child = new PluginContainer();
082    
083            child.addPlugin( createPlugin( "group3", "artifact3", "1.0", Collections.EMPTY_MAP ) );
084    
085            ModelUtils.mergePluginLists( child, parent, true );
086    
087            List results = child.getPlugins();
088    
089            assertEquals( 1, results.size() );
090    
091            Plugin result1 = (Plugin) results.get( 0 );
092            assertEquals( "group3", result1.getGroupId() );
093            assertEquals( "artifact3", result1.getArtifactId() );
094        }
095    
096        /**
097         * Test that this is the resulting ordering of plugins after merging:
098         *
099         * Given:
100         *
101         *   parent: X -> A -> B -> D -> E
102         *   child: Y -> A -> C -> D -> F
103         *
104         * Result:
105         *
106         *   X -> Y -> A -> B -> C -> D -> E -> F
107         */
108        public void testShouldPreserveChildOrderingOfPluginsAfterParentMerge()
109        {
110            PluginContainer parent = new PluginContainer();
111    
112            parent.addPlugin( createPlugin( "group", "artifact", "1.0", Collections.EMPTY_MAP ) );
113            parent.addPlugin( createPlugin( "group2", "artifact2", "1.0", Collections.singletonMap( "key", "value" ) ) );
114    
115            PluginContainer child = new PluginContainer();
116    
117            child.addPlugin( createPlugin( "group3", "artifact3", "1.0", Collections.EMPTY_MAP ) );
118            child.addPlugin( createPlugin( "group2", "artifact2", "1.0", Collections.singletonMap( "key2", "value2" ) ) );
119    
120            ModelUtils.mergePluginLists( child, parent, true );
121    
122            List results = child.getPlugins();
123    
124            assertEquals( 3, results.size() );
125    
126            Plugin result1 = (Plugin) results.get( 0 );
127    
128            assertEquals( "group", result1.getGroupId() );
129            assertEquals( "artifact", result1.getArtifactId() );
130    
131            Plugin result2 = (Plugin) results.get( 1 );
132    
133            assertEquals( "group3", result2.getGroupId() );
134            assertEquals( "artifact3", result2.getArtifactId() );
135    
136            Plugin result3 = (Plugin) results.get( 2 );
137    
138            assertEquals( "group2", result3.getGroupId() );
139            assertEquals( "artifact2", result3.getArtifactId() );
140    
141            Xpp3Dom result3Config = (Xpp3Dom) result3.getConfiguration();
142    
143            assertNotNull( result3Config );
144    
145            assertEquals( "value", result3Config.getChild( "key" ).getValue() );
146            assertEquals( "value2", result3Config.getChild( "key2" ).getValue() );
147        }
148    
149        private Plugin createPlugin( String groupId, String artifactId, String version, Map configuration )
150        {
151            Plugin plugin = new Plugin();
152            plugin.setGroupId( groupId );
153            plugin.setArtifactId( artifactId );
154            plugin.setVersion( version );
155    
156            Xpp3Dom config = new Xpp3Dom( "configuration" );
157    
158            if( configuration != null )
159            {
160                for ( Iterator it = configuration.entrySet().iterator(); it.hasNext(); )
161                {
162                    Map.Entry entry = (Map.Entry) it.next();
163    
164                    Xpp3Dom param = new Xpp3Dom( String.valueOf( entry.getKey() ) );
165                    param.setValue( String.valueOf( entry.getValue() ) );
166    
167                    config.addChild( param );
168                }
169            }
170    
171            plugin.setConfiguration( config );
172    
173            return plugin;
174        }
175    
176        public void testShouldInheritOnePluginWithExecution()
177        {
178            Plugin parent = new Plugin();
179            parent.setArtifactId( "testArtifact" );
180            parent.setGroupId( "testGroup" );
181            parent.setVersion( "1.0" );
182    
183            PluginExecution parentExecution = new PluginExecution();
184            parentExecution.setId( "testExecution" );
185    
186            parent.addExecution( parentExecution );
187    
188            Plugin child = new Plugin();
189            child.setArtifactId( "testArtifact" );
190            child.setGroupId( "testGroup" );
191            child.setVersion( "1.0" );
192    
193            ModelUtils.mergePluginDefinitions( child, parent, false );
194    
195            assertEquals( 1, child.getExecutions().size() );
196        }
197    
198        public void testShouldMergeInheritedPluginHavingExecutionWithLocalPlugin()
199        {
200            Plugin parent = new Plugin();
201            parent.setArtifactId( "testArtifact" );
202            parent.setGroupId( "testGroup" );
203            parent.setVersion( "1.0" );
204    
205            PluginExecution parentExecution = new PluginExecution();
206            parentExecution.setId( "testExecution" );
207    
208            parent.addExecution( parentExecution );
209    
210            Plugin child = new Plugin();
211            child.setArtifactId( "testArtifact" );
212            child.setGroupId( "testGroup" );
213            child.setVersion( "1.0" );
214    
215            PluginExecution childExecution = new PluginExecution();
216            childExecution.setId( "testExecution2" );
217    
218            child.addExecution( childExecution );
219    
220            ModelUtils.mergePluginDefinitions( child, parent, false );
221    
222            assertEquals( 2, child.getExecutions().size() );
223        }
224    
225        public void testShouldMergeOnePluginWithInheritExecutionWithoutDuplicatingPluginInList()
226        {
227            Plugin parent = new Plugin();
228            parent.setArtifactId( "testArtifact" );
229            parent.setGroupId( "testGroup" );
230            parent.setVersion( "1.0" );
231    
232            PluginExecution parentExecution = new PluginExecution();
233            parentExecution.setId( "testExecution" );
234    
235            parent.addExecution( parentExecution );
236    
237            Build parentContainer = new Build();
238            parentContainer.addPlugin( parent );
239    
240            Plugin child = new Plugin();
241            child.setArtifactId( "testArtifact" );
242            child.setGroupId( "testGroup" );
243            child.setVersion( "1.0" );
244    
245            Build childContainer = new Build();
246            childContainer.addPlugin( child );
247    
248            ModelUtils.mergePluginLists( childContainer, parentContainer, true );
249    
250            List plugins = childContainer.getPlugins();
251    
252            assertEquals( 1, plugins.size() );
253    
254            Plugin plugin = (Plugin) plugins.get( 0 );
255    
256            assertEquals( 1, plugin.getExecutions().size() );
257        }
258    
259        public void testShouldMergePluginWithDifferentExecutionFromParentWithoutDuplicatingPluginInList()
260        {
261            Plugin parent = new Plugin();
262            parent.setArtifactId( "testArtifact" );
263            parent.setGroupId( "testGroup" );
264            parent.setVersion( "1.0" );
265    
266            PluginExecution parentExecution = new PluginExecution();
267            parentExecution.setId( "testExecution" );
268    
269            parent.addExecution( parentExecution );
270    
271            Build parentContainer = new Build();
272            parentContainer.addPlugin( parent );
273    
274            Plugin child = new Plugin();
275            child.setArtifactId( "testArtifact" );
276            child.setGroupId( "testGroup" );
277            child.setVersion( "1.0" );
278    
279            PluginExecution childExecution = new PluginExecution();
280            childExecution.setId( "testExecution2" );
281    
282            child.addExecution( childExecution );
283    
284    
285            Build childContainer = new Build();
286            childContainer.addPlugin( child );
287    
288            ModelUtils.mergePluginLists( childContainer, parentContainer, true );
289    
290            List plugins = childContainer.getPlugins();
291    
292            assertEquals( 1, plugins.size() );
293    
294            Plugin plugin = (Plugin) plugins.get( 0 );
295    
296            assertEquals( 2, plugin.getExecutions().size() );
297        }
298    
299        public void testShouldNOTMergeInheritedPluginHavingInheritEqualFalse()
300        {
301            Plugin parent = new Plugin();
302            parent.setArtifactId( "testArtifact" );
303            parent.setGroupId( "testGroup" );
304            parent.setVersion( "1.0" );
305            parent.setInherited( "false" );
306    
307            PluginExecution parentExecution = new PluginExecution();
308            parentExecution.setId( "testExecution" );
309    
310            parent.addExecution( parentExecution );
311    
312            Plugin child = new Plugin();
313            child.setArtifactId( "testArtifact" );
314            child.setGroupId( "testGroup" );
315            child.setVersion( "1.0" );
316    
317            ModelUtils.mergePluginDefinitions( child, parent, true );
318    
319            assertEquals( 0, child.getExecutions().size() );
320        }
321    
322        /**
323         * Verifies MNG-1499: The order of the merged list should be the plugins specified by the parent followed by the
324         * child list.
325         */
326        public void testShouldKeepOriginalPluginOrdering()
327        {
328            Plugin parentPlugin1 = new Plugin();
329            parentPlugin1.setArtifactId( "testArtifact" );
330            parentPlugin1.setGroupId( "zzz" );  // This will put this plugin last in the sorted map
331            parentPlugin1.setVersion( "1.0" );
332    
333            PluginExecution parentExecution1 = new PluginExecution();
334            parentExecution1.setId( "testExecution" );
335    
336            parentPlugin1.addExecution( parentExecution1 );
337    
338            Plugin parentPlugin2 = new Plugin();
339            parentPlugin2.setArtifactId( "testArtifact" );
340            parentPlugin2.setGroupId( "yyy" );
341            parentPlugin2.setVersion( "1.0" );
342    
343            PluginExecution parentExecution2 = new PluginExecution();
344            parentExecution2.setId( "testExecution" );
345    
346            parentPlugin2.addExecution( parentExecution2 );
347    
348            PluginContainer parentContainer = new PluginContainer();
349            parentContainer.addPlugin(parentPlugin1);
350            parentContainer.addPlugin(parentPlugin2);
351    
352    
353            Plugin childPlugin1 = new Plugin();
354            childPlugin1.setArtifactId( "testArtifact" );
355            childPlugin1.setGroupId( "bbb" );
356            childPlugin1.setVersion( "1.0" );
357    
358            PluginExecution childExecution1 = new PluginExecution();
359            childExecution1.setId( "testExecution" );
360    
361            childPlugin1.addExecution( childExecution1 );
362    
363            Plugin childPlugin2 = new Plugin();
364            childPlugin2.setArtifactId( "testArtifact" );
365            childPlugin2.setGroupId( "aaa" );
366            childPlugin2.setVersion( "1.0" );
367    
368            PluginExecution childExecution2 = new PluginExecution();
369            childExecution2.setId( "testExecution" );
370    
371            childPlugin2.addExecution( childExecution2 );
372    
373            PluginContainer childContainer = new PluginContainer();
374            childContainer.addPlugin(childPlugin1);
375            childContainer.addPlugin(childPlugin2);
376    
377    
378            ModelUtils.mergePluginLists(childContainer, parentContainer, true);
379    
380            assertEquals( 4, childContainer.getPlugins().size() );
381            assertSame(parentPlugin1, childContainer.getPlugins().get(0));
382            assertSame(parentPlugin2, childContainer.getPlugins().get(1));
383            assertSame(childPlugin1, childContainer.getPlugins().get(2));
384            assertSame(childPlugin2, childContainer.getPlugins().get(3));
385        }
386    
387        /**
388         * Verifies MNG-1499: The ordering of plugin executions should also be in the specified order.
389         */
390        public void testShouldKeepOriginalPluginExecutionOrdering()
391        {
392            Plugin parent = new Plugin();
393            parent.setArtifactId( "testArtifact" );
394            parent.setGroupId( "testGroup" );
395            parent.setVersion( "1.0" );
396    
397            PluginExecution parentExecution1 = new PluginExecution();
398            parentExecution1.setId( "zzz" );  // Will show up last in the sorted map
399            PluginExecution parentExecution2 = new PluginExecution();
400            parentExecution2.setId( "yyy" );  // Will show up last in the sorted map
401    
402            parent.addExecution( parentExecution1 );
403            parent.addExecution( parentExecution2 );
404    
405            // this block verifies MNG-1703
406            Dependency dep = new Dependency();
407            dep.setGroupId( "depGroupId" );
408            dep.setArtifactId( "depArtifactId" );
409            dep.setVersion( "depVersion" );
410            parent.setDependencies( Collections.singletonList( dep ) );
411    
412            Plugin child = new Plugin();
413            child.setArtifactId( "testArtifact" );
414            child.setGroupId( "testGroup" );
415            child.setVersion( "1.0" );
416    
417            PluginExecution childExecution1 = new PluginExecution();
418            childExecution1.setId( "bbb" );
419            PluginExecution childExecution2 = new PluginExecution();
420            childExecution2.setId( "aaa" );
421    
422            child.addExecution( childExecution1 );
423            child.addExecution( childExecution2 );
424    
425            ModelUtils.mergePluginDefinitions( child, parent, false );
426    
427            assertEquals( 4, child.getExecutions().size() );
428            assertSame(parentExecution1, child.getExecutions().get(0));
429            assertSame(parentExecution2, child.getExecutions().get(1));
430            assertSame(childExecution1, child.getExecutions().get(2));
431            assertSame(childExecution2, child.getExecutions().get(3));
432    
433            // this block prevents MNG-1703
434            assertEquals( 1, child.getDependencies().size() );
435            Dependency dep2 = (Dependency) child.getDependencies().get( 0 );
436            assertEquals( dep.getManagementKey(), dep2.getManagementKey() );
437        }
438    
439        public void testShouldOverwritePluginConfigurationSubItemsByDefault()
440            throws XmlPullParserException, IOException
441        {
442            String parentConfigStr = "<configuration><items><item>one</item><item>two</item></items></configuration>";
443            Xpp3Dom parentConfig = Xpp3DomBuilder.build( new StringReader( parentConfigStr ) );
444    
445            Plugin parentPlugin = createPlugin( "group", "artifact", "1", null );
446            parentPlugin.setConfiguration( parentConfig );
447    
448            String childConfigStr = "<configuration><items><item>three</item></items></configuration>";
449            Xpp3Dom childConfig = Xpp3DomBuilder.build( new StringReader( childConfigStr ) );
450    
451            Plugin childPlugin = createPlugin( "group", "artifact", "1", null );
452            childPlugin.setConfiguration( childConfig );
453    
454            ModelUtils.mergePluginDefinitions( childPlugin, parentPlugin, true );
455    
456            Xpp3Dom result = (Xpp3Dom) childPlugin.getConfiguration();
457            Xpp3Dom items = result.getChild( "items" );
458    
459            assertEquals( 1, items.getChildCount() );
460    
461            Xpp3Dom item = items.getChild( 0 );
462            assertEquals( "three", item.getValue() );
463        }
464    
465        public void testShouldMergePluginConfigurationSubItemsWithMergeAttributeSet()
466            throws XmlPullParserException, IOException
467        {
468            String parentConfigStr = "<configuration><items><item>one</item><item>two</item></items></configuration>";
469            Xpp3Dom parentConfig = Xpp3DomBuilder.build( new StringReader( parentConfigStr ) );
470    
471            Plugin parentPlugin = createPlugin( "group", "artifact", "1", null );
472            parentPlugin.setConfiguration( parentConfig );
473    
474            String childConfigStr = "<configuration><items combine.children=\"append\"><item>three</item></items></configuration>";
475            Xpp3Dom childConfig = Xpp3DomBuilder.build( new StringReader( childConfigStr ) );
476    
477            Plugin childPlugin = createPlugin( "group", "artifact", "1", null );
478            childPlugin.setConfiguration( childConfig );
479    
480            ModelUtils.mergePluginDefinitions( childPlugin, parentPlugin, true );
481    
482            Xpp3Dom result = (Xpp3Dom) childPlugin.getConfiguration();
483            Xpp3Dom items = result.getChild( "items" );
484    
485            assertEquals( 3, items.getChildCount() );
486    
487            Xpp3Dom[] item = items.getChildren();
488    
489            List<String> actual = Arrays.asList( item[0].getValue(), item[1].getValue(), item[2].getValue() );
490            List<String> expected = Arrays.asList( "one", "two", "three" );
491            Collections.sort( actual );
492            Collections.sort( expected );
493            assertEquals( expected, actual );
494        }
495    
496        public void testShouldNotMergePluginExecutionWhenExecInheritedIsFalseAndTreatAsInheritanceIsTrue()
497        {
498            String gid = "group";
499            String aid = "artifact";
500            String ver = "1";
501    
502            PluginContainer parent = new PluginContainer();
503            Plugin pParent = createPlugin( gid, aid, ver, Collections.EMPTY_MAP );
504    
505            pParent.setInherited( Boolean.toString( true ) );
506    
507            PluginExecution eParent = new PluginExecution();
508    
509            String testId = "test";
510    
511            eParent.setId( testId );
512            eParent.addGoal( "run" );
513            eParent.setPhase( "initialize" );
514            eParent.setInherited( Boolean.toString( false ) );
515    
516            pParent.addExecution( eParent );
517            parent.addPlugin( pParent );
518    
519            PluginContainer child = new PluginContainer();
520            Plugin pChild = createPlugin( gid, aid, ver, Collections.EMPTY_MAP );
521            PluginExecution eChild = new PluginExecution();
522    
523            eChild.setId( "child-specified" );
524            eChild.addGoal( "child" );
525            eChild.setPhase( "compile" );
526    
527            pChild.addExecution( eChild );
528            child.addPlugin( pChild );
529    
530            ModelUtils.mergePluginDefinitions( pChild, pParent, true );
531    
532            Map executionMap = pChild.getExecutionsAsMap();
533            assertNull( "test execution should not be inherited from parent.", executionMap.get( testId ) );
534        }
535    
536        public void testShouldNotMergePluginExecutionWhenPluginInheritedIsFalseAndTreatAsInheritanceIsTrue()
537        {
538            String gid = "group";
539            String aid = "artifact";
540            String ver = "1";
541    
542            PluginContainer parent = new PluginContainer();
543            Plugin pParent = createPlugin( gid, aid, ver, Collections.EMPTY_MAP );
544    
545            pParent.setInherited( Boolean.toString( false ) );
546    
547            PluginExecution eParent = new PluginExecution();
548    
549            String testId = "test";
550    
551            eParent.setId( testId );
552            eParent.addGoal( "run" );
553            eParent.setPhase( "initialize" );
554            eParent.setInherited( Boolean.toString( true ) );
555    
556            pParent.addExecution( eParent );
557            parent.addPlugin( pParent );
558    
559            PluginContainer child = new PluginContainer();
560            Plugin pChild = createPlugin( gid, aid, ver, Collections.EMPTY_MAP );
561            PluginExecution eChild = new PluginExecution();
562    
563            eChild.setId( "child-specified" );
564            eChild.addGoal( "child" );
565            eChild.setPhase( "compile" );
566    
567            pChild.addExecution( eChild );
568            child.addPlugin( pChild );
569    
570            ModelUtils.mergePluginDefinitions( pChild, pParent, true );
571    
572            Map executionMap = pChild.getExecutionsAsMap();
573            assertNull( "test execution should not be inherited from parent.", executionMap.get( testId ) );
574        }
575    
576        public void testShouldMergePluginExecutionWhenExecInheritedIsTrueAndTreatAsInheritanceIsTrue()
577        {
578            String gid = "group";
579            String aid = "artifact";
580            String ver = "1";
581    
582            PluginContainer parent = new PluginContainer();
583            Plugin pParent = createPlugin( gid, aid, ver, Collections.EMPTY_MAP );
584    
585            pParent.setInherited( Boolean.toString( true ) );
586    
587            PluginExecution eParent = new PluginExecution();
588    
589            String testId = "test";
590    
591            eParent.setId( testId );
592            eParent.addGoal( "run" );
593            eParent.setPhase( "initialize" );
594            eParent.setInherited( Boolean.toString( true ) );
595    
596            pParent.addExecution( eParent );
597            parent.addPlugin( pParent );
598    
599            PluginContainer child = new PluginContainer();
600            Plugin pChild = createPlugin( gid, aid, ver, Collections.EMPTY_MAP );
601            PluginExecution eChild = new PluginExecution();
602    
603            eChild.setId( "child-specified" );
604            eChild.addGoal( "child" );
605            eChild.setPhase( "compile" );
606    
607            pChild.addExecution( eChild );
608            child.addPlugin( pChild );
609    
610            ModelUtils.mergePluginDefinitions( pChild, pParent, true );
611    
612            Map executionMap = pChild.getExecutionsAsMap();
613            assertNotNull( "test execution should be inherited from parent.", executionMap.get( testId ) );
614        }
615    
616    }