Added inheritance of Plugins according to the rules we decided upon. This consists of:

- inheritanceApplied flag on Plugin and Goal (NOT fields, just a code-only flag)
- flushGoalMap/flushPluginMap to clear caching of these calculated attributes
- ModelUtils.mergePluginLists() and ModelUtils.mergePluginDefinitions() for use in both
    * DefaultModelInheritanceAssembler (Plugin/PluginManagement lists)
    * DefaultModelDefaultsInjector (PluginManagement -> Plugin merges)

- Also added a few unit tests for basic Plugin inheritance stuff. This could be more thoroughly tested...

git-svn-id: https://svn.apache.org/repos/asf/maven/components/trunk@178825 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
John Dennis Casey 2005-05-27 21:47:12 +00:00
parent 771fc3a8c9
commit 6ca4de295d
5 changed files with 320 additions and 121 deletions

View File

@ -680,6 +680,11 @@
<version>4.0.0</version>
<code><![CDATA[
Map pluginMap;
public void flushPluginMap()
{
this.pluginMap = null;
}
public Map getPluginsAsMap()
{
@ -2045,6 +2050,22 @@
<version>4.0.0</version>
<code><![CDATA[
private Map goalMap = null;
private boolean inheritanceApplied = false;
public void setInheritanceApplied()
{
this.inheritanceApplied = true;
}
public boolean isInheritanceApplied()
{
return inheritanceApplied;
}
public void flushGoalMap()
{
this.goalMap = null;
}
public Map getGoalsAsMap()
{
@ -2096,6 +2117,23 @@
<type>DOM</type>
</field>
</fields>
<codeSegments>
<codeSegment>
<code><![CDATA[
private boolean inheritanceApplied = false;
public void setInheritanceApplied()
{
this.inheritanceApplied = true;
}
public boolean isInheritanceApplied()
{
return inheritanceApplied;
}
]]></code>
</codeSegment>
</codeSegments>
</class>
<class>
<name>DependencyManagement</name>

View File

@ -2,11 +2,14 @@ package org.apache.maven.project;
import org.apache.maven.model.Goal;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginContainer;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
/*
* Copyright 2001-2005 The Apache Software Foundation.
@ -26,44 +29,152 @@ import java.util.Map;
public final class ModelUtils
{
public static void mergeSupplementalPluginDefinition( Plugin main, Plugin supplemental )
public static void mergePluginLists( PluginContainer childContainer, PluginContainer parentContainer,
boolean handleAsInheritance )
{
if ( main.getVersion() == null && supplemental.getVersion() != null )
if( childContainer == null || parentContainer == null )
{
main.setVersion( supplemental.getVersion() );
// nothing to do.
return;
}
List parentPlugins = parentContainer.getPlugins();
if ( parentPlugins != null && !parentPlugins.isEmpty() )
{
Map assembledPlugins = new TreeMap();
Map childPlugins = childContainer.getPluginsAsMap();
for ( Iterator it = parentPlugins.iterator(); it.hasNext(); )
{
Plugin parentPlugin = (Plugin) it.next();
String parentInherited = parentPlugin.getInherited();
if ( !handleAsInheritance || parentInherited == null
|| Boolean.valueOf( parentInherited ).booleanValue() )
{
Plugin assembledPlugin = parentPlugin;
Plugin childPlugin = (Plugin) childPlugins.get( parentPlugin.getKey() );
if ( childPlugin != null )
{
assembledPlugin = childPlugin;
ModelUtils.mergePluginDefinitions( childPlugin, parentPlugin, handleAsInheritance );
}
if ( handleAsInheritance )
{
assembledPlugin.setInheritanceApplied();
}
assembledPlugins.put( assembledPlugin.getKey(), assembledPlugin );
}
}
for ( Iterator it = childPlugins.values().iterator(); it.hasNext(); )
{
Plugin childPlugin = (Plugin) it.next();
if ( !assembledPlugins.containsKey( childPlugin.getKey() ) )
{
assembledPlugins.put( childPlugin.getKey(), childPlugin );
}
}
childContainer.setPlugins( new ArrayList( assembledPlugins.values() ) );
childContainer.flushPluginMap();
}
}
public static void mergePluginDefinitions( Plugin child, Plugin parent, boolean handleAsInheritance )
{
if( child == null || parent == null )
{
// nothing to do.
return;
}
if ( child.getVersion() == null && parent.getVersion() != null )
{
child.setVersion( parent.getVersion() );
}
Map supplementalGoals = supplemental.getGoalsAsMap();
List parentGoals = parent.getGoals();
List pluginGoals = main.getGoals();
if ( pluginGoals != null )
// if the supplemental goals are non-existent, then nothing related to goals changes.
if ( parentGoals != null && !parentGoals.isEmpty() )
{
for ( Iterator it = pluginGoals.iterator(); it.hasNext(); )
Map assembledGoals = new TreeMap();
Map childGoals = child.getGoalsAsMap();
if ( childGoals != null )
{
Goal pluginGoal = (Goal) it.next();
Goal supplementalGoal = (Goal) supplementalGoals.get( pluginGoal.getId() );
if ( supplementalGoal != null )
for ( Iterator it = parentGoals.iterator(); it.hasNext(); )
{
Xpp3Dom pluginGoalConfig = (Xpp3Dom) pluginGoal.getConfiguration();
Xpp3Dom supplementalGoalConfig = (Xpp3Dom) supplementalGoal.getConfiguration();
Goal parentGoal = (Goal) it.next();
pluginGoalConfig = Xpp3Dom.mergeXpp3Dom( pluginGoalConfig, supplementalGoalConfig );
String parentInherited = parentGoal.getInherited();
pluginGoal.setConfiguration( pluginGoalConfig );
if ( !handleAsInheritance || parentInherited == null
|| Boolean.valueOf( parentInherited ).booleanValue() )
{
Goal assembledGoal = parentGoal;
Goal childGoal = (Goal) childGoals.get( parentGoal.getId() );
if ( childGoal != null )
{
Xpp3Dom childGoalConfig = (Xpp3Dom) childGoal.getConfiguration();
Xpp3Dom parentGoalConfig = (Xpp3Dom) parentGoal.getConfiguration();
childGoalConfig = Xpp3Dom.mergeXpp3Dom( childGoalConfig, parentGoalConfig );
childGoal.setConfiguration( childGoalConfig );
assembledGoal = childGoal;
}
if ( handleAsInheritance )
{
assembledGoal.setInheritanceApplied();
}
assembledGoals.put( assembledGoal.getId(), assembledGoal );
}
}
for ( Iterator it = childGoals.entrySet().iterator(); it.hasNext(); )
{
Map.Entry entry = (Map.Entry) it.next();
String key = (String) entry.getKey();
Goal childGoal = (Goal) entry.getValue();
if ( !assembledGoals.containsKey( key ) )
{
assembledGoals.put( key, childGoal );
}
}
child.setGoals( new ArrayList( assembledGoals.values() ) );
child.flushGoalMap();
}
}
Xpp3Dom pluginConfiguration = (Xpp3Dom) main.getConfiguration();
Xpp3Dom supplementalConfiguration = (Xpp3Dom) supplemental.getConfiguration();
Xpp3Dom childConfiguration = (Xpp3Dom) child.getConfiguration();
Xpp3Dom parentConfiguration = (Xpp3Dom) parent.getConfiguration();
pluginConfiguration = Xpp3Dom.mergeXpp3Dom( pluginConfiguration, supplementalConfiguration );
childConfiguration = Xpp3Dom.mergeXpp3Dom( childConfiguration, parentConfiguration );
main.setConfiguration( pluginConfiguration );
child.setConfiguration( childConfiguration );
}
}

View File

@ -20,15 +20,13 @@ import org.apache.maven.model.Build;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.DependencyManagement;
import org.apache.maven.model.DistributionManagement;
import org.apache.maven.model.Goal;
import org.apache.maven.model.Model;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginManagement;
import org.apache.maven.model.Repository;
import org.apache.maven.model.Scm;
import org.apache.maven.model.Site;
import org.apache.maven.project.ModelUtils;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import java.util.Iterator;
import java.util.List;
@ -202,70 +200,8 @@ public class DefaultModelInheritanceAssembler
}
assembleDependencyManagementInheritance( child, parent );
}
private void assemblePluginManagementInheritance( Build childBuild, Build parentBuild )
{
PluginManagement parentPluginMgmt = parentBuild.getPluginManagement();
PluginManagement childPluginMgmt = childBuild.getPluginManagement();
if ( parentPluginMgmt != null )
{
if ( childPluginMgmt == null )
{
childBuild.setPluginManagement( parentPluginMgmt );
}
else
{
Map mappedChildPlugins = childPluginMgmt.getPluginsAsMap();
for ( Iterator it = parentPluginMgmt.getPlugins().iterator(); it.hasNext(); )
{
Plugin plugin = (Plugin) it.next();
if ( !mappedChildPlugins.containsKey( plugin.getKey() ) )
{
childPluginMgmt.addPlugin( plugin );
}
else
{
Plugin childPlugin = (Plugin) mappedChildPlugins.get( plugin.getKey() );
if ( childPlugin.getVersion() == null )
{
childPlugin.setVersion( childPlugin.getVersion() );
}
Map mappedChildGoals = childPlugin.getGoalsAsMap();
for ( Iterator itGoals = plugin.getGoals().iterator(); itGoals.hasNext(); )
{
Goal parentGoal = (Goal) itGoals.next();
Goal childGoal = (Goal) mappedChildGoals.get( parentGoal.getId() );
if ( childGoal == null )
{
childPlugin.addGoal( parentGoal );
}
else
{
Xpp3Dom childDom = (Xpp3Dom) childGoal.getConfiguration();
Xpp3Dom parentDom = (Xpp3Dom) parentGoal.getConfiguration();
childGoal.setConfiguration( Xpp3Dom.mergeXpp3Dom( childDom, parentDom ) );
}
}
Xpp3Dom childConfig = (Xpp3Dom) childPlugin.getConfiguration();
Xpp3Dom parentConfig = (Xpp3Dom) plugin.getConfiguration();
childPlugin.setConfiguration( Xpp3Dom.mergeXpp3Dom( childConfig, parentConfig ) );
}
}
}
}
}
private void assembleDependencyManagementInheritance( Model child, Model parent )
{
DependencyManagement parentDepMgmt = parent.getDependencyManagement();
@ -369,9 +305,14 @@ public class DefaultModelInheritanceAssembler
childBuild.setTestResources( parentBuild.getTestResources() );
}
// Plugins are not aggregated, but management is
assemblePluginManagementInheritance( childBuild, parentBuild );
// Plugins are aggregated if Plugin.inherit != false
ModelUtils.mergePluginLists( childBuild, parentBuild, true );
// Plugin management :: aggregate
if( childBuild != null && parentBuild != null )
{
ModelUtils.mergePluginLists( childBuild.getPluginManagement(), parentBuild.getPluginManagement(), false );
}
}
}

View File

@ -18,12 +18,9 @@ package org.apache.maven.project.injection;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.DependencyManagement;
import org.apache.maven.model.Goal;
import org.apache.maven.model.Model;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginManagement;
import org.apache.maven.project.ModelUtils;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import java.util.Iterator;
import java.util.List;
@ -42,38 +39,13 @@ public class DefaultModelDefaultsInjector
injectDependencyDefaults( model.getDependencies(), model.getDependencyManagement() );
if ( model.getBuild() != null )
{
injectPluginDefaults( model.getBuild().getPluginsAsMap(), model.getBuild().getPluginManagement() );
}
}
private void injectPluginDefaults( Map pluginMap, PluginManagement pluginManagement )
{
if ( pluginManagement != null )
{
// a given project's plugins should be smaller than the
// group-defined defaults set...
// in other words, the project's plugins will probably be a subset
// of
// those specified in defaults.
List managedPlugins = pluginManagement.getPlugins();
for ( Iterator it = managedPlugins.iterator(); it.hasNext(); )
{
Plugin def = (Plugin) it.next();
Plugin plugin = (Plugin) pluginMap.get( def.getKey() );
if ( plugin != null )
{
mergePluginWithDefaults( plugin, def );
}
}
ModelUtils.mergePluginLists( model.getBuild(), model.getBuild().getPluginManagement(), false );
}
}
public void mergePluginWithDefaults( Plugin plugin, Plugin def )
{
ModelUtils.mergeSupplementalPluginDefinition( plugin, def );
ModelUtils.mergePluginDefinitions( plugin, def, false );
}
private void injectDependencyDefaults( List dependencies, DependencyManagement dependencyManagement )

View File

@ -18,8 +18,10 @@ package org.apache.maven.project.inheritance;
import junit.framework.TestCase;
import org.apache.maven.model.Build;
import org.apache.maven.model.Goal;
import org.apache.maven.model.Model;
import org.apache.maven.model.Parent;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.Repository;
import org.apache.maven.model.Resource;
import org.apache.maven.model.Scm;
@ -28,6 +30,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* @author jdcasey
@ -267,6 +270,140 @@ public class DefaultModelInheritanceAssemblerTest
assertRepositories( repos, child.getRepositories() );
}
public void testPluginInheritanceWhereParentPluginWithoutInheritFlagAndChildHasNoPlugins()
{
Model parent = makeBaseModel( "parent" );
Model child = makeBaseModel( "child" );
Plugin parentPlugin = new Plugin();
parentPlugin.setArtifactId( "maven-testInheritance-plugin" );
parentPlugin.setGroupId( "org.apache.maven.plugins" );
parentPlugin.setVersion( "1.0" );
List parentPlugins = Collections.singletonList( parentPlugin );
Build parentBuild = new Build();
parentBuild.setPlugins( parentPlugins );
parent.setBuild( parentBuild );
assembler.assembleModelInheritance( child, parent );
assertPlugins( parentPlugins, child );
}
public void testPluginInheritanceWhereParentPluginWithTrueInheritFlagAndChildHasNoPlugins()
{
Model parent = makeBaseModel( "parent" );
Model child = makeBaseModel( "child" );
Plugin parentPlugin = new Plugin();
parentPlugin.setArtifactId( "maven-testInheritance2-plugin" );
parentPlugin.setGroupId( "org.apache.maven.plugins" );
parentPlugin.setVersion( "1.0" );
parentPlugin.setInherited( "true" );
List parentPlugins = Collections.singletonList( parentPlugin );
Build parentBuild = new Build();
parentBuild.setPlugins( parentPlugins );
parent.setBuild( parentBuild );
assembler.assembleModelInheritance( child, parent );
assertPlugins( parentPlugins, child );
}
public void testPluginInheritanceWhereParentPluginWithFalseInheritFlagAndChildHasNoPlugins()
{
Model parent = makeBaseModel( "parent" );
Model child = makeBaseModel( "child" );
Plugin parentPlugin = new Plugin();
parentPlugin.setArtifactId("maven-testInheritance3-plugin");
parentPlugin.setGroupId("org.apache.maven.plugins");
parentPlugin.setVersion("1.0");
parentPlugin.setInherited("false");
List parentPlugins = Collections.singletonList(parentPlugin);
Build parentBuild = new Build();
parentBuild.setPlugins(parentPlugins);
parent.setBuild(parentBuild);
assembler.assembleModelInheritance( child, parent );
assertPlugins( new ArrayList(), child );
}
private void assertPlugins( List expectedPlugins, Model child )
{
Build childBuild = child.getBuild();
if( expectedPlugins != null && !expectedPlugins.isEmpty() )
{
assertNotNull( childBuild );
Map childPluginsMap = childBuild.getPluginsAsMap();
if( childPluginsMap != null )
{
assertEquals( expectedPlugins.size(), childPluginsMap.size() );
for ( Iterator it = expectedPlugins.iterator(); it.hasNext(); )
{
Plugin expectedPlugin = (Plugin) it.next();
Plugin childPlugin = (Plugin) childPluginsMap.get( expectedPlugin.getKey() );
assertPluginsEqual( expectedPlugin, childPlugin );
}
}
else
{
fail( "child plugins collection is null, but expectations map is not." );
}
}
else
{
assertTrue( childBuild == null || childBuild.getPlugins() == null || childBuild.getPlugins().isEmpty() );
}
}
private void assertPluginsEqual( Plugin reference, Plugin test )
{
assertEquals("Plugin keys don't match", reference.getKey(), test.getKey());
assertEquals("Plugin configurations don't match", reference.getConfiguration(), test.getConfiguration());
List referenceGoals = reference.getGoals();
Map testGoalsMap = test.getGoalsAsMap();
if( referenceGoals != null && !referenceGoals.isEmpty() )
{
assertTrue( "Missing goals specification", ( testGoalsMap != null && !testGoalsMap.isEmpty() ) );
for ( Iterator it = referenceGoals.iterator(); it.hasNext(); )
{
Goal referenceGoal = (Goal) it.next();
Goal testGoal = (Goal) testGoalsMap.get( referenceGoal.getId() );
assertNotNull( "Goal from reference not found in test", testGoal );
assertEquals( "Goal IDs don't match", referenceGoal.getId(), testGoal.getId() );
assertEquals( "Goal configurations don't match", referenceGoal.getConfiguration(), testGoal.getConfiguration() );
}
}
else
{
assertTrue( "Unexpected goals specification", ( testGoalsMap == null || testGoalsMap.isEmpty() ) );
}
}
// ----------------------------------------------------------------------
//
// ----------------------------------------------------------------------