You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by jd...@apache.org on 2008/08/21 23:27:10 UTC

svn commit: r687867 [1/2] - in /maven/components/branches/maven-2.0.10-RC: ./ maven-core/src/main/java/org/apache/maven/ maven-core/src/main/java/org/apache/maven/lifecycle/ maven-project/src/main/java/org/apache/maven/project/ maven-project/src/main/j...

Author: jdcasey
Date: Thu Aug 21 14:27:09 2008
New Revision: 687867

URL: http://svn.apache.org/viewvc?rev=687867&view=rev
Log:
[MNG-3698] Refactored clone methods in ModelUtils to use object construction directly instead of serialize/deserialize, refactored the StringSearchModelInterpolator to use reflection instead of serialize/deserialize, and added logic to the restore transition for the build section to detect whether the just-executed mojo actually changed anything in the core build paths or POM properties; if not, leave it concrete for the next mojo execution, otherwise determine the dynamic state once again for reinterpolation before the next mojo run. This improves performance significantly.

Modified:
    maven/components/branches/maven-2.0.10-RC/maven-core/src/main/java/org/apache/maven/MavenArtifactFilterManager.java
    maven/components/branches/maven-2.0.10-RC/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java
    maven/components/branches/maven-2.0.10-RC/maven-project/src/main/java/org/apache/maven/project/DefaultMavenProjectBuilder.java
    maven/components/branches/maven-2.0.10-RC/maven-project/src/main/java/org/apache/maven/project/MavenProject.java
    maven/components/branches/maven-2.0.10-RC/maven-project/src/main/java/org/apache/maven/project/ModelUtils.java
    maven/components/branches/maven-2.0.10-RC/maven-project/src/main/java/org/apache/maven/project/interpolation/AbstractStringBasedModelInterpolator.java
    maven/components/branches/maven-2.0.10-RC/maven-project/src/main/java/org/apache/maven/project/interpolation/StringSearchModelInterpolator.java
    maven/components/branches/maven-2.0.10-RC/maven-project/src/test/java/org/apache/maven/project/MavenProjectDynamismTest.java
    maven/components/branches/maven-2.0.10-RC/maven-project/src/test/java/org/apache/maven/project/interpolation/AbstractModelInterpolatorTest.java
    maven/components/branches/maven-2.0.10-RC/maven-project/src/test/java/org/apache/maven/project/interpolation/ModelInterpolationEdgeCases.java
    maven/components/branches/maven-2.0.10-RC/maven-project/src/test/java/org/apache/maven/project/interpolation/StringSearchModelInterpolatorTest.java
    maven/components/branches/maven-2.0.10-RC/pom.xml

Modified: maven/components/branches/maven-2.0.10-RC/maven-core/src/main/java/org/apache/maven/MavenArtifactFilterManager.java
URL: http://svn.apache.org/viewvc/maven/components/branches/maven-2.0.10-RC/maven-core/src/main/java/org/apache/maven/MavenArtifactFilterManager.java?rev=687867&r1=687866&r2=687867&view=diff
==============================================================================
--- maven/components/branches/maven-2.0.10-RC/maven-core/src/main/java/org/apache/maven/MavenArtifactFilterManager.java (original)
+++ maven/components/branches/maven-2.0.10-RC/maven-core/src/main/java/org/apache/maven/MavenArtifactFilterManager.java Thu Aug 21 14:27:09 2008
@@ -43,6 +43,7 @@
         artifacts.add( "wagon-ssh-external" );
         artifacts.add( "wagon-ssh-common" );
         artifacts.add( "wagon-http-shared" );
+        artifacts.add( "wagon-webdav-jackrabbit" );
 
         return new ExclusionSetFilter( artifacts );
     }

Modified: maven/components/branches/maven-2.0.10-RC/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java
URL: http://svn.apache.org/viewvc/maven/components/branches/maven-2.0.10-RC/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java?rev=687867&r1=687866&r2=687867&view=diff
==============================================================================
--- maven/components/branches/maven-2.0.10-RC/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java (original)
+++ maven/components/branches/maven-2.0.10-RC/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java Thu Aug 21 14:27:09 2008
@@ -564,13 +564,13 @@
             MojoExecution mojoExecution = (MojoExecution) i.next();
 
             MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
-
+            
             calculateConcreteState( project, session );
             
             PlexusConfiguration configuration = mojoDescriptor.getMojoConfiguration();
-            boolean usesAllProjects = mojoDescriptor.isAggregator() || usesSessionOrReactorProjects( configuration );
+            boolean usesReactorProjects = mojoDescriptor.isAggregator() || usesSessionOrReactorProjects( configuration );
             
-            if ( usesAllProjects )
+            if ( usesReactorProjects )
             {
                 calculateAllConcreteStates( session );
             }
@@ -605,7 +605,7 @@
             {
                 createExecutionProject( project, session );
                 
-                if ( usesAllProjects )
+                if ( usesReactorProjects )
                 {
                     List reactorProjects = session.getSortedProjects();
                     for ( Iterator it = reactorProjects.iterator(); it.hasNext(); )
@@ -655,7 +655,7 @@
                 // TODO: Would be nice to find a way to cause the execution project to stay in a concrete state...
                 calculateConcreteState( project.getExecutionProject(), session );
                 
-                if ( usesAllProjects )
+                if ( usesReactorProjects )
                 {
                     List reactorProjects = session.getSortedProjects();
                     for ( Iterator it = reactorProjects.iterator(); it.hasNext(); )
@@ -701,24 +701,24 @@
                 throw new LifecycleExecutionException( e.getMessage(), e );
             }
             
-            if ( hasFork )
-            {
-                project.setExecutionProject( null );
-                
-                if ( usesAllProjects )
-                {
-                    List reactorProjects = session.getSortedProjects();
-                    for ( Iterator it = reactorProjects.iterator(); it.hasNext(); )
-                    {
-                        MavenProject reactorProject = (MavenProject) it.next();
-                        reactorProject.setExecutionProject( null );
-                    }
-                }
-            }
+//            if ( hasFork )
+//            {
+//                project.setExecutionProject( null );
+//                
+//                if ( usesReactorProjects )
+//                {
+//                    List reactorProjects = session.getSortedProjects();
+//                    for ( Iterator it = reactorProjects.iterator(); it.hasNext(); )
+//                    {
+//                        MavenProject reactorProject = (MavenProject) it.next();
+//                        reactorProject.setExecutionProject( null );
+//                    }
+//                }
+//            }
             
             restoreDynamicState( project, session );
             
-            if ( usesAllProjects )
+            if ( usesReactorProjects )
             {
                 restoreAllDynamicStates( session );
             }
@@ -728,11 +728,14 @@
     private void createExecutionProject( MavenProject project, MavenSession session )
         throws LifecycleExecutionException
     {
-        MavenProject executionProject = new MavenProject( project );
-        
-        calculateConcreteState( executionProject, session );
-        
-        project.setExecutionProject( executionProject );
+        if ( project.getExecutionProject() == null )
+        {
+            MavenProject executionProject = new MavenProject( project );
+            
+            calculateConcreteState( executionProject, session );
+            
+            project.setExecutionProject( executionProject );
+        }
     }
 
     private boolean usesSessionOrReactorProjects( PlexusConfiguration configuration )
@@ -820,7 +823,7 @@
     private void calculateConcreteState( MavenProject project, MavenSession session )
         throws LifecycleExecutionException
     {
-        if ( mavenProjectBuilder != null && project != null && !project.isConcrete() )
+        if ( mavenProjectBuilder != null && project != null )
         {
             try
             {

Modified: maven/components/branches/maven-2.0.10-RC/maven-project/src/main/java/org/apache/maven/project/DefaultMavenProjectBuilder.java
URL: http://svn.apache.org/viewvc/maven/components/branches/maven-2.0.10-RC/maven-project/src/main/java/org/apache/maven/project/DefaultMavenProjectBuilder.java?rev=687867&r1=687866&r2=687867&view=diff
==============================================================================
--- maven/components/branches/maven-2.0.10-RC/maven-project/src/main/java/org/apache/maven/project/DefaultMavenProjectBuilder.java (original)
+++ maven/components/branches/maven-2.0.10-RC/maven-project/src/main/java/org/apache/maven/project/DefaultMavenProjectBuilder.java Thu Aug 21 14:27:09 2008
@@ -98,6 +98,7 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Properties;
 import java.util.Set;
 import java.util.TreeMap;
 
@@ -999,7 +1000,7 @@
         mergeDeterministicBuildElements( model.getBuild(), dynamicBuild );
 
         model.setBuild( dynamicBuild );
-
+        
         // MNG-3482: Make sure depMgmt is interpolated before merging.
         if ( !isSuperPom )
         {
@@ -1017,7 +1018,7 @@
         project = new MavenProject( model );
 
         project.setOriginalModel( originalModel );
-
+        
         project.setActiveProfiles( activeProfiles );
 
         // TODO: maybe not strictly correct, while we should enfore that packaging has a type handler of the same id, we don't
@@ -1094,7 +1095,7 @@
         project.setReportArtifacts( createReportArtifacts( projectId, project.getReportPlugins() ) );
 
         project.setExtensionArtifacts( createExtensionArtifacts( projectId, project.getBuildExtensions() ) );
-
+        
         return project;
     }
 
@@ -1810,66 +1811,67 @@
     public void calculateConcreteState( MavenProject project, ProjectBuilderConfiguration config )
         throws ModelInterpolationException
     {
-        if ( project.isConcrete() )
-        {
-            return;
-        }
-
-        Build build = project.getBuild();
-        if ( build != null )
+        if ( !project.isConcrete() )
         {
-            initResourceMergeIds( build.getResources() );
-            initResourceMergeIds( build.getTestResources() );
-        }
-
-        // NOTE: Since interpolation makes a copy through serialization, we don't need this.
-        // See note below.
-        //
-        // Model model = ModelUtils.cloneModel( project.getModel() );
-
-        File basedir = project.getBasedir();
-
-        // NOTE: If we ever get past serialization/deserialization for interpolation, we'll need to copy the model here!
-        Model model = modelInterpolator.interpolate( project.getModel(), project.getBasedir(), config, getLogger().isDebugEnabled() );
+            Build build = project.getBuild();
+            if ( build != null )
+            {
+                initResourceMergeIds( build.getResources() );
+                initResourceMergeIds( build.getTestResources() );
+            }
 
-        List originalInterpolatedCompileSourceRoots = interpolateListOfStrings( project.getCompileSourceRoots(),
-                                                                           model,
-                                                                           project.getBasedir(),
-                                                                           config,
-                                                                           getLogger().isDebugEnabled() );
+            // NOTE: Since interpolation makes a copy through serialization, we don't need this.
+            // See note below.
+            //
+            // Model model = ModelUtils.cloneModel( project.getModel() );
 
-        project.preserveCompileSourceRoots( originalInterpolatedCompileSourceRoots );
+            File basedir = project.getBasedir();
 
-        project.setCompileSourceRoots( originalInterpolatedCompileSourceRoots == null ? null
-                        : translateListOfPaths( originalInterpolatedCompileSourceRoots, basedir ) );
+            // NOTE: If we ever get past serialization/deserialization for interpolation, we'll need to copy the model here!
+            Model model = ModelUtils.cloneModel( project.getModel() );
+            model = modelInterpolator.interpolate( model, project.getBasedir(), config, getLogger().isDebugEnabled() );
 
-        List originalInterpolatedTestCompileSourceRoots = interpolateListOfStrings( project.getTestCompileSourceRoots(),
+            List originalInterpolatedCompileSourceRoots = interpolateListOfStrings( project.getCompileSourceRoots(),
                                                                                model,
                                                                                project.getBasedir(),
                                                                                config,
                                                                                getLogger().isDebugEnabled() );
 
-        project.preserveTestCompileSourceRoots( originalInterpolatedTestCompileSourceRoots );
-        project.setTestCompileSourceRoots( originalInterpolatedTestCompileSourceRoots == null ? null
-                        : translateListOfPaths( originalInterpolatedTestCompileSourceRoots, basedir ) );
+            project.preserveCompileSourceRoots( originalInterpolatedCompileSourceRoots );
 
-        List originalInterpolatedScriptSourceRoots = interpolateListOfStrings( project.getScriptSourceRoots(),
-                                                                          model,
-                                                                          project.getBasedir(),
-                                                                          config,
-                                                                          getLogger().isDebugEnabled() );
+            project.setCompileSourceRoots( originalInterpolatedCompileSourceRoots == null ? null
+                            : translateListOfPaths( originalInterpolatedCompileSourceRoots, basedir ) );
 
-        project.preserveScriptSourceRoots( originalInterpolatedScriptSourceRoots );
-        project.setScriptSourceRoots( originalInterpolatedScriptSourceRoots == null ? null
-                        : translateListOfPaths( originalInterpolatedScriptSourceRoots, basedir ) );
+            List originalInterpolatedTestCompileSourceRoots = interpolateListOfStrings( project.getTestCompileSourceRoots(),
+                                                                                   model,
+                                                                                   project.getBasedir(),
+                                                                                   config,
+                                                                                   getLogger().isDebugEnabled() );
 
-        if ( basedir != null )
-        {
-            pathTranslator.alignToBaseDirectory( model, basedir );
-        }
+            project.preserveTestCompileSourceRoots( originalInterpolatedTestCompileSourceRoots );
+            project.setTestCompileSourceRoots( originalInterpolatedTestCompileSourceRoots == null ? null
+                            : translateListOfPaths( originalInterpolatedTestCompileSourceRoots, basedir ) );
+
+            List originalInterpolatedScriptSourceRoots = interpolateListOfStrings( project.getScriptSourceRoots(),
+                                                                              model,
+                                                                              project.getBasedir(),
+                                                                              config,
+                                                                              getLogger().isDebugEnabled() );
 
-        project.preserveBuild( ModelUtils.cloneBuild( model.getBuild() ) );
-        project.setBuild( model.getBuild() );
+            project.preserveScriptSourceRoots( originalInterpolatedScriptSourceRoots );
+            project.setScriptSourceRoots( originalInterpolatedScriptSourceRoots == null ? null
+                            : translateListOfPaths( originalInterpolatedScriptSourceRoots, basedir ) );
+
+            if ( basedir != null )
+            {
+                pathTranslator.alignToBaseDirectory( model, basedir );
+            }
+
+            project.preserveBuild( ModelUtils.cloneBuild( model.getBuild() ) );
+            project.preserveProperties();
+            project.preserveBasedir();
+            project.setBuild( model.getBuild() );
+        }
 
         calculateConcreteProjectReferences( project, config );
 
@@ -1939,7 +1941,7 @@
     public void restoreDynamicState( MavenProject project, ProjectBuilderConfiguration config )
         throws ModelInterpolationException
     {
-        if ( !project.isConcrete() )
+        if ( !project.isConcrete() || !projectWasChanged( project ) )
         {
             return;
         }
@@ -1957,6 +1959,54 @@
         project.setConcrete( false );
     }
 
+    private boolean projectWasChanged( MavenProject project )
+    {
+        if ( !objectEquals( project.getBasedir(), project.getPreservedBasedir() ) )
+        {
+            return true;
+        }
+        
+        if ( !objectEquals( project.getProperties(), project.getPreservedProperties() ) )
+        {
+            return true;
+        }
+        
+        Build oBuild = project.getOriginalInterpolatedBuild();
+        Build build = project.getBuild();
+        
+        if ( !objectEquals( oBuild.getDirectory(), build.getDirectory() ) )
+        {
+            return true;
+        }
+        
+        if ( !objectEquals( oBuild.getOutputDirectory(), build.getOutputDirectory() ) )
+        {
+            return true;
+        }
+        
+        if ( !objectEquals( oBuild.getSourceDirectory(), build.getSourceDirectory() ) )
+        {
+            return true;
+        }
+        
+        if ( !objectEquals( oBuild.getTestSourceDirectory(), build.getTestSourceDirectory() ) )
+        {
+            return true;
+        }
+        
+        if ( !objectEquals( oBuild.getScriptSourceDirectory(), build.getScriptSourceDirectory() ) )
+        {
+            return true;
+        }
+        
+        return false;
+    }
+
+    private boolean objectEquals( Object obj1, Object obj2 )
+    {
+        return obj1 == null ? obj2 == null : obj1 == obj2 || obj1.equals( obj2 );
+    }
+
     private void propagateNewPlugins( MavenProject project )
     {
         Build changedBuild = project.getBuild();

Modified: maven/components/branches/maven-2.0.10-RC/maven-project/src/main/java/org/apache/maven/project/MavenProject.java
URL: http://svn.apache.org/viewvc/maven/components/branches/maven-2.0.10-RC/maven-project/src/main/java/org/apache/maven/project/MavenProject.java?rev=687867&r1=687866&r2=687867&view=diff
==============================================================================
--- maven/components/branches/maven-2.0.10-RC/maven-project/src/main/java/org/apache/maven/project/MavenProject.java (original)
+++ maven/components/branches/maven-2.0.10-RC/maven-project/src/main/java/org/apache/maven/project/MavenProject.java Thu Aug 21 14:27:09 2008
@@ -24,6 +24,7 @@
 import java.io.Writer;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -149,7 +150,7 @@
     private Map moduleAdjustments;
 
     private File basedir;
-
+    
     public MavenProject()
     {
         Model model = new Model();
@@ -307,6 +308,8 @@
             }
         }
 
+        preservedProperties = project.preservedProperties;
+        preservedBasedir = project.preservedBasedir;
         setConcrete( project.isConcrete() );
     }
     
@@ -1826,7 +1829,7 @@
 // ----------------------------------------------------------------------------
 // CODE BELOW IS USED TO PRESERVE DYNAMISM IN THE BUILD SECTION OF THE POM.
 // ----------------------------------------------------------------------------
-
+    
     private Build dynamicBuild;
 
     private Build originalInterpolatedBuild;
@@ -1977,5 +1980,38 @@
     {
         this.originalInterpolatedScriptSourceRoots = originalInterpolatedScriptSourceRoots;
     }
+    
+    private Properties preservedProperties;
+    
+    public Properties getPreservedProperties()
+    {
+        return preservedProperties;
+    }
+
+    public void preserveProperties()
+    {
+        Properties p = getProperties();
+        if ( p != null )
+        {
+            preservedProperties = new Properties();
+            for( Enumeration e = p.propertyNames(); e.hasMoreElements(); )
+            {
+                String key = (String) e.nextElement();
+                preservedProperties.setProperty( key, p.getProperty( key ) );
+            }
+        }
+    }
+    
+    private File preservedBasedir;
+    
+    public File getPreservedBasedir()
+    {
+        return preservedBasedir;
+    }
+
+    public void preserveBasedir()
+    {
+        this.preservedBasedir = getBasedir();
+    }
 
 }

Modified: maven/components/branches/maven-2.0.10-RC/maven-project/src/main/java/org/apache/maven/project/ModelUtils.java
URL: http://svn.apache.org/viewvc/maven/components/branches/maven-2.0.10-RC/maven-project/src/main/java/org/apache/maven/project/ModelUtils.java?rev=687867&r1=687866&r2=687867&view=diff
==============================================================================
--- maven/components/branches/maven-2.0.10-RC/maven-project/src/main/java/org/apache/maven/project/ModelUtils.java (original)
+++ maven/components/branches/maven-2.0.10-RC/maven-project/src/main/java/org/apache/maven/project/ModelUtils.java Thu Aug 21 14:27:09 2008
@@ -19,23 +19,43 @@
  * under the License.
  */
 
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.TreeMap;
+
 import org.apache.maven.model.Activation;
 import org.apache.maven.model.ActivationFile;
+import org.apache.maven.model.ActivationOS;
 import org.apache.maven.model.ActivationProperty;
 import org.apache.maven.model.Build;
 import org.apache.maven.model.BuildBase;
+import org.apache.maven.model.CiManagement;
+import org.apache.maven.model.Contributor;
 import org.apache.maven.model.Dependency;
 import org.apache.maven.model.DependencyManagement;
 import org.apache.maven.model.DeploymentRepository;
+import org.apache.maven.model.Developer;
 import org.apache.maven.model.DistributionManagement;
 import org.apache.maven.model.Exclusion;
 import org.apache.maven.model.Extension;
+import org.apache.maven.model.IssueManagement;
+import org.apache.maven.model.License;
+import org.apache.maven.model.MailingList;
 import org.apache.maven.model.Model;
+import org.apache.maven.model.ModelBase;
+import org.apache.maven.model.Notifier;
+import org.apache.maven.model.Organization;
 import org.apache.maven.model.Parent;
 import org.apache.maven.model.Plugin;
 import org.apache.maven.model.PluginContainer;
 import org.apache.maven.model.PluginExecution;
 import org.apache.maven.model.PluginManagement;
+import org.apache.maven.model.Prerequisites;
 import org.apache.maven.model.Profile;
 import org.apache.maven.model.Relocation;
 import org.apache.maven.model.ReportPlugin;
@@ -45,28 +65,133 @@
 import org.apache.maven.model.RepositoryBase;
 import org.apache.maven.model.RepositoryPolicy;
 import org.apache.maven.model.Resource;
+import org.apache.maven.model.Scm;
 import org.apache.maven.model.Site;
-import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
-import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
-import org.apache.maven.project.inheritance.DefaultModelInheritanceAssembler;
-import org.apache.maven.project.inheritance.ModelInheritanceAssembler;
 import org.codehaus.plexus.util.xml.Xpp3Dom;
-import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.TreeMap;
 
 public final class ModelUtils
 {
 
+    private static final ModelPartCloner DEPENDENCY_CLONER = new ModelPartCloner()
+    {
+        public Object cloneModelPart( Object src )
+        {
+            return ModelUtils.cloneDependency( (Dependency) src );
+        }
+    };
+
+    private static final ModelPartCloner PLUGIN_CLONER = new ModelPartCloner()
+    {
+        public Object cloneModelPart( Object src )
+        {
+            return ModelUtils.clonePlugin( (Plugin) src );
+        }
+    };
+
+    private static final ModelPartCloner EXTENSION_CLONER = new ModelPartCloner()
+    {
+        public Object cloneModelPart( Object src )
+        {
+            return ModelUtils.cloneExtension( (Extension) src );
+        }
+    };
+
+    private static final ModelPartCloner RESOURCE_CLONER = new ModelPartCloner()
+    {
+        public Object cloneModelPart( Object src )
+        {
+            return ModelUtils.cloneResource( (Resource) src );
+        }
+    };
+
+    private static final ModelPartCloner NOTIFIER_CLONER = new ModelPartCloner()
+    {
+        public Object cloneModelPart( Object src )
+        {
+            return ModelUtils.cloneNotifier( (Notifier) src );
+        }
+    };
+
+    private static final ModelPartCloner CONTRIBUTOR_CLONER = new ModelPartCloner()
+    {
+        public Object cloneModelPart( Object src )
+        {
+            return ModelUtils.cloneContributor( (Contributor) src );
+        }
+    };
+
+    private static final ModelPartCloner DEVELOPER_CLONER = new ModelPartCloner()
+    {
+        public Object cloneModelPart( Object src )
+        {
+            return ModelUtils.cloneDeveloper( (Developer) src );
+        }
+    };
+
+    private static final ModelPartCloner LICENSE_CLONER = new ModelPartCloner()
+    {
+        public Object cloneModelPart( Object src )
+        {
+            return ModelUtils.cloneLicense( (License) src );
+        }
+    };
+
+    private static final ModelPartCloner MAILING_LIST_CLONER = new ModelPartCloner()
+    {
+        public Object cloneModelPart( Object src )
+        {
+            return ModelUtils.cloneMailingList( (MailingList) src );
+        }
+    };
+
+    private static final ModelPartCloner REPOSITORY_CLONER = new ModelPartCloner()
+    {
+        public Object cloneModelPart( Object src )
+        {
+            return ModelUtils.cloneRepository( (Repository) src );
+        }
+    };
+
+    private static final ModelPartCloner PROFILE_CLONER = new ModelPartCloner()
+    {
+        public Object cloneModelPart( Object src )
+        {
+            return ModelUtils.cloneProfile( (Profile) src );
+        }
+    };
+
+    private static final ModelPartCloner REPORT_PLUGIN_CLONER = new ModelPartCloner()
+    {
+        public Object cloneModelPart( Object src )
+        {
+            return ModelUtils.cloneReportPlugin( (ReportPlugin) src );
+        }
+    };
+
+    private static final ModelPartCloner REPORT_SET_CLONER = new ModelPartCloner()
+    {
+        public Object cloneModelPart( Object src )
+        {
+            return ModelUtils.cloneReportSet( (ReportSet) src );
+        }
+    };
+
+    private static final ModelPartCloner DEPENDENCY_EXCLUSION_CLONER = new ModelPartCloner()
+    {
+        public Object cloneModelPart( Object src )
+        {
+            return ModelUtils.cloneExclusion( (Exclusion) src );
+        }
+    };
+
+    private static final ModelPartCloner PLUGIN_EXECUTION_CLONER = new ModelPartCloner()
+    {
+        public Object cloneModelPart( Object src )
+        {
+            return ModelUtils.clonePluginExecution( (PluginExecution) src );
+        }
+    };
+
     /**
      * Given this plugin list:
      *
@@ -115,6 +240,215 @@
         pluginContainer.setPlugins( normalized );
     }
 
+    public static ReportSet cloneReportSet( ReportSet src )
+    {
+        if ( src == null )
+        {
+            return null;
+        }
+        
+        ReportSet result = new ReportSet();
+        
+        result.setConfiguration( cloneConfiguration( src.getConfiguration() ) );
+        result.setId( src.getId() );
+        result.setInherited( src.getInherited() );
+        result.setReports( cloneListOfStrings( src.getReports() ) );
+        
+        return result;
+    }
+
+    public static ReportPlugin cloneReportPlugin( ReportPlugin src )
+    {
+        if ( src == null )
+        {
+            return null;
+        }
+        
+        ReportPlugin result = new ReportPlugin();
+        
+        result.setArtifactId( src.getArtifactId() );
+        result.setConfiguration( cloneConfiguration( src.getConfiguration() ) );
+        result.setGroupId( src.getGroupId() );
+        result.setInherited( src.getInherited() );
+        result.setReportSets( cloneList( src.getReportSets(), REPORT_SET_CLONER ) );
+        result.setVersion( src.getVersion() );
+        
+        return result;
+    }
+
+    public static Profile cloneProfile( Profile src )
+    {
+        if ( src == null )
+        {
+            return null;
+        }
+        
+        Profile result = new Profile();
+        
+        cloneModelBaseFields( src, result );
+        
+        result.setActivation( cloneActivation( src.getActivation() ) );
+        
+        BuildBase resultBuild = null;
+        if ( src.getBuild() != null )
+        {
+            resultBuild = new BuildBase();
+            cloneBuildBaseFields( src.getBuild(), resultBuild );
+        }
+        result.setBuild( resultBuild );
+        
+        result.setId( src.getId() );
+        result.setSource( src.getSource() );
+        
+        return result;
+    }
+
+    private static void cloneModelBaseFields( ModelBase src, ModelBase result )
+    {
+        result.setDependencies( cloneList( src.getDependencies(), DEPENDENCY_CLONER ) );
+        result.setDependencyManagement( cloneDependencyManagement( src.getDependencyManagement() ) );
+        result.setDistributionManagement( cloneDistributionManagement( src.getDistributionManagement() ) );
+        
+        result.setModules( cloneListOfStrings( src.getModules() ) );
+
+        result.setPluginRepositories( cloneList( src.getPluginRepositories(), REPOSITORY_CLONER ) );
+        result.setProperties( cloneProperties( src.getProperties() ) );
+        result.setReporting( cloneReporting( src.getReporting() ) );
+        result.setRepositories( cloneList( src.getRepositories(), REPOSITORY_CLONER ) );
+    }
+
+    public static Reporting cloneReporting( Reporting src )
+    {
+        if ( src == null )
+        {
+            return null;
+        }
+        
+        Reporting result = new Reporting();
+        
+        result.setExcludeDefaults( src.isExcludeDefaults() );
+        result.setOutputDirectory( src.getOutputDirectory() );
+        result.setPlugins( cloneList( src.getPlugins(), REPORT_PLUGIN_CLONER ) );
+        
+        return result;
+    }
+
+    public static Activation cloneActivation( Activation src )
+    {
+        if ( src == null )
+        {
+            return null;
+        }
+        
+        Activation result = new Activation();
+        result.setActiveByDefault( src.isActiveByDefault() );
+        result.setFile( cloneActivationFile( src.getFile() ) );
+        result.setJdk( src.getJdk() );
+        result.setOs( cloneActivationOs( src.getOs() ) );
+        result.setProperty( cloneActivationProperty( src.getProperty() ) );
+        
+        return result;
+    }
+
+    public static ActivationProperty cloneActivationProperty( ActivationProperty src )
+    {
+        if ( src == null )
+        {
+            return null;
+        }
+        
+        ActivationProperty result = new ActivationProperty();
+        
+        result.setName( src.getName() );
+        result.setValue( src.getValue() );
+        
+        return result;
+    }
+
+    public static ActivationOS cloneActivationOs( ActivationOS src )
+    {
+        if ( src == null )
+        {
+            return null;
+        }
+        
+        ActivationOS result = new ActivationOS();
+        
+        result.setArch( src.getArch() );
+        result.setFamily( src.getFamily() );
+        result.setName( src.getName() );
+        result.setVersion( src.getVersion() );
+        
+        return result;
+    }
+
+    public static ActivationFile cloneActivationFile( ActivationFile src )
+    {
+        if ( src == null )
+        {
+            return null;
+        }
+        
+        ActivationFile result = new ActivationFile();
+        
+        result.setExists( src.getExists() );
+        result.setMissing( src.getMissing() );
+
+        return result;
+    }
+
+    public static Repository cloneRepository( Repository src )
+    {
+        if ( src == null )
+        {
+            return null;
+        }
+        
+        Repository result = new Repository();
+        
+        result.setReleases( cloneRepositoryPolicy( src.getReleases() ) );
+        result.setSnapshots( cloneRepositoryPolicy( src.getSnapshots() ) );
+        
+        cloneRepositoryBaseFields( src, result );
+        
+        return result;
+    }
+
+    public static RepositoryPolicy cloneRepositoryPolicy( RepositoryPolicy src )
+    {
+        if ( src == null )
+        {
+            return null;
+        }
+        
+        RepositoryPolicy result = new RepositoryPolicy();
+        
+        result.setChecksumPolicy( src.getChecksumPolicy() );
+        result.setEnabled( src.isEnabled() );
+        result.setUpdatePolicy( src.getUpdatePolicy() );
+        
+        return result;
+    }
+
+    public static MailingList cloneMailingList( MailingList src )
+    {
+        if ( src == null )
+        {
+            return null;
+        }
+        
+        MailingList result = new MailingList();
+        
+        result.setArchive( src.getArchive() );
+        result.setName( src.getName() );
+        result.setOtherArchives( src.getOtherArchives() );
+        result.setPost( src.getPost() );
+        result.setSubscribe( src.getSubscribe() );
+        result.setUnsubscribe( src.getUnsubscribe() );
+        
+        return result;
+    }
+
     /**
      * This should be the resulting ordering of plugins after merging:
      *
@@ -565,593 +899,540 @@
         child.setConfiguration( childConfiguration );
     }
 
-    public static Model cloneModel( Model model )
+    public static Model cloneModel( Model src )
     {
-        StringWriter writer = new StringWriter();
-        try
+        if ( src == null )
         {
-            new MavenXpp3Writer().write( writer, model );
+            return null;
         }
-        catch ( IOException e )
+        
+        Model result = new Model();
+        
+        cloneModelBaseFields( src, result );
+
+        result.setArtifactId( src.getArtifactId() );
+        result.setBuild( cloneBuild( src.getBuild() ) );
+        result.setCiManagement( cloneCiManagement( src.getCiManagement() ) );
+        
+        result.setContributors( cloneList( src.getContributors(), CONTRIBUTOR_CLONER ) );
+        
+        result.setDescription( src.getDescription() );
+        result.setDevelopers( cloneList( src.getDevelopers(), DEVELOPER_CLONER ) );
+        
+        result.setGroupId( src.getGroupId() );
+        result.setInceptionYear( src.getInceptionYear() );
+        result.setIssueManagement( cloneIssueManagement( src.getIssueManagement() ) );
+        result.setLicenses( cloneList( src.getLicenses(), LICENSE_CLONER ) );
+        
+        result.setMailingLists( cloneList( src.getMailingLists(), MAILING_LIST_CLONER ) );
+        result.setModelVersion( src.getModelVersion() );
+        result.setName( src.getName() );
+        result.setOrganization( cloneOrganization( src.getOrganization() ) );
+        result.setPackaging( src.getPackaging() );
+        result.setParent( cloneParent( src.getParent() ) );
+        
+        result.setPrerequisites( clonePrerequisites( src.getPrerequisites() ) );
+        result.setProfiles( cloneList( src.getProfiles(), PROFILE_CLONER ) );
+        
+        result.setScm( cloneScm( src.getScm() ) );
+        result.setUrl( src.getUrl() );
+        result.setVersion( src.getVersion() );
+
+        return result;
+    }
+
+    public static Scm cloneScm( Scm src )
+    {
+        if ( src == null )
         {
+            return null;
         }
         
-        try
+        Scm result = new Scm();
+        
+        result.setConnection( src.getConnection() );
+        result.setDeveloperConnection( src.getDeveloperConnection() );
+        result.setTag( src.getTag() );
+        result.setUrl( src.getUrl() );
+        
+        return result;
+    }
+
+    public static Prerequisites clonePrerequisites( Prerequisites src )
+    {
+        if ( src == null )
         {
-            return new MavenXpp3Reader().read( new StringReader( writer.toString() ) );
+            return null;
         }
-        catch ( IOException e )
+        
+        Prerequisites result = new Prerequisites();
+        
+        result.setMaven( src.getMaven() );
+
+        return result;
+    }
+
+    public static Organization cloneOrganization( Organization src )
+    {
+        if ( src == null )
         {
+            return null;
         }
-        catch ( XmlPullParserException e )
+        
+        Organization result = new Organization();
+        
+        result.setName( src.getName() );
+        result.setUrl( src.getUrl() );
+        
+        return result;
+    }
+
+    public static License cloneLicense( License src )
+    {
+        if ( src == null )
         {
+            return null;
         }
         
-        return null;
+        License result = new License();
+        
+        result.setComments( src.getComments() );
+        result.setDistribution( src.getDistribution() );
+        result.setName( src.getName() );
+        result.setUrl( src.getUrl() );
         
-        // TODO: would be nice for the modello:java code to generate this as a copy constructor
-        // FIXME: Fix deep cloning issues with existing plugin instances (setting 
-        //       a version when resolved will pollute the original model instance)
-//        Model newModel = new Model();
-//        ModelInheritanceAssembler assembler = new DefaultModelInheritanceAssembler();
-//        newModel.setModelVersion( model.getModelVersion() );
-//        newModel.setName( model.getName() );
-//        newModel.setParent( cloneParent( model.getParent() ) );
-//        newModel.setVersion( model.getVersion() );
-//        newModel.setArtifactId( model.getArtifactId() );
-//        newModel.setProperties( new Properties( model.getProperties() ) );
-//        newModel.setGroupId( model.getGroupId() );
-//        newModel.setPackaging( model.getPackaging() );
-//        newModel.setModules( cloneModules( model.getModules() ) );
-//
-//        newModel.setProfiles( cloneProfiles( model.getProfiles() ) );
-//
-//        assembler.copyModel( newModel, model );
-//
-//        return newModel;
+        return result;
     }
 
-    public static Build cloneBuild( Build build )
+    public static IssueManagement cloneIssueManagement( IssueManagement src )
     {
-        Model model = new Model();
-        model.setBuild( build );
-        
-        StringWriter writer = new StringWriter();
-        try
+        if ( src == null )
         {
-            new MavenXpp3Writer().write( writer, model );
+            return null;
         }
-        catch ( IOException e )
+        
+        IssueManagement result = new IssueManagement();
+        
+        result.setSystem( src.getSystem() );
+        result.setUrl( src.getUrl() );
+        
+        return result;
+    }
+
+    public static DistributionManagement cloneDistributionManagement( DistributionManagement src )
+    {
+        if ( src == null )
         {
+            return null;
         }
         
-        try
+        DistributionManagement result = new DistributionManagement();
+        
+        result.setDownloadUrl( src.getDownloadUrl() );
+        result.setRelocation( cloneRelocation( src.getRelocation() ) );
+        result.setRepository( cloneDeploymentRepository( src.getRepository() ) );
+        result.setSite( cloneSite( src.getSite() ) );
+        result.setSnapshotRepository( cloneDeploymentRepository( src.getSnapshotRepository() ) );
+        result.setStatus( src.getStatus() );
+        
+        return result;
+    }
+
+    public static Site cloneSite( Site src )
+    {
+        if ( src == null )
         {
-            return new MavenXpp3Reader().read( new StringReader( writer.toString() ) ).getBuild();
+            return null;
         }
-        catch ( IOException e )
+        
+        Site result = new Site();
+        
+        result.setId( src.getId() );
+        result.setName( src.getName() );
+        result.setUrl( src.getUrl() );
+        
+        return result;
+    }
+
+    public static DeploymentRepository cloneDeploymentRepository( DeploymentRepository src )
+    {
+        if ( src == null )
         {
+            return null;
         }
-        catch ( XmlPullParserException e )
+        
+        DeploymentRepository result = new DeploymentRepository();
+        
+        result.setUniqueVersion( src.isUniqueVersion() );
+        
+        cloneRepositoryBaseFields( src, result );
+        
+        return result;
+    }
+
+    private static void cloneRepositoryBaseFields( RepositoryBase src, RepositoryBase result )
+    {
+        result.setId( src.getId() );
+        result.setLayout( src.getLayout() );
+        result.setName( src.getName() );
+        result.setUrl( src.getUrl() );
+    }
+
+    public static Relocation cloneRelocation( Relocation src )
+    {
+        if ( src == null )
         {
+            return null;
         }
         
-        return null;
+        Relocation result = new Relocation();
+        
+        result.setArtifactId( src.getArtifactId() );
+        result.setGroupId( src.getGroupId() );
+        result.setMessage( src.getMessage() );
+        result.setVersion( src.getVersion() );
         
-//        ModelInheritanceAssembler assembler = new DefaultModelInheritanceAssembler();
-//
-//        Build clone = new Build();
-//
-//        assembler.assembleBuildInheritance( clone, build, false );
-//
-//        return clone;
+        return result;
     }
 
-    private static List cloneProfiles( List profiles )
+    public static DependencyManagement cloneDependencyManagement( DependencyManagement src )
     {
-        if ( profiles == null )
+        if ( src == null )
         {
-            return profiles;
+            return null;
         }
+        
+        DependencyManagement result = new DependencyManagement();
+        result.setDependencies( cloneList( src.getDependencies(), DEPENDENCY_CLONER ) );
+        
+        return result;
+    }
 
-        List newProfiles = new ArrayList( profiles.size() );
-
-        for ( Iterator it = profiles.iterator(); it.hasNext(); )
+    private static List cloneList( List src, ModelPartCloner cloner )
+    {
+        List result = null;
+        if ( src != null )
         {
-            Profile profile = (Profile) it.next();
-
-            Profile newProfile = new Profile();
-
-            newProfile.setId( profile.getId() );
-
-            newProfile.setActivation( cloneProfileActivation( profile.getActivation() ) );
-
-            newProfile.setBuild( cloneProfileBuild( profile.getBuild() ) );
-
-            newProfile.setDependencies( cloneProfileDependencies( profile.getDependencies() ) );
-
-            DependencyManagement dm = profile.getDependencyManagement();
-
-            if ( dm != null )
-            {
-                DependencyManagement newDM = new DependencyManagement();
-
-                newDM.setDependencies( cloneProfileDependencies( dm.getDependencies() ) );
-
-                newProfile.setDependencyManagement( newDM );
-            }
-
-            newProfile.setDistributionManagement( cloneProfileDistributionManagement( profile
-                .getDistributionManagement() ) );
-
-            List modules = profile.getModules();
-
-            if ( ( modules != null ) && !modules.isEmpty() )
+            result = new ArrayList( src.size() );
+            for ( Iterator it = src.iterator(); it.hasNext(); )
             {
-                newProfile.setModules( new ArrayList( modules ) );
+                result.add( cloner.cloneModelPart( (Object) it.next() ) );
             }
-
-            newProfile.setPluginRepositories( cloneProfileRepositories( profile.getPluginRepositories() ) );
-
-            Properties props = profile.getProperties();
-
-            if ( props != null )
-            {
-                Properties newProps = new Properties();
-                newProps.putAll( props );
-
-                newProfile.setProperties( newProps );
-            }
-
-            newProfile.setReporting( cloneProfileReporting( profile.getReporting() ) );
-
-            newProfile.setReports( profile.getReports() );
-
-            newProfile.setRepositories( cloneProfileRepositories( profile.getRepositories() ) );
-
-            newProfile.setSource( profile.getSource() );
-
-            newProfiles.add( newProfile );
         }
-
-        return newProfiles;
+        
+        return result;
     }
 
-    private static Reporting cloneProfileReporting( Reporting reporting )
+    public static Contributor cloneContributor( Contributor src )
     {
-        Reporting newR = null;
-
-        if ( reporting != null )
+        if ( src == null )
         {
-            newR = new Reporting();
-
-            newR.setOutputDirectory( reporting.getOutputDirectory() );
-
-            List plugins = reporting.getPlugins();
-
-            if ( plugins != null )
-            {
-                List newP = new ArrayList( plugins.size() );
-
-                for ( Iterator it = plugins.iterator(); it.hasNext(); )
-                {
-                    ReportPlugin plugin = (ReportPlugin) it.next();
-
-                    ReportPlugin newPlugin = new ReportPlugin();
-
-                    newPlugin.setArtifactId( plugin.getArtifactId() );
-                    newPlugin.setGroupId( plugin.getGroupId() );
-                    newPlugin.setVersion( plugin.getVersion() );
-                    newPlugin.setInherited( plugin.getInherited() );
-                    newPlugin.setReportSets( cloneReportSets( plugin.getReportSets() ) );
-
-                    // TODO: Implement deep-copy of configuration.
-                    newPlugin.setConfiguration( plugin.getConfiguration() );
-
-                    newP.add( newPlugin );
-                }
-
-                newR.setPlugins( newP );
-            }
+            return null;
         }
-
-        return newR;
+        
+        Contributor result = new Contributor();
+        cloneContributorFields( src, result );
+        
+        return result;
     }
-
-    private static List cloneReportSets( List sets )
+    
+    public static Developer cloneDeveloper( Developer src )
     {
-        List newSets = null;
-
-        if ( sets != null )
+        if ( src == null )
         {
-            newSets = new ArrayList( sets.size() );
-
-            for ( Iterator it = sets.iterator(); it.hasNext(); )
-            {
-                ReportSet set = (ReportSet) it.next();
-
-                ReportSet newSet = new ReportSet();
-
-                // TODO: Deep-copy config.
-                newSet.setConfiguration( set.getConfiguration() );
-
-                newSet.setId( set.getId() );
-                newSet.setInherited( set.getInherited() );
-
-                newSet.setReports( new ArrayList( set.getReports() ) );
-
-                newSets.add( newSet );
-            }
+            return null;
         }
-
-        return newSets;
+        
+        Developer result = new Developer();
+        
+        result.setId( src.getId() );
+        
+        cloneContributorFields( src, result );
+        
+        return result;
     }
-
-    private static List cloneProfileRepositories( List repos )
+    
+    private static void cloneContributorFields( Contributor src, Contributor result )
     {
-        List newRepos = null;
+        result.setEmail( src.getEmail() );
+        result.setName( src.getName() );
+        result.setOrganization( src.getOrganization() );
+        result.setOrganizationUrl( src.getOrganizationUrl() );
+        result.setProperties( cloneProperties( src.getProperties() ) );
+        result.setRoles( cloneListOfStrings( src.getRoles() ) );
+        result.setTimezone( src.getTimezone() );
+        result.setUrl( src.getUrl() );
+    }
 
-        if ( repos != null )
+    public static CiManagement cloneCiManagement( CiManagement src )
+    {
+        if ( src == null )
         {
-            newRepos = new ArrayList( repos.size() );
-
-            for ( Iterator it = repos.iterator(); it.hasNext(); )
+            return null;
+        }
+        
+        CiManagement result = new CiManagement();
+        
+        List notifiers = null;
+        if ( src.getNotifiers() != null )
+        {
+            notifiers = new ArrayList( src.getNotifiers().size() );
+            for ( Iterator it = src.getNotifiers().iterator(); it.hasNext(); )
             {
-                Repository repo = (Repository) it.next();
-
-                Repository newRepo = new Repository();
-
-                newRepo.setId( repo.getId() );
-                newRepo.setLayout( repo.getLayout() );
-                newRepo.setName( repo.getName() );
-
-                RepositoryPolicy releasePolicy = repo.getReleases();
-
-                if ( releasePolicy != null )
-                {
-                    RepositoryPolicy newPolicy = new RepositoryPolicy();
-                    newPolicy.setEnabled( releasePolicy.isEnabled() );
-                    newPolicy.setChecksumPolicy( releasePolicy.getChecksumPolicy() );
-                    newPolicy.setUpdatePolicy( releasePolicy.getUpdatePolicy() );
-
-                    newRepo.setReleases( newPolicy );
-                }
-
-                RepositoryPolicy snapPolicy = repo.getSnapshots();
-
-                if ( snapPolicy != null )
-                {
-                    RepositoryPolicy newPolicy = new RepositoryPolicy();
-                    newPolicy.setEnabled( snapPolicy.isEnabled() );
-                    newPolicy.setChecksumPolicy( snapPolicy.getChecksumPolicy() );
-                    newPolicy.setUpdatePolicy( snapPolicy.getUpdatePolicy() );
-
-                    newRepo.setSnapshots( newPolicy );
-                }
-
-                newRepo.setUrl( repo.getUrl() );
-
-                newRepos.add( newRepo );
+                notifiers.add( cloneNotifier( (Notifier) it.next() ) );
             }
         }
-
-        return newRepos;
+        result.setNotifiers( cloneList( src.getNotifiers(), NOTIFIER_CLONER ) );
+        
+        result.setSystem( src.getSystem() );
+        result.setUrl( src.getUrl() );
+        
+        return result;
     }
 
-    private static DistributionManagement cloneProfileDistributionManagement( DistributionManagement dm )
+    public static Notifier cloneNotifier( Notifier src )
     {
-        DistributionManagement newDM = null;
-
-        if ( dm != null )
+        if ( src == null )
         {
-            newDM = new DistributionManagement();
-
-            newDM.setDownloadUrl( dm.getDownloadUrl() );
-            newDM.setStatus( dm.getStatus() );
-
-            Relocation relocation = dm.getRelocation();
-
-            if ( relocation != null )
-            {
-                Relocation newR = new Relocation();
-
-                newR.setArtifactId( relocation.getArtifactId() );
-                newR.setGroupId( relocation.getGroupId() );
-                newR.setMessage( relocation.getMessage() );
-                newR.setVersion( relocation.getVersion() );
-
-                newDM.setRelocation( newR );
-            }
-
-            RepositoryBase repo = dm.getRepository();
-
-            if ( repo != null )
-            {
-                DeploymentRepository newRepo = new DeploymentRepository();
-
-                newRepo.setId( repo.getId() );
-                newRepo.setLayout( repo.getLayout() );
-                newRepo.setName( repo.getName() );
-                newRepo.setUrl( repo.getUrl() );
-
-                newDM.setRepository( newRepo );
-            }
-
-            Site site = dm.getSite();
-
-            if ( site != null )
-            {
-                Site newSite = new Site();
-
-                newSite.setId( site.getId() );
-                newSite.setName( site.getName() );
-                newSite.setUrl( site.getUrl() );
-
-                newDM.setSite( newSite );
-            }
-
-            RepositoryBase sRepo = dm.getSnapshotRepository();
-
-            if ( sRepo != null )
-            {
-                DeploymentRepository newRepo = new DeploymentRepository();
-
-                newRepo.setId( sRepo.getId() );
-                newRepo.setLayout( sRepo.getLayout() );
-                newRepo.setName( sRepo.getName() );
-                newRepo.setUrl( sRepo.getUrl() );
-
-                newDM.setSnapshotRepository( newRepo );
-            }
+            return null;
         }
-
-        return newDM;
+        
+        Notifier result = new Notifier();
+        result.setAddress( src.getAddress() );
+        result.setConfiguration( cloneProperties( src.getConfiguration() ) );
+        result.setSendOnError( src.isSendOnError() );
+        result.setSendOnFailure( result.isSendOnFailure() );
+        result.setSendOnSuccess( result.isSendOnSuccess() );
+        result.setSendOnWarning( result.isSendOnWarning() );
+        
+        return result;
     }
 
-    private static List cloneProfileDependencies( List dependencies )
+    public static Properties cloneProperties( Properties src )
     {
-        List newDependencies = null;
-
-        if ( dependencies != null )
+        if ( src == null )
         {
-            newDependencies = new ArrayList( dependencies.size() );
-
-            for ( Iterator it = dependencies.iterator(); it.hasNext(); )
-            {
-                Dependency dep = (Dependency) it.next();
-
-                Dependency newDep = new Dependency();
-
-                newDep.setArtifactId( dep.getArtifactId() );
-                newDep.setClassifier( dep.getClassifier() );
-                newDep.setExclusions( cloneDependencyExclusions( dep.getExclusions() ) );
-                newDep.setGroupId( dep.getGroupId() );
-                newDep.setScope( dep.getScope() );
-                newDep.setSystemPath( dep.getSystemPath() );
-                newDep.setType( dep.getType() );
-                newDep.setVersion( dep.getVersion() );
-
-                newDependencies.add( newDep );
-            }
+            return null;
         }
-
-        return newDependencies;
+        
+        Properties result = new Properties();
+        for( Enumeration e = src.propertyNames(); e.hasMoreElements(); )
+        {
+            String key = (String) e.nextElement();
+            result.setProperty( key, src.getProperty( key ) );
+        }
+        
+        return result;
     }
 
-    private static List cloneDependencyExclusions( List ex )
+    public static Build cloneBuild( Build src )
     {
-        List newEx = null;
-
-        if ( ex != null )
+        if ( src == null )
         {
-            newEx = new ArrayList( ex.size() );
-
-            for ( Iterator it = ex.iterator(); it.hasNext(); )
-            {
-                Exclusion exclusion = (Exclusion) it.next();
+            return null;
+        }
 
-                Exclusion newExclusion = new Exclusion();
+        Build result = new Build();
+        
+        cloneBuildBaseFields( src, result );
+        
+        result.setExtensions( cloneList( src.getExtensions(), EXTENSION_CLONER ) );
+        result.setOutputDirectory( src.getOutputDirectory() );
+        
+        result.setScriptSourceDirectory( src.getScriptSourceDirectory() );
+        result.setSourceDirectory( src.getSourceDirectory() );
+        result.setTestOutputDirectory( src.getTestOutputDirectory() );
+        result.setTestSourceDirectory( src.getTestSourceDirectory() );
+        
+        return result;
+    }
 
-                newExclusion.setArtifactId( exclusion.getArtifactId() );
-                newExclusion.setGroupId( exclusion.getGroupId() );
+    public static void cloneBuildBaseFields( BuildBase src, BuildBase result )
+    {
+        result.setDefaultGoal( src.getDefaultGoal() );
+        result.setDirectory( src.getDirectory() );
+        
+        result.setFilters( cloneListOfStrings( src.getFilters() ) );
+        result.setFinalName( src.getFinalName() );
+        
+        result.setPluginManagement( clonePluginManagement( src.getPluginManagement() ) );
+        result.setPlugins( cloneList( src.getPlugins(), PLUGIN_CLONER ) );
+ 
+        result.setResources( cloneList( src.getResources(), RESOURCE_CLONER ) );
+        
+        result.setTestResources( cloneList( src.getTestResources(), RESOURCE_CLONER ) );
+    }
 
-                newEx.add( newExclusion );
-            }
+    public static PluginManagement clonePluginManagement( PluginManagement src )
+    {
+        PluginManagement pMgmt = null;
+        if ( src != null )
+        {
+            pMgmt = new PluginManagement();
+            pMgmt.setPlugins( cloneList( src.getPlugins(), PLUGIN_CLONER ) );
         }
-
-        return newEx;
+        
+        return pMgmt;
     }
 
-    private static BuildBase cloneProfileBuild( BuildBase build )
+    public static Resource cloneResource( Resource src )
     {
-        BuildBase newBuild = null;
-        if ( build != null )
+        Resource result = null;
+        if ( src != null )
         {
-            newBuild = new BuildBase();
-
-            newBuild.setDefaultGoal( build.getDefaultGoal() );
-            newBuild.setDirectory( build.getDirectory() );
-            newBuild.setFinalName( build.getFinalName() );
-
-            newBuild.setPluginManagement( cloneProfilePluginManagement( build.getPluginManagement() ) );
-            newBuild.setPlugins( cloneProfilePlugins( build.getPlugins() ) );
-            newBuild.setResources( cloneProfileResources( build.getResources() ) );
-            newBuild.setTestResources( cloneProfileResources( build.getTestResources() ) );
+            result = new Resource();
+            
+            result.setDirectory( src.getDirectory() );
+            result.setExcludes( cloneListOfStrings( src.getExcludes() ) );
+            result.setFiltering( src.isFiltering() );
+            result.setIncludes( cloneListOfStrings( src.getIncludes() ) );
+            result.setMergeId( src.getMergeId() );
+            result.setTargetPath( src.getTargetPath() );
         }
-
-        return newBuild;
+        
+        return result;
     }
 
-    private static List cloneProfileResources( List resources )
+    public static Plugin clonePlugin( Plugin src )
     {
-        List newResources = null;
-
-        if ( resources != null )
+        Plugin result = null;
+        if ( src != null )
         {
-            newResources = new ArrayList( resources.size() );
-
-            for ( Iterator it = resources.iterator(); it.hasNext(); )
-            {
-                Resource resource = (Resource) it.next();
-
-                Resource newResource = new Resource();
-
-                newResource.setDirectory( resource.getDirectory() );
-                newResource.setExcludes( new ArrayList( resource.getExcludes() ) );
-                newResource.setFiltering( resource.isFiltering() );
-                newResource.setIncludes( new ArrayList( resource.getIncludes() ) );
-                newResource.setTargetPath( resource.getTargetPath() );
-
-                newResources.add( newResource );
-            }
+            result = new Plugin();
+            result.setArtifactId( src.getArtifactId() );
+            
+            result.setConfiguration( cloneConfiguration( src.getConfiguration() ) );
+            
+            result.setDependencies( cloneList( src.getDependencies(), DEPENDENCY_CLONER ) );
+            result.setExecutions( cloneList( src.getExecutions(), PLUGIN_EXECUTION_CLONER ) );
+            
+            result.setExtensions( src.isExtensions() );
+            result.setGroupId( src.getGroupId() );
+            result.setInherited( src.getInherited() );
+            result.setVersion( src.getVersion() );
         }
-
-        return newResources;
+        
+        return result;
     }
 
-    private static PluginManagement cloneProfilePluginManagement( PluginManagement pluginManagement )
+    public static PluginExecution clonePluginExecution( PluginExecution src )
     {
-        PluginManagement newPM = null;
-
-        if ( pluginManagement != null )
+        PluginExecution result = null;
+        
+        if ( src != null )
         {
-            newPM = new PluginManagement();
-
-            List plugins = pluginManagement.getPlugins();
-
-            newPM.setPlugins( cloneProfilePlugins( plugins ) );
+            result = new PluginExecution();
+            
+            result.setId( src.getId() );
+            result.setGoals( cloneListOfStrings( src.getGoals() ) );
+            result.setConfiguration( cloneConfiguration( src.getConfiguration() ) );
+            result.setInherited( src.getInherited() );
+            result.setPhase( src.getPhase() );
         }
-
-        return newPM;
+        
+        return result;
     }
 
-    private static List cloneProfilePlugins( List plugins )
+    // FIXME: We need something better than this for configurations!
+    public static Object cloneConfiguration( Object configuration )
     {
-        List newPlugins = null;
-
-        if ( plugins != null )
+        if ( configuration == null )
         {
-            newPlugins = new ArrayList( plugins.size() );
-
-            for ( Iterator it = plugins.iterator(); it.hasNext(); )
-            {
-                Plugin plugin = (Plugin) it.next();
-
-                Plugin newPlugin = new Plugin();
-
-                newPlugin.setArtifactId( plugin.getArtifactId() );
-                newPlugin.setExtensions( plugin.isExtensions() );
-                newPlugin.setGroupId( plugin.getGroupId() );
-                newPlugin.setInherited( plugin.getInherited() );
-                newPlugin.setVersion( plugin.getVersion() );
-
-                // TODO: Deep-copy this!
-                newPlugin.setConfiguration( plugin.getConfiguration() );
-
-                newPlugin.setExecutions( cloneExecutions( plugin.getExecutions() ) );
-
-                newPlugins.add( newPlugin );
-            }
+            return null;
         }
-
-        return newPlugins;
+        
+        return new Xpp3Dom( (Xpp3Dom) configuration );
     }
 
-    private static List cloneExecutions( List executions )
+    public static Dependency cloneDependency( Dependency src )
     {
-        List newExecs = null;
-
-        if ( executions != null )
+        Dependency result = null;
+        if ( src != null )
         {
-            newExecs = new ArrayList( executions.size() );
-
-            for ( Iterator it = executions.iterator(); it.hasNext(); )
-            {
-                PluginExecution exec = (PluginExecution) it.next();
-
-                PluginExecution newExec = new PluginExecution();
-
-                // TODO: Deep-copy configs.
-                newExec.setConfiguration( exec.getConfiguration() );
-
-                newExec.setId( exec.getId() );
-                newExec.setInherited( exec.getInherited() );
-                newExec.setPhase( exec.getPhase() );
-
-                List goals = exec.getGoals();
-
-                if ( ( goals != null ) && !goals.isEmpty() )
-                {
-                    newExec.setGoals( new ArrayList( goals ) );
-                }
-
-                newExecs.add( newExec );
-            }
+            result = new Dependency();
+            
+            result.setArtifactId( src.getArtifactId() );
+            result.setClassifier( src.getClassifier() );
+            result.setExclusions( cloneList( src.getExclusions(), DEPENDENCY_EXCLUSION_CLONER ) );
+            result.setGroupId( src.getGroupId() );
+            result.setOptional( src.isOptional() );
+            result.setScope( src.getScope() );
+            result.setSystemPath( src.getSystemPath() );
+            result.setType( src.getType() );
+            result.setVersion( src.getVersion() );
         }
-
-        return newExecs;
+        
+        return result;
     }
 
-    private static Activation cloneProfileActivation( Activation activation )
+    public static Exclusion cloneExclusion( Exclusion src )
     {
-        Activation newActivation = null;
-        if ( activation != null )
+        Exclusion result = null;
+        if ( src != null )
         {
-            newActivation = new Activation();
-
-            newActivation.setActiveByDefault( activation.isActiveByDefault() );
-
-            ActivationFile af = activation.getFile();
-
-            if ( af != null )
-            {
-                ActivationFile afNew = new ActivationFile();
-                afNew.setExists( af.getExists() );
-                afNew.setMissing( af.getMissing() );
-
-                newActivation.setFile( afNew );
-            }
-
-            newActivation.setJdk( activation.getJdk() );
-
-            ActivationProperty ap = activation.getProperty();
+            result = new Exclusion();
+            result.setArtifactId( src.getArtifactId() );
+            result.setGroupId( src.getGroupId() );
+        }
+        
+        return result;
+    }
 
-            if ( ap != null )
+    public static List cloneListOfStrings( List src )
+    {
+        List result = null;
+        if ( src != null )
+        {
+            result = new ArrayList( src.size() );
+            for ( Iterator it = src.iterator(); it.hasNext(); )
             {
-                ActivationProperty newAp = new ActivationProperty();
-
-                newAp.setName( ap.getName() );
-                newAp.setValue( ap.getValue() );
-
-                newActivation.setProperty( newAp );
+                String item = (String) it.next();
+                result.add( item );
             }
         }
+        
+        return result;
+    }
 
-        return newActivation;
+    public static Extension cloneExtension( Extension src )
+    {
+        Extension rExt = new Extension();
+        rExt.setArtifactId( src.getArtifactId() );
+        rExt.setGroupId( src.getGroupId() );
+        rExt.setVersion( src.getVersion() );
+        
+        return rExt;
     }
 
-    private static List cloneModules( List modules )
+    public static Exclusion cloneDependencyExclusion( Exclusion src )
     {
-        if ( modules == null )
+        if ( src == null )
         {
-            return modules;
+            return null;
         }
-        return new ArrayList( modules );
+        
+        Exclusion result = new Exclusion();
+
+        result.setArtifactId( src.getArtifactId() );
+        result.setGroupId( src.getGroupId() );
+        
+        return result;
     }
 
-    private static Parent cloneParent( Parent parent )
+    public static Parent cloneParent( Parent src )
     {
-        if ( parent == null )
+        if ( src == null )
         {
-            return parent;
+            return null;
         }
 
-        Parent newParent = new Parent();
-        newParent.setArtifactId( parent.getArtifactId() );
-        newParent.setGroupId( parent.getGroupId() );
-        newParent.setRelativePath( parent.getRelativePath() );
-        newParent.setVersion( parent.getVersion() );
-        return newParent;
+        Parent result = new Parent();
+        result.setArtifactId( src.getArtifactId() );
+        result.setGroupId( src.getGroupId() );
+        result.setRelativePath( src.getRelativePath() );
+        result.setVersion( src.getVersion() );
+        
+        return result;
     }
 
     public static List mergeRepositoryLists( List dominant, List recessive )
@@ -1238,5 +1519,11 @@
 
         return new ArrayList( depsMap.values() );
     }
+    
+    public static interface ModelPartCloner
+    {
+        Object cloneModelPart( Object src );
+    }
+    
 
 }

Modified: maven/components/branches/maven-2.0.10-RC/maven-project/src/main/java/org/apache/maven/project/interpolation/AbstractStringBasedModelInterpolator.java
URL: http://svn.apache.org/viewvc/maven/components/branches/maven-2.0.10-RC/maven-project/src/main/java/org/apache/maven/project/interpolation/AbstractStringBasedModelInterpolator.java?rev=687867&r1=687866&r2=687867&view=diff
==============================================================================
--- maven/components/branches/maven-2.0.10-RC/maven-project/src/main/java/org/apache/maven/project/interpolation/AbstractStringBasedModelInterpolator.java (original)
+++ maven/components/branches/maven-2.0.10-RC/maven-project/src/main/java/org/apache/maven/project/interpolation/AbstractStringBasedModelInterpolator.java Thu Aug 21 14:27:09 2008
@@ -25,6 +25,7 @@
 import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -37,6 +38,7 @@
 import org.apache.maven.project.ProjectBuilderConfiguration;
 import org.apache.maven.project.path.PathTranslator;
 import org.codehaus.plexus.interpolation.InterpolationException;
+import org.codehaus.plexus.interpolation.InterpolationPostProcessor;
 import org.codehaus.plexus.interpolation.Interpolator;
 import org.codehaus.plexus.interpolation.MapBasedValueSource;
 import org.codehaus.plexus.interpolation.ObjectBasedValueSource;
@@ -199,8 +201,14 @@
                                boolean debug )
         throws ModelInterpolationException
     {
-        Logger logger = getLogger();
-
+        List valueSources = createValueSources( model, projectDir, config );
+        List postProcessors = createPostProcessors( model, projectDir, config );
+        
+        return interpolateInternal( src, valueSources, postProcessors, debug );
+    }
+    
+    protected List createValueSources( final Model model, final File projectDir, final ProjectBuilderConfiguration config )
+    {
         String timestampFormat = DEFAULT_BUILD_TIMESTAMP_FORMAT;
 
         Properties modelProperties = model.getProperties();
@@ -224,23 +232,34 @@
             }
         },
         PROJECT_PREFIXES, true );
-
-        PathTranslatingPostProcessor pathTranslatingPostProcessor =
-            new PathTranslatingPostProcessor( TRANSLATED_PATH_EXPRESSIONS, projectDir, pathTranslator );
         
+        List valueSources = new ArrayList( 7 );
+        
+        // NOTE: Order counts here!
+        valueSources.add( basedirValueSource );
+        valueSources.add( new BuildTimestampValueSource( config.getBuildStartTime(), timestampFormat ) );
+        valueSources.add( new MapBasedValueSource( config.getExecutionProperties() ) );
+        valueSources.add( modelValueSource1 );
+        valueSources.add( new PrefixedValueSourceWrapper( new MapBasedValueSource( modelProperties ), PROJECT_PREFIXES, true ) );
+        valueSources.add( modelValueSource2 );
+        valueSources.add( new MapBasedValueSource( config.getUserProperties() ) );
+        
+        return valueSources;
+    }
+    
+    protected List createPostProcessors( final Model model, final File projectDir, final ProjectBuilderConfiguration config )
+    {
+        return Collections.singletonList( new PathTranslatingPostProcessor( TRANSLATED_PATH_EXPRESSIONS, projectDir, pathTranslator ) );
+    }
+    
+    protected String interpolateInternal( String src, List valueSources, List postProcessors, boolean debug )
+        throws ModelInterpolationException
+    {
+        Logger logger = getLogger();
+
         String result = src;
         synchronized( this )
         {
-            List valueSources = new ArrayList( 7 );
-            
-            // NOTE: Order counts here!
-            valueSources.add( basedirValueSource );
-            valueSources.add( new BuildTimestampValueSource( config.getBuildStartTime(), timestampFormat ) );
-            valueSources.add( new MapBasedValueSource( config.getExecutionProperties() ) );
-            valueSources.add( modelValueSource1 );
-            valueSources.add( new PrefixedValueSourceWrapper( new MapBasedValueSource( modelProperties ), PROJECT_PREFIXES, true ) );
-            valueSources.add( modelValueSource2 );
-            valueSources.add( new MapBasedValueSource( config.getUserProperties() ) );
             
             for ( Iterator it = valueSources.iterator(); it.hasNext(); )
             {
@@ -248,7 +267,12 @@
                 interpolator.addValueSource( vs );
             }
             
-            interpolator.addPostProcessor( pathTranslatingPostProcessor );
+            for ( Iterator it = postProcessors.iterator(); it.hasNext(); )
+            {
+                InterpolationPostProcessor postProcessor = (InterpolationPostProcessor) it.next();
+                
+                interpolator.addPostProcessor( postProcessor );
+            }
 
             try
             {
@@ -302,7 +326,7 @@
                     }
                 }
 
-                interpolator.clearFeedback();
+//                interpolator.clearFeedback();
             }
             finally
             {
@@ -312,7 +336,11 @@
                     interpolator.removeValuesSource( vs );
                 }
                 
-                interpolator.removePostProcessor( pathTranslatingPostProcessor );
+                for ( Iterator iterator = postProcessors.iterator(); iterator.hasNext(); )
+                {
+                    InterpolationPostProcessor postProcessor = (InterpolationPostProcessor) iterator.next();
+                    interpolator.removePostProcessor( postProcessor );
+                }
             }
         }