Index: maven-model/src/main/mdo/maven.mdo
===================================================================
--- maven-model/src/main/mdo/maven.mdo	(revision 708754)
+++ maven-model/src/main/mdo/maven.mdo	(working copy)
@@ -3224,6 +3224,37 @@
     {
         return inheritanceApplied;
     }
+
+    /**
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    public boolean equals( Object other )
+    {
+        if ( other instanceof ReportPlugin )
+        {
+            ReportPlugin otherPlugin = (ReportPlugin) other;
+
+            return getKey().equals( otherPlugin.getKey() );
+        }
+
+        return false;
+    }
+
+    /**
+     * @see java.lang.Object#hashCode()
+     */
+    public int hashCode()
+    {
+        return getKey().hashCode();
+    }
+
+    /**
+     * @see java.lang.Object#toString()
+     */
+    public String toString()
+    {
+        return "ReportPlugin [" + getKey() + "]";
+    }
             ]]>
           </code>
         </codeSegment>
Index: maven-project/src/main/java/org/apache/maven/project/ModelUtils.java
===================================================================
--- maven-project/src/main/java/org/apache/maven/project/ModelUtils.java	(revision 708754)
+++ maven-project/src/main/java/org/apache/maven/project/ModelUtils.java	(working copy)
@@ -461,16 +461,16 @@
      *
      *   X -> Y -> A -> B -> C -> D -> E -> F
      */
-    public static void mergePluginLists( PluginContainer childContainer, PluginContainer parentContainer,
+    public static void mergePluginLists( PluginContainer child, PluginContainer parent,
                                          boolean handleAsInheritance )
     {
-        if ( ( childContainer == null ) || ( parentContainer == null ) )
+        if ( ( child == null ) || ( parent == null ) )
         {
             // nothing to do.
             return;
         }
 
-        List parentPlugins = parentContainer.getPlugins();
+        List parentPlugins = parent.getPlugins();
 
         if ( ( parentPlugins != null ) && !parentPlugins.isEmpty() )
         {
@@ -495,7 +495,7 @@
 
             List assembledPlugins = new ArrayList();
 
-            Map childPlugins = childContainer.getPluginsAsMap();
+            Map childPlugins = child.getPluginsAsMap();
 
             for ( Iterator it = parentPlugins.iterator(); it.hasNext(); )
             {
@@ -535,12 +535,12 @@
                 // very important to use the parentPlugins List, rather than parentContainer.getPlugins()
                 // since this list is a local one, and may have been modified during processing.
                 List results = ModelUtils.orderAfterMerge( assembledPlugins, parentPlugins,
-                                                                        childContainer.getPlugins() );
+                                                                        child.getPlugins() );
 
 
-                childContainer.setPlugins( results );
+                child.setPlugins( results );
 
-                childContainer.flushPluginMap();
+                child.flushPluginMap();
             }
         }
     }
@@ -602,6 +602,14 @@
         return results;
     }
 
+    /**
+     * Merge the list of reporting plugins from parent pom and child pom
+     * TODO it's pretty much a copy of {@link #mergePluginLists(PluginContainer, PluginContainer, boolean)}
+     * 
+     * @param child
+     * @param parent
+     * @param handleAsInheritance
+     */
     public static void mergeReportPluginLists( Reporting child, Reporting parent, boolean handleAsInheritance )
     {
         if ( ( child == null ) || ( parent == null ) )
@@ -614,8 +622,27 @@
 
         if ( ( parentPlugins != null ) && !parentPlugins.isEmpty() )
         {
-            Map assembledPlugins = new TreeMap();
+            parentPlugins = new ArrayList( parentPlugins );
 
+            // If we're processing this merge as an inheritance, we have to build up a list of
+            // plugins that were considered for inheritance.
+            if ( handleAsInheritance )
+            {
+                for ( Iterator it = parentPlugins.iterator(); it.hasNext(); )
+                {
+                    ReportPlugin plugin = (ReportPlugin) it.next();
+
+                    String inherited = plugin.getInherited();
+
+                    if ( ( inherited != null ) && !Boolean.valueOf( inherited ).booleanValue() )
+                    {
+                        it.remove();
+                    }
+                }
+            }
+
+            List assembledPlugins = new ArrayList();
+
             Map childPlugins = child.getReportPluginsAsMap();
 
             for ( Iterator it = parentPlugins.iterator(); it.hasNext(); )
@@ -624,43 +651,44 @@
 
                 String parentInherited = parentPlugin.getInherited();
 
+                // only merge plugin definition from the parent if at least one
+                // of these is true:
+                // 1. we're not processing the plugins in an inheritance-based merge
+                // 2. the parent's <inherited/> flag is not set
+                // 3. the parent's <inherited/> flag is set to true
                 if ( !handleAsInheritance || ( parentInherited == null ) ||
                     Boolean.valueOf( parentInherited ).booleanValue() )
                 {
-
-                    ReportPlugin assembledPlugin = parentPlugin;
-
                     ReportPlugin childPlugin = (ReportPlugin) childPlugins.get( parentPlugin.getKey() );
 
-                    if ( childPlugin != null )
+                    if ( ( childPlugin != null ) && !assembledPlugins.contains( childPlugin ) )
                     {
-                        assembledPlugin = childPlugin;
+                        ReportPlugin assembledPlugin = childPlugin;
 
                         mergeReportPluginDefinitions( childPlugin, parentPlugin, handleAsInheritance );
+
+                        // fix for MNG-2221 (assembly cache was not being populated for later reference):
+                        assembledPlugins.add( assembledPlugin );
                     }
 
+                    // if we're processing this as an inheritance-based merge, and
+                    // the parent's <inherited/> flag is not set, then we need to
+                    // clear the inherited flag in the merge result.
                     if ( handleAsInheritance && ( parentInherited == null ) )
                     {
-                        assembledPlugin.unsetInheritanceApplied();
+                        parentPlugin.unsetInheritanceApplied();
                     }
-
-                    assembledPlugins.put( assembledPlugin.getKey(), assembledPlugin );
                 }
-            }
 
-            for ( Iterator it = childPlugins.values().iterator(); it.hasNext(); )
-            {
-                ReportPlugin childPlugin = (ReportPlugin) it.next();
+                // very important to use the parentPlugins List, rather than parentContainer.getPlugins()
+                // since this list is a local one, and may have been modified during processing.
+                List results = ModelUtils.orderAfterMerge( assembledPlugins, parentPlugins,
+                                                                        child.getPlugins() );
 
-                if ( !assembledPlugins.containsKey( childPlugin.getKey() ) )
-                {
-                    assembledPlugins.put( childPlugin.getKey(), childPlugin );
-                }
+                child.setPlugins( results );
+
+                child.flushReportPluginMap();
             }
-
-            child.setPlugins( new ArrayList( assembledPlugins.values() ) );
-
-            child.flushReportPluginMap();
         }
     }
 
Index: maven-project/src/test/java/org/apache/maven/project/ModelUtilsTest.java
===================================================================
--- maven-project/src/test/java/org/apache/maven/project/ModelUtilsTest.java	(revision 708754)
+++ maven-project/src/test/java/org/apache/maven/project/ModelUtilsTest.java	(working copy)
@@ -24,6 +24,8 @@
 import org.apache.maven.model.Plugin;
 import org.apache.maven.model.PluginContainer;
 import org.apache.maven.model.PluginExecution;
+import org.apache.maven.model.ReportPlugin;
+import org.apache.maven.model.Reporting;
 import org.codehaus.plexus.util.xml.Xpp3Dom;
 
 import java.util.Collections;
@@ -136,18 +138,71 @@
         Xpp3Dom result3Config = (Xpp3Dom) result3.getConfiguration();
 
         assertNotNull( result3Config );
+        assertNotNull( result3Config.getChild( "key" ) );
+        assertNotNull( result3Config.getChild( "key2" ) );
 
         assertEquals( "value", result3Config.getChild( "key" ).getValue() );
         assertEquals( "value2", result3Config.getChild( "key2" ).getValue() );
     }
 
-    private Plugin createPlugin( String groupId, String artifactId, String version, Map configuration )
+    /**
+     * Test that this is the resulting ordering of reports after merging:
+     *
+     * Given:
+     *
+     *   parent: X -> A -> B -> D -> E
+     *   child: Y -> A -> C -> D -> F
+     *
+     * Result:
+     *
+     *   X -> Y -> A -> B -> C -> D -> E -> F
+     */
+    public void testShouldPreserveChildOrderingOfReportsAfterParentMerge()
     {
-        Plugin plugin = new Plugin();
-        plugin.setGroupId( groupId );
-        plugin.setArtifactId( artifactId );
-        plugin.setVersion( version );
+        Reporting parent = new Reporting();
 
+        parent.addPlugin( createReportPlugin( "group", "artifact", "1.0", Collections.EMPTY_MAP ) );
+        parent.addPlugin( createReportPlugin( "group2", "artifact2", "1.0", Collections.singletonMap( "key", "value" ) ) );
+
+        Reporting child = new Reporting();
+
+        child.addPlugin( createReportPlugin( "group3", "artifact3", "1.0", Collections.EMPTY_MAP ) );
+        child.addPlugin( createReportPlugin( "group2", "artifact2", "1.0", Collections.singletonMap( "key2", "value2" ) ) );
+
+        ModelUtils.mergeReportPluginLists( child, parent, true );
+
+        List results = child.getPlugins();
+
+        assertEquals( 3, results.size() );
+
+        ReportPlugin result1 = (ReportPlugin) results.get( 0 );
+
+        assertEquals( "group", result1.getGroupId() );
+        assertEquals( "artifact", result1.getArtifactId() );
+
+        ReportPlugin result2 = (ReportPlugin) results.get( 1 );
+
+        assertEquals( "group3", result2.getGroupId() );
+        assertEquals( "artifact3", result2.getArtifactId() );
+
+        ReportPlugin result3 = (ReportPlugin) results.get( 2 );
+
+        assertEquals( "group2", result3.getGroupId() );
+        assertEquals( "artifact2", result3.getArtifactId() );
+
+        Xpp3Dom result3Config = (Xpp3Dom) result3.getConfiguration();
+
+        assertNotNull( result3Config );
+        // Carlos: Current behavior is not to merge the ocnfiguration, although dont know why 
+        assertNull( result3Config.getChild( "key" ) );
+        assertNotNull( result3Config.getChild( "key2" ) );
+
+        //assertEquals( "value", result3Config.getChild( "key" ).getValue() );
+        assertEquals( "value2", result3Config.getChild( "key2" ).getValue() );
+    }
+
+    private Xpp3Dom createConfiguration( Map configuration )
+    {
         Xpp3Dom config = new Xpp3Dom( "configuration" );
 
         if( configuration != null )
@@ -163,11 +218,29 @@
             }
         }
 
-        plugin.setConfiguration( config );
+        return config;
+    }
 
+    private Plugin createPlugin( String groupId, String artifactId, String version, Map configuration )
+    {
+        Plugin plugin = new Plugin();
+        plugin.setGroupId( groupId );
+        plugin.setArtifactId( artifactId );
+        plugin.setVersion( version );
+        plugin.setConfiguration( createConfiguration( configuration ) );
         return plugin;
     }
 
+    private ReportPlugin createReportPlugin( String groupId, String artifactId, String version, Map configuration )
+    {
+        ReportPlugin plugin = new ReportPlugin();
+        plugin.setGroupId( groupId );
+        plugin.setArtifactId( artifactId );
+        plugin.setVersion( version );
+        plugin.setConfiguration( createConfiguration( configuration ) );
+        return plugin;
+    }
+
     public void testShouldInheritOnePluginWithExecution()
     {
         Plugin parent = new Plugin();

