From 26a35db0c775e137865a08602155eaac1ace7e0b Mon Sep 17 00:00:00 2001 From: Benjamin Bentmann Date: Mon, 1 Jun 2009 12:17:53 +0000 Subject: [PATCH] o Introduced ModelBuilder component that now hosts most of the logic from the project builder to construct the effective model. With maven-model-builder we now should have a rather slim module that tools can re-use for building models. The project builder is simply layered on top of the model builder. git-svn-id: https://svn.apache.org/repos/asf/maven/components/trunk@780627 13f79535-47bb-0310-9956-ffa450edef68 --- .../profiles/ProfileActivationContext.java | 21 + .../maven/project/DefaultProjectBuilder.java | 477 +-------- .../DefaultProjectBuilderConfiguration.java | 135 +-- .../DefaultProjectBuildingRequest.java | 66 +- .../maven/project/ProjectBuildingRequest.java | 6 +- .../project/RepositoryModelResolver.java | 126 +++ .../maven/project/PomConstructionTest.java | 1 - .../maven/model/DefaultModelBuilder.java | 481 +++++++++ .../model/DefaultModelBuildingRequest.java | 142 +++ .../model/DefaultModelBuildingResult.java | 125 +++ .../apache/maven/model/FileModelSource.java | 79 ++ .../maven/model/InvalidModelException.java | 53 + .../maven/model/InvalidProfileException.java | 59 ++ .../org/apache/maven/model/ModelBuilder.java | 38 + .../maven/model/ModelBuildingException.java | 41 + .../maven/model/ModelBuildingRequest.java | 138 +++ .../maven/model/ModelBuildingResult.java | 40 + .../org/apache/maven/model/ModelSource.java | 49 + .../org/apache/maven/model/ModelUtils.java | 929 ++++++++++++++++++ .../model/UnparseableModelException.java | 76 ++ .../model/UnresolvableParentException.java | 41 + .../apache/maven/model/UrlModelSource.java | 78 ++ .../DefaultProfileActivationContext.java | 96 ++ .../profile/ProfileActivationContext.java | 24 + .../resolver/InvalidRepositoryException.java | 70 ++ .../maven/model/resolver/ModelResolver.java | 42 + .../resolver/UnresolvableModelException.java | 52 + .../AbstractProfileActivatorTest.java | 23 +- maven-model/src/main/mdo/maven.mdo | 24 +- 29 files changed, 2862 insertions(+), 670 deletions(-) create mode 100644 maven-core/src/main/java/org/apache/maven/project/RepositoryModelResolver.java create mode 100644 maven-model-builder/src/main/java/org/apache/maven/model/DefaultModelBuilder.java create mode 100644 maven-model-builder/src/main/java/org/apache/maven/model/DefaultModelBuildingRequest.java create mode 100644 maven-model-builder/src/main/java/org/apache/maven/model/DefaultModelBuildingResult.java create mode 100644 maven-model-builder/src/main/java/org/apache/maven/model/FileModelSource.java create mode 100644 maven-model-builder/src/main/java/org/apache/maven/model/InvalidModelException.java create mode 100644 maven-model-builder/src/main/java/org/apache/maven/model/InvalidProfileException.java create mode 100644 maven-model-builder/src/main/java/org/apache/maven/model/ModelBuilder.java create mode 100644 maven-model-builder/src/main/java/org/apache/maven/model/ModelBuildingException.java create mode 100644 maven-model-builder/src/main/java/org/apache/maven/model/ModelBuildingRequest.java create mode 100644 maven-model-builder/src/main/java/org/apache/maven/model/ModelBuildingResult.java create mode 100644 maven-model-builder/src/main/java/org/apache/maven/model/ModelSource.java create mode 100644 maven-model-builder/src/main/java/org/apache/maven/model/ModelUtils.java create mode 100644 maven-model-builder/src/main/java/org/apache/maven/model/UnparseableModelException.java create mode 100644 maven-model-builder/src/main/java/org/apache/maven/model/UnresolvableParentException.java create mode 100644 maven-model-builder/src/main/java/org/apache/maven/model/UrlModelSource.java create mode 100644 maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileActivationContext.java create mode 100644 maven-model-builder/src/main/java/org/apache/maven/model/resolver/InvalidRepositoryException.java create mode 100644 maven-model-builder/src/main/java/org/apache/maven/model/resolver/ModelResolver.java create mode 100644 maven-model-builder/src/main/java/org/apache/maven/model/resolver/UnresolvableModelException.java diff --git a/maven-compat/src/main/java/org/apache/maven/profiles/ProfileActivationContext.java b/maven-compat/src/main/java/org/apache/maven/profiles/ProfileActivationContext.java index 4f2a2434cc..850dfac750 100644 --- a/maven-compat/src/main/java/org/apache/maven/profiles/ProfileActivationContext.java +++ b/maven-compat/src/main/java/org/apache/maven/profiles/ProfileActivationContext.java @@ -160,4 +160,25 @@ public class ProfileActivationContext return getExplicitlyInactiveProfileIds(); } + public org.apache.maven.model.profile.ProfileActivationContext setActiveProfileIds( List activeProfileIds ) + { + setExplicitlyActiveProfileIds( activeProfileIds ); + return this; + } + + public org.apache.maven.model.profile.ProfileActivationContext setExecutionProperties( + Properties executionProperties ) + { + this.executionProperties.clear(); + this.executionProperties.putAll( executionProperties ); + return this; + } + + public org.apache.maven.model.profile.ProfileActivationContext setInactiveProfileIds( + List inactiveProfileIds ) + { + setExplicitlyInactiveProfileIds( inactiveProfileIds ); + return this; + } + } diff --git a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java index b5d04fe91a..a250c92fe5 100644 --- a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java @@ -17,16 +17,10 @@ package org.apache.maven.project; import java.io.File; import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.ArtifactUtils; import org.apache.maven.artifact.InvalidRepositoryException; -import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.resolver.ArtifactResolutionException; import org.apache.maven.artifact.resolver.ArtifactResolutionRequest; import org.apache.maven.artifact.resolver.ArtifactResolutionResult; @@ -35,21 +29,11 @@ import org.apache.maven.lifecycle.LifecycleExecutionException; import org.apache.maven.lifecycle.LifecycleExecutor; import org.apache.maven.model.Build; import org.apache.maven.model.Model; -import org.apache.maven.model.Parent; -import org.apache.maven.model.Profile; -import org.apache.maven.model.Repository; -import org.apache.maven.model.inheritance.InheritanceAssembler; -import org.apache.maven.model.interpolator.Interpolator; +import org.apache.maven.model.ModelBuilder; +import org.apache.maven.model.ModelBuildingException; +import org.apache.maven.model.ModelBuildingResult; import org.apache.maven.model.io.ModelReader; -import org.apache.maven.model.management.ManagementInjector; -import org.apache.maven.model.normalization.ModelNormalizer; -import org.apache.maven.model.plugin.LifecycleBindingsInjector; -import org.apache.maven.model.plugin.PluginConfigurationExpander; -import org.apache.maven.model.profile.ProfileActivationException; -import org.apache.maven.model.profile.ProfileInjector; -import org.apache.maven.model.profile.ProfileSelector; -import org.apache.maven.model.validation.ModelValidationResult; -import org.apache.maven.model.validation.ModelValidator; +import org.apache.maven.model.resolver.ModelResolver; import org.apache.maven.project.artifact.ProjectArtifact; import org.apache.maven.repository.RepositorySystem; import org.codehaus.plexus.component.annotations.Component; @@ -68,10 +52,10 @@ public class DefaultProjectBuilder private Logger logger; @Requirement - private ModelReader modelReader; + private ModelBuilder modelBuilder; @Requirement - private ModelValidator validator; + private ModelReader modelReader; @Requirement private LifecycleExecutor lifecycle; @@ -79,30 +63,6 @@ public class DefaultProjectBuilder @Requirement private RepositorySystem repositorySystem; - @Requirement - private ModelNormalizer normalizer; - - @Requirement - private InheritanceAssembler inheritanceAssembler; - - @Requirement - private Interpolator interpolator; - - @Requirement - private ProfileSelector profileSelector; - - @Requirement - private ProfileInjector profileInjector; - - @Requirement - private ManagementInjector managementInjector; - - @Requirement - private LifecycleBindingsInjector lifecycleBindingsInjector; - - @Requirement - private PluginConfigurationExpander pluginConfigurationExpander; - @Requirement private ResolutionErrorHandler resolutionErrorHandler; @@ -133,80 +93,31 @@ public class DefaultProjectBuilder return project; } - List models; - + ModelResolver resolver = + new RepositoryModelResolver( repositorySystem, resolutionErrorHandler, configuration.getLocalRepository(), + configuration.getRemoteRepositories() ); + + ModelBuildingResult result; try { - models = build( "unknown", pomFile, configuration ); + result = modelBuilder.build( pomFile, configuration.getModelBuildingRequest(), resolver ); } - catch ( IOException e ) + catch ( ModelBuildingException e ) { - throw new ProjectBuildingException( "", "", e ); - } - - Model model = models.get(0); - - model.setProjectDirectory( projectDirectory ); - - //Profiles - // - // Active profiles can be contributed to the MavenExecutionRequest as well as from the POM - - List projectProfiles; - - try - { - projectProfiles = new ArrayList(); - projectProfiles.addAll( model.getProfiles() ); - if ( configuration.getProfiles() != null ) - { - projectProfiles.addAll( configuration.getProfiles() ); - } - projectProfiles = profileSelector.getActiveProfiles( projectProfiles, configuration ); - } - catch ( ProfileActivationException e ) - { - throw new ProjectBuildingException( model.getId(), "Failed to activate pom profiles.", e ); - } - - for ( Profile p : projectProfiles ) - { - if ( !"pom".equals( p.getSource() ) ) - { - logger.debug( "Merging profile into model (build): Model = " + model.getId() + ", Profile = " - + p.getId() ); - profileInjector.injectProfile( model, p ); - } + throw new ProjectBuildingException( "[unknown]", "Failed to build project for " + pomFile, pomFile, e ); } + Model model = result.getEffectiveModel(); + + project = fromModelToMavenProject( model, result.getRawModels().get( 1 ).getPomFile(), configuration, model.getPomFile() ); + try { - model = interpolateModel( model, configuration, pomFile ); - - if ( configuration.isProcessPlugins() ) - { - lifecycleBindingsInjector.injectLifecycleBindings( model ); - } - - managementInjector.injectManagement( model ); - - validateModel( model, pomFile, configuration.istLenientValidation() ); - - File parentFile = ( models.size() > 1 ) ? models.get( 1 ).getPomFile() : null; - - project = fromModelToMavenProject( model, parentFile, configuration, pomFile ); - if ( configuration.isProcessPlugins() ) { - pluginConfigurationExpander.expandPluginConfiguration( project.getModel() ); - - lifecycle.populateDefaultConfigurationForPlugins( project.getModel().getBuild().getPlugins(), configuration.getLocalRepository(), project.getRemoteArtifactRepositories() ); + lifecycle.populateDefaultConfigurationForPlugins( model.getBuild().getPlugins(), configuration.getLocalRepository(), project.getRemoteArtifactRepositories() ); } } - catch ( IOException e ) - { - throw new ProjectBuildingException( "", "", e ); - } catch ( LifecycleExecutionException e ) { throw new ProjectBuildingException( "", e.getMessage(), e ); @@ -219,7 +130,7 @@ public class DefaultProjectBuilder project.addCompileSourceRoot( build.getSourceDirectory() ); project.addTestCompileSourceRoot( build.getTestSourceDirectory() ); project.setFile( pomFile ); - project.setActiveProfiles( projectProfiles ); + project.setActiveProfiles( result.getActiveProfiles( result.getRawModel() ) ); projectCache.put( cacheKey, project ); @@ -321,24 +232,8 @@ public class DefaultProjectBuilder return new MavenProjectBuildingResult( project, result ); } - private Model interpolateModel( Model model, ProjectBuildingRequest config, File projectDescriptor ) - throws ProjectBuildingException - { - try - { - model = interpolator.interpolateModel( model, config.getExecutionProperties(), model.getProjectDirectory() ); - } - catch ( IOException e ) - { - String projectId = safeVersionlessKey( model.getGroupId(), model.getArtifactId() ); - throw new ProjectBuildingException( projectId, "", projectDescriptor, e ); - } - - return model; - } - private MavenProject fromModelToMavenProject( Model model, File parentFile, ProjectBuildingRequest config, File projectDescriptor ) - throws InvalidProjectModelException, IOException + throws InvalidProjectModelException { MavenProject project; String projectId = safeVersionlessKey( model.getGroupId(), model.getArtifactId() ); @@ -360,134 +255,6 @@ public class DefaultProjectBuilder return project; } - private List build( String projectId, File pomFile, ProjectBuildingRequest projectBuilderConfiguration ) - throws ProjectBuildingException, IOException - { - Model mainModel = readModel( projectId, pomFile, !projectBuilderConfiguration.istLenientValidation() ); - mainModel.setProjectDirectory( pomFile.getParentFile() ); - - List domainModels = new ArrayList(); - - domainModels.add( mainModel ); - - ArtifactRepository localRepository = projectBuilderConfiguration.getLocalRepository(); - - List remoteRepositories = new ArrayList(); - try - { - for ( Profile profile : profileSelector.getActiveProfiles( projectBuilderConfiguration.getProfiles(), - projectBuilderConfiguration ) ) - { - for ( Repository repository : profile.getRepositories() ) - { - try - { - remoteRepositories.add( repositorySystem.buildArtifactRepository( repository ) ); - } - catch ( InvalidRepositoryException e ) - { - throw new ProjectBuildingException( projectId, "Failed to create remote repository " - + repository, pomFile, e ); - } - } - } - remoteRepositories = repositorySystem.getMirrors( remoteRepositories ); - } - catch ( ProfileActivationException e ) - { - throw new ProjectBuildingException( projectId, "Failed to determine active profiles", pomFile, e ); - } - remoteRepositories.addAll( projectBuilderConfiguration.getRemoteRepositories() ); - - if ( mainModel.getParent() != null ) - { - List mavenParents; - - if ( isParentLocal( mainModel.getParent().getRelativePath(), pomFile.getParentFile() ) ) - { - mavenParents = getDomainModelParentsFromLocalPath( mainModel, localRepository, remoteRepositories, pomFile.getParentFile(), projectBuilderConfiguration ); - } - else - { - mavenParents = getDomainModelParentsFromRepository( mainModel, localRepository, remoteRepositories ); - } - - domainModels.addAll( mavenParents ); - } - - for ( Model model : domainModels ) - { - normalizer.mergeDuplicates( model ); - } - - domainModels.add( getSuperModel() ); - List profileModels = new ArrayList(); - //Process Profiles - for ( Model model : domainModels ) - { - if ( !model.getProfiles().isEmpty() ) - { - Collection profiles; - try - { - profiles = - profileSelector.getActiveProfiles( model.getProfiles(), projectBuilderConfiguration ); - } - catch ( ProfileActivationException e ) - { - throw new ProjectBuildingException( projectId, "Failed to determine active profiles", pomFile, e ); - } - if ( !profiles.isEmpty() ) - { - for ( Profile p : profiles ) - { - logger.debug( "Merging profile into model: Model = " + model.getId() + ", Profile = " + p.getId() ); - profileInjector.injectProfile( model, p ); - } - } - } - profileModels.add( model ); - } - - processModelsForInheritance( profileModels ); - - return profileModels; - } - - private Model processModelsForInheritance( List models ) - { - List parentsFirst = new ArrayList( models ); - Collections.reverse( parentsFirst ); - - Model previousModel = null; - - for ( Model currentModel : parentsFirst ) - { - inheritanceAssembler.assembleModelInheritance( currentModel, previousModel ); - previousModel = currentModel; - } - - return previousModel; - } - - private void validateModel( Model model, File pomFile, boolean lenient ) - throws InvalidProjectModelException - { - // Must validate before artifact construction to make sure dependencies are good - ModelValidationResult validationResult = validator.validateEffectiveModel( model, lenient ); - - String projectId = safeVersionlessKey( model.getGroupId(), model.getArtifactId() ); - - if ( validationResult.getMessageCount() > 0 ) - { - for ( String s : validationResult.getMessages() ) - { - logger.error( s ); - } - throw new InvalidProjectModelException( projectId, "Failed to validate POM", pomFile, validationResult ); - } - } - private static String safeVersionlessKey( String groupId, String artifactId ) { String gid = groupId; @@ -507,208 +274,6 @@ public class DefaultProjectBuilder return ArtifactUtils.versionlessKey( gid, aid ); } - /** - * Returns true if the relative path of the specified parent references a pom, otherwise returns - * false. - * - * @param relativePath the parent model info - * @param projectDirectory the project directory of the child pom - * @return true if the relative path of the specified parent references a pom, otherwise returns - * fals - */ - private static boolean isParentLocal( String relativePath, File projectDirectory ) - { - File f = new File( projectDirectory, relativePath ).getAbsoluteFile(); - - if ( f.isDirectory() ) - { - f = new File( f, "pom.xml" ); - } - - return f.isFile(); - } - - private List getDomainModelParentsFromRepository( Model model, ArtifactRepository localRepository, List remoteRepositories ) - throws IOException, ProjectBuildingException - { - List models = new ArrayList(); - - Parent parent = model.getParent(); - - if ( parent == null || localRepository == null ) - { - return models; - } - - Artifact artifactParent = - repositorySystem.createProjectArtifact( parent.getGroupId(), parent.getArtifactId(), parent.getVersion() ); - - ArtifactResolutionRequest request = new ArtifactResolutionRequest() - .setArtifact( artifactParent ) - .setLocalRepository( localRepository ) - .setRemoteRepostories( remoteRepositories ); - - ArtifactResolutionResult result; - try - { - result = repositorySystem.resolve( request ); - } - catch ( Exception e ) - { - throw (IOException) new IOException( "The parent POM " + artifactParent + " could not be retrieved from any repository" ).initCause( e ); - } - - try - { - resolutionErrorHandler.throwErrors( request, result ); - } - catch ( ArtifactResolutionException e ) - { - throw (IOException) new IOException( "The parent POM " + artifactParent + " could not be retrieved from any repository" ).initCause( e ); - } - - Model parentModel = readModel( parent.getId(), artifactParent.getFile(), true ); - - if ( !isMatchingParent( parentModel, parent ) ) - { - //shane: what does this mean exactly and why does it occur - logger.debug( "Parent pom ids do not match: Parent File = " + artifactParent.getFile().getAbsolutePath() + ": Child ID = " + model.getId() ); - - // return domainModels; - // TODO: review the proper handling of this, can it happen at all and if should we really continue or error out? - } - - models.add( parentModel ); - - models.addAll( getDomainModelParentsFromRepository( parentModel, localRepository, remoteRepositories ) ); - return models; - } - - /** - * Returns list of domain model parents of the specified domain model. The parent domain models - * are part - * - * @param domainModel - * @param projectDirectory - * @return - * @throws IOException - * @throws ProjectBuildingException - */ - private List getDomainModelParentsFromLocalPath( Model model, ArtifactRepository localRepository, List remoteRepositories, File projectDirectory, - ProjectBuildingRequest projectBuilderConfiguration ) - throws IOException, ProjectBuildingException - { - List models = new ArrayList(); - - Parent parent = model.getParent(); - - if ( parent == null ) - { - return models; - } - - File parentFile = new File( projectDirectory, parent.getRelativePath() ).getCanonicalFile(); - if ( parentFile.isDirectory() ) - { - parentFile = new File( parentFile.getAbsolutePath(), "pom.xml" ); - } - - if ( !parentFile.isFile() ) - { - throw new IOException( "File does not exist: File = " + parentFile.getAbsolutePath() ); - } - - Model parentModel = readModel( parent.getId(), parentFile, true ); - parentModel.setProjectDirectory( parentFile.getParentFile() ); - - if ( !isMatchingParent( parentModel, parent ) ) - { - logger.info( "Parent pom ids do not match: Parent File = " + parentFile.getAbsolutePath() + ", Parent ID = " + parentModel.getId() + ", Child ID = " + model.getId() - + ", Expected Parent ID = " + parent.getId() ); - - List parentModels = getDomainModelParentsFromRepository( model, localRepository, remoteRepositories ); - - if ( parentModels.isEmpty() ) - { - throw new IOException( "Unable to find parent pom on local path or repo: " + parent.getId() ); - } - - models.addAll( parentModels ); - return models; - } - - models.add( parentModel ); - - if ( parentModel.getParent() != null ) - { - if ( isParentLocal( parentModel.getParent().getRelativePath(), parentFile.getParentFile() ) ) - { - models.addAll( getDomainModelParentsFromLocalPath( parentModel, localRepository, remoteRepositories, - parentFile.getParentFile(), - projectBuilderConfiguration ) ); - } - else - { - models.addAll( getDomainModelParentsFromRepository( parentModel, localRepository, remoteRepositories ) ); - } - } - - return models; - } - - private boolean isMatchingParent( Model parentModel, Parent parent ) - { - if ( parentModel.getGroupId() != null ) - { - if ( !parent.getGroupId().equals( parentModel.getGroupId() ) ) - { - return false; - } - } - else if ( parentModel.getParent() == null || !parent.getGroupId().equals( parentModel.getParent().getGroupId() ) ) - { - return false; - } - if ( !parent.getArtifactId().equals( parentModel.getArtifactId() ) ) - { - return false; - } - if ( parentModel.getVersion() != null ) - { - if ( !parent.getVersion().equals( parentModel.getVersion() ) ) - { - return false; - } - } - else if ( parentModel.getParent() == null || !parent.getVersion().equals( parentModel.getParent().getVersion() ) ) - { - return false; - } - return true; - } - - private Model readModel( String projectId, File pomFile, boolean strict ) - throws ProjectBuildingException - { - Model model; - - Map options = - Collections. singletonMap( ModelReader.IS_STRICT, Boolean.valueOf( strict ) ); - try - { - model = modelReader.read( pomFile, options ); - } - catch ( IOException e ) - { - throw new ProjectBuildingException( projectId, "Failed to read POM for " + projectId + " from " + pomFile - + ": " + e.getMessage(), pomFile, e ); - } - - validator.validateRawModel( model, !strict ); - - return model; - } - // Super Model Handling private static final String MAVEN_MODEL_VERSION = "4.0.0"; diff --git a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilderConfiguration.java b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilderConfiguration.java index a3cb858127..0382abdbb0 100644 --- a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilderConfiguration.java +++ b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilderConfiguration.java @@ -19,171 +19,52 @@ package org.apache.maven.project; * under the License. */ -import java.util.ArrayList; import java.util.List; import java.util.Properties; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.model.ModelEventListener; -import org.apache.maven.model.Profile; +@Deprecated public class DefaultProjectBuilderConfiguration + extends DefaultProjectBuildingRequest implements ProjectBuilderConfiguration { - private ArtifactRepository localRepository; - - private List remoteRepositories; - - private Properties executionProperties; - - private List listeners; - - private MavenProject topProject; - - private boolean processPlugins = true; - - private boolean lenientValidation; - - private List activeProfileIds; - - private List inactiveProfileIds; - - private List profiles; - - public MavenProject getTopLevelProjectFromReactor() - { - return topProject; - } - - public void setTopLevelProjectForReactor(MavenProject mavenProject) - { - this.topProject = mavenProject; - } public ProjectBuilderConfiguration setLocalRepository( ArtifactRepository localRepository ) { - this.localRepository = localRepository; + super.setLocalRepository( localRepository ); return this; } - public ArtifactRepository getLocalRepository() - { - return localRepository; - } - - public List getRemoteRepositories() - { - if ( remoteRepositories == null ) - { - remoteRepositories = new ArrayList(); - } - return remoteRepositories; - } - public ProjectBuilderConfiguration setRemoteRepositories( List remoteRepositories ) { - this.remoteRepositories = remoteRepositories; + super.setRemoteRepositories( remoteRepositories ); return this; } - - public Properties getExecutionProperties() - { - if ( executionProperties == null ) - { - executionProperties = new Properties(); - } - return executionProperties; - } public ProjectBuilderConfiguration setExecutionProperties( Properties executionProperties ) { - this.executionProperties = executionProperties; + super.setExecutionProperties( executionProperties ); return this; } - public List getModelEventListeners() - { - return listeners; - } - public ProjectBuilderConfiguration setModelEventListeners( List listeners ) { - this.listeners = listeners; + super.setModelEventListeners( listeners ); return this; } - public boolean isProcessPlugins() - { - return processPlugins; - } - public ProjectBuilderConfiguration setProcessPlugins( boolean processPlugins ) { - this.processPlugins = processPlugins; + super.setProcessPlugins( processPlugins ); return this; } public ProjectBuilderConfiguration setLenientValidation( boolean lenientValidation ) { - this.lenientValidation = lenientValidation; + super.setLenientValidation( lenientValidation ); return this; } - public boolean istLenientValidation() - { - return lenientValidation; - } - - public List getActiveProfileIds() - { - if ( activeProfileIds == null ) - { - activeProfileIds = new ArrayList(); - } - return activeProfileIds; - } - - public void setActiveProfileIds( List activeProfileIds ) - { - this.activeProfileIds = activeProfileIds; - } - - public List getInactiveProfileIds() - { - if ( inactiveProfileIds == null ) - { - inactiveProfileIds = new ArrayList(); - } - return inactiveProfileIds; - } - - public void setInactiveProfileIds( List inactiveProfileIds ) - { - this.inactiveProfileIds = inactiveProfileIds; - } - - public void setProfiles( List profiles ) - { - this.profiles = profiles; - } - - public void addProfile( Profile profile ) - { - if ( profiles == null ) - { - profiles = new ArrayList(); - } - - profiles.add( profile ); - } - - public List getProfiles() - { - if ( profiles == null ) - { - profiles = new ArrayList(); - } - return profiles; - } - } diff --git a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingRequest.java b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingRequest.java index a57583263e..6c66fb665e 100644 --- a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingRequest.java +++ b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingRequest.java @@ -24,6 +24,8 @@ import java.util.List; import java.util.Properties; import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.model.DefaultModelBuildingRequest; +import org.apache.maven.model.ModelBuildingRequest; import org.apache.maven.model.ModelEventListener; import org.apache.maven.model.Profile; @@ -33,23 +35,13 @@ public class DefaultProjectBuildingRequest private ArtifactRepository localRepository; private List remoteRepositories; - - private Properties executionProperties; private List listeners; private MavenProject topProject; - - private boolean processPlugins = true; - private boolean lenientValidation; + private ModelBuildingRequest modelBuildingRequest = new DefaultModelBuildingRequest().setProcessPlugins( true ); - private List activeProfileIds; - - private List inactiveProfileIds; - - private List profiles; - public MavenProject getTopLevelProjectFromReactor() { return topProject; @@ -88,16 +80,12 @@ public class DefaultProjectBuildingRequest public Properties getExecutionProperties() { - if ( executionProperties == null ) - { - executionProperties = new Properties(); - } - return executionProperties; + return modelBuildingRequest.getExecutionProperties(); } public ProjectBuildingRequest setExecutionProperties( Properties executionProperties ) { - this.executionProperties = executionProperties; + modelBuildingRequest.setExecutionProperties( executionProperties ); return this; } @@ -114,76 +102,64 @@ public class DefaultProjectBuildingRequest public boolean isProcessPlugins() { - return processPlugins; + return modelBuildingRequest.isProcessPlugins(); } public ProjectBuildingRequest setProcessPlugins( boolean processPlugins ) { - this.processPlugins = processPlugins; + modelBuildingRequest.setProcessPlugins( processPlugins ); return this; } public ProjectBuildingRequest setLenientValidation( boolean lenientValidation ) { - this.lenientValidation = lenientValidation; + modelBuildingRequest.setLenientValidation( lenientValidation ); return this; } public boolean istLenientValidation() { - return lenientValidation; + return modelBuildingRequest.istLenientValidation(); } public List getActiveProfileIds() { - if ( activeProfileIds == null ) - { - activeProfileIds = new ArrayList(); - } - return activeProfileIds; + return modelBuildingRequest.getActiveProfileIds(); } public void setActiveProfileIds( List activeProfileIds ) { - this.activeProfileIds = activeProfileIds; + modelBuildingRequest.setActiveProfileIds( activeProfileIds ); } public List getInactiveProfileIds() { - if ( inactiveProfileIds == null ) - { - inactiveProfileIds = new ArrayList(); - } - return inactiveProfileIds; + return modelBuildingRequest.getInactiveProfileIds(); } public void setInactiveProfileIds( List inactiveProfileIds ) { - this.inactiveProfileIds = inactiveProfileIds; + modelBuildingRequest.setInactiveProfileIds( inactiveProfileIds ); } public void setProfiles( List profiles ) { - this.profiles = profiles; + modelBuildingRequest.setProfiles( profiles ); } public void addProfile( Profile profile ) { - if ( profiles == null ) - { - profiles = new ArrayList(); - } - - profiles.add( profile ); + modelBuildingRequest.getProfiles().add(profile); } public List getProfiles() { - if ( profiles == null ) - { - profiles = new ArrayList(); - } - return profiles; + return modelBuildingRequest.getProfiles(); + } + + public ModelBuildingRequest getModelBuildingRequest() + { + return modelBuildingRequest; } } diff --git a/maven-core/src/main/java/org/apache/maven/project/ProjectBuildingRequest.java b/maven-core/src/main/java/org/apache/maven/project/ProjectBuildingRequest.java index 8b7e989f19..4420f8cf42 100644 --- a/maven-core/src/main/java/org/apache/maven/project/ProjectBuildingRequest.java +++ b/maven-core/src/main/java/org/apache/maven/project/ProjectBuildingRequest.java @@ -4,11 +4,10 @@ import java.util.List; import java.util.Properties; import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.model.ModelBuildingRequest; import org.apache.maven.model.Profile; -import org.apache.maven.model.profile.ProfileActivationContext; public interface ProjectBuildingRequest - extends ProfileActivationContext { ProjectBuildingRequest setLocalRepository( ArtifactRepository localRepository ); @@ -72,4 +71,7 @@ public interface ProjectBuildingRequest void setProfiles( List profiles ); List getProfiles(); + + ModelBuildingRequest getModelBuildingRequest(); + } diff --git a/maven-core/src/main/java/org/apache/maven/project/RepositoryModelResolver.java b/maven-core/src/main/java/org/apache/maven/project/RepositoryModelResolver.java new file mode 100644 index 0000000000..ff01e3c182 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/project/RepositoryModelResolver.java @@ -0,0 +1,126 @@ +package org.apache.maven.project; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.artifact.resolver.ArtifactResolutionException; +import org.apache.maven.artifact.resolver.ArtifactResolutionRequest; +import org.apache.maven.artifact.resolver.ArtifactResolutionResult; +import org.apache.maven.artifact.resolver.ResolutionErrorHandler; +import org.apache.maven.model.FileModelSource; +import org.apache.maven.model.ModelSource; +import org.apache.maven.model.Repository; +import org.apache.maven.model.resolver.InvalidRepositoryException; +import org.apache.maven.model.resolver.ModelResolver; +import org.apache.maven.model.resolver.UnresolvableModelException; +import org.apache.maven.repository.RepositorySystem; + +/** + * Implements a model resolver backed by the Maven Repository API. + * + * @author Benjamin Bentmann + */ +class RepositoryModelResolver + implements ModelResolver +{ + + private RepositorySystem repositorySystem; + + private ResolutionErrorHandler resolutionErrorHandler; + + private ArtifactRepository localRepository; + + private List remoteRepositories; + + public RepositoryModelResolver( RepositorySystem repositorySystem, ResolutionErrorHandler resolutionErrorHandler, + ArtifactRepository localRepository, List remoteRepositories ) + { + if ( repositorySystem == null ) + { + throw new IllegalArgumentException( "no repository system specified" ); + } + this.repositorySystem = repositorySystem; + + if ( resolutionErrorHandler == null ) + { + throw new IllegalArgumentException( "no resolution error handler specified" ); + } + this.resolutionErrorHandler = resolutionErrorHandler; + + if ( localRepository == null ) + { + throw new IllegalArgumentException( "no local repository specified" ); + } + this.localRepository = localRepository; + + if ( remoteRepositories == null ) + { + throw new IllegalArgumentException( "no remote repositories specified" ); + } + this.remoteRepositories = new ArrayList( remoteRepositories ); + } + + public void addRepository( Repository repository ) + throws InvalidRepositoryException + { + try + { + ArtifactRepository repo = repositorySystem.buildArtifactRepository( repository ); + remoteRepositories.addAll( 0, repositorySystem.getMirrors( Arrays.asList( repo ) ) ); + } + catch ( org.apache.maven.artifact.InvalidRepositoryException e ) + { + throw new InvalidRepositoryException( "Failed to create artifact repository for " + repository.getId() + + " with layout " + repository.getLayout() + " and URL " + repository.getUrl(), repository, e ); + } + + } + + public ModelSource resolveModel( String groupId, String artifactId, String version ) + throws UnresolvableModelException + { + Artifact artifactParent = repositorySystem.createProjectArtifact( groupId, artifactId, version ); + + ArtifactResolutionRequest request = new ArtifactResolutionRequest(); + request.setArtifact( artifactParent ); + request.setLocalRepository( localRepository ); + request.setRemoteRepostories( remoteRepositories ); + + ArtifactResolutionResult result = repositorySystem.resolve( request ); + + try + { + resolutionErrorHandler.throwErrors( request, result ); + } + catch ( ArtifactResolutionException e ) + { + throw new UnresolvableModelException( "Failed to resolve POM for " + groupId + ":" + artifactId + ":" + + version, e ); + } + + return new FileModelSource( artifactParent.getFile() ); + } + +} diff --git a/maven-core/src/test/java/org/apache/maven/project/PomConstructionTest.java b/maven-core/src/test/java/org/apache/maven/project/PomConstructionTest.java index 3cf4cb9446..ed6b35c9de 100644 --- a/maven-core/src/test/java/org/apache/maven/project/PomConstructionTest.java +++ b/maven-core/src/test/java/org/apache/maven/project/PomConstructionTest.java @@ -221,7 +221,6 @@ public class PomConstructionTest throws Exception { PomTestWrapper pom = buildPom( "reporting-interpolation" ); - pom = new PomTestWrapper(pom.getMavenProject()); assertEquals( createPath(Arrays.asList(System.getProperty("user.dir"), "src", "test", "resources-project-builder", "reporting-interpolation", "target", "site")), pom.getValue( "reporting/outputDirectory" ) ); diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/DefaultModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/DefaultModelBuilder.java new file mode 100644 index 0000000000..0931086563 --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/DefaultModelBuilder.java @@ -0,0 +1,481 @@ +package org.apache.maven.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.apache.maven.model.inheritance.InheritanceAssembler; +import org.apache.maven.model.interpolator.Interpolator; +import org.apache.maven.model.io.ModelParseException; +import org.apache.maven.model.io.ModelReader; +import org.apache.maven.model.management.ManagementInjector; +import org.apache.maven.model.normalization.ModelNormalizer; +import org.apache.maven.model.plugin.LifecycleBindingsInjector; +import org.apache.maven.model.plugin.PluginConfigurationExpander; +import org.apache.maven.model.profile.ProfileActivationException; +import org.apache.maven.model.profile.ProfileInjector; +import org.apache.maven.model.profile.ProfileSelector; +import org.apache.maven.model.resolver.InvalidRepositoryException; +import org.apache.maven.model.resolver.ModelResolver; +import org.apache.maven.model.resolver.UnresolvableModelException; +import org.apache.maven.model.validation.ModelValidationResult; +import org.apache.maven.model.validation.ModelValidator; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.component.annotations.Requirement; + +/** + * @author Benjamin Bentmann + */ +@Component( role = ModelBuilder.class ) +public class DefaultModelBuilder + implements ModelBuilder +{ + + private Model superModel; + + @Requirement + private ModelReader modelReader; + + @Requirement + private ModelValidator modelValidator; + + @Requirement + private ModelNormalizer modelNormalizer; + + @Requirement + private Interpolator modelInterpolator; + + @Requirement + private InheritanceAssembler inheritanceAssembler; + + @Requirement + private ProfileSelector profileSelector; + + @Requirement + private ProfileInjector profileInjector; + + @Requirement + private ManagementInjector managementInjector; + + @Requirement + private LifecycleBindingsInjector lifecycleBindingsInjector; + + @Requirement + private PluginConfigurationExpander pluginConfigurationExpander; + + public ModelBuildingResult build( File pomFile, ModelBuildingRequest request, ModelResolver modelResolver ) + throws ModelBuildingException + { + return build( new FileModelSource( pomFile ), pomFile, request, modelResolver ); + } + + public ModelBuildingResult build( ModelSource modelSource, ModelBuildingRequest request, ModelResolver modelResolver ) + throws ModelBuildingException + { + return build( modelSource, null, request, modelResolver ); + } + + private ModelBuildingResult build( ModelSource modelSource, File pomFile, ModelBuildingRequest request, + ModelResolver modelResolver ) + throws ModelBuildingException + { + DefaultModelBuildingResult result = new DefaultModelBuildingResult(); + + List activeExternalProfiles = getActiveExternalProfiles( request ); + + Model model = readModel( modelSource, request ); + model.setPomFile( pomFile ); + + List rawModels = new ArrayList(); + List resultModels = new ArrayList(); + + for ( Model current = model; current != null; current = readParent( current, request, modelResolver ) ) + { + Model resultModel = current; + resultModels.add( resultModel ); + + Model rawModel = ModelUtils.cloneModel( current ); + rawModels.add( rawModel ); + + modelNormalizer.mergeDuplicates( resultModel ); + + List activeProjectProfiles = getActiveProjectProfiles( rawModel, request ); + + List activeProfiles = activeProjectProfiles; + if ( current == model ) + { + activeProfiles = new ArrayList( activeProjectProfiles.size() + activeExternalProfiles.size() ); + activeProfiles.addAll( activeProjectProfiles ); + activeProfiles.addAll( activeExternalProfiles ); + } + + for ( Profile activeProfile : activeProfiles ) + { + profileInjector.injectProfile( resultModel, activeProfile ); + } + + result.setActiveProfiles( rawModel, activeProfiles ); + + configureResolver( modelResolver, resultModel ); + } + + Model superModel = getSuperModel(); + rawModels.add( superModel ); + resultModels.add( superModel ); + + result.setRawModels( rawModels ); + + assembleInheritance( resultModels ); + + Model resultModel = resultModels.get( 0 ); + + resultModel = interpolateModel( resultModel, request ); + resultModels.set( 0, resultModel ); + + if ( request.isProcessPlugins() ) + { + lifecycleBindingsInjector.injectLifecycleBindings( resultModel ); + } + + managementInjector.injectManagement( resultModel ); + + if ( request.isProcessPlugins() ) + { + pluginConfigurationExpander.expandPluginConfiguration( resultModel ); + } + + validateModel( resultModel, false, request ); + + result.setEffectiveModel( resultModel ); + + return result; + } + + private Model readModel( ModelSource modelSource, ModelBuildingRequest request ) + throws ModelBuildingException + { + Model model; + + try + { + Map options = + Collections. singletonMap( ModelReader.IS_STRICT, + Boolean.valueOf( !request.istLenientValidation() ) ); + model = modelReader.read( modelSource.getInputStream(), options ); + } + catch ( ModelParseException e ) + { + throw new UnparseableModelException( "Failed to parse POM " + modelSource.getLocation(), e.getLineNumber(), + e.getColumnNumber(), e ); + } + catch ( IOException e ) + { + throw new UnparseableModelException( "Failed to read POM " + modelSource.getLocation(), -1, -1, e ); + } + + validateModel( model, true, request ); + + return model; + } + + private void validateModel( Model model, boolean raw, ModelBuildingRequest request ) + throws ModelBuildingException + { + ModelValidationResult result; + + if ( raw ) + { + result = modelValidator.validateRawModel( model, request.istLenientValidation() ); + } + else + { + result = modelValidator.validateEffectiveModel( model, request.istLenientValidation() ); + } + + if ( result.getMessageCount() > 0 ) + { + throw new InvalidModelException( "Failed to validate POM " + toSourceHint( model ), result ); + } + } + + private List getActiveExternalProfiles( ModelBuildingRequest request ) + throws ModelBuildingException + { + try + { + return profileSelector.getActiveProfiles( request.getProfiles(), request.getProfileActivationContext() ); + } + catch ( ProfileActivationException e ) + { + throw new InvalidProfileException( "Failed to determine activation status of external profile " + + e.getProfile(), e.getProfile(), e ); + } + } + + private List getActiveProjectProfiles( Model model, ModelBuildingRequest request ) + throws ModelBuildingException + { + try + { + return profileSelector.getActiveProfiles( model.getProfiles(), request.getProfileActivationContext() ); + } + catch ( ProfileActivationException e ) + { + throw new InvalidProfileException( "Failed to determine activation status of project profile " + + e.getProfile() + " for POM " + toSourceHint( model ), e.getProfile(), e ); + } + } + + private void configureResolver( ModelResolver modelResolver, Model model ) + throws ModelBuildingException + { + for ( Repository repository : model.getRepositories() ) + { + try + { + modelResolver.addRepository( repository ); + } + catch ( InvalidRepositoryException e ) + { + throw new InvalidModelException( "Failed to validate repository " + repository.getId() + " for POM " + + toSourceHint( model ), e ); + } + } + } + + private void assembleInheritance( List models ) + { + for ( int i = models.size() - 2; i >= 0; i-- ) + { + Model parent = models.get( i + 1 ); + Model child = models.get( i ); + inheritanceAssembler.assembleModelInheritance( child, parent ); + } + } + + private Model interpolateModel( Model model, ModelBuildingRequest request ) + throws ModelBuildingException + { + try + { + Model result = + modelInterpolator.interpolateModel( model, + request.getProfileActivationContext().getExecutionProperties(), + model.getProjectDirectory() ); + result.setPomFile( model.getPomFile() ); + return result; + } + catch ( IOException e ) + { + throw new ModelBuildingException( "Failed to interpolate model " + toSourceHint( model ), e ); + } + } + + private Model readParent( Model childModel, ModelBuildingRequest request, ModelResolver modelResolver ) + throws ModelBuildingException + { + Model parentModel; + + Parent parent = childModel.getParent(); + + if ( parent != null ) + { + parentModel = readParentLocally( childModel, request ); + + if ( parentModel == null ) + { + parentModel = readParentExternally( childModel, request, modelResolver ); + } + } + else + { + parentModel = null; + } + + return parentModel; + } + + private Model readParentLocally( Model childModel, ModelBuildingRequest request ) + throws ModelBuildingException + { + File projectDirectory = childModel.getProjectDirectory(); + if ( projectDirectory == null ) + { + return null; + } + + Parent parent = childModel.getParent(); + + File pomFile = new File( new File( projectDirectory, parent.getRelativePath() ).toURI().normalize() ); + if ( !pomFile.isFile() ) + { + return null; + } + + Model candidateModel = readModel( new FileModelSource( pomFile ), request ); + candidateModel.setPomFile( pomFile ); + + String groupId = candidateModel.getGroupId(); + if ( groupId == null && candidateModel.getParent() != null ) + { + groupId = candidateModel.getParent().getGroupId(); + } + String artifactId = candidateModel.getArtifactId(); + String version = candidateModel.getVersion(); + if ( version == null && candidateModel.getParent() != null ) + { + version = candidateModel.getParent().getVersion(); + } + + if ( groupId == null || !groupId.equals( parent.getGroupId() ) ) + { + return null; + } + if ( artifactId == null || !artifactId.equals( parent.getArtifactId() ) ) + { + return null; + } + if ( version == null || !version.equals( parent.getVersion() ) ) + { + return null; + } + + return candidateModel; + } + + private Model readParentExternally( Model childModel, ModelBuildingRequest request, ModelResolver modelResolver ) + throws ModelBuildingException + { + Parent parent = childModel.getParent(); + + ModelSource modelSource; + try + { + modelSource = modelResolver.resolveModel( parent.getGroupId(), parent.getArtifactId(), parent.getVersion() ); + } + catch ( UnresolvableModelException e ) + { + throw new UnresolvableParentException( "Failed to resolve parent POM " + toId( parent ) + " for POM " + + toSourceHint( childModel ), e ); + } + + return readModel( modelSource, request ); + } + + private Model getSuperModel() + { + if ( superModel == null ) + { + InputStream is = getClass().getResourceAsStream( "/org/apache/maven/project/pom-4.0.0.xml" ); + try + { + superModel = modelReader.read( is, null ); + } + catch ( IOException e ) + { + throw new IllegalStateException( "The super POM is damaged" + + ", please verify the integrity of your Maven installation", e ); + } + } + + return ModelUtils.cloneModel( superModel ); + } + + private String toSourceHint( Model model ) + { + StringBuilder buffer = new StringBuilder( 128 ); + + buffer.append( toId( model ) ); + + File pomFile = model.getPomFile(); + if ( pomFile != null ) + { + buffer.append( " (" ).append( pomFile ).append( ")" ); + } + + return buffer.toString(); + } + + private String toId( Model model ) + { + StringBuilder buffer = new StringBuilder( 64 ); + + if ( model.getGroupId() != null ) + { + buffer.append( model.getGroupId() ); + } + else if ( model.getParent() != null && model.getParent().getGroupId() != null ) + { + buffer.append( model.getParent().getGroupId() ); + } + else + { + buffer.append( "[unknown-group-id]" ); + } + + buffer.append( ':' ); + + if ( model.getArtifactId() != null ) + { + buffer.append( model.getArtifactId() ); + } + else + { + buffer.append( "[unknown-artifact-id]" ); + } + + buffer.append( ':' ); + + if ( model.getVersion() != null ) + { + buffer.append( model.getVersion() ); + } + else if ( model.getParent() != null && model.getParent().getVersion() != null ) + { + buffer.append( model.getParent().getVersion() ); + } + else + { + buffer.append( "[unknown-version]" ); + } + + return buffer.toString(); + } + + private String toId( Parent parent ) + { + StringBuilder buffer = new StringBuilder( 64 ); + + buffer.append( parent.getGroupId() ); + buffer.append( ':' ); + buffer.append( parent.getArtifactId() ); + buffer.append( ':' ); + buffer.append( parent.getVersion() ); + + return buffer.toString(); + } + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/DefaultModelBuildingRequest.java b/maven-model-builder/src/main/java/org/apache/maven/model/DefaultModelBuildingRequest.java new file mode 100644 index 0000000000..3c91996402 --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/DefaultModelBuildingRequest.java @@ -0,0 +1,142 @@ +package org.apache.maven.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.apache.maven.model.profile.DefaultProfileActivationContext; +import org.apache.maven.model.profile.ProfileActivationContext; + +/** + * Collects settings that control building of effective models. + * + * @author Benjamin Bentmann + */ +public class DefaultModelBuildingRequest + implements ModelBuildingRequest +{ + + private boolean lenientValidation; + + private boolean processPlugins; + + private List profiles; + + private ProfileActivationContext profileActivationContext; + + public DefaultModelBuildingRequest() + { + profiles = new ArrayList(); + profileActivationContext = new DefaultProfileActivationContext(); + } + + public boolean istLenientValidation() + { + return lenientValidation; + } + + public DefaultModelBuildingRequest setLenientValidation( boolean lenientValidation ) + { + this.lenientValidation = lenientValidation; + + return this; + } + + public boolean isProcessPlugins() + { + return processPlugins; + } + + public DefaultModelBuildingRequest setProcessPlugins( boolean processPlugins ) + { + this.processPlugins = processPlugins; + + return this; + } + + public List getProfiles() + { + return profiles; + } + + public DefaultModelBuildingRequest setProfiles( List profiles ) + { + this.profiles.clear(); + if ( profiles != null ) + { + this.profiles.addAll( profiles ); + } + + return this; + } + + public List getActiveProfileIds() + { + return profileActivationContext.getActiveProfileIds(); + } + + public ModelBuildingRequest setActiveProfileIds( List activeProfileIds ) + { + profileActivationContext.setActiveProfileIds( activeProfileIds ); + return this; + } + + public List getInactiveProfileIds() + { + return profileActivationContext.getInactiveProfileIds(); + } + + public ModelBuildingRequest setInactiveProfileIds( List inactiveProfileIds ) + { + profileActivationContext.setInactiveProfileIds( inactiveProfileIds ); + return this; + } + + public Properties getExecutionProperties() + { + return profileActivationContext.getExecutionProperties(); + } + + public ModelBuildingRequest setExecutionProperties( Properties executionProperties ) + { + profileActivationContext.setExecutionProperties( executionProperties ); + return this; + } + + public ProfileActivationContext getProfileActivationContext() + { + return profileActivationContext; + } + + public DefaultModelBuildingRequest setProfileActivationContext( ProfileActivationContext profileActivationContext ) + { + if ( profileActivationContext == null ) + { + throw new IllegalArgumentException( "no profile activation context specified" ); + } + + this.profileActivationContext = profileActivationContext; + + return this; + } + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/DefaultModelBuildingResult.java b/maven-model-builder/src/main/java/org/apache/maven/model/DefaultModelBuildingResult.java new file mode 100644 index 0000000000..9dd0f8a1c7 --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/DefaultModelBuildingResult.java @@ -0,0 +1,125 @@ +package org.apache.maven.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Collects the output of the model builder. + * + * @author Benjamin Bentmann + */ +public class DefaultModelBuildingResult + implements ModelBuildingResult +{ + + private Model model; + + private List rawModels; + + private Map> activeProfiles; + + public DefaultModelBuildingResult() + { + rawModels = new ArrayList(); + activeProfiles = new HashMap>(); + } + + public Model getEffectiveModel() + { + return model; + } + + public DefaultModelBuildingResult setEffectiveModel( Model model ) + { + this.model = model; + + return this; + } + + public Model getRawModel() + { + return rawModels.get( 0 ); + } + + public List getRawModels() + { + return Collections.unmodifiableList( rawModels ); + } + + public DefaultModelBuildingResult setRawModels( List rawModels ) + { + this.rawModels.clear(); + if ( rawModels != null ) + { + this.rawModels.addAll( rawModels ); + } + + return this; + } + + public List getActiveProfiles( Model rawModel ) + { + List profiles = this.activeProfiles.get( rawModel ); + return ( profiles == null ) ? Collections. emptyList() : Collections.unmodifiableList( profiles ); + } + + public DefaultModelBuildingResult setActiveProfiles( Model rawModel, List activeProfiles ) + { + if ( rawModel == null ) + { + throw new IllegalArgumentException( "no model specified" ); + } + + if ( activeProfiles != null ) + { + this.activeProfiles.put( rawModel, new ArrayList( activeProfiles ) ); + } + else + { + this.activeProfiles.remove( rawModel ); + } + + return this; + } + + public DefaultModelBuildingResult addActiveProfiles( Model rawModel, List activeProfiles ) + { + if ( rawModel == null ) + { + throw new IllegalArgumentException( "no model specified" ); + } + + List currentProfiles = this.activeProfiles.get( rawModel ); + if ( currentProfiles == null ) + { + currentProfiles = new ArrayList( activeProfiles.size() ); + this.activeProfiles.put( rawModel, currentProfiles ); + } + currentProfiles.addAll( activeProfiles ); + + return this; + } + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/FileModelSource.java b/maven-model-builder/src/main/java/org/apache/maven/model/FileModelSource.java new file mode 100644 index 0000000000..f128315bb2 --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/FileModelSource.java @@ -0,0 +1,79 @@ +package org.apache.maven.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * Wraps an ordinary {@link File} as a model source. + * + * @author Benjamin Bentmann + */ +public class FileModelSource + implements ModelSource +{ + + private File pomFile; + + /** + * Creates a new model source backed by the specified file. + * + * @param pomFile The POM file, must not be {@code null}. + */ + public FileModelSource( File pomFile ) + { + if ( pomFile == null ) + { + throw new IllegalArgumentException( "no POM file specified" ); + } + this.pomFile = pomFile; + } + + public InputStream getInputStream() + throws IOException + { + return new FileInputStream( pomFile ); + } + + public String getLocation() + { + return pomFile.getPath(); + } + + /** + * Gets the POM file of this model source. + * + * @return The underlying POM file, never {@code null}. + */ + public File getPomFile() + { + return pomFile; + } + + @Override + public String toString() + { + return getLocation(); + } + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/InvalidModelException.java b/maven-model-builder/src/main/java/org/apache/maven/model/InvalidModelException.java new file mode 100644 index 0000000000..97bf22c4cb --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/InvalidModelException.java @@ -0,0 +1,53 @@ +package org.apache.maven.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.model.validation.ModelValidationResult; + +/** + * Signals an error due to invalid or missing model values. + * + * @author Benjamin Bentmann + */ +public class InvalidModelException + extends ModelBuildingException +{ + + private ModelValidationResult validationResult; + + public InvalidModelException( String message, ModelValidationResult validationResult ) + { + super( message ); + this.validationResult = validationResult; + } + + public InvalidModelException( String message, Throwable cause ) + { + super( message, cause ); + validationResult = new ModelValidationResult(); + validationResult.addMessage( ( cause != null ) ? cause.getMessage() : message ); + } + + public ModelValidationResult getValidationResult() + { + return validationResult; + } + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/InvalidProfileException.java b/maven-model-builder/src/main/java/org/apache/maven/model/InvalidProfileException.java new file mode 100644 index 0000000000..bcbdc821bf --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/InvalidProfileException.java @@ -0,0 +1,59 @@ +package org.apache.maven.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Signals an error during profile activation. + * + * @author Benjamin Bentmann + */ +public class InvalidProfileException + extends ModelBuildingException +{ + + /** + * The profile which raised this error, can be {@code null}. + */ + private Profile profile; + + /** + * Creates a new exception with specified detail message and cause for the given profile. + * + * @param message The detail message, may be {@code null}. + * @param profile The profile that caused the error, may be {@code null}. + * @param cause The cause, may be {@code null}. + */ + public InvalidProfileException( String message, Profile profile, Throwable cause ) + { + super( message ); + this.profile = profile; + } + + /** + * Gets the profile that causes this error (if any). + * + * @return The profile that causes this error or {@code null} if not applicable. + */ + public Profile getProfile() + { + return profile; + } + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/ModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/ModelBuilder.java new file mode 100644 index 0000000000..1df5a51012 --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/ModelBuilder.java @@ -0,0 +1,38 @@ +package org.apache.maven.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; + +import org.apache.maven.model.resolver.ModelResolver; + +/** + * @author Benjamin Bentmann + */ +public interface ModelBuilder +{ + + ModelBuildingResult build( File pomFile, ModelBuildingRequest request, ModelResolver modelResolver ) + throws ModelBuildingException; + + ModelBuildingResult build( ModelSource modelSource, ModelBuildingRequest request, ModelResolver modelResolver ) + throws ModelBuildingException; + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/ModelBuildingException.java b/maven-model-builder/src/main/java/org/apache/maven/model/ModelBuildingException.java new file mode 100644 index 0000000000..91661a8df5 --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/ModelBuildingException.java @@ -0,0 +1,41 @@ +package org.apache.maven.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Signals an error during model building. + * + * @author Benjamin Bentmann + */ +public class ModelBuildingException + extends Exception +{ + + public ModelBuildingException( String message ) + { + super( message ); + } + + public ModelBuildingException( String message, Throwable cause ) + { + super( message, cause ); + } + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/ModelBuildingRequest.java b/maven-model-builder/src/main/java/org/apache/maven/model/ModelBuildingRequest.java new file mode 100644 index 0000000000..32ec452c40 --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/ModelBuildingRequest.java @@ -0,0 +1,138 @@ +package org.apache.maven.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.List; +import java.util.Properties; + +import org.apache.maven.model.profile.ProfileActivationContext; + +/** + * Collects settings that control building of effective models. + * + * @author Benjamin Bentmann + */ +public interface ModelBuildingRequest +{ + + /** + * Gets the level of validation to perform on processed models. + * + * @return {@code true} if lenient validation is enabled and only the dependency information is to be validated, + * {@code false} if strict validation is enabled and the entire model is validated. + */ + boolean istLenientValidation(); + + /** + * Sets the level of validation to perform on processed models. By default, models are validated in strict mode. + * + * @param lenientValidation A flag whether validation should be lenient instead of strict. For building of projects, + * strict validation should be used to ensure proper building. For the mere retrievel of dependencies + * during artifact resolution, lenient validation should be used to account for models of poor quality. + * @return This request, never {@code null}. + */ + ModelBuildingRequest setLenientValidation( boolean lenientValidation ); + + /** + * Indicates whether plugin executions and configurations should be processed. If enabled, lifecycle-induced plugin + * executions will be injected into the model and common plugin configuration will be propagated to individual + * executions. + * + * @return {@code true} if plugins should be processed, {@code false} otherwise. + */ + boolean isProcessPlugins(); + + /** + * Controls the processing of plugin executions and configurations. + * + * @param processPlugins {@code true} to enable plugin processing, {@code false} otherwise. + * @return This request, never {@code null}. + */ + ModelBuildingRequest setProcessPlugins( boolean processPlugins ); + + /** + * Gets the external profiles that should be considered for model building. + * + * @return The external profiles that should be considered for model building, never {@code null}. + */ + List getProfiles(); + + /** + * Sets the external profiles that should be considered for model building. + * + * @param profiles The external profiles that should be considered for model building, may be {@code null}. + * @return This request, never {@code null}. + */ + ModelBuildingRequest setProfiles( List profiles ); + + /** + * Gets the identifiers of those profiles that should be activated by explicit demand. + * + * @return The identifiers of those profiles to activate, never {@code null}. + */ + List getActiveProfileIds(); + + /** + * Sets the identifiers of those profiles that should be activated by explicit demand. + * + * @param activeProfileIds The identifiers of those profiles to activate, may be {@code null}. + * @return This request, never {@code null}. + */ + ModelBuildingRequest setActiveProfileIds( List activeProfileIds ); + + /** + * Gets the identifiers of those profiles that should be deactivated by explicit demand. + * + * @return The identifiers of those profiles to deactivate, never {@code null}. + */ + List getInactiveProfileIds(); + + /** + * Sets the identifiers of those profiles that should be deactivated by explicit demand. + * + * @param inactiveProfileIds The identifiers of those profiles to deactivate, may be {@code null}. + * @return This request, never {@code null}. + */ + ModelBuildingRequest setInactiveProfileIds( List inactiveProfileIds ); + + /** + * Gets the execution properties. + * + * @return The execution properties, never {@code null}. + */ + Properties getExecutionProperties(); + + /** + * Sets the execution properties. + * + * @param executionProperties The execution properties, may be {@code null}. + * @return This request, never {@code null}. + */ + ModelBuildingRequest setExecutionProperties( Properties executionProperties ); + + /** + * Gets the profile activation context for this request. The activation context is basically a view on a subset of + * settings from this request, manipulations to the request are reflected by the activation context and vice versa. + * + * @return The profile activation context for this request, never {@code null}. + */ + ProfileActivationContext getProfileActivationContext(); + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/ModelBuildingResult.java b/maven-model-builder/src/main/java/org/apache/maven/model/ModelBuildingResult.java new file mode 100644 index 0000000000..92484c7c08 --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/ModelBuildingResult.java @@ -0,0 +1,40 @@ +package org.apache.maven.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.List; + +/** + * Collects the output of the model builder. + * + * @author Benjamin Bentmann + */ +public interface ModelBuildingResult +{ + + Model getEffectiveModel(); + + Model getRawModel(); + + List getRawModels(); + + List getActiveProfiles( Model rawModel ); + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/ModelSource.java b/maven-model-builder/src/main/java/org/apache/maven/model/ModelSource.java new file mode 100644 index 0000000000..ca6ef87b0a --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/ModelSource.java @@ -0,0 +1,49 @@ +package org.apache.maven.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.IOException; +import java.io.InputStream; + +/** + * Provides access to the contents of a POM independently of the backing store (e.g. file system, database, memory). + * + * @author Benjamin Bentmann + */ +public interface ModelSource +{ + + /** + * Gets a byte stream to the POM contents. Closing the returned stream is the responsibility of the caller. + * + * @return A byte stream to the POM contents, never {@code null}. + */ + InputStream getInputStream() + throws IOException; + + /** + * Provides a human-readable hint about the location of the POM. This could be a local file path, a URI or just an + * empty string. The intention is to assist users during error reporting. + * + * @return A human-readable hint about the location of the POM, never {@code null}. + */ + String getLocation(); + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/ModelUtils.java b/maven-model-builder/src/main/java/org/apache/maven/model/ModelUtils.java new file mode 100644 index 0000000000..356b2b8d3b --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/ModelUtils.java @@ -0,0 +1,929 @@ +package org.apache.maven.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; + +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.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; +import org.apache.maven.model.ReportSet; +import org.apache.maven.model.Reporting; +import org.apache.maven.model.Repository; +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.codehaus.plexus.util.xml.Xpp3Dom; + +final class ModelUtils +{ + + // TODO: Replace this with MODELLO-191 + + private static final ModelPartCloner DEPENDENCY_CLONER = new ModelPartCloner() + { + public Dependency cloneModelPart( Dependency src ) + { + return ModelUtils.cloneDependency( src ); + } + }; + + private static final ModelPartCloner PLUGIN_CLONER = new ModelPartCloner() + { + public Plugin cloneModelPart( Plugin src ) + { + return ModelUtils.clonePlugin( src ); + } + }; + + private static final ModelPartCloner EXTENSION_CLONER = new ModelPartCloner() + { + public Extension cloneModelPart( Extension src ) + { + return ModelUtils.cloneExtension( src ); + } + }; + + private static final ModelPartCloner RESOURCE_CLONER = new ModelPartCloner() + { + public Resource cloneModelPart( Resource src ) + { + return ModelUtils.cloneResource( src ); + } + }; + + private static final ModelPartCloner NOTIFIER_CLONER = new ModelPartCloner() + { + public Notifier cloneModelPart( Notifier src ) + { + return ModelUtils.cloneNotifier( src ); + } + }; + + private static final ModelPartCloner CONTRIBUTOR_CLONER = new ModelPartCloner() + { + public Contributor cloneModelPart( Contributor src ) + { + return ModelUtils.cloneContributor( src ); + } + }; + + private static final ModelPartCloner DEVELOPER_CLONER = new ModelPartCloner() + { + public Developer cloneModelPart( Developer src ) + { + return ModelUtils.cloneDeveloper( src ); + } + }; + + private static final ModelPartCloner LICENSE_CLONER = new ModelPartCloner() + { + public License cloneModelPart( License src ) + { + return ModelUtils.cloneLicense( src ); + } + }; + + private static final ModelPartCloner MAILING_LIST_CLONER = new ModelPartCloner() + { + public MailingList cloneModelPart( MailingList src ) + { + return ModelUtils.cloneMailingList( src ); + } + }; + + private static final ModelPartCloner REPOSITORY_CLONER = new ModelPartCloner() + { + public Repository cloneModelPart( Repository src ) + { + return ModelUtils.cloneRepository( src ); + } + }; + + private static final ModelPartCloner PROFILE_CLONER = new ModelPartCloner() + { + public Profile cloneModelPart( Profile src ) + { + return ModelUtils.cloneProfile( src ); + } + }; + + private static final ModelPartCloner REPORT_PLUGIN_CLONER = new ModelPartCloner() + { + public ReportPlugin cloneModelPart( ReportPlugin src ) + { + return ModelUtils.cloneReportPlugin( src ); + } + }; + + private static final ModelPartCloner REPORT_SET_CLONER = new ModelPartCloner() + { + public ReportSet cloneModelPart( ReportSet src ) + { + return ModelUtils.cloneReportSet( src ); + } + }; + + private static final ModelPartCloner DEPENDENCY_EXCLUSION_CLONER = new ModelPartCloner() + { + public Exclusion cloneModelPart( Exclusion src ) + { + return ModelUtils.cloneExclusion( src ); + } + }; + + private static final ModelPartCloner PLUGIN_EXECUTION_CLONER = new ModelPartCloner() + { + public PluginExecution cloneModelPart( PluginExecution src ) + { + return ModelUtils.clonePluginExecution( src ); + } + }; + + 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.getEnabled() ); + 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; + } + + public static Model cloneModel( Model src ) + { + if ( src == null ) + { + return null; + } + + 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() ); + + result.setPomFile( src.getPomFile() ); + + return result; + } + + public static Scm cloneScm( Scm src ) + { + if ( src == null ) + { + return null; + } + + 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 null; + } + + Prerequisites result = new Prerequisites(); + + result.setMaven( src.getMaven() ); + + return result; + } + + public static Organization cloneOrganization( Organization src ) + { + if ( src == null ) + { + return null; + } + + 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; + } + + License result = new License(); + + result.setComments( src.getComments() ); + result.setDistribution( src.getDistribution() ); + result.setName( src.getName() ); + result.setUrl( src.getUrl() ); + + return result; + } + + public static IssueManagement cloneIssueManagement( IssueManagement src ) + { + if ( src == null ) + { + return null; + } + + 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; + } + + 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 null; + } + + 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; + } + + 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; + } + + Relocation result = new Relocation(); + + result.setArtifactId( src.getArtifactId() ); + result.setGroupId( src.getGroupId() ); + result.setMessage( src.getMessage() ); + result.setVersion( src.getVersion() ); + + return result; + } + + public static DependencyManagement cloneDependencyManagement( DependencyManagement src ) + { + if ( src == null ) + { + return null; + } + + DependencyManagement result = new DependencyManagement(); + result.setDependencies( cloneList( src.getDependencies(), DEPENDENCY_CLONER ) ); + + return result; + } + + private static List cloneList( List src, ModelPartCloner cloner ) + { + List result = null; + if ( src != null ) + { + result = new ArrayList( src.size() ); + for ( Iterator it = src.iterator(); it.hasNext(); ) + { + result.add( cloner.cloneModelPart( it.next() ) ); + } + } + + return result; + } + + public static Contributor cloneContributor( Contributor src ) + { + if ( src == null ) + { + return null; + } + + Contributor result = new Contributor(); + cloneContributorFields( src, result ); + + return result; + } + + public static Developer cloneDeveloper( Developer src ) + { + if ( src == null ) + { + return null; + } + + Developer result = new Developer(); + + result.setId( src.getId() ); + + cloneContributorFields( src, result ); + + return result; + } + + private static void cloneContributorFields( Contributor src, Contributor result ) + { + 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() ); + } + + public static CiManagement cloneCiManagement( CiManagement src ) + { + if ( src == null ) + { + return null; + } + + CiManagement result = new CiManagement(); + + result.setNotifiers( cloneList( src.getNotifiers(), NOTIFIER_CLONER ) ); + result.setSystem( src.getSystem() ); + result.setUrl( src.getUrl() ); + + return result; + } + + public static Notifier cloneNotifier( Notifier src ) + { + if ( src == null ) + { + return null; + } + + Notifier result = new Notifier(); + result.setType( src.getType() ); + result.setAddress( src.getAddress() ); + result.setConfiguration( cloneProperties( src.getConfiguration() ) ); + result.setSendOnError( src.isSendOnError() ); + result.setSendOnFailure( src.isSendOnFailure() ); + result.setSendOnSuccess( src.isSendOnSuccess() ); + result.setSendOnWarning( src.isSendOnWarning() ); + + return result; + } + + public static Properties cloneProperties( Properties src ) + { + if ( src == null ) + { + return null; + } + + Properties result = new Properties(); + result.putAll( src ); + + return result; + } + + public static Build cloneBuild( Build src ) + { + if ( src == null ) + { + return null; + } + + 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; + } + + 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 ) ); + } + + public static PluginManagement clonePluginManagement( PluginManagement src ) + { + PluginManagement pMgmt = null; + if ( src != null ) + { + pMgmt = new PluginManagement(); + pMgmt.setPlugins( cloneList( src.getPlugins(), PLUGIN_CLONER ) ); + } + + return pMgmt; + } + + public static Resource cloneResource( Resource src ) + { + Resource result = null; + if ( src != null ) + { + result = new Resource(); + + result.setDirectory( src.getDirectory() ); + result.setExcludes( cloneListOfStrings( src.getExcludes() ) ); + result.setFiltering( src.getFiltering() ); + result.setIncludes( cloneListOfStrings( src.getIncludes() ) ); + result.setMergeId( src.getMergeId() ); + result.setTargetPath( src.getTargetPath() ); + } + + return result; + } + + public static Plugin clonePlugin( Plugin src ) + { + Plugin result = null; + if ( src != null ) + { + 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 result; + } + + public static PluginExecution clonePluginExecution( PluginExecution src ) + { + PluginExecution result = null; + + if ( src != null ) + { + 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 result; + } + + public static Object cloneConfiguration( Object configuration ) + { + if ( configuration == null ) + { + return null; + } + + return new Xpp3Dom( (Xpp3Dom) configuration ); + } + + public static Dependency cloneDependency( Dependency src ) + { + Dependency result = null; + if ( src != null ) + { + 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 result; + } + + public static Exclusion cloneExclusion( Exclusion src ) + { + Exclusion result = null; + if ( src != null ) + { + result = new Exclusion(); + result.setArtifactId( src.getArtifactId() ); + result.setGroupId( src.getGroupId() ); + } + + return result; + } + + public static List cloneListOfStrings( List src ) + { + List result = null; + if ( src != null ) + { + result = new ArrayList( src.size() ); + for ( String item : src ) + { + result.add( item ); + } + } + + return result; + } + + public static Extension cloneExtension( Extension src ) + { + Extension rExt = new Extension(); + rExt.setArtifactId( src.getArtifactId() ); + rExt.setGroupId( src.getGroupId() ); + rExt.setVersion( src.getVersion() ); + + return rExt; + } + + public static Exclusion cloneDependencyExclusion( Exclusion src ) + { + if ( src == null ) + { + return null; + } + + Exclusion result = new Exclusion(); + + result.setArtifactId( src.getArtifactId() ); + result.setGroupId( src.getGroupId() ); + + return result; + } + + public static Parent cloneParent( Parent src ) + { + if ( src == null ) + { + return null; + } + + Parent result = new Parent(); + result.setArtifactId( src.getArtifactId() ); + result.setGroupId( src.getGroupId() ); + result.setRelativePath( src.getRelativePath() ); + result.setVersion( src.getVersion() ); + + return result; + } + + public static interface ModelPartCloner + { + T cloneModelPart( T src ); + } + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/UnparseableModelException.java b/maven-model-builder/src/main/java/org/apache/maven/model/UnparseableModelException.java new file mode 100644 index 0000000000..4c247428e2 --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/UnparseableModelException.java @@ -0,0 +1,76 @@ +package org.apache.maven.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Signals a failure to read/parse a POM file. + * + * @author Benjamin Bentmann + */ +public class UnparseableModelException + extends ModelBuildingException +{ + + /** + * The one-based index of the line containing the error. + */ + private int lineNumber; + + /** + * The one-based index of the column containing the error. + */ + private int columnNumber; + + /** + * Creates a new parser exception with the specified details. + * + * @param message The error message, may be {@code null}. + * @param lineNumber The one-based index of the line containing the error or {@code -1} if unknown. + * @param columnNumber The one-based index of the column containing the error or {@code -1} if unknown. + * @param cause The nested cause of this error, may be {@code null}. + */ + public UnparseableModelException( String message, int lineNumber, int columnNumber, Throwable cause ) + { + super( message, cause ); + this.lineNumber = lineNumber; + this.columnNumber = columnNumber; + } + + /** + * Gets the one-based index of the line containing the error. + * + * @return The one-based index of the line containing the error or a non-positive value if unknown. + */ + public int getLineNumber() + { + return lineNumber; + } + + /** + * Gets the one-based index of the column containing the error. + * + * @return The one-based index of the column containing the error or non-positive value if unknown. + */ + public int getColumnNumber() + { + return columnNumber; + } + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/UnresolvableParentException.java b/maven-model-builder/src/main/java/org/apache/maven/model/UnresolvableParentException.java new file mode 100644 index 0000000000..68f2ffd3b0 --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/UnresolvableParentException.java @@ -0,0 +1,41 @@ +package org.apache.maven.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Signals an error when resolving a child's parent model. + * + * @author Benjamin Bentmann + */ +public class UnresolvableParentException + extends ModelBuildingException +{ + + public UnresolvableParentException( String message, Throwable cause ) + { + super( message, cause ); + } + + public UnresolvableParentException( String message ) + { + super( message ); + } + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/UrlModelSource.java b/maven-model-builder/src/main/java/org/apache/maven/model/UrlModelSource.java new file mode 100644 index 0000000000..84482701a7 --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/UrlModelSource.java @@ -0,0 +1,78 @@ +package org.apache.maven.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +/** + * Wraps an ordinary {@link URL} as a model source. + * + * @author Benjamin Bentmann + */ +public class UrlModelSource + implements ModelSource +{ + + private URL pomUrl; + + /** + * Creates a new model source backed by the specified URL. + * + * @param pomUrl The POM file, must not be {@code null}. + */ + public UrlModelSource( URL pomUrl ) + { + if ( pomUrl == null ) + { + throw new IllegalArgumentException( "no POM URL specified" ); + } + this.pomUrl = pomUrl; + } + + public InputStream getInputStream() + throws IOException + { + return pomUrl.openStream(); + } + + public String getLocation() + { + return pomUrl.toString(); + } + + /** + * Gets the POM URL of this model source. + * + * @return The underlying POM URL, never {@code null}. + */ + public URL getPomUrl() + { + return pomUrl; + } + + @Override + public String toString() + { + return getLocation(); + } + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileActivationContext.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileActivationContext.java new file mode 100644 index 0000000000..5003c95b03 --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileActivationContext.java @@ -0,0 +1,96 @@ +package org.apache.maven.model.profile; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +/** + * Describes the environmental context used to determine the activation status of profiles. + * + * @author Benjamin Bentmann + */ +public class DefaultProfileActivationContext + implements ProfileActivationContext +{ + + private List activeProfileIds; + + private List inactiveProfileIds; + + private Properties executionProperties; + + public DefaultProfileActivationContext() + { + activeProfileIds = new ArrayList(); + inactiveProfileIds = new ArrayList(); + executionProperties = new Properties(); + } + + public List getActiveProfileIds() + { + return activeProfileIds; + } + + public DefaultProfileActivationContext setActiveProfileIds( List activeProfileIds ) + { + this.activeProfileIds.clear(); + if ( activeProfileIds != null ) + { + this.activeProfileIds.addAll( activeProfileIds ); + } + + return this; + } + + public List getInactiveProfileIds() + { + return inactiveProfileIds; + } + + public DefaultProfileActivationContext setInactiveProfileIds( List inactiveProfileIds ) + { + this.inactiveProfileIds.clear(); + if ( inactiveProfileIds != null ) + { + this.inactiveProfileIds.addAll( inactiveProfileIds ); + } + + return this; + } + + public Properties getExecutionProperties() + { + return executionProperties; + } + + public DefaultProfileActivationContext setExecutionProperties( Properties executionProperties ) + { + this.executionProperties.clear(); + if ( executionProperties != null ) + { + this.executionProperties.putAll( executionProperties ); + } + + return this; + } + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileActivationContext.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileActivationContext.java index 925f523519..29db4fd6b5 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileActivationContext.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileActivationContext.java @@ -37,6 +37,14 @@ public interface ProfileActivationContext */ List getActiveProfileIds(); + /** + * Sets the identifiers of those profiles that should be activated by explicit demand. + * + * @param activeProfileIds The identifiers of those profiles to activate, may be {@code null}. + * @return This context, never {@code null}. + */ + ProfileActivationContext setActiveProfileIds( List activeProfileIds ); + /** * Gets the identifiers of those profiles that should be deactivated by explicit demand. * @@ -44,6 +52,14 @@ public interface ProfileActivationContext */ List getInactiveProfileIds(); + /** + * Sets the identifiers of those profiles that should be deactivated by explicit demand. + * + * @param inactiveProfileIds The identifiers of those profiles to deactivate, may be {@code null}. + * @return This context, never {@code null}. + */ + ProfileActivationContext setInactiveProfileIds( List inactiveProfileIds ); + /** * Gets the execution properties. * @@ -51,4 +67,12 @@ public interface ProfileActivationContext */ Properties getExecutionProperties(); + /** + * Sets the execution properties. + * + * @param executionProperties The execution properties, may be {@code null}. + * @return This context, never {@code null}. + */ + ProfileActivationContext setExecutionProperties( Properties executionProperties ); + } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/resolver/InvalidRepositoryException.java b/maven-model-builder/src/main/java/org/apache/maven/model/resolver/InvalidRepositoryException.java new file mode 100644 index 0000000000..c4bf71fd14 --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/resolver/InvalidRepositoryException.java @@ -0,0 +1,70 @@ +package org.apache.maven.model.resolver; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.model.Repository; + +/** + * Signals an error when adding a repository to the model resolver. + * + * @author Benjamin Bentmann + */ +public class InvalidRepositoryException + extends Exception +{ + + private Repository repository; + + /** + * Creates a new exception with specified detail message and cause for the given repository. + * + * @param message The detail message, may be {@code null}. + * @param repository The repository that caused the error, may be {@code null}. + * @param cause The cause, may be {@code null}. + */ + public InvalidRepositoryException( String message, Repository repository, Throwable cause ) + { + super( message, cause ); + this.repository = repository; + } + + /** + * Creates a new exception with specified detail message for the given repository. + * + * @param message The detail message, may be {@code null}. + * @param repository The repository that caused the error, may be {@code null}. + */ + public InvalidRepositoryException( String message, Repository repository ) + { + super( message ); + this.repository = repository; + } + + /** + * Gets the repository that causes this error (if any). + * + * @return The repository that causes this error or {@code null} if not known. + */ + public Repository getRepository() + { + return repository; + } + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/resolver/ModelResolver.java b/maven-model-builder/src/main/java/org/apache/maven/model/resolver/ModelResolver.java new file mode 100644 index 0000000000..81d2e757d7 --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/resolver/ModelResolver.java @@ -0,0 +1,42 @@ +package org.apache.maven.model.resolver; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.model.ModelBuilder; +import org.apache.maven.model.ModelSource; +import org.apache.maven.model.Repository; + +/** + * Resolves a POM from its coordinates. During the build process, the {@link ModelBuilder} will add any relevant + * repositories to the model resolver. In other words, the model resolver is stateful and should not be reused across + * multiple model building requests. + * + * @author Benjamin Bentmann + */ +public interface ModelResolver +{ + + ModelSource resolveModel( String groupId, String artifactId, String version ) + throws UnresolvableModelException; + + void addRepository( Repository repository ) + throws InvalidRepositoryException; + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/resolver/UnresolvableModelException.java b/maven-model-builder/src/main/java/org/apache/maven/model/resolver/UnresolvableModelException.java new file mode 100644 index 0000000000..23c548c43a --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/resolver/UnresolvableModelException.java @@ -0,0 +1,52 @@ +package org.apache.maven.model.resolver; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Signals an error when resolving the path to an external model. + * + * @author Benjamin Bentmann + */ +public class UnresolvableModelException + extends Exception +{ + + /** + * Creates a new exception with specified detail message and cause. + * + * @param message The detail message, may be {@code null}. + * @param cause The cause, may be {@code null}. + */ + public UnresolvableModelException( String message, Throwable cause ) + { + super( message, cause ); + } + + /** + * Creates a new exception with specified detail message. + * + * @param message The detail message, may be {@code null}. + */ + public UnresolvableModelException( String message ) + { + super( message ); + } + +} diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/profile/activator/AbstractProfileActivatorTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/profile/activator/AbstractProfileActivatorTest.java index 6a3dd3155b..dc5a252048 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/profile/activator/AbstractProfileActivatorTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/profile/activator/AbstractProfileActivatorTest.java @@ -19,10 +19,9 @@ package org.apache.maven.model.profile.activator; * under the License. */ -import java.util.Collections; -import java.util.List; import java.util.Properties; +import org.apache.maven.model.profile.DefaultProfileActivationContext; import org.apache.maven.model.profile.ProfileActivationContext; import org.codehaus.plexus.PlexusTestCase; import org.codehaus.plexus.component.annotations.Component; @@ -74,25 +73,7 @@ public abstract class AbstractProfileActivatorTest protected ProfileActivationContext newContext( final Properties executionProperties ) { - return new ProfileActivationContext() - { - - public List getActiveProfileIds() - { - return Collections.emptyList(); - } - - public List getInactiveProfileIds() - { - return Collections.emptyList(); - } - - public Properties getExecutionProperties() - { - return executionProperties; - } - - }; + return new DefaultProfileActivationContext().setExecutionProperties( executionProperties ); } } diff --git a/maven-model/src/main/mdo/maven.mdo b/maven-model/src/main/mdo/maven.mdo index 17d539bdca..07bafade62 100644 --- a/maven-model/src/main/mdo/maven.mdo +++ b/maven-model/src/main/mdo/maven.mdo @@ -572,10 +572,10 @@ private java.io.File pomFile; /** - * Gets the POM file from which this model originated. This can either be a {@code pom.xml} of some project being - * built or the {@code *.pom} of some artifact being resolved from the repository. + * Gets the POM file for the corresponding project (if any). * - * @return The POM file from which this model originated or {@code null} if unknown. + * @return The POM file from which this model originated or {@code null} if this model does not belong to a local + * project (e.g. describes the metadata of some artifact from the repository). */ public java.io.File getPomFile() { @@ -588,26 +588,14 @@ } /** - * The base directory for the corresponding project (if any). This is transient runtime state and therefore not - * managed by Modello. - */ - private java.io.File projectDirectory; - - /** - * Gets the base directory for the corresponding project (if any). Note that this is really a separate piece of - * information and not necessarily equivalent to the parent directory of {@link #getPomFile()}. + * Gets the base directory for the corresponding project (if any). * * @return The base directory for the corresponding project or {@code null} if this model does not belong to a local - * project but describes the metadata of some artifact from the repository. + * project (e.g. describes the metadata of some artifact from the repository). */ public java.io.File getProjectDirectory() { - return projectDirectory; - } - - public void setProjectDirectory( java.io.File projectDirectory ) - { - this.projectDirectory = projectDirectory; + return ( pomFile != null ) ? pomFile.getParentFile() : null; } /**