From 5c32bc6b2847aef96f7b6853feb38d4a374bd1cf Mon Sep 17 00:00:00 2001 From: John Dennis Casey Date: Mon, 30 Jun 2008 14:35:43 +0000 Subject: [PATCH] All tests pass on my localhost...committing to see how it works on hudson. git-svn-id: https://svn.apache.org/repos/asf/maven/components/trunk@672782 13f79535-47bb-0310-9956-ffa450edef68 --- .../maven/compat/Maven20xCompatAspect.aj | 19 +- .../errors/ExtensionErrorReporterAspect.aj | 15 +- .../DefaultBuildExtensionScanner.java | 20 +- .../extension/DefaultExtensionManager.java | 57 +- .../maven/plugin/DefaultPluginManager.java | 48 +- .../settings/DefaultMavenSettingsBuilder.java | 18 +- maven-distribution/pom.xml | 4 +- .../activation/FileProfileActivator.java | 34 +- .../project/DefaultMavenProjectBuilder.java | 527 +++++++++++++++- .../apache/maven/project/MavenProject.java | 199 +++++- .../maven/project/MavenProjectBuilder.java | 18 + .../org/apache/maven/project/ModelUtils.java | 11 + .../project/artifact/MavenMetadataSource.java | 14 +- .../DefaultModelInheritanceAssembler.java | 165 ++--- .../ModelInheritanceAssembler.java | 4 + .../project/path/DefaultPathTranslator.java | 47 +- .../DefaultMavenProjectBuilderTest.java | 5 + .../project/MavenProjectDynamismTest.java | 570 ++++++++++++++++++ .../ProjectBaseDirectoryAlignmentTest.java | 1 + .../resources/project-dynamism/pom-interp.xml | 28 + .../project-dynamism/pom-relative.xml | 36 ++ .../test/resources/project-dynamism/pom.xml | 36 ++ pom.xml | 32 +- 23 files changed, 1708 insertions(+), 200 deletions(-) create mode 100644 maven-project/src/test/java/org/apache/maven/project/MavenProjectDynamismTest.java create mode 100644 maven-project/src/test/resources/project-dynamism/pom-interp.xml create mode 100644 maven-project/src/test/resources/project-dynamism/pom-relative.xml create mode 100644 maven-project/src/test/resources/project-dynamism/pom.xml diff --git a/maven-core/src/main/aspect/org/apache/maven/compat/Maven20xCompatAspect.aj b/maven-core/src/main/aspect/org/apache/maven/compat/Maven20xCompatAspect.aj index 09f71cf015..02c1b3eb92 100644 --- a/maven-core/src/main/aspect/org/apache/maven/compat/Maven20xCompatAspect.aj +++ b/maven-core/src/main/aspect/org/apache/maven/compat/Maven20xCompatAspect.aj @@ -46,7 +46,6 @@ import org.codehaus.plexus.logging.Logger; import java.util.List; import java.io.IOException; import java.util.Iterator; -import java.util.Collection; import java.util.Set; import java.util.LinkedHashSet; @@ -156,16 +155,16 @@ public privileged aspect Maven20xCompatAspect // Intercept retrieval of artifact dependencies of an extension, inject plexus-utils if it's not there. private pointcut extDepArtifactsResolved( DefaultExtensionManager mgr ): - call( public Set ResolutionGroup+.getArtifacts() ) + call( public Set ResolutionGroup+.getArtifacts() ) && within( DefaultExtensionManager+ ) && this( mgr ) && notHere(); // We use the same hack here to make sure that plexus 1.1 is available for extensions that do // not declare plexus-utils but need it. MNG-2900 - Set around( DefaultExtensionManager mgr ): extDepArtifactsResolved( mgr ) + Set around( DefaultExtensionManager mgr ): extDepArtifactsResolved( mgr ) { - Set result = proceed( mgr ); + Set result = proceed( mgr ); result = checkPlexusUtils( result, mgr.artifactFactory ); @@ -174,14 +173,14 @@ public privileged aspect Maven20xCompatAspect // Intercept retrieval of artifact dependencies of a plugin, inject plexus-utils if it's not there. private pointcut pluginDepArtifactsResolved( DefaultPluginManager mgr ): - call( public Set ResolutionGroup+.getArtifacts() ) - && cflow( execution( Set DefaultPluginManager+.getPluginArtifacts(..) ) ) + call( public Set ResolutionGroup+.getArtifacts() ) + && cflow( execution( List DefaultPluginManager+.getPluginArtifacts(..) ) ) && this( mgr ) && notHere(); - Set around( DefaultPluginManager mgr ): pluginDepArtifactsResolved( mgr ) + Set around( DefaultPluginManager mgr ): pluginDepArtifactsResolved( mgr ) { - Set result = proceed( mgr ); + Set result = proceed( mgr ); result = checkPlexusUtils( result, mgr.artifactFactory ); @@ -306,7 +305,7 @@ public privileged aspect Maven20xCompatAspect // UTILITIES // -------------------------- - private Set checkPlexusUtils( Set dependencyArtifacts, ArtifactFactory artifactFactory ) + private Set checkPlexusUtils( Set dependencyArtifacts, ArtifactFactory artifactFactory ) { // ---------------------------------------------------------------------------- // If the plugin already declares a dependency on plexus-utils then we're all @@ -354,7 +353,7 @@ public privileged aspect Maven20xCompatAspect "jar" ); } - Set result = new LinkedHashSet( dependencyArtifacts ); + Set result = new LinkedHashSet( dependencyArtifacts ); result.add( plexusUtilsArtifact ); return result; diff --git a/maven-core/src/main/aspect/org/apache/maven/errors/ExtensionErrorReporterAspect.aj b/maven-core/src/main/aspect/org/apache/maven/errors/ExtensionErrorReporterAspect.aj index c778d2594c..f860de98a4 100644 --- a/maven-core/src/main/aspect/org/apache/maven/errors/ExtensionErrorReporterAspect.aj +++ b/maven-core/src/main/aspect/org/apache/maven/errors/ExtensionErrorReporterAspect.aj @@ -1,5 +1,6 @@ package org.apache.maven.errors; +import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.resolver.ArtifactResolutionException; import org.apache.maven.artifact.resolver.ArtifactNotFoundException; import org.apache.maven.artifact.resolver.ArtifactResolutionResult; @@ -22,6 +23,7 @@ import org.apache.maven.model.Plugin; import org.apache.maven.extension.ExtensionScanningException; import org.apache.maven.extension.DefaultBuildExtensionScanner; import org.apache.maven.project.artifact.InvalidDependencyVersionException; +import org.apache.maven.project.ProjectBuilderConfiguration; import org.apache.maven.project.interpolation.ModelInterpolator; import org.apache.maven.project.interpolation.ModelInterpolationException; import org.apache.maven.extension.ExtensionManagerException; @@ -32,18 +34,17 @@ import org.apache.maven.plugin.version.DefaultPluginVersionManager; import org.apache.maven.realm.RealmManagementException; import org.apache.maven.execution.RuntimeInformation; import org.apache.maven.artifact.metadata.ArtifactMetadataSource; -import org.apache.maven.artifact.versioning.VersionRange; import java.io.File; +import java.util.HashMap; import java.util.List; -import java.util.Map; public privileged aspect ExtensionErrorReporterAspect extends AbstractCoreReporterAspect { before( ProjectBuildingException cause ): - withincode( List DefaultBuildExtensionScanner.getInitialRemoteRepositories() ) + withincode( List DefaultBuildExtensionScanner.getInitialRemoteRepositories( ProjectBuilderConfiguration ) ) && call( ExtensionScanningException.new( String, ProjectBuildingException ) ) && args( *, cause ) { @@ -54,14 +55,14 @@ public privileged aspect ExtensionErrorReporterAspect execution( void DefaultBuildExtensionScanner.scanInternal( File, MavenExecutionRequest, .. ) ) && args( pomFile, request, .. ); - after( File pomFile, MavenExecutionRequest request, Model model, Map inheritedValues ) + after( File pomFile, MavenExecutionRequest request, Model model, ProjectBuilderConfiguration config ) throwing( ModelInterpolationException cause ): cflow( dbes_scanInternal( pomFile, request ) ) && within( DefaultBuildExtensionScanner ) - && call( Model ModelInterpolator+.interpolate( Model, Map, .. ) ) - && args( model, inheritedValues, .. ) + && call( Model ModelInterpolator+.interpolate( Model, File, ProjectBuilderConfiguration, .. ) ) + && args( model, *, config, .. ) { - getReporter().reportErrorInterpolatingModel( model, inheritedValues, pomFile, request, cause ); + getReporter().reportErrorInterpolatingModel( model, new HashMap( config.getExecutionProperties() ), pomFile, request, cause ); } private pointcut dem_addExtension( Artifact extensionArtifact, Artifact projectArtifact, List remoteRepos, MavenExecutionRequest request ): diff --git a/maven-core/src/main/java/org/apache/maven/extension/DefaultBuildExtensionScanner.java b/maven-core/src/main/java/org/apache/maven/extension/DefaultBuildExtensionScanner.java index 2bb2ffbf7b..9750aee844 100644 --- a/maven-core/src/main/java/org/apache/maven/extension/DefaultBuildExtensionScanner.java +++ b/maven-core/src/main/java/org/apache/maven/extension/DefaultBuildExtensionScanner.java @@ -20,6 +20,7 @@ */ import org.apache.maven.artifact.ArtifactUtils; +import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.model.Build; import org.apache.maven.model.Extension; @@ -157,12 +158,25 @@ private void scanInternal( File pom, String key = createKey( model ); - if ( inheritedInterpolationValues == null ) + ProjectBuilderConfiguration config = request.getProjectBuildingConfiguration(); + Properties execProps = new Properties(); + if ( config.getExecutionProperties() != null ) + { + execProps.putAll( config.getExecutionProperties() ); + } + + if ( inheritedInterpolationValues != null ) + { + execProps.putAll( inheritedInterpolationValues ); + } + else { inheritedInterpolationValues = new HashMap(); } - model = modelInterpolator.interpolate( model, modelPom.getParentFile(), request.getProjectBuildingConfiguration(), getLogger().isDebugEnabled() ); + config.setExecutionProperties( execProps ); + + model = modelInterpolator.interpolate( model, modelPom.getParentFile(), config, getLogger().isDebugEnabled() ); grabManagedPluginsWithExtensionsFlagTurnedOn( model, managedPluginsWithExtensionsFlag ); @@ -437,7 +451,7 @@ private ModelLineage buildModelLineage( File pom, ProjectBuilderConfiguration co return lineage; } - private List getInitialRemoteRepositories( ProjectBuilderConfiguration config ) + private List getInitialRemoteRepositories( ProjectBuilderConfiguration config ) throws ExtensionScanningException { if ( basicSuperProject == null ) diff --git a/maven-core/src/main/java/org/apache/maven/extension/DefaultExtensionManager.java b/maven-core/src/main/java/org/apache/maven/extension/DefaultExtensionManager.java index 3471968074..9e606c3957 100644 --- a/maven-core/src/main/java/org/apache/maven/extension/DefaultExtensionManager.java +++ b/maven-core/src/main/java/org/apache/maven/extension/DefaultExtensionManager.java @@ -34,9 +34,6 @@ import org.apache.maven.artifact.resolver.ArtifactResolutionResult; import org.apache.maven.artifact.resolver.ArtifactResolver; import org.apache.maven.artifact.resolver.filter.ArtifactFilter; -import org.apache.maven.artifact.versioning.DefaultArtifactVersion; -import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; -import org.apache.maven.artifact.versioning.VersionRange; import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.execution.MavenSession; import org.apache.maven.model.Extension; @@ -294,7 +291,7 @@ public void addExtension( Extension extension, private void addExtension( Artifact extensionArtifact, Artifact projectArtifact, - List remoteRepositories, + List remoteRepositories, MavenExecutionRequest request, ActiveArtifactResolver activeArtifactResolver, String projectGroupId, @@ -331,7 +328,7 @@ private void addExtension( Artifact extensionArtifact, extensionArtifact.getId() + "': " + e.getMessage(), extensionArtifact, projectGroupId, projectArtifactId, projectVersion, e ); } - Set dependencies = new LinkedHashSet(); + Set dependencies = new LinkedHashSet(); dependencies.add( extensionArtifact ); dependencies.addAll( resolutionGroup.getArtifacts() ); @@ -438,54 +435,4 @@ public boolean include( Artifact artifact ) return projectDependencyConflictId.equals( depConflictId ) || passThroughFilter.include( artifact ); } } - - public static void checkPlexusUtils( ResolutionGroup resolutionGroup, ArtifactFactory artifactFactory ) - { - // ---------------------------------------------------------------------------- - // If the plugin already declares a dependency on plexus-utils then we're all - // set as the plugin author is aware of its use. If we don't have a dependency - // on plexus-utils then we must protect users from stupid plugin authors who - // did not declare a direct dependency on plexus-utils because the version - // Maven uses is hidden from downstream use. We will also bump up any - // anything below 1.1 to 1.1 as this mimics the behaviour in 2.0.5 where - // plexus-utils 1.1 was being forced into use. - // ---------------------------------------------------------------------------- - - VersionRange vr = null; - - try - { - vr = VersionRange.createFromVersionSpec( "[1.1,)" ); - } - catch ( InvalidVersionSpecificationException e ) - { - // Won't happen - } - - boolean plexusUtilsPresent = false; - - for ( Iterator i = resolutionGroup.getArtifacts().iterator(); i.hasNext(); ) - { - Artifact a = (Artifact) i.next(); - - if ( a.getArtifactId().equals( "plexus-utils" ) && - vr.containsVersion( new DefaultArtifactVersion( a.getVersion() ) ) ) - { - plexusUtilsPresent = true; - - break; - } - } - - if ( !plexusUtilsPresent ) - { - // We will add plexus-utils as every plugin was getting this anyway from Maven itself. We will set the - // version to the latest version we know that works as of the 2.0.6 release. We set the scope to runtime - // as this is what's implicitly happening in 2.0.6. - - resolutionGroup.getArtifacts().add( artifactFactory.createArtifact( "org.codehaus.plexus", - "plexus-utils", "1.1", - Artifact.SCOPE_RUNTIME, "jar" ) ); - } - } } diff --git a/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginManager.java b/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginManager.java index 70d514c5da..7c1f567004 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginManager.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginManager.java @@ -58,6 +58,7 @@ import org.apache.maven.project.ProjectBuildingException; import org.apache.maven.project.artifact.InvalidDependencyVersionException; import org.apache.maven.project.artifact.MavenMetadataSource; +import org.apache.maven.project.interpolation.ModelInterpolationException; import org.apache.maven.project.path.PathTranslator; import org.apache.maven.realm.MavenRealmManager; import org.apache.maven.realm.RealmManagementException; @@ -269,15 +270,17 @@ protected void addPlugin( Plugin plugin, { projectPlugin = plugin; } - else if ( projectPlugin.getVersion() == null || - Artifact.RELEASE_VERSION.equals(projectPlugin.getVersion()) || + else if ( projectPlugin.getVersion() == null || + Artifact.RELEASE_VERSION.equals(projectPlugin.getVersion()) || Artifact.LATEST_VERSION.equals(projectPlugin.getVersion())) { projectPlugin.setVersion( plugin.getVersion() ); } - List artifacts = getPluginArtifacts( pluginArtifact, projectPlugin, project, - session.getLocalRepository() ); + Set artifactSet = getPluginArtifacts( pluginArtifact, projectPlugin, project, session.getLocalRepository() ); + + List artifacts = ( artifactSet == null || artifactSet.isEmpty() ) + ? new ArrayList() : new ArrayList( artifactSet ); getLogger().debug( "Got plugin artifacts:\n\n" + artifacts ); @@ -347,7 +350,7 @@ else if ( projectPlugin.getVersion() == null || } else { - List managedPluginArtifacts = realmManager.getPluginArtifacts( projectPlugin ); + List managedPluginArtifacts = realmManager.getPluginArtifacts( projectPlugin ); if ( ( managedPluginArtifacts == null ) || ( managedPluginArtifacts.isEmpty() && !artifacts.isEmpty() ) ) { @@ -356,14 +359,14 @@ else if ( projectPlugin.getVersion() == null || } } - private List getPluginArtifacts( Artifact pluginArtifact, + private Set getPluginArtifacts( Artifact pluginArtifact, Plugin plugin, MavenProject project, ArtifactRepository localRepository ) throws InvalidPluginException, ArtifactNotFoundException, ArtifactResolutionException { - Set projectPluginDependencies; + Set projectPluginDependencies; try { @@ -417,7 +420,7 @@ private List getPluginArtifacts( Artifact pluginArtifact, // checkPlexusUtils( resolutionGroup, artifactFactory ); - Set dependencies = new LinkedHashSet(); + Set dependencies = new LinkedHashSet(); // resolve the plugin dependencies specified in first: dependencies.addAll( projectPluginDependencies ); @@ -445,16 +448,18 @@ private List getPluginArtifacts( Artifact pluginArtifact, artifactMetadataSource, filter ); - List resolved = new ArrayList( result.getArtifacts() ); + Set resolved = new HashSet(); - for ( Iterator it = resolved.iterator(); it.hasNext(); ) + for ( Iterator it = result.getArtifacts().iterator(); it.hasNext(); ) { - Artifact artifact = (Artifact) it.next(); + Artifact artifact = it.next(); if ( !artifact.equals( pluginArtifact ) ) { artifact = project.replaceWithActiveArtifact( artifact ); } + + resolved.add( artifact ); } getLogger().debug( @@ -502,6 +507,18 @@ public void executeMojo( MavenProject project, getLogger().warn( "Mojo: " + mojoDescriptor.getGoal() + " is deprecated.\n" + mojoDescriptor.getDeprecated() ); } + if ( !project.isConcrete() ) + { + try + { + mavenProjectBuilder.calculateConcreteState( project, session.getProjectBuilderConfiguration() ); + } + catch ( ModelInterpolationException e ) + { + throw new PluginManagerException( mojoDescriptor, project, "Failed to calculate concrete state for project.", e ); + } + } + if ( mojoDescriptor.isDependencyResolutionRequired() != null ) { Collection projects; @@ -674,6 +691,15 @@ public void executeMojo( MavenProject project, Thread.currentThread().setContextClassLoader( oldClassLoader ); } + + try + { + mavenProjectBuilder.restoreDynamicState( project, session.getProjectBuilderConfiguration() ); + } + catch ( ModelInterpolationException e ) + { + throw new PluginManagerException( mojoDescriptor, project, "Failed to restore dynamic state for project.", e ); + } } private Plugin createDummyPlugin( PluginDescriptor pluginDescriptor ) diff --git a/maven-core/src/main/java/org/apache/maven/settings/DefaultMavenSettingsBuilder.java b/maven-core/src/main/java/org/apache/maven/settings/DefaultMavenSettingsBuilder.java index b814bdae63..1b267f8e50 100644 --- a/maven-core/src/main/java/org/apache/maven/settings/DefaultMavenSettingsBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/settings/DefaultMavenSettingsBuilder.java @@ -32,6 +32,8 @@ import org.codehaus.plexus.util.interpolation.RegexBasedInterpolator; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import hidden.org.codehaus.plexus.interpolation.InterpolationException; + import java.io.File; import java.io.IOException; import java.io.Reader; @@ -119,9 +121,19 @@ private Settings interpolate( Settings settings, MavenExecutionRequest request ) interpolator.addValueSource( new EnvarBasedValueSource() ); - serializedSettings = interpolator.interpolate( - serializedSettings, - "settings" ); + try + { + serializedSettings = interpolator.interpolate( + serializedSettings, + "settings" ); + } + catch ( InterpolationException e ) + { + IOException error = new IOException( "Failed to interpolate settings." ); + error.initCause( e ); + + throw error; + } Settings result = new SettingsXpp3Reader().read( new StringReader( serializedSettings ) ); diff --git a/maven-distribution/pom.xml b/maven-distribution/pom.xml index bcd778b65c..581cdfb897 100644 --- a/maven-distribution/pom.xml +++ b/maven-distribution/pom.xml @@ -206,7 +206,7 @@ under the License. maven-assembly-plugin - 2.2-beta-1 + 2.2-beta-2 create-distro @@ -216,7 +216,7 @@ under the License. src/main/assembly/bin.xml - apache-maven-${pom.version} + apache-maven-${project.version} diff --git a/maven-project/src/main/java/org/apache/maven/profiles/activation/FileProfileActivator.java b/maven-project/src/main/java/org/apache/maven/profiles/activation/FileProfileActivator.java index 58960df001..4ef6b583fc 100644 --- a/maven-project/src/main/java/org/apache/maven/profiles/activation/FileProfileActivator.java +++ b/maven-project/src/main/java/org/apache/maven/profiles/activation/FileProfileActivator.java @@ -30,6 +30,8 @@ import org.codehaus.plexus.util.interpolation.MapBasedValueSource; import org.codehaus.plexus.util.interpolation.RegexBasedInterpolator; +import hidden.org.codehaus.plexus.interpolation.InterpolationException; + import java.io.IOException; public class FileProfileActivator @@ -67,7 +69,21 @@ public boolean isActive( Profile profile, ProfileActivationContext context ) if ( StringUtils.isNotEmpty( fileString ) ) { - fileString = StringUtils.replace( interpolator.interpolate( fileString, "" ), "\\", "/" ); + try + { + fileString = StringUtils.replace( interpolator.interpolate( fileString, "" ), "\\", "/" ); + } + catch ( InterpolationException e ) + { + if ( logger.isDebugEnabled() ) + { + logger.debug( "Failed to interpolate exists file location for profile activator: " + fileString, e ); + } + else + { + logger.warn( "Failed to interpolate exists file location for profile activator: " + fileString + ". Run in debug mode (-X) for more information." ); + } + } boolean result = FileUtils.fileExists( fileString ); @@ -84,7 +100,21 @@ public boolean isActive( Profile profile, ProfileActivationContext context ) if ( StringUtils.isNotEmpty( fileString ) ) { - fileString = StringUtils.replace( interpolator.interpolate( fileString, "" ), "\\", "/" ); + try + { + fileString = StringUtils.replace( interpolator.interpolate( fileString, "" ), "\\", "/" ); + } + catch ( InterpolationException e ) + { + if ( logger.isDebugEnabled() ) + { + logger.debug( "Failed to interpolate missing file location for profile activator: " + fileString, e ); + } + else + { + logger.warn( "Failed to interpolate missing file location for profile activator: " + fileString + ". Run in debug mode (-X) for more information." ); + } + } boolean result = !FileUtils.fileExists( fileString ); diff --git a/maven-project/src/main/java/org/apache/maven/project/DefaultMavenProjectBuilder.java b/maven-project/src/main/java/org/apache/maven/project/DefaultMavenProjectBuilder.java index 97e684e953..9f08943edc 100644 --- a/maven-project/src/main/java/org/apache/maven/project/DefaultMavenProjectBuilder.java +++ b/maven-project/src/main/java/org/apache/maven/project/DefaultMavenProjectBuilder.java @@ -45,8 +45,10 @@ import org.apache.maven.model.Extension; import org.apache.maven.model.Model; import org.apache.maven.model.Plugin; +import org.apache.maven.model.PluginManagement; import org.apache.maven.model.ReportPlugin; import org.apache.maven.model.Repository; +import org.apache.maven.model.Resource; import org.apache.maven.model.io.xpp3.MavenXpp3Reader; import org.apache.maven.profiles.MavenProfilesBuilder; import org.apache.maven.profiles.ProfileManager; @@ -317,7 +319,7 @@ public MavenProject buildStandaloneSuperProject( ProjectBuilderConfiguration con // we shouldn't be swallowing exceptions, no matter how unlikely. // or, if we do, we should pay attention to the one coming from getSuperModel()... throw new ProjectBuildingException( STANDALONE_SUPERPOM_GROUPID + ":" - + STANDALONE_SUPERPOM_ARTIFACTID, + + STANDALONE_SUPERPOM_ARTIFACTID, "Maven super-POM contains an invalid repository!", e ); } @@ -326,7 +328,7 @@ public MavenProject buildStandaloneSuperProject( ProjectBuilderConfiguration con // we shouldn't be swallowing exceptions, no matter how unlikely. // or, if we do, we should pay attention to the one coming from getSuperModel()... throw new ProjectBuildingException( STANDALONE_SUPERPOM_GROUPID + ":" - + STANDALONE_SUPERPOM_ARTIFACTID, + + STANDALONE_SUPERPOM_ARTIFACTID, "Maven super-POM contains an invalid expressions!", e ); } @@ -537,8 +539,8 @@ private Model findModelFromRepository( Artifact artifact, else { getLogger().warn( "Attempting to build MavenProject instance for Artifact (" + artifact.getGroupId() + ":" - + artifact.getArtifactId() + ":" + artifact.getVersion() + ") of type: " - + artifact.getType() + "; constructing POM artifact instead." ); + + artifact.getArtifactId() + ":" + artifact.getVersion() + ") of type: " + + artifact.getType() + "; constructing POM artifact instead." ); projectArtifact = artifactFactory.createProjectArtifact( artifact.getGroupId(), artifact.getArtifactId(), @@ -829,9 +831,6 @@ private MavenProject buildInternal( Model model, // the plugin tools compose basedir and scriptSourceRoot into a single file. project.addScriptSourceRoot( build.getScriptSourceDirectory() ); - getLogger().debug( "Aligning project: " + project.getId() + " to base directory: " + projectDescriptor.getParentFile() ); - pathTranslator.alignToBaseDirectory( project.getModel(), projectDescriptor.getParentFile() ); - project.addCompileSourceRoot( build.getSourceDirectory() ); project.addTestCompileSourceRoot( build.getTestSourceDirectory() ); @@ -906,8 +905,8 @@ private void collectInitialRepositoriesFromModel( LinkedHashSet collected, catch ( InvalidRepositoryException e ) { throw new ProjectBuildingException( safeVersionlessKey( model.getGroupId(), model.getArtifactId() ), - "Failed to construct ArtifactRepository instances for repositories declared in: " - + model.getId(), e ); + "Failed to construct ArtifactRepository instances for repositories declared in: " + + model.getId(), e ); } } } @@ -973,8 +972,14 @@ private MavenProject processProjectLogic( MavenProject project, projectDir = pomFile.getAbsoluteFile().getParentFile(); } + Build dynamicBuild = model.getBuild(); + model.setBuild( ModelUtils.cloneBuild( dynamicBuild ) ); + model = modelInterpolator.interpolate( model, projectDir, config, getLogger().isDebugEnabled() ); + mergeDeterministicBuildElements( model.getBuild(), dynamicBuild ); + model.setBuild( dynamicBuild ); + // We must inject any imported dependencyManagement information ahead of the defaults injection. if ( !isSuperPom ) { @@ -1063,6 +1068,510 @@ private MavenProject processProjectLogic( MavenProject project, return project; } + // TODO: Remove this! + @SuppressWarnings("unchecked") + private void mergeDeterministicBuildElements( Build interpolatedBuild, + Build dynamicBuild ) + { + List dPlugins = dynamicBuild.getPlugins(); + + if ( dPlugins != null ) + { + List iPlugins = interpolatedBuild.getPlugins(); + + for ( int i = 0; i < dPlugins.size(); i++ ) + { + Plugin dPlugin = dPlugins.get( i ); + Plugin iPlugin = iPlugins.get( i ); + + dPlugin.setGroupId( iPlugin.getGroupId() ); + dPlugin.setArtifactId( iPlugin.getArtifactId() ); + dPlugin.setVersion( iPlugin.getVersion() ); + } + } + + PluginManagement dPluginMgmt = dynamicBuild.getPluginManagement(); + + if ( dPluginMgmt != null ) + { + PluginManagement iPluginMgmt = interpolatedBuild.getPluginManagement(); + dPlugins = dPluginMgmt.getPlugins(); + if ( dPlugins != null ) + { + List iPlugins = iPluginMgmt.getPlugins(); + + for ( int i = 0; i < dPlugins.size(); i++ ) + { + Plugin dPlugin = dPlugins.get( i ); + Plugin iPlugin = iPlugins.get( i ); + + dPlugin.setGroupId( iPlugin.getGroupId() ); + dPlugin.setArtifactId( iPlugin.getArtifactId() ); + dPlugin.setVersion( iPlugin.getVersion() ); + } + } + } + + if ( dynamicBuild.getExtensions() != null ) + { + dynamicBuild.setExtensions( interpolatedBuild.getExtensions() ); + } + } + + public void calculateConcreteState( MavenProject project, ProjectBuilderConfiguration config ) + throws ModelInterpolationException + { + if ( project.isConcrete() ) + { + return; + } + + Model model = ModelUtils.cloneModel( project.getModel() ); + + File basedir = project.getBasedir(); + + model = modelInterpolator.interpolate( model, basedir, config, getLogger().isDebugEnabled() ); + + List originalInterpolatedCompileSourceRoots = interpolateListOfStrings( project.getCompileSourceRoots(), + model, + project.getBasedir(), + config ); + + project.preserveCompileSourceRoots( originalInterpolatedCompileSourceRoots ); + + project.setCompileSourceRoots( originalInterpolatedCompileSourceRoots == null ? null + : translateListOfPaths( originalInterpolatedCompileSourceRoots, basedir ) ); + + List originalInterpolatedTestCompileSourceRoots = interpolateListOfStrings( project.getTestCompileSourceRoots(), + model, + project.getBasedir(), + config ); + + project.preserveTestCompileSourceRoots( originalInterpolatedTestCompileSourceRoots ); + project.setTestCompileSourceRoots( originalInterpolatedTestCompileSourceRoots == null ? null + : translateListOfPaths( originalInterpolatedTestCompileSourceRoots, basedir ) ); + + List originalInterpolatedScriptSourceRoots = interpolateListOfStrings( project.getScriptSourceRoots(), + model, + project.getBasedir(), + config ); + + project.preserveScriptSourceRoots( originalInterpolatedScriptSourceRoots ); + project.setScriptSourceRoots( originalInterpolatedScriptSourceRoots == null ? null + : translateListOfPaths( originalInterpolatedScriptSourceRoots, basedir ) ); + + Model model2 = ModelUtils.cloneModel( model ); + + pathTranslator.alignToBaseDirectory( model, basedir ); + + project.preserveBuild( model2.getBuild() ); + project.setBuild( model.getBuild() ); + + calculateConcreteProjectReferences( project, config ); + + MavenProject executionProject = project.getExecutionProject(); + if ( executionProject != null && executionProject != project ) + { + calculateConcreteState( executionProject, config ); + } + + project.setConcrete( true ); + } + + private void calculateConcreteProjectReferences( MavenProject project, + ProjectBuilderConfiguration config ) + throws ModelInterpolationException + { + Map projectRefs = project.getProjectReferences(); + + if ( projectRefs != null ) + { + for ( Iterator it = projectRefs.values().iterator(); it.hasNext(); ) + { + MavenProject reference = (MavenProject) it.next(); + calculateConcreteState( reference, config ); + } + } + } + + private List translateListOfPaths( List paths, File basedir ) + { + if ( paths == null ) + { + return null; + } + else if ( basedir == null ) + { + return paths; + } + + List result = new ArrayList( paths.size() ); + for ( Iterator it = paths.iterator(); it.hasNext(); ) + { + String path = (String) it.next(); + + String aligned = pathTranslator.alignToBaseDirectory( path, basedir ); + + result.add( aligned ); + } + + return result; + } + + public void restoreDynamicState( MavenProject project, ProjectBuilderConfiguration config ) + throws ModelInterpolationException + { + if ( !project.isConcrete() ) + { + return; + } + + restoreBuildRoots( project, config ); + restoreModelBuildSection( project, config ); + + restoreDynamicProjectReferences( project, config ); + + MavenProject executionProject = project.getExecutionProject(); + if ( executionProject != null && executionProject != project ) + { + restoreDynamicState( executionProject, config ); + } + + project.setConcrete( false ); + } + + private void restoreDynamicProjectReferences( MavenProject project, + ProjectBuilderConfiguration config ) + throws ModelInterpolationException + { + Map projectRefs = project.getProjectReferences(); + if ( projectRefs != null ) + { + for ( Iterator it = projectRefs.values().iterator(); it.hasNext(); ) + { + MavenProject projectRef = (MavenProject) it.next(); + restoreDynamicState( projectRef, config ); + } + } + } + + private void restoreBuildRoots( MavenProject project, + ProjectBuilderConfiguration config ) + throws ModelInterpolationException + { + project.setCompileSourceRoots( restoreListOfStrings( project.getDynamicCompileSourceRoots(), + project.getOriginalInterpolatedCompileSourceRoots(), + project.getCompileSourceRoots(), + project, + config ) ); + + project.setTestCompileSourceRoots( restoreListOfStrings( project.getDynamicTestCompileSourceRoots(), + project.getOriginalInterpolatedTestCompileSourceRoots(), + project.getTestCompileSourceRoots(), + project, + config ) ); + + project.setScriptSourceRoots( restoreListOfStrings( project.getDynamicScriptSourceRoots(), + project.getOriginalInterpolatedScriptSourceRoots(), + project.getScriptSourceRoots(), + project, + config ) ); + + project.clearRestorableRoots(); + } + + private void restoreModelBuildSection( MavenProject project, + ProjectBuilderConfiguration config ) + throws ModelInterpolationException + { + Build changedBuild = project.getBuild(); + Build dynamicBuild = project.getDynamicBuild(); + Build originalInterpolatedBuild = project.getOriginalInterpolatedBuild(); + + dynamicBuild.setResources( restoreResources( dynamicBuild.getResources(), + originalInterpolatedBuild.getResources(), + changedBuild.getResources(), + project, + config ) ); + + dynamicBuild.setTestResources( restoreResources( dynamicBuild.getTestResources(), + originalInterpolatedBuild.getTestResources(), + changedBuild.getTestResources(), + project, + config ) ); + + dynamicBuild.setFilters( restoreListOfStrings( dynamicBuild.getFilters(), + originalInterpolatedBuild.getFilters(), + changedBuild.getFilters(), + project, + config ) ); + + dynamicBuild.setFinalName( restoreString( dynamicBuild.getFinalName(), + originalInterpolatedBuild.getFinalName(), + changedBuild.getFinalName(), + project, + config ) ); + + dynamicBuild.setDefaultGoal( restoreString( dynamicBuild.getDefaultGoal(), + originalInterpolatedBuild.getDefaultGoal(), + changedBuild.getDefaultGoal(), + project, + config ) ); + + dynamicBuild.setSourceDirectory( restoreString( dynamicBuild.getSourceDirectory(), + originalInterpolatedBuild.getSourceDirectory(), + changedBuild.getSourceDirectory(), + project, + config ) ); + + dynamicBuild.setTestSourceDirectory( restoreString( dynamicBuild.getTestSourceDirectory(), + originalInterpolatedBuild.getTestSourceDirectory(), + changedBuild.getTestSourceDirectory(), + project, + config ) ); + + dynamicBuild.setScriptSourceDirectory( restoreString( dynamicBuild.getScriptSourceDirectory(), + originalInterpolatedBuild.getScriptSourceDirectory(), + changedBuild.getScriptSourceDirectory(), + project, + config ) ); + + dynamicBuild.setOutputDirectory( restoreString( dynamicBuild.getOutputDirectory(), + originalInterpolatedBuild.getOutputDirectory(), + changedBuild.getOutputDirectory(), + project, + config ) ); + + dynamicBuild.setTestOutputDirectory( restoreString( dynamicBuild.getTestOutputDirectory(), + originalInterpolatedBuild.getTestOutputDirectory(), + changedBuild.getTestOutputDirectory(), + project, + config ) ); + + dynamicBuild.setDirectory( restoreString( dynamicBuild.getDirectory(), + originalInterpolatedBuild.getDirectory(), + changedBuild.getDirectory(), + project, + config ) ); + + project.setBuild( dynamicBuild ); + + project.clearRestorableBuild(); + } + + private List interpolateListOfStrings( List originalStrings, + Model model, + File projectDir, + ProjectBuilderConfiguration config ) + throws ModelInterpolationException + { + if ( originalStrings == null ) + { + return null; + } + + List result = new ArrayList(); + + for ( Iterator it = originalStrings.iterator(); it.hasNext(); ) + { + String original = (String) it.next(); + String interpolated = modelInterpolator.interpolate( original, model, projectDir, config, getLogger().isDebugEnabled() ); + + result.add( interpolated ); + } + + return result; + } + + private String restoreString( String originalString, + String originalInterpolatedString, + String changedString, + MavenProject project, + ProjectBuilderConfiguration config ) + throws ModelInterpolationException + { + if ( originalString == null ) + { + return changedString; + } + else if ( changedString == null ) + { + return originalString; + } + + Model model = project.getModel(); + + String relativeChangedString; + if ( project.getBasedir() != null ) + { + relativeChangedString = pathTranslator.unalignFromBaseDirectory( changedString, project.getBasedir() ); + } + else + { + relativeChangedString = changedString; + } + + String interpolatedOriginal = modelInterpolator.interpolate( originalString, model, project.getBasedir(), config, getLogger().isDebugEnabled() ); + String interpolatedOriginal2 = modelInterpolator.interpolate( originalInterpolatedString, + model, + project.getBasedir(), config, getLogger().isDebugEnabled() ); + + String interpolatedChanged = modelInterpolator.interpolate( changedString, model, project.getBasedir(), config, getLogger().isDebugEnabled() ); + String relativeInterpolatedChanged = modelInterpolator.interpolate( relativeChangedString, model, project.getBasedir(), config, getLogger().isDebugEnabled() ); + + if ( interpolatedOriginal.equals( interpolatedChanged ) + || interpolatedOriginal2.equals( interpolatedChanged ) ) + { + return originalString; + } + else if ( interpolatedOriginal.equals( relativeInterpolatedChanged ) + || interpolatedOriginal2.equals( relativeInterpolatedChanged ) ) + { + return originalString; + } + + return relativeChangedString; + } + + private List restoreListOfStrings( List originalStrings, + List originalInterpolatedStrings, + List changedStrings, + MavenProject project, + ProjectBuilderConfiguration config ) + throws ModelInterpolationException + { + if ( originalStrings == null ) + { + return changedStrings; + } + else if ( changedStrings == null ) + { + return originalStrings; + } + + List result = new ArrayList(); + + Map orig = new HashMap(); + for ( int idx = 0; idx < originalStrings.size(); idx++ ) + { + String[] permutations = new String[2]; + + permutations[0] = (String) originalInterpolatedStrings.get( idx ); + permutations[1] = (String) originalStrings.get( idx ); + + orig.put( permutations[0], permutations ); + } + + for ( Iterator it = changedStrings.iterator(); it.hasNext(); ) + { + String changedString = (String) it.next(); + String relativeChangedString; + if ( project.getBasedir() != null ) + { + relativeChangedString = pathTranslator.unalignFromBaseDirectory( changedString, project.getBasedir() ); + } + else + { + relativeChangedString = changedString; + } + + String interpolated = modelInterpolator.interpolate( changedString, + project.getModel(), + project.getBasedir(), + config, + getLogger().isDebugEnabled() ); + + String relativeInterpolated = modelInterpolator.interpolate( relativeChangedString, + project.getModel(), + project.getBasedir(), + config, + getLogger().isDebugEnabled() ); + + String[] original = (String[]) orig.get( interpolated ); + if ( original == null ) + { + original = (String[]) orig.get( relativeInterpolated ); + } + + if ( original == null ) + { + result.add( relativeChangedString ); + } + else + { + result.add( original[1] ); + } + } + + return result; + } + + private List restoreResources( List originalResources, + List originalInterpolatedResources, + List changedResources, + MavenProject project, + ProjectBuilderConfiguration config ) + throws ModelInterpolationException + { + if ( originalResources == null || changedResources == null ) + { + return originalResources; + } + + List result = new ArrayList(); + + Map orig = new HashMap(); + for ( int idx = 0; idx < originalResources.size(); idx++ ) + { + Resource[] permutations = new Resource[2]; + + permutations[0] = (Resource) originalInterpolatedResources.get( idx ); + permutations[1] = (Resource) originalResources.get( idx ); + + orig.put( permutations[0].getDirectory(), permutations ); + } + + for ( Iterator it = changedResources.iterator(); it.hasNext(); ) + { + Resource resource = (Resource) it.next(); + String rDir = modelInterpolator.interpolate( resource.getDirectory(), project.getModel(), project.getBasedir(), config, getLogger().isDebugEnabled() ); + + String relativeDir; + if ( project.getBasedir() != null ) + { + relativeDir = pathTranslator.unalignFromBaseDirectory( resource.getDirectory(), + project.getBasedir() ); + } + else + { + relativeDir = resource.getDirectory(); + } + + String relativeRDir = modelInterpolator.interpolate( relativeDir, project.getModel(), project.getBasedir(), config, getLogger().isDebugEnabled() ); + + Resource[] original = (Resource[]) orig.get( rDir ); + if ( original == null ) + { + original = (Resource[]) orig.get( relativeRDir ); + } + + if ( original == null ) + { + result.add( resource ); + } + else + { + // TODO: Synchronize all non-directory fields, such as targetPath, includes, and excludes. +// String target = interpolator.interpolate( resource.getTargetPath(), model, context ); +// String oTarget = interpolator.interpolate( originalResource.getTargetPath(), model, context ); + + result.add( original[1] ); + } + } + + return result; + } + private void validateModel( Model model, File pomFile ) throws InvalidProjectModelException diff --git a/maven-project/src/main/java/org/apache/maven/project/MavenProject.java b/maven-project/src/main/java/org/apache/maven/project/MavenProject.java index c29de8e16e..cb95d52355 100644 --- a/maven-project/src/main/java/org/apache/maven/project/MavenProject.java +++ b/maven-project/src/main/java/org/apache/maven/project/MavenProject.java @@ -98,9 +98,9 @@ public class MavenProject private Artifact parentArtifact; - private Set pluginArtifacts; + private Set pluginArtifacts; - private List remoteArtifactRepositories; + private List remoteArtifactRepositories; private List collectedProjects = Collections.EMPTY_LIST; @@ -172,6 +172,7 @@ public MavenProject( Model model ) /** * @deprecated use {@link #clone()} so subclasses can provide a copy of the same class */ + @Deprecated public MavenProject( MavenProject project ) { deepCopy( project ); @@ -282,6 +283,38 @@ private final void deepCopy(MavenProject project){ { setSnapshotArtifactRepository( project.getSnapshotArtifactRepository() ); } + + if ( project.isConcrete() ) + { + setDynamicBuild( ModelUtils.cloneBuild( project.getDynamicBuild() ) ); + setOriginalInterpolatedBuild( ModelUtils.cloneBuild( project.getOriginalInterpolatedBuild() ) ); + + List dynamicRoots = project.getDynamicCompileSourceRoots(); + if ( dynamicRoots != null ) + { + setDynamicCompileSourceRoots( new ArrayList( dynamicRoots ) ); + setOriginalInterpolatedCompileSourceRoots( new ArrayList( + project.getOriginalInterpolatedCompileSourceRoots() ) ); + } + + dynamicRoots = project.getDynamicTestCompileSourceRoots(); + if ( dynamicRoots != null ) + { + setDynamicTestCompileSourceRoots( new ArrayList( dynamicRoots ) ); + setOriginalInterpolatedTestCompileSourceRoots( new ArrayList( + project.getOriginalInterpolatedTestCompileSourceRoots() ) ); + } + + dynamicRoots = project.getDynamicScriptSourceRoots(); + if ( dynamicRoots != null ) + { + setDynamicScriptSourceRoots( new ArrayList( dynamicRoots ) ); + setOriginalInterpolatedScriptSourceRoots( new ArrayList( + project.getOriginalInterpolatedScriptSourceRoots() ) ); + } + } + + setConcrete( project.isConcrete() ); } // TODO: Find a way to use here...it's tricky, because the moduleProject @@ -376,7 +409,7 @@ public void setRemoteArtifactRepositories( List remoteArtifactRepositories ) this.remoteArtifactRepositories = remoteArtifactRepositories; } - public List getRemoteArtifactRepositories() + public List getRemoteArtifactRepositories() { return remoteArtifactRepositories; } @@ -1537,6 +1570,7 @@ public Map getManagedVersionMap() return managedVersionMap; } + @Override public boolean equals( Object other ) { if ( other == this ) @@ -1555,6 +1589,7 @@ else if ( !( other instanceof MavenProject ) ) } } + @Override public int hashCode() { return getId().hashCode(); @@ -1598,6 +1633,7 @@ private static String getProjectReferenceId( String groupId, String artifactId, /** * @deprecated Use MavenProjectHelper.attachArtifact(..) instead. */ + @Deprecated public void attachArtifact( String type, String classifier, File file ) { } @@ -1807,6 +1843,7 @@ public Plugin getPlugin( String pluginKey ) /** * Default toString */ + @Override public String toString() { StringBuffer sb = new StringBuffer(30); @@ -1834,6 +1871,7 @@ public String toString() * @throws CloneNotSupportedException * @since 2.0.9 */ + @Override public Object clone() throws CloneNotSupportedException { @@ -1842,4 +1880,159 @@ public Object clone() return clone; } +// ---------------------------------------------------------------------------- +// CODE BELOW IS USED TO PRESERVE DYNAMISM IN THE BUILD SECTION OF THE POM. +// ---------------------------------------------------------------------------- + + private Build dynamicBuild; + + private Build originalInterpolatedBuild; + + private List dynamicCompileSourceRoots; + + private List originalInterpolatedCompileSourceRoots; + + private List dynamicTestCompileSourceRoots; + + private List originalInterpolatedTestCompileSourceRoots; + + private List dynamicScriptSourceRoots; + + private List originalInterpolatedScriptSourceRoots; + + private boolean isConcrete = false; + + public boolean isConcrete() + { + return isConcrete; + } + + public void setConcrete( boolean concrete ) + { + isConcrete = concrete; + } + + public Build getDynamicBuild() + { + return dynamicBuild; + } + + public Build getOriginalInterpolatedBuild() + { + return originalInterpolatedBuild; + } + + public List getDynamicCompileSourceRoots() + { + return dynamicCompileSourceRoots; + } + + public List getOriginalInterpolatedCompileSourceRoots() + { + return originalInterpolatedCompileSourceRoots; + } + + public List getDynamicTestCompileSourceRoots() + { + return dynamicTestCompileSourceRoots; + } + + public List getOriginalInterpolatedTestCompileSourceRoots() + { + return originalInterpolatedTestCompileSourceRoots; + } + + public List getDynamicScriptSourceRoots() + { + return dynamicScriptSourceRoots; + } + + public List getOriginalInterpolatedScriptSourceRoots() + { + return originalInterpolatedScriptSourceRoots; + } + + public void clearRestorableRoots() + { + dynamicCompileSourceRoots = null; + dynamicTestCompileSourceRoots = null; + dynamicScriptSourceRoots = null; + originalInterpolatedCompileSourceRoots = null; + originalInterpolatedScriptSourceRoots = null; + originalInterpolatedTestCompileSourceRoots = null; + } + + public void clearRestorableBuild() + { + dynamicBuild = null; + originalInterpolatedBuild = null; + } + + public void preserveCompileSourceRoots( List originalInterpolatedCompileSourceRoots ) + { + dynamicCompileSourceRoots = getCompileSourceRoots(); + this.originalInterpolatedCompileSourceRoots = originalInterpolatedCompileSourceRoots; + } + + public void preserveTestCompileSourceRoots( List originalInterpolatedTestCompileSourceRoots ) + { + dynamicTestCompileSourceRoots = getTestCompileSourceRoots(); + this.originalInterpolatedTestCompileSourceRoots = originalInterpolatedTestCompileSourceRoots; + } + + public void preserveScriptSourceRoots( List originalInterpolatedScriptSourceRoots ) + { + dynamicScriptSourceRoots = getScriptSourceRoots(); + this.originalInterpolatedScriptSourceRoots = originalInterpolatedScriptSourceRoots; + } + + public void preserveBuild( Build originalInterpolatedBuild ) + { + dynamicBuild = getBuild(); + this.originalInterpolatedBuild = originalInterpolatedBuild; + + this.originalInterpolatedBuild.setPluginManagement( null ); + this.originalInterpolatedBuild.setPlugins( null ); + } + + protected void setDynamicBuild( Build dynamicBuild ) + { + this.dynamicBuild = dynamicBuild; + } + + protected void setOriginalInterpolatedBuild( Build originalInterpolatedBuild ) + { + this.originalInterpolatedBuild = originalInterpolatedBuild; + } + + protected void setDynamicCompileSourceRoots( List dynamicCompileSourceRoots ) + { + this.dynamicCompileSourceRoots = dynamicCompileSourceRoots; + } + + protected void setOriginalInterpolatedCompileSourceRoots( List originalInterpolatedCompileSourceRoots ) + { + this.originalInterpolatedCompileSourceRoots = originalInterpolatedCompileSourceRoots; + } + + protected void setDynamicTestCompileSourceRoots( List dynamicTestCompileSourceRoots ) + { + this.dynamicTestCompileSourceRoots = dynamicTestCompileSourceRoots; + } + + protected void setOriginalInterpolatedTestCompileSourceRoots( List originalInterpolatedTestCompileSourceRoots ) + { + this.originalInterpolatedTestCompileSourceRoots = originalInterpolatedTestCompileSourceRoots; + } + + protected void setDynamicScriptSourceRoots( List dynamicScriptSourceRoots ) + { + this.dynamicScriptSourceRoots = dynamicScriptSourceRoots; + } + + protected void setOriginalInterpolatedScriptSourceRoots( List originalInterpolatedScriptSourceRoots ) + { + this.originalInterpolatedScriptSourceRoots = originalInterpolatedScriptSourceRoots; + } + } diff --git a/maven-project/src/main/java/org/apache/maven/project/MavenProjectBuilder.java b/maven-project/src/main/java/org/apache/maven/project/MavenProjectBuilder.java index e2195b8375..f65963901c 100644 --- a/maven-project/src/main/java/org/apache/maven/project/MavenProjectBuilder.java +++ b/maven-project/src/main/java/org/apache/maven/project/MavenProjectBuilder.java @@ -22,6 +22,7 @@ import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.profiles.ProfileManager; +import org.apache.maven.project.interpolation.ModelInterpolationException; import java.io.File; import java.util.List; @@ -41,6 +42,7 @@ public interface MavenProjectBuilder /** * @deprecated Use {@link MavenProjectBuilder#build(File, ProjectBuilderConfiguration)} instead. */ + @Deprecated MavenProject build( File project, ArtifactRepository localRepository, ProfileManager globalProfileManager ) @@ -62,6 +64,7 @@ MavenProjectBuildingResult buildProjectWithDependencies( File project, /** * @deprecated Use {@link MavenProjectBuilder#buildProjectWithDependencies(File, ProjectBuilderConfiguration)} instead. */ + @Deprecated MavenProjectBuildingResult buildProjectWithDependencies( File project, ArtifactRepository localRepository, ProfileManager globalProfileManager ) @@ -74,6 +77,7 @@ MavenProject buildFromRepository( Artifact artifact, throws ProjectBuildingException; /** @deprecated We do not want to allow projects to not have POMs. Maven 1.x repositories be damned. */ + @Deprecated MavenProject buildFromRepository( Artifact artifact, List remoteArtifactRepositories, ArtifactRepository localRepository, @@ -83,15 +87,29 @@ MavenProject buildFromRepository( Artifact artifact, /** * @deprecated Use {@link MavenProjectBuilder#buildStandaloneSuperProject(ProjectBuilderConfiguration)} instead. */ + @Deprecated MavenProject buildStandaloneSuperProject() throws ProjectBuildingException; /** * @deprecated Use {@link MavenProjectBuilder#buildStandaloneSuperProject(ProjectBuilderConfiguration)} instead. */ + @Deprecated MavenProject buildStandaloneSuperProject( ProfileManager profileManager ) throws ProjectBuildingException; MavenProject buildStandaloneSuperProject( ProjectBuilderConfiguration config ) throws ProjectBuildingException; + + // ---------------------------------------------------------------------------- + // API BELOW IS USED TO PRESERVE DYNAMISM IN THE BUILD SECTION OF THE POM. + // ---------------------------------------------------------------------------- + + void calculateConcreteState( MavenProject project, + ProjectBuilderConfiguration config ) + throws ModelInterpolationException; + + void restoreDynamicState( MavenProject project, + ProjectBuilderConfiguration config ) + throws ModelInterpolationException; } diff --git a/maven-project/src/main/java/org/apache/maven/project/ModelUtils.java b/maven-project/src/main/java/org/apache/maven/project/ModelUtils.java index d8d07c43cc..ba61f9ac5b 100644 --- a/maven-project/src/main/java/org/apache/maven/project/ModelUtils.java +++ b/maven-project/src/main/java/org/apache/maven/project/ModelUtils.java @@ -581,6 +581,17 @@ public static Model cloneModel( Model model ) return newModel; } + public static Build cloneBuild( Build build ) + { + ModelInheritanceAssembler assembler = new DefaultModelInheritanceAssembler(); + + Build clone = new Build(); + + assembler.assembleBuildInheritance( clone, build ); + + return clone; + } + private static List cloneProfiles( List profiles ) { if ( profiles == null ) diff --git a/maven-project/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java b/maven-project/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java index b5d402a38a..4baa016cf3 100644 --- a/maven-project/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java +++ b/maven-project/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java @@ -363,15 +363,15 @@ private List aggregateRepositoryLists( List remoteRepositories, List remoteArtif * @todo desperately needs refactoring. It's just here because it's implementation is maven-project specific * @return {@link Set} < {@link Artifact} > */ - public static Set createArtifacts( ArtifactFactory artifactFactory, List dependencies, String inheritedScope, + public static Set createArtifacts( ArtifactFactory artifactFactory, List dependencies, String inheritedScope, ArtifactFilter dependencyFilter, MavenProject project ) throws InvalidDependencyVersionException { - Set projectArtifacts = new LinkedHashSet( dependencies.size() ); + Set projectArtifacts = new LinkedHashSet( dependencies.size() ); - for ( Iterator i = dependencies.iterator(); i.hasNext(); ) + for ( Iterator i = dependencies.iterator(); i.hasNext(); ) { - Dependency d = (Dependency) i.next(); + Dependency d = i.next(); String scope = d.getScope(); @@ -406,10 +406,10 @@ public static Set createArtifacts( ArtifactFactory artifactFactory, List depende { if ( ( d.getExclusions() != null ) && !d.getExclusions().isEmpty() ) { - List exclusions = new ArrayList(); - for ( Iterator j = d.getExclusions().iterator(); j.hasNext(); ) + List exclusions = new ArrayList(); + for ( Iterator j = d.getExclusions().iterator(); j.hasNext(); ) { - Exclusion e = (Exclusion) j.next(); + Exclusion e = j.next(); exclusions.add( e.getGroupId() + ":" + e.getArtifactId() ); } diff --git a/maven-project/src/main/java/org/apache/maven/project/inheritance/DefaultModelInheritanceAssembler.java b/maven-project/src/main/java/org/apache/maven/project/inheritance/DefaultModelInheritanceAssembler.java index a0c1620cf9..b879a2f5a8 100644 --- a/maven-project/src/main/java/org/apache/maven/project/inheritance/DefaultModelInheritanceAssembler.java +++ b/maven-project/src/main/java/org/apache/maven/project/inheritance/DefaultModelInheritanceAssembler.java @@ -27,6 +27,7 @@ import org.apache.maven.model.Model; import org.apache.maven.model.PluginManagement; import org.apache.maven.model.Reporting; +import org.apache.maven.model.Resource; import org.apache.maven.model.Scm; import org.apache.maven.model.Site; import org.apache.maven.project.ModelUtils; @@ -184,6 +185,8 @@ private void assembleModelInheritance( Model child, Model parent, String childPa child.setProperties( props ); } + // TODO: Remove this! + @SuppressWarnings("unchecked") private void assembleDependencyManagementInheritance( Model child, Model parent ) { DependencyManagement parentDepMgmt = parent.getDependencyManagement(); @@ -198,18 +201,18 @@ private void assembleDependencyManagementInheritance( Model child, Model parent } else { - List childDeps = childDepMgmt.getDependencies(); + List childDeps = childDepMgmt.getDependencies(); - Map mappedChildDeps = new TreeMap(); - for ( Iterator it = childDeps.iterator(); it.hasNext(); ) + Map mappedChildDeps = new TreeMap(); + for ( Iterator it = childDeps.iterator(); it.hasNext(); ) { - Dependency dep = (Dependency) it.next(); + Dependency dep = it.next(); mappedChildDeps.put( dep.getManagementKey(), dep ); } - for ( Iterator it = parentDepMgmt.getDependencies().iterator(); it.hasNext(); ) + for ( Iterator it = parentDepMgmt.getDependencies().iterator(); it.hasNext(); ) { - Dependency dep = (Dependency) it.next(); + Dependency dep = it.next(); if ( !mappedChildDeps.containsKey( dep.getManagementKey() ) ) { childDepMgmt.addDependency( dep ); @@ -244,17 +247,19 @@ private void assembleReportingInheritance( Model child, Model parent ) } } + // TODO: Remove this! + @SuppressWarnings("unchecked") private void assembleDependencyInheritance( Model child, Model parent ) { - Map depsMap = new LinkedHashMap(); + Map depsMap = new LinkedHashMap(); - List deps = parent.getDependencies(); + List deps = parent.getDependencies(); if ( deps != null ) { - for ( Iterator it = deps.iterator(); it.hasNext(); ) + for ( Iterator it = deps.iterator(); it.hasNext(); ) { - Dependency dependency = (Dependency) it.next(); + Dependency dependency = it.next(); depsMap.put( dependency.getManagementKey(), dependency ); } } @@ -263,14 +268,14 @@ private void assembleDependencyInheritance( Model child, Model parent ) if ( deps != null ) { - for ( Iterator it = deps.iterator(); it.hasNext(); ) + for ( Iterator it = deps.iterator(); it.hasNext(); ) { - Dependency dependency = (Dependency) it.next(); + Dependency dependency = it.next(); depsMap.put( dependency.getManagementKey(), dependency ); } } - child.setDependencies( new ArrayList( depsMap.values() ) ); + child.setDependencies( new ArrayList( depsMap.values() ) ); } private void assembleBuildInheritance( Model child, Model parent ) @@ -286,83 +291,91 @@ private void assembleBuildInheritance( Model child, Model parent ) child.setBuild( childBuild ); } - // The build has been set but we want to step in here and fill in - // values that have not been set by the child. + assembleBuildInheritance( childBuild, parentBuild ); + } + } - if ( childBuild.getSourceDirectory() == null ) - { - childBuild.setSourceDirectory( parentBuild.getSourceDirectory() ); - } + // TODO: Remove this! + @SuppressWarnings("unchecked") + public void assembleBuildInheritance( Build childBuild, + Build parentBuild ) + { + // The build has been set but we want to step in here and fill in + // values that have not been set by the child. - if ( childBuild.getScriptSourceDirectory() == null ) - { - childBuild.setScriptSourceDirectory( parentBuild.getScriptSourceDirectory() ); - } + if ( childBuild.getSourceDirectory() == null ) + { + childBuild.setSourceDirectory( parentBuild.getSourceDirectory() ); + } - if ( childBuild.getTestSourceDirectory() == null ) - { - childBuild.setTestSourceDirectory( parentBuild.getTestSourceDirectory() ); - } + if ( childBuild.getScriptSourceDirectory() == null ) + { + childBuild.setScriptSourceDirectory( parentBuild.getScriptSourceDirectory() ); + } - if ( childBuild.getOutputDirectory() == null ) - { - childBuild.setOutputDirectory( parentBuild.getOutputDirectory() ); - } + if ( childBuild.getTestSourceDirectory() == null ) + { + childBuild.setTestSourceDirectory( parentBuild.getTestSourceDirectory() ); + } - if ( childBuild.getTestOutputDirectory() == null ) - { - childBuild.setTestOutputDirectory( parentBuild.getTestOutputDirectory() ); - } + if ( childBuild.getOutputDirectory() == null ) + { + childBuild.setOutputDirectory( parentBuild.getOutputDirectory() ); + } - // Extensions are accumlated - ModelUtils.mergeExtensionLists( childBuild, parentBuild ); + if ( childBuild.getTestOutputDirectory() == null ) + { + childBuild.setTestOutputDirectory( parentBuild.getTestOutputDirectory() ); + } - if ( childBuild.getDirectory() == null ) - { - childBuild.setDirectory( parentBuild.getDirectory() ); - } + // Extensions are accumlated + ModelUtils.mergeExtensionLists( childBuild, parentBuild ); - if ( childBuild.getDefaultGoal() == null ) - { - childBuild.setDefaultGoal( parentBuild.getDefaultGoal() ); - } + if ( childBuild.getDirectory() == null ) + { + childBuild.setDirectory( parentBuild.getDirectory() ); + } - if ( childBuild.getFinalName() == null ) - { - childBuild.setFinalName( parentBuild.getFinalName() ); - } + if ( childBuild.getDefaultGoal() == null ) + { + childBuild.setDefaultGoal( parentBuild.getDefaultGoal() ); + } - ModelUtils.mergeFilterLists( childBuild.getFilters(), parentBuild.getFilters() ); + if ( childBuild.getFinalName() == null ) + { + childBuild.setFinalName( parentBuild.getFinalName() ); + } - List resources = childBuild.getResources(); - if ( ( resources == null ) || resources.isEmpty() ) - { - childBuild.setResources( parentBuild.getResources() ); - } + ModelUtils.mergeFilterLists( childBuild.getFilters(), parentBuild.getFilters() ); - resources = childBuild.getTestResources(); - if ( ( resources == null ) || resources.isEmpty() ) - { - childBuild.setTestResources( parentBuild.getTestResources() ); - } + List resources = childBuild.getResources(); + if ( ( resources == null ) || resources.isEmpty() ) + { + childBuild.setResources( parentBuild.getResources() ); + } - // Plugins are aggregated if Plugin.inherit != false - ModelUtils.mergePluginLists( childBuild, parentBuild, true ); + resources = childBuild.getTestResources(); + if ( ( resources == null ) || resources.isEmpty() ) + { + childBuild.setTestResources( parentBuild.getTestResources() ); + } - // Plugin management :: aggregate - PluginManagement dominantPM = childBuild.getPluginManagement(); - PluginManagement recessivePM = parentBuild.getPluginManagement(); + // Plugins are aggregated if Plugin.inherit != false + ModelUtils.mergePluginLists( childBuild, parentBuild, true ); - if ( ( dominantPM == null ) && ( recessivePM != null ) ) - { - // FIXME: Filter out the inherited == false stuff! - childBuild.setPluginManagement( recessivePM ); - } - else - { - ModelUtils.mergePluginLists( childBuild.getPluginManagement(), parentBuild.getPluginManagement(), - false ); - } + // Plugin management :: aggregate + PluginManagement dominantPM = childBuild.getPluginManagement(); + PluginManagement recessivePM = parentBuild.getPluginManagement(); + + if ( ( dominantPM == null ) && ( recessivePM != null ) ) + { + // FIXME: Filter out the inherited == false stuff! + childBuild.setPluginManagement( recessivePM ); + } + else + { + ModelUtils.mergePluginLists( childBuild.getPluginManagement(), parentBuild.getPluginManagement(), + false ); } } @@ -525,7 +538,7 @@ protected String appendPath( String parentPath, String childPath, String pathAdj // TODO: Move this to plexus-utils' PathTool. private static String resolvePath( String uncleanPath ) { - LinkedList pathElements = new LinkedList(); + LinkedList pathElements = new LinkedList(); StringTokenizer tokenizer = new StringTokenizer( uncleanPath, "/" ); diff --git a/maven-project/src/main/java/org/apache/maven/project/inheritance/ModelInheritanceAssembler.java b/maven-project/src/main/java/org/apache/maven/project/inheritance/ModelInheritanceAssembler.java index aafe60f762..6ffb3c305c 100644 --- a/maven-project/src/main/java/org/apache/maven/project/inheritance/ModelInheritanceAssembler.java +++ b/maven-project/src/main/java/org/apache/maven/project/inheritance/ModelInheritanceAssembler.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.model.Build; import org.apache.maven.model.Model; /** @@ -33,5 +34,8 @@ public interface ModelInheritanceAssembler void assembleModelInheritance( Model child, Model parent ); + void assembleBuildInheritance( Build childBuild, + Build parentBuild ); + void copyModel( Model dest, Model source ); } diff --git a/maven-project/src/main/java/org/apache/maven/project/path/DefaultPathTranslator.java b/maven-project/src/main/java/org/apache/maven/project/path/DefaultPathTranslator.java index 7a90b5e989..710b941d1c 100644 --- a/maven-project/src/main/java/org/apache/maven/project/path/DefaultPathTranslator.java +++ b/maven-project/src/main/java/org/apache/maven/project/path/DefaultPathTranslator.java @@ -31,6 +31,12 @@ public class DefaultPathTranslator implements PathTranslator { + private static final String[] BASEDIR_EXPRESSIONS = { + "${basedir}", + "${pom.basedir}", + "${project.basedir}" + }; + private String FILE_SEPARATOR = "/"; public void alignToBaseDirectory( Model model, File basedir ) @@ -91,18 +97,28 @@ public String alignToBaseDirectory( String path, File basedir ) private String stripBasedirToken( String s ) { - String basedirExpr = "${basedir}"; - if ( s != null ) { - s = s.trim(); + String basedirExpr = null; + for ( int i = 0; i < BASEDIR_EXPRESSIONS.length; i++ ) + { + basedirExpr = BASEDIR_EXPRESSIONS[i]; + if ( s.startsWith( basedirExpr ) ) + { + break; + } + else + { + basedirExpr = null; + } + } - if ( s.startsWith( basedirExpr ) ) + if ( basedirExpr != null ) { if ( s.length() > basedirExpr.length() ) { - // Take out ${basedir} and the leading slash - s = s.substring( basedirExpr.length() + 1 ); + // Take out basedir expression and the leading slash + s = chopLeadingFileSeparator( s.substring( basedirExpr.length() ) ); } else { @@ -114,6 +130,25 @@ private String stripBasedirToken( String s ) return s; } + /** + * Removes the leading directory separator from the specified filesystem path (if any). For platform-independent + * behavior, this method accepts both the forward slash and the backward slash as separator. + * + * @param path The filesystem path, may be null. + * @return The altered filesystem path or null if the input path was null. + */ + private String chopLeadingFileSeparator( String path ) + { + if ( path != null ) + { + if ( path.startsWith( "/" ) || path.startsWith( "\\" ) ) + { + path = path.substring( 1 ); + } + } + return path; + } + private boolean requiresBaseDirectoryAlignment( String s ) { if ( s != null ) diff --git a/maven-project/src/test/java/org/apache/maven/project/DefaultMavenProjectBuilderTest.java b/maven-project/src/test/java/org/apache/maven/project/DefaultMavenProjectBuilderTest.java index 24f8f7af4e..9d00d5adf8 100644 --- a/maven-project/src/test/java/org/apache/maven/project/DefaultMavenProjectBuilderTest.java +++ b/maven-project/src/test/java/org/apache/maven/project/DefaultMavenProjectBuilderTest.java @@ -42,6 +42,7 @@ public class DefaultMavenProjectBuilderTest private DefaultMavenProjectBuilder projectBuilder; + @Override public void setUp() throws Exception { @@ -55,6 +56,7 @@ public void setUp() filesToDelete.add( localRepoDir ); } + @Override public void tearDown() throws Exception { @@ -114,6 +116,8 @@ public void testBuildDirectoryExpressionInterpolatedWithTranslatedValue() MavenProject project = getProject( pom ); + projectBuilder.calculateConcreteState( project, new DefaultProjectBuilderConfiguration() ); + Build build = project.getBuild(); assertNotNull( "Project should have a build section containing the test resource.", build ); @@ -132,6 +136,7 @@ public void testBuildDirectoryExpressionInterpolatedWithTranslatedValue() System.out.println( "Interpolated, translated resource directory is: " + res.getDirectory() ); } + @Override protected ArtifactRepository getLocalRepository() throws Exception { diff --git a/maven-project/src/test/java/org/apache/maven/project/MavenProjectDynamismTest.java b/maven-project/src/test/java/org/apache/maven/project/MavenProjectDynamismTest.java new file mode 100644 index 0000000000..2023c217fd --- /dev/null +++ b/maven-project/src/test/java/org/apache/maven/project/MavenProjectDynamismTest.java @@ -0,0 +1,570 @@ +package org.apache.maven.project; + +import org.apache.maven.model.Build; +import org.apache.maven.model.Plugin; +import org.apache.maven.model.Resource; +import org.apache.maven.project.interpolation.ModelInterpolationException; +import org.codehaus.plexus.PlexusTestCase; +import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.Iterator; +import java.util.List; + +public class MavenProjectDynamismTest + extends PlexusTestCase +{ + + private MavenProjectBuilder projectBuilder; + + @Override + public void setUp() + throws Exception + { + super.setUp(); + + projectBuilder = (MavenProjectBuilder) lookup( MavenProjectBuilder.class.getName() ); + } + + public void testBuildSectionGroupIdInterpolation() + throws IOException, XmlPullParserException, URISyntaxException, ProjectBuildingException, + ModelInterpolationException + { + MavenProject project = buildProject( "pom-interp.xml" ); + + projectBuilder.calculateConcreteState( project, new DefaultProjectBuilderConfiguration() ); + + String basepath = "/" + project.getGroupId(); + + Build build = project.getBuild(); + + assertTrue( build.getSourceDirectory().startsWith( basepath ) ); + assertTrue( build.getTestSourceDirectory().startsWith( basepath ) ); + assertTrue( build.getScriptSourceDirectory().startsWith( basepath ) ); + + List plugins = build.getPlugins(); + assertNotNull( plugins ); + assertEquals( 1, plugins.size() ); + + Plugin plugin = (Plugin) plugins.get( 0 ); + assertEquals( "my-plugin", plugin.getArtifactId() ); + + Xpp3Dom conf = (Xpp3Dom) plugin.getConfiguration(); + assertNotNull( conf ); + + Xpp3Dom[] children = conf.getChildren(); + assertEquals( 3, children.length ); + + for ( int i = 0; i < children.length; i++ ) + { + assertEquals( "Configuration parameter: " + + children[i].getName() + + " should have a an interpolated POM groupId as its value.", + children[i].getValue(), + project.getGroupId() ); + } + + projectBuilder.restoreDynamicState( project, new DefaultProjectBuilderConfiguration() ); + + String projectGidExpr = "${project.groupId}"; + String pomGidExpr = "${pom.groupId}"; + String nakedGidExpr = "${groupId}"; + + build = project.getBuild(); + + assertTrue( build.getSourceDirectory().startsWith( "/" + projectGidExpr ) ); + assertTrue( build.getTestSourceDirectory().startsWith( "/" + pomGidExpr ) ); + assertTrue( build.getScriptSourceDirectory().startsWith( "/" + nakedGidExpr ) ); + + plugins = build.getPlugins(); + assertNotNull( plugins ); + assertEquals( 1, plugins.size() ); + + plugin = (Plugin) plugins.get( 0 ); + assertEquals( "my-plugin", plugin.getArtifactId() ); + + conf = (Xpp3Dom) plugin.getConfiguration(); + assertNotNull( conf ); + + children = conf.getChildren(); + assertEquals( 3, children.length ); + + assertEquals( "Configuration parameter: " + children[0].getName() + " should have " + + projectGidExpr + " as its value.", children[0].getValue(), projectGidExpr ); + + assertEquals( "Configuration parameter: " + children[1].getName() + " should have " + + pomGidExpr + " as its value.", children[1].getValue(), pomGidExpr ); + + assertEquals( "Configuration parameter: " + children[2].getName() + " should have " + + nakedGidExpr + " as its value.", children[2].getValue(), nakedGidExpr ); + } + + public void testRoundTrip() + throws IOException, XmlPullParserException, URISyntaxException, + ModelInterpolationException, ProjectBuildingException + { + MavenProject project = buildProject( "pom.xml" ); + ProjectBuilderConfiguration config = new DefaultProjectBuilderConfiguration(); + projectBuilder.calculateConcreteState( project, config ); + + File baseDir = project.getBasedir(); + File buildDir = new File( baseDir, "target" ); + + String basedirExpr = "${pom.basedir}"; + String buildDirExpr = "${pom.build.directory}"; + + assertTrue( project.isConcrete() ); + + Build build = project.getBuild(); + + assertEquals( "Concrete source directory should be absolute.", + new File( baseDir, "/src/main/java" ).getAbsolutePath(), + build.getSourceDirectory() ); + + assertEquals( "Concrete test-source directory should be absolute.", + new File( baseDir, "/src/test/java" ).getAbsolutePath(), + build.getTestSourceDirectory() ); + + assertEquals( "Concrete script-source directory should be absolute.", + new File( baseDir, "/src/main/scripts" ).getAbsolutePath(), + build.getScriptSourceDirectory() ); + + List compileSourceRoots = project.getCompileSourceRoots(); + + assertNotNull( "Concrete compile-source roots should not be null.", compileSourceRoots ); + + assertEquals( "Concrete compile-source roots should contain one entry.", + 1, + compileSourceRoots.size() ); + + assertEquals( "Concrete compile-source roots should contain interpolated source-directory value.", + new File( baseDir, "/src/main/java" ).getAbsolutePath(), + compileSourceRoots.get( 0 ) ); + + List testCompileSourceRoots = project.getTestCompileSourceRoots(); + + assertNotNull( "Concrete test-compile-source roots should not be null.", + testCompileSourceRoots ); + + assertEquals( "Concrete test-compile-source roots should contain one entry.", + 1, + testCompileSourceRoots.size() ); + + assertEquals( "Concrete test-compile-source roots should contain interpolated test-source-directory value.", + new File( baseDir, "/src/test/java" ).getAbsolutePath(), + testCompileSourceRoots.get( 0 ) ); + + List scriptSourceRoots = project.getScriptSourceRoots(); + + assertNotNull( "Concrete script-source roots should not be null.", scriptSourceRoots ); + + assertEquals( "Concrete script-source roots should contain one entry.", + 1, + scriptSourceRoots.size() ); + + assertEquals( "Concrete script-source roots should contain interpolated script-source-directory value.", + new File( baseDir, "/src/main/scripts" ).getAbsolutePath(), + scriptSourceRoots.get( 0 ) ); + + List resources = build.getResources(); + + assertNotNull( "Concrete resources should not be null.", resources ); + + assertEquals( "Concrete resources should contain one entry.", 1, resources.size() ); + + assertEquals( "Concrete resource should contain absolute path.", + new File( buildDir, "generated-resources/plexus" ).getAbsolutePath(), + ( (Resource) resources.get( 0 ) ).getDirectory() ); + + List filters = build.getFilters(); + + assertNotNull( "Concrete filters should not be null.", filters ); + + assertEquals( "Concrete filters should contain one entry.", 1, filters.size() ); + + assertEquals( "Concrete filter entry should contain absolute path.", + new File( buildDir, "/generated-filters.properties" ).getAbsolutePath(), + filters.get( 0 ) ); + + assertEquals( "Concrete output-directory should be absolute.", + new File( buildDir, "/classes" ).getAbsolutePath(), + build.getOutputDirectory() ); + + assertEquals( "Concrete test-output-directory should be absolute.", + new File( buildDir, "/test-classes" ).getAbsolutePath(), + build.getTestOutputDirectory() ); + + assertEquals( "Concrete build directory should be absolute.", + new File( baseDir, "target" ).getAbsolutePath(), + build.getDirectory() ); + + // -------------------------------------------------------------------- + // NOW, RESTORE THE DYNAMIC STATE FOR THE BUILD SECTION AND + // ASSOCIATED DIRECTORIES ATTACHED TO THE PROJECT INSTANCE. + // -------------------------------------------------------------------- + + projectBuilder.restoreDynamicState( project, config ); + + assertFalse( project.isConcrete() ); + + build = project.getBuild(); + + assertEquals( "Restored source directory should be expressed in terms of the basedir.", + basedirExpr + "/src/main/java", + build.getSourceDirectory() ); + + assertEquals( "Restored test-source directory should be expressed in terms of the basedir.", + basedirExpr + "/src/test/java", + build.getTestSourceDirectory() ); + + assertEquals( "Restored script-source directory should be expressed in terms of the basedir.", + basedirExpr + "/src/main/scripts", + build.getScriptSourceDirectory() ); + + compileSourceRoots = project.getCompileSourceRoots(); + + assertNotNull( "Restored compile-source roots should not be null.", compileSourceRoots ); + + assertEquals( "Restored compile-source roots should contain one entry.", + 1, + compileSourceRoots.size() ); + + assertEquals( "Restored compile-source roots should contain uninterpolated source-directory value.", + "${pom.basedir}/src/main/java", + compileSourceRoots.get( 0 ) ); + + testCompileSourceRoots = project.getTestCompileSourceRoots(); + + assertNotNull( "Restored test-compile-source roots should not be null.", + testCompileSourceRoots ); + + assertEquals( "Restored test-compile-source roots should contain one entry.", + 1, + testCompileSourceRoots.size() ); + + assertEquals( "Restored test-compile-source roots should contain uninterpolated test-source-directory value.", + "${pom.basedir}/src/test/java", + testCompileSourceRoots.get( 0 ) ); + + scriptSourceRoots = project.getScriptSourceRoots(); + + assertNotNull( "Restored script-source roots should not be null.", scriptSourceRoots ); + + assertEquals( "Restored script-source roots should contain one entry.", + 1, + scriptSourceRoots.size() ); + + assertEquals( "Restored script-source roots should contain uninterpolated script-source-directory value.", + "${pom.basedir}/src/main/scripts", + scriptSourceRoots.get( 0 ) ); + + resources = build.getResources(); + + assertNotNull( "Restored resources should not be null.", resources ); + + assertEquals( "Restored resources should contain one entry.", 1, resources.size() ); + + assertEquals( "Restored resource should contain uninterpolated reference to build directory.", + buildDirExpr + "/generated-resources/plexus", + ( (Resource) resources.get( 0 ) ).getDirectory() ); + + filters = build.getFilters(); + + assertNotNull( "Restored filters should not be null.", filters ); + + assertEquals( "Restored filters should contain one entry.", 1, filters.size() ); + + assertEquals( "Restored filter entry should contain uninterpolated reference to build directory.", + buildDirExpr + "/generated-filters.properties", + filters.get( 0 ) ); + + assertEquals( "Restored output-directory should be expressed in terms of the build-directory.", + buildDirExpr + "/classes", + build.getOutputDirectory() ); + + assertEquals( "Restored test-output-directory should be expressed in terms of the build-directory.", + buildDirExpr + "/test-classes", + build.getTestOutputDirectory() ); + + assertEquals( "Restored build directory should be relative.", + "target", + build.getDirectory() ); + } + + public void testShouldPreserveAddedResourceInRestoredState() + throws IOException, XmlPullParserException, URISyntaxException, ProjectBuildingException, + ModelInterpolationException + { + MavenProject project = buildProject( "pom.xml" ); + + ProjectBuilderConfiguration config = new DefaultProjectBuilderConfiguration(); + + projectBuilder.calculateConcreteState( project, config ); + + Build build = project.getBuild(); + + Resource r = new Resource(); + r.setDirectory( "myDir" ); + + build.addResource( r ); + + List resources = build.getResources(); + assertNotNull( "Concrete resources should not be null.", resources ); + assertEquals( "Concrete resources should contain two entries.", 2, resources.size() ); + assertResourcePresent( "concrete resources", + new File( build.getDirectory(), "generated-resources/plexus" ).getAbsolutePath(), + resources ); + assertResourcePresent( "concrete resources", "myDir", resources ); + + projectBuilder.restoreDynamicState( project, config ); + + build = project.getBuild(); + + resources = build.getResources(); + assertNotNull( "Restored resources should not be null.", resources ); + assertEquals( "Restored resources should contain two entries.", 2, resources.size() ); + assertResourcePresent( "restored resources", + "${pom.build.directory}/generated-resources/plexus", + resources ); + assertResourcePresent( "restored resources", "myDir", resources ); + } + + public void testShouldPreserveAddedFilterInRestoredState() + throws IOException, XmlPullParserException, URISyntaxException, ProjectBuildingException, + ModelInterpolationException + { + MavenProject project = buildProject( "pom.xml" ); + + ProjectBuilderConfiguration config = new DefaultProjectBuilderConfiguration(); + projectBuilder.calculateConcreteState( project, config ); + + Build build = project.getBuild(); + + build.addFilter( "myDir/filters.properties" ); + + List filters = build.getFilters(); + assertNotNull( "Concrete filters should not be null.", filters ); + assertEquals( "Concrete filters should contain two entries.", 2, filters.size() ); + assertFilterPresent( "concrete filters", + new File( build.getDirectory(), "generated-filters.properties" ).getAbsolutePath(), + filters ); + + assertFilterPresent( "concrete filters", "myDir/filters.properties", filters ); + + projectBuilder.restoreDynamicState( project, config ); + + build = project.getBuild(); + + filters = build.getFilters(); + assertNotNull( "Restored filters should not be null.", filters ); + assertEquals( "Restored filters should contain two entries.", 2, filters.size() ); + assertFilterPresent( "restored filters", + "${pom.build.directory}/generated-filters.properties", + filters ); + assertFilterPresent( "restored filters", "myDir/filters.properties", filters ); + } + + public void testShouldIncorporateChangedBuildDirectoryViaExpressionsOnNextConcreteCalculation() + throws IOException, XmlPullParserException, URISyntaxException, ProjectBuildingException, + ModelInterpolationException + { + MavenProject project = buildProject( "pom.xml" ); + + ProjectBuilderConfiguration config = new DefaultProjectBuilderConfiguration(); + projectBuilder.calculateConcreteState( project, config ); + + Build build = project.getBuild(); + + assertEquals( "First concrete build directory should be absolute and point to target dir.", + new File( project.getBasedir(), "target" ).getAbsolutePath(), + build.getDirectory() ); + assertEquals( "First concrete build output-directory should be absolute and point to target/classes dir.", + new File( project.getBasedir(), "target/classes" ).getAbsolutePath(), + build.getOutputDirectory() ); + + build.setDirectory( "target2" ); + + assertEquals( "AFTER CHANGING BUILD DIRECTORY, build directory should be relative and point to target2 dir.", + "target2", + build.getDirectory() ); + assertEquals( "AFTER CHANGING BUILD DIRECTORY, build output-directory should be absolute and still point to target/classes dir.", + new File( project.getBasedir(), "target/classes" ).getAbsolutePath(), + build.getOutputDirectory() ); + + projectBuilder.restoreDynamicState( project, config ); + projectBuilder.calculateConcreteState( project, config ); + + build = project.getBuild(); + + assertEquals( "Second concrete build directory should be absolute and point to target2 dir.", + new File( project.getBasedir(), "target2" ).getAbsolutePath(), + build.getDirectory() ); + assertEquals( "Second concrete build output-directory should be absolute and point to target2/classes dir.", + new File( project.getBasedir(), "target2/classes" ).getAbsolutePath(), + build.getOutputDirectory() ); + } + + public void testShouldPreserveInitialValuesForPropertiesReferencingBuildPaths() + throws IOException, XmlPullParserException, URISyntaxException, ProjectBuildingException, + ModelInterpolationException + { + MavenProject project = buildProject( "pom.xml" ); + + ProjectBuilderConfiguration config = new DefaultProjectBuilderConfiguration(); + projectBuilder.calculateConcreteState( project, config ); + + project.getBuild().setDirectory( "target2" ); + + String originalValue = project.getProperties().getProperty( "myProperty" ); + + projectBuilder.restoreDynamicState( project, config ); + projectBuilder.calculateConcreteState( project, config ); + + assertEquals( "After resetting build-directory and going through a recalculation phase for the project, " + + "property value for 'myProperty' should STILL be the absolute initial build directory.", + originalValue, + project.getProperties().getProperty( "myProperty" ) ); + } + + public void testShouldAlignCompileSourceRootsInConcreteState() + throws IOException, XmlPullParserException, URISyntaxException, ProjectBuildingException, + ModelInterpolationException + { + MavenProject project = buildProject( "pom-relative.xml" ); + + ProjectBuilderConfiguration config = new DefaultProjectBuilderConfiguration(); + projectBuilder.calculateConcreteState( project, config ); + + List compileSourceRoots = project.getCompileSourceRoots(); + assertNotNull( "First concrete state compile-source roots should not be null.", + compileSourceRoots ); + assertEquals( "First concrete state should contain one compile-source root.", + 1, + compileSourceRoots.size() ); + assertEquals( "First concrete state should have an absolute path for compile-source root.", + new File( project.getBasedir(), "src/main/java" ).getAbsolutePath(), + compileSourceRoots.get( 0 ) ); + + String newSourceRoot = new File( project.getBuild().getDirectory(), + "generated-sources/modello" ).getAbsolutePath(); + + project.addCompileSourceRoot( newSourceRoot ); + + projectBuilder.restoreDynamicState( project, config ); + + compileSourceRoots = project.getCompileSourceRoots(); + assertNotNull( "Restored dynamic state compile-source roots should not be null.", + compileSourceRoots ); + assertEquals( "Restored dynamic state should contain two compile-source roots.", + 2, + compileSourceRoots.size() ); + assertEquals( "Restored dynamic state should have a relative path for original compile-source root.", + "src/main/java", + compileSourceRoots.get( 0 ) ); + assertEquals( "Restored dynamic state should have a relative path for new compile-source root.", + "target/generated-sources/modello", + compileSourceRoots.get( 1 ) ); + + projectBuilder.calculateConcreteState( project, config ); + + compileSourceRoots = project.getCompileSourceRoots(); + assertNotNull( "Second concrete state compile-source roots should not be null.", + compileSourceRoots ); + assertEquals( "Second concrete state should contain two compile-source roots.", + 2, + compileSourceRoots.size() ); + assertEquals( "Second concrete state should have an absolute path for original compile-source root.", + new File( project.getBasedir(), "src/main/java" ).getAbsolutePath(), + compileSourceRoots.get( 0 ) ); + assertEquals( "Second concrete state should have an absolute path for new compile-source root.", + newSourceRoot, + compileSourceRoots.get( 1 ) ); + } + + // Useful for diagnostics. +// private void displayPOM( Model model ) +// throws IOException +// { +// StringWriter writer = new StringWriter(); +// new MavenXpp3Writer().write( writer, model ); +// +// System.out.println( writer.toString() ); +// } + + private void assertResourcePresent( String testLabel, + String directory, + List resources ) + { + boolean found = false; + + if ( resources != null ) + { + for ( Iterator it = resources.iterator(); it.hasNext(); ) + { + Resource resource = (Resource) it.next(); + if ( directory.equals( resource.getDirectory() ) ) + { + found = true; + break; + } + } + } + + if ( !found ) + { + fail( "Missing resource with directory: " + directory + " in " + testLabel ); + } + } + + private void assertFilterPresent( String testLabel, + String path, + List filters ) + { + boolean found = false; + + if ( filters != null ) + { + for ( Iterator it = filters.iterator(); it.hasNext(); ) + { + String filterPath = (String) it.next(); + if ( path.equals( filterPath ) ) + { + found = true; + break; + } + } + } + + if ( !found ) + { + fail( "Missing filter with path: " + path + " in " + testLabel ); + } + } + + private MavenProject buildProject( String path ) + throws IOException, XmlPullParserException, URISyntaxException, ProjectBuildingException + { + ClassLoader cloader = Thread.currentThread().getContextClassLoader(); + URL resource = cloader.getResource( "project-dynamism/" + path ); + + if ( resource == null ) + { + fail( "Cannot find classpath resource for POM: " + path ); + } + + File pomFile = new File( resource.getPath() ); + pomFile = pomFile.getAbsoluteFile(); + + MavenProject project = projectBuilder.build( pomFile, + new DefaultProjectBuilderConfiguration() ); + + assertEquals( pomFile, project.getFile() ); + + return project; + } + +} diff --git a/maven-project/src/test/java/org/apache/maven/project/ProjectBaseDirectoryAlignmentTest.java b/maven-project/src/test/java/org/apache/maven/project/ProjectBaseDirectoryAlignmentTest.java index 573c883a6e..960b2abdf6 100644 --- a/maven-project/src/test/java/org/apache/maven/project/ProjectBaseDirectoryAlignmentTest.java +++ b/maven-project/src/test/java/org/apache/maven/project/ProjectBaseDirectoryAlignmentTest.java @@ -35,6 +35,7 @@ public void testProjectDirectoryBaseDirectoryAlignment() File f = getTestFile( dir + "project-which-needs-directory-alignment.xml" ); MavenProject project = getProject( f ); + projectBuilder.calculateConcreteState( project, new DefaultProjectBuilderConfiguration() ); assertNotNull( "Test project can't be null!", project ); diff --git a/maven-project/src/test/resources/project-dynamism/pom-interp.xml b/maven-project/src/test/resources/project-dynamism/pom-interp.xml new file mode 100644 index 0000000000..2ad098aab3 --- /dev/null +++ b/maven-project/src/test/resources/project-dynamism/pom-interp.xml @@ -0,0 +1,28 @@ + + + + 4.0.0 + + org.test + test-build-dynamism + 1 + + + /${project.groupId}/src/main/java + /${pom.groupId}/src/test/java + /${groupId}/src/main/scripts + + + + my-plugin + + ${project.groupId} + ${pom.groupId} + ${groupId} + + + + + + \ No newline at end of file diff --git a/maven-project/src/test/resources/project-dynamism/pom-relative.xml b/maven-project/src/test/resources/project-dynamism/pom-relative.xml new file mode 100644 index 0000000000..a24aebe68e --- /dev/null +++ b/maven-project/src/test/resources/project-dynamism/pom-relative.xml @@ -0,0 +1,36 @@ + + + + 4.0.0 + + org.test + test-build-dynamism + 1 + + + ${pom.build.directory} + + + + + + ${pom.build.directory}/generated-resources/plexus + + + + + ${pom.build.directory}/generated-filters.properties + + + target + + src/main/java + src/test/java + src/main/scripts + + ${pom.build.directory}/classes + ${pom.build.directory}/test-classes + + + \ No newline at end of file diff --git a/maven-project/src/test/resources/project-dynamism/pom.xml b/maven-project/src/test/resources/project-dynamism/pom.xml new file mode 100644 index 0000000000..02bbed08f0 --- /dev/null +++ b/maven-project/src/test/resources/project-dynamism/pom.xml @@ -0,0 +1,36 @@ + + + + 4.0.0 + + org.test + test-build-dynamism + 1 + + + ${pom.build.directory} + + + + + + ${pom.build.directory}/generated-resources/plexus + + + + + ${pom.build.directory}/generated-filters.properties + + + target + + ${pom.basedir}/src/main/java + ${pom.basedir}/src/test/java + ${pom.basedir}/src/main/scripts + + ${pom.build.directory}/classes + ${pom.build.directory}/test-classes + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 93d8c7e6b8..ac08f791a1 100644 --- a/pom.xml +++ b/pom.xml @@ -46,9 +46,25 @@ under the License. + + apache.snapshots + http://people.apache.org/repo/m2-snapshot-repository/ + + true + + + false + + codehaus.snapshots http://snapshots.repository.codehaus.org/ + + true + + + false + @@ -221,6 +237,7 @@ under the License. 1.0-alpha-48 1.0-beta-3 + 3.0-20080627-013430-64 @@ -286,6 +303,11 @@ under the License. maven-core 2.1-SNAPSHOT + + org.codehaus.plexus + plexus-utils + 1.5.4 + org.codehaus.plexus plexus-container-default @@ -296,11 +318,6 @@ under the License. plexus-classworlds 1.2-alpha-12 - - org.codehaus.plexus - plexus-utils - 1.5.1 - org.codehaus.plexus plexus-interpolation @@ -334,6 +351,9 @@ under the License. org.apache.maven.artifact maven-artifact + 3.0-SNAPSHOT @@ -389,7 +409,7 @@ under the License. - + apache.website