aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/maven/apache-maven-3.3.3/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/maven/apache-maven-3.3.3/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java')
-rw-r--r--framework/src/maven/apache-maven-3.3.3/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java1309
1 files changed, 1309 insertions, 0 deletions
diff --git a/framework/src/maven/apache-maven-3.3.3/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java b/framework/src/maven/apache-maven-3.3.3/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java
new file mode 100644
index 00000000..52b3c9c8
--- /dev/null
+++ b/framework/src/maven/apache-maven-3.3.3/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java
@@ -0,0 +1,1309 @@
+package org.apache.maven.model.building;
+
+/*
+ * 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 static org.apache.maven.model.building.Result.error;
+import static org.apache.maven.model.building.Result.newResult;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.maven.model.Activation;
+import org.apache.maven.model.Build;
+import org.apache.maven.model.Dependency;
+import org.apache.maven.model.DependencyManagement;
+import org.apache.maven.model.InputLocation;
+import org.apache.maven.model.InputSource;
+import org.apache.maven.model.Model;
+import org.apache.maven.model.Parent;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.model.PluginManagement;
+import org.apache.maven.model.Profile;
+import org.apache.maven.model.Repository;
+import org.apache.maven.model.building.ModelProblem.Severity;
+import org.apache.maven.model.building.ModelProblem.Version;
+import org.apache.maven.model.composition.DependencyManagementImporter;
+import org.apache.maven.model.inheritance.InheritanceAssembler;
+import org.apache.maven.model.interpolation.ModelInterpolator;
+import org.apache.maven.model.io.ModelParseException;
+import org.apache.maven.model.management.DependencyManagementInjector;
+import org.apache.maven.model.management.PluginManagementInjector;
+import org.apache.maven.model.normalization.ModelNormalizer;
+import org.apache.maven.model.path.ModelPathTranslator;
+import org.apache.maven.model.path.ModelUrlNormalizer;
+import org.apache.maven.model.plugin.LifecycleBindingsInjector;
+import org.apache.maven.model.plugin.PluginConfigurationExpander;
+import org.apache.maven.model.plugin.ReportConfigurationExpander;
+import org.apache.maven.model.plugin.ReportingConverter;
+import org.apache.maven.model.profile.DefaultProfileActivationContext;
+import org.apache.maven.model.profile.ProfileInjector;
+import org.apache.maven.model.profile.ProfileSelector;
+import org.apache.maven.model.resolution.InvalidRepositoryException;
+import org.apache.maven.model.resolution.ModelResolver;
+import org.apache.maven.model.resolution.UnresolvableModelException;
+import org.apache.maven.model.resolution.WorkspaceModelResolver;
+import org.apache.maven.model.superpom.SuperPomProvider;
+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
+{
+ @Requirement
+ private ModelProcessor modelProcessor;
+
+ @Requirement
+ private ModelValidator modelValidator;
+
+ @Requirement
+ private ModelNormalizer modelNormalizer;
+
+ @Requirement
+ private ModelInterpolator modelInterpolator;
+
+ @Requirement
+ private ModelPathTranslator modelPathTranslator;
+
+ @Requirement
+ private ModelUrlNormalizer modelUrlNormalizer;
+
+ @Requirement
+ private SuperPomProvider superPomProvider;
+
+ @Requirement
+ private InheritanceAssembler inheritanceAssembler;
+
+ @Requirement
+ private ProfileSelector profileSelector;
+
+ @Requirement
+ private ProfileInjector profileInjector;
+
+ @Requirement
+ private PluginManagementInjector pluginManagementInjector;
+
+ @Requirement
+ private DependencyManagementInjector dependencyManagementInjector;
+
+ @Requirement
+ private DependencyManagementImporter dependencyManagementImporter;
+
+ @Requirement( optional = true )
+ private LifecycleBindingsInjector lifecycleBindingsInjector;
+
+ @Requirement
+ private PluginConfigurationExpander pluginConfigurationExpander;
+
+ @Requirement
+ private ReportConfigurationExpander reportConfigurationExpander;
+
+ @Requirement
+ private ReportingConverter reportingConverter;
+
+ public DefaultModelBuilder setModelProcessor( ModelProcessor modelProcessor )
+ {
+ this.modelProcessor = modelProcessor;
+ return this;
+ }
+
+ public DefaultModelBuilder setModelValidator( ModelValidator modelValidator )
+ {
+ this.modelValidator = modelValidator;
+ return this;
+ }
+
+ public DefaultModelBuilder setModelNormalizer( ModelNormalizer modelNormalizer )
+ {
+ this.modelNormalizer = modelNormalizer;
+ return this;
+ }
+
+ public DefaultModelBuilder setModelInterpolator( ModelInterpolator modelInterpolator )
+ {
+ this.modelInterpolator = modelInterpolator;
+ return this;
+ }
+
+ public DefaultModelBuilder setModelPathTranslator( ModelPathTranslator modelPathTranslator )
+ {
+ this.modelPathTranslator = modelPathTranslator;
+ return this;
+ }
+
+ public DefaultModelBuilder setModelUrlNormalizer( ModelUrlNormalizer modelUrlNormalizer )
+ {
+ this.modelUrlNormalizer = modelUrlNormalizer;
+ return this;
+ }
+
+ public DefaultModelBuilder setSuperPomProvider( SuperPomProvider superPomProvider )
+ {
+ this.superPomProvider = superPomProvider;
+ return this;
+ }
+
+ public DefaultModelBuilder setProfileSelector( ProfileSelector profileSelector )
+ {
+ this.profileSelector = profileSelector;
+ return this;
+ }
+
+ public DefaultModelBuilder setProfileInjector( ProfileInjector profileInjector )
+ {
+ this.profileInjector = profileInjector;
+ return this;
+ }
+
+ public DefaultModelBuilder setInheritanceAssembler( InheritanceAssembler inheritanceAssembler )
+ {
+ this.inheritanceAssembler = inheritanceAssembler;
+ return this;
+ }
+
+ public DefaultModelBuilder setDependencyManagementImporter( DependencyManagementImporter depMngmntImporter )
+ {
+ this.dependencyManagementImporter = depMngmntImporter;
+ return this;
+ }
+
+ public DefaultModelBuilder setDependencyManagementInjector( DependencyManagementInjector depMngmntInjector )
+ {
+ this.dependencyManagementInjector = depMngmntInjector;
+ return this;
+ }
+
+ public DefaultModelBuilder setLifecycleBindingsInjector( LifecycleBindingsInjector lifecycleBindingsInjector )
+ {
+ this.lifecycleBindingsInjector = lifecycleBindingsInjector;
+ return this;
+ }
+
+ public DefaultModelBuilder setPluginConfigurationExpander( PluginConfigurationExpander pluginConfigurationExpander )
+ {
+ this.pluginConfigurationExpander = pluginConfigurationExpander;
+ return this;
+ }
+
+ public DefaultModelBuilder setPluginManagementInjector( PluginManagementInjector pluginManagementInjector )
+ {
+ this.pluginManagementInjector = pluginManagementInjector;
+ return this;
+ }
+
+ public DefaultModelBuilder setReportConfigurationExpander( ReportConfigurationExpander reportConfigurationExpander )
+ {
+ this.reportConfigurationExpander = reportConfigurationExpander;
+ return this;
+ }
+
+ public DefaultModelBuilder setReportingConverter( ReportingConverter reportingConverter )
+ {
+ this.reportingConverter = reportingConverter;
+ return this;
+ }
+
+ @Override
+ public ModelBuildingResult build( ModelBuildingRequest request )
+ throws ModelBuildingException
+ {
+ // phase 1
+ DefaultModelBuildingResult result = new DefaultModelBuildingResult();
+
+ DefaultModelProblemCollector problems = new DefaultModelProblemCollector( result );
+
+ // profile activation
+ DefaultProfileActivationContext profileActivationContext = getProfileActivationContext( request );
+
+ problems.setSource( "(external profiles)" );
+ List<Profile> activeExternalProfiles = profileSelector.getActiveProfiles( request.getProfiles(),
+ profileActivationContext, problems );
+
+ result.setActiveExternalProfiles( activeExternalProfiles );
+
+ if ( !activeExternalProfiles.isEmpty() )
+ {
+ Properties profileProps = new Properties();
+ for ( Profile profile : activeExternalProfiles )
+ {
+ profileProps.putAll( profile.getProperties() );
+ }
+ profileProps.putAll( profileActivationContext.getUserProperties() );
+ profileActivationContext.setUserProperties( profileProps );
+ }
+
+ // read and validate raw model
+ Model inputModel = request.getRawModel();
+ if ( inputModel == null )
+ {
+ inputModel = readModel( request.getModelSource(), request.getPomFile(), request, problems );
+ }
+
+ problems.setRootModel( inputModel );
+
+ ModelData resultData = new ModelData( request.getModelSource(), inputModel );
+ ModelData superData = new ModelData( null, getSuperModel() );
+
+ Collection<String> parentIds = new LinkedHashSet<String>();
+ List<ModelData> lineage = new ArrayList<ModelData>();
+
+ for ( ModelData currentData = resultData; currentData != null; )
+ {
+ lineage.add( currentData );
+
+ Model rawModel = currentData.getModel();
+ currentData.setRawModel( rawModel );
+
+ Model tmpModel = rawModel.clone();
+ currentData.setModel( tmpModel );
+
+ problems.setSource( tmpModel );
+
+ // model normalization
+ modelNormalizer.mergeDuplicates( tmpModel, request, problems );
+
+ profileActivationContext.setProjectProperties( tmpModel.getProperties() );
+
+ List<Profile> activePomProfiles = profileSelector.getActiveProfiles( rawModel.getProfiles(),
+ profileActivationContext, problems );
+ currentData.setActiveProfiles( activePomProfiles );
+
+ Map<String, Activation> interpolatedActivations = getProfileActivations( rawModel, false );
+ injectProfileActivations( tmpModel, interpolatedActivations );
+
+ // profile injection
+ for ( Profile activeProfile : activePomProfiles )
+ {
+ profileInjector.injectProfile( tmpModel, activeProfile, request, problems );
+ }
+
+ if ( currentData == resultData )
+ {
+ for ( Profile activeProfile : activeExternalProfiles )
+ {
+ profileInjector.injectProfile( tmpModel, activeProfile, request, problems );
+ }
+ }
+
+ if ( currentData == superData )
+ {
+ break;
+ }
+
+ configureResolver( request.getModelResolver(), tmpModel, problems );
+
+ ModelData parentData = readParent( tmpModel, currentData.getSource(), request, problems );
+
+ if ( parentData == null )
+ {
+ currentData = superData;
+ }
+ else if ( currentData == resultData )
+ { // First iteration - add initial parent id after version resolution.
+ currentData.setGroupId( currentData.getRawModel().getGroupId() == null ? parentData.getGroupId()
+ : currentData.getRawModel()
+ .getGroupId() );
+
+ currentData.setVersion( currentData.getRawModel().getVersion() == null ? parentData.getVersion()
+ : currentData.getRawModel()
+ .getVersion() );
+
+ currentData.setArtifactId( currentData.getRawModel().getArtifactId() );
+ parentIds.add( currentData.getId() );
+ // Reset - only needed for 'getId'.
+ currentData.setGroupId( null );
+ currentData.setArtifactId( null );
+ currentData.setVersion( null );
+ currentData = parentData;
+ }
+ else if ( !parentIds.add( parentData.getId() ) )
+ {
+ String message = "The parents form a cycle: ";
+ for ( String modelId : parentIds )
+ {
+ message += modelId + " -> ";
+ }
+ message += parentData.getId();
+
+ problems.add( new ModelProblemCollectorRequest( ModelProblem.Severity.FATAL, ModelProblem.Version.BASE )
+ .setMessage( message ) );
+
+ throw problems.newModelBuildingException();
+ }
+ else
+ {
+ currentData = parentData;
+ }
+ }
+
+ problems.setSource( inputModel );
+ checkPluginVersions( lineage, request, problems );
+
+ // inheritance assembly
+ assembleInheritance( lineage, request, problems );
+
+ Model resultModel = resultData.getModel();
+
+ problems.setSource( resultModel );
+ problems.setRootModel( resultModel );
+
+ // model interpolation
+ resultModel = interpolateModel( resultModel, request, problems );
+ resultData.setModel( resultModel );
+
+ // url normalization
+ modelUrlNormalizer.normalize( resultModel, request );
+
+ // Now the fully interpolated model is available: reconfigure the resolver
+ configureResolver( request.getModelResolver(), resultModel, problems, true );
+
+ resultData.setGroupId( resultModel.getGroupId() );
+ resultData.setArtifactId( resultModel.getArtifactId() );
+ resultData.setVersion( resultModel.getVersion() );
+
+ result.setEffectiveModel( resultModel );
+
+ for ( ModelData currentData : lineage )
+ {
+ String modelId = ( currentData != superData ) ? currentData.getId() : "";
+
+ result.addModelId( modelId );
+ result.setActivePomProfiles( modelId, currentData.getActiveProfiles() );
+ result.setRawModel( modelId, currentData.getRawModel() );
+ }
+
+ if ( !request.isTwoPhaseBuilding() )
+ {
+ build( request, result );
+ }
+
+ return result;
+ }
+
+ @Override
+ public ModelBuildingResult build( ModelBuildingRequest request, ModelBuildingResult result )
+ throws ModelBuildingException
+ {
+ return build( request, result, new LinkedHashSet<String>() );
+ }
+
+ private ModelBuildingResult build( ModelBuildingRequest request, ModelBuildingResult result,
+ Collection<String> imports )
+ throws ModelBuildingException
+ {
+ // phase 2
+ Model resultModel = result.getEffectiveModel();
+
+ DefaultModelProblemCollector problems = new DefaultModelProblemCollector( result );
+ problems.setSource( resultModel );
+ problems.setRootModel( resultModel );
+
+ // model path translation
+ modelPathTranslator.alignToBaseDirectory( resultModel, resultModel.getProjectDirectory(), request );
+
+ // plugin management injection
+ pluginManagementInjector.injectManagement( resultModel, request, problems );
+
+ fireEvent( resultModel, request, problems, ModelBuildingEventCatapult.BUILD_EXTENSIONS_ASSEMBLED );
+
+ if ( request.isProcessPlugins() )
+ {
+ if ( lifecycleBindingsInjector == null )
+ {
+ throw new IllegalStateException( "lifecycle bindings injector is missing" );
+ }
+
+ // lifecycle bindings injection
+ lifecycleBindingsInjector.injectLifecycleBindings( resultModel, request, problems );
+ }
+
+ // dependency management import
+ importDependencyManagement( resultModel, request, problems, imports );
+
+ // dependency management injection
+ dependencyManagementInjector.injectManagement( resultModel, request, problems );
+
+ modelNormalizer.injectDefaultValues( resultModel, request, problems );
+
+ if ( request.isProcessPlugins() )
+ {
+ // reports configuration
+ reportConfigurationExpander.expandPluginConfiguration( resultModel, request, problems );
+
+ // reports conversion to decoupled site plugin
+ reportingConverter.convertReporting( resultModel, request, problems );
+
+ // plugins configuration
+ pluginConfigurationExpander.expandPluginConfiguration( resultModel, request, problems );
+ }
+
+ // effective model validation
+ modelValidator.validateEffectiveModel( resultModel, request, problems );
+
+ if ( hasModelErrors( problems ) )
+ {
+ throw problems.newModelBuildingException();
+ }
+
+ return result;
+ }
+
+ @Override
+ public Result<? extends Model> buildRawModel( File pomFile, int validationLevel, boolean locationTracking )
+ {
+ final ModelBuildingRequest request = new DefaultModelBuildingRequest().setValidationLevel( validationLevel )
+ .setLocationTracking( locationTracking );
+ final DefaultModelProblemCollector collector =
+ new DefaultModelProblemCollector( new DefaultModelBuildingResult() );
+ try
+ {
+ return newResult( readModel( null, pomFile, request, collector ), collector.getProblems() );
+ }
+ catch ( ModelBuildingException e )
+ {
+ return error( collector.getProblems() );
+ }
+ }
+
+ private Model readModel( ModelSource modelSource, File pomFile, ModelBuildingRequest request,
+ DefaultModelProblemCollector problems )
+ throws ModelBuildingException
+ {
+ Model model;
+
+ if ( modelSource == null )
+ {
+ if ( pomFile != null )
+ {
+ modelSource = new FileModelSource( pomFile );
+ }
+ else
+ {
+ throw new IllegalArgumentException( "neither model source nor input file are specified" );
+ }
+ }
+
+ problems.setSource( modelSource.getLocation() );
+ try
+ {
+ boolean strict = request.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0;
+ InputSource source = request.isLocationTracking() ? new InputSource() : null;
+
+ Map<String, Object> options = new HashMap<String, Object>();
+ options.put( ModelProcessor.IS_STRICT, strict );
+ options.put( ModelProcessor.INPUT_SOURCE, source );
+ options.put( ModelProcessor.SOURCE, modelSource );
+
+ try
+ {
+ model = modelProcessor.read( modelSource.getInputStream(), options );
+ }
+ catch ( ModelParseException e )
+ {
+ if ( !strict )
+ {
+ throw e;
+ }
+
+ options.put( ModelProcessor.IS_STRICT, Boolean.FALSE );
+
+ try
+ {
+ model = modelProcessor.read( modelSource.getInputStream(), options );
+ }
+ catch ( ModelParseException ne )
+ {
+ // still unreadable even in non-strict mode, rethrow original error
+ throw e;
+ }
+
+ if ( pomFile != null )
+ {
+ problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.V20 )
+ .setMessage( "Malformed POM " + modelSource.getLocation() + ": " + e.getMessage() )
+ .setException( e ) );
+ }
+ else
+ {
+ problems.add( new ModelProblemCollectorRequest( Severity.WARNING, Version.V20 )
+ .setMessage( "Malformed POM " + modelSource.getLocation() + ": " + e.getMessage() )
+ .setException( e ) );
+ }
+ }
+
+ if ( source != null )
+ {
+ source.setModelId( ModelProblemUtils.toId( model ) );
+ source.setLocation( modelSource.getLocation() );
+ }
+ }
+ catch ( ModelParseException e )
+ {
+ problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.BASE )
+ .setMessage( "Non-parseable POM " + modelSource.getLocation() + ": " + e.getMessage() )
+ .setException( e ) );
+ throw problems.newModelBuildingException();
+ }
+ catch ( IOException e )
+ {
+ String msg = e.getMessage();
+ if ( msg == null || msg.length() <= 0 )
+ {
+ // NOTE: There's java.nio.charset.MalformedInputException and sun.io.MalformedInputException
+ if ( e.getClass().getName().endsWith( "MalformedInputException" ) )
+ {
+ msg = "Some input bytes do not match the file encoding.";
+ }
+ else
+ {
+ msg = e.getClass().getSimpleName();
+ }
+ }
+ problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.BASE )
+ .setMessage( "Non-readable POM " + modelSource.getLocation() + ": " + msg ).setException( e ) );
+ throw problems.newModelBuildingException();
+ }
+
+ model.setPomFile( pomFile );
+
+ problems.setSource( model );
+ modelValidator.validateRawModel( model, request, problems );
+
+ if ( hasFatalErrors( problems ) )
+ {
+ throw problems.newModelBuildingException();
+ }
+
+ return model;
+ }
+
+ private DefaultProfileActivationContext getProfileActivationContext( ModelBuildingRequest request )
+ {
+ DefaultProfileActivationContext context = new DefaultProfileActivationContext();
+
+ context.setActiveProfileIds( request.getActiveProfileIds() );
+ context.setInactiveProfileIds( request.getInactiveProfileIds() );
+ context.setSystemProperties( request.getSystemProperties() );
+ context.setUserProperties( request.getUserProperties() );
+ context.setProjectDirectory( ( request.getPomFile() != null ) ? request.getPomFile().getParentFile() : null );
+
+ return context;
+ }
+
+ private void configureResolver( ModelResolver modelResolver, Model model, DefaultModelProblemCollector problems )
+ {
+ configureResolver( modelResolver, model, problems, false );
+ }
+
+ private void configureResolver( ModelResolver modelResolver, Model model, DefaultModelProblemCollector problems,
+ boolean replaceRepositories )
+ {
+ if ( modelResolver == null )
+ {
+ return;
+ }
+
+ problems.setSource( model );
+
+ List<Repository> repositories = model.getRepositories();
+
+ for ( Repository repository : repositories )
+ {
+ try
+ {
+ modelResolver.addRepository( repository, replaceRepositories );
+ }
+ catch ( InvalidRepositoryException e )
+ {
+ problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
+ .setMessage( "Invalid repository " + repository.getId() + ": " + e.getMessage() )
+ .setLocation( repository.getLocation( "" ) ).setException( e ) );
+ }
+ }
+ }
+
+ private void checkPluginVersions( List<ModelData> lineage, ModelBuildingRequest request,
+ ModelProblemCollector problems )
+ {
+ if ( request.getValidationLevel() < ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0 )
+ {
+ return;
+ }
+
+ Map<String, Plugin> plugins = new HashMap<String, Plugin>();
+ Map<String, String> versions = new HashMap<String, String>();
+ Map<String, String> managedVersions = new HashMap<String, String>();
+
+ for ( int i = lineage.size() - 1; i >= 0; i-- )
+ {
+ Model model = lineage.get( i ).getModel();
+ Build build = model.getBuild();
+ if ( build != null )
+ {
+ for ( Plugin plugin : build.getPlugins() )
+ {
+ String key = plugin.getKey();
+ if ( versions.get( key ) == null )
+ {
+ versions.put( key, plugin.getVersion() );
+ plugins.put( key, plugin );
+ }
+ }
+ PluginManagement mngt = build.getPluginManagement();
+ if ( mngt != null )
+ {
+ for ( Plugin plugin : mngt.getPlugins() )
+ {
+ String key = plugin.getKey();
+ if ( managedVersions.get( key ) == null )
+ {
+ managedVersions.put( key, plugin.getVersion() );
+ }
+ }
+ }
+ }
+ }
+
+ for ( String key : versions.keySet() )
+ {
+ if ( versions.get( key ) == null && managedVersions.get( key ) == null )
+ {
+ InputLocation location = plugins.get( key ).getLocation( "" );
+ problems
+ .add( new ModelProblemCollectorRequest( Severity.WARNING, Version.V20 )
+ .setMessage( "'build.plugins.plugin.version' for " + key + " is missing." )
+ .setLocation( location ) );
+ }
+ }
+ }
+
+ private void assembleInheritance( List<ModelData> lineage, ModelBuildingRequest request,
+ ModelProblemCollector problems )
+ {
+ for ( int i = lineage.size() - 2; i >= 0; i-- )
+ {
+ Model parent = lineage.get( i + 1 ).getModel();
+ Model child = lineage.get( i ).getModel();
+ inheritanceAssembler.assembleModelInheritance( child, parent, request, problems );
+ }
+ }
+
+ private Map<String, Activation> getProfileActivations( Model model, boolean clone )
+ {
+ Map<String, Activation> activations = new HashMap<String, Activation>();
+ for ( Profile profile : model.getProfiles() )
+ {
+ Activation activation = profile.getActivation();
+
+ if ( activation == null )
+ {
+ continue;
+ }
+
+ if ( clone )
+ {
+ activation = activation.clone();
+ }
+
+ activations.put( profile.getId(), activation );
+ }
+
+ return activations;
+ }
+
+ private void injectProfileActivations( Model model, Map<String, Activation> activations )
+ {
+ for ( Profile profile : model.getProfiles() )
+ {
+ Activation activation = profile.getActivation();
+
+ if ( activation == null )
+ {
+ continue;
+ }
+
+ // restore activation
+ profile.setActivation( activations.get( profile.getId() ) );
+ }
+ }
+
+ private Model interpolateModel( Model model, ModelBuildingRequest request, ModelProblemCollector problems )
+ {
+ // save profile activations before interpolation, since they are evaluated with limited scope
+ Map<String, Activation> originalActivations = getProfileActivations( model, true );
+
+ Model result = modelInterpolator.interpolateModel( model, model.getProjectDirectory(), request, problems );
+ result.setPomFile( model.getPomFile() );
+
+ // restore profiles with file activation to their value before full interpolation
+ injectProfileActivations( model, originalActivations );
+
+ return result;
+ }
+
+ private ModelData readParent( Model childModel, ModelSource childSource, ModelBuildingRequest request,
+ DefaultModelProblemCollector problems )
+ throws ModelBuildingException
+ {
+ ModelData parentData;
+
+ Parent parent = childModel.getParent();
+
+ if ( parent != null )
+ {
+ String groupId = parent.getGroupId();
+ String artifactId = parent.getArtifactId();
+ String version = parent.getVersion();
+
+ parentData = getCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.RAW );
+
+ if ( parentData == null )
+ {
+ parentData = readParentLocally( childModel, childSource, request, problems );
+
+ if ( parentData == null )
+ {
+ parentData = readParentExternally( childModel, request, problems );
+ }
+
+ putCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.RAW, parentData );
+ }
+ else
+ {
+ /*
+ * NOTE: This is a sanity check of the cache hit. If the cached parent POM was locally resolved, the
+ * child's <relativePath> should point at that parent, too. If it doesn't, we ignore the cache and
+ * resolve externally, to mimic the behavior if the cache didn't exist in the first place. Otherwise,
+ * the cache would obscure a bad POM.
+ */
+
+ File pomFile = parentData.getModel().getPomFile();
+ if ( pomFile != null )
+ {
+ ModelSource expectedParentSource = getParentPomFile( childModel, childSource );
+
+ if ( expectedParentSource instanceof ModelSource2
+ && !pomFile.toURI().equals( ( (ModelSource2) expectedParentSource ).getLocationURI() ) )
+ {
+ parentData = readParentExternally( childModel, request, problems );
+ }
+ }
+ }
+
+ Model parentModel = parentData.getModel();
+
+ if ( !"pom".equals( parentModel.getPackaging() ) )
+ {
+ problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
+ .setMessage( "Invalid packaging for parent POM " + ModelProblemUtils.toSourceHint( parentModel )
+ + ", must be \"pom\" but is \"" + parentModel.getPackaging() + "\"" )
+ .setLocation( parentModel.getLocation( "packaging" ) ) );
+ }
+ }
+ else
+ {
+ parentData = null;
+ }
+
+ return parentData;
+ }
+
+ private ModelData readParentLocally( Model childModel, ModelSource childSource, ModelBuildingRequest request,
+ DefaultModelProblemCollector problems )
+ throws ModelBuildingException
+ {
+ final Parent parent = childModel.getParent();
+ final ModelSource candidateSource;
+ final Model candidateModel;
+ final WorkspaceModelResolver resolver = request.getWorkspaceModelResolver();
+ if ( resolver == null )
+ {
+ candidateSource = getParentPomFile( childModel, childSource );
+
+ if ( candidateSource == null )
+ {
+ return null;
+ }
+
+ File pomFile = null;
+ if ( candidateSource instanceof FileModelSource )
+ {
+ pomFile = ( (FileModelSource) candidateSource ).getPomFile();
+ }
+
+ candidateModel = readModel( candidateSource, pomFile, request, problems );
+ }
+ else
+ {
+ try
+ {
+ candidateModel =
+ resolver.resolveRawModel( parent.getGroupId(), parent.getArtifactId(), parent.getVersion() );
+ }
+ catch ( UnresolvableModelException e )
+ {
+ problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.BASE ) //
+ .setMessage( e.getMessage().toString() ).setLocation( parent.getLocation( "" ) ).setException( e ) );
+ throw problems.newModelBuildingException();
+ }
+ if ( candidateModel == null )
+ {
+ return null;
+ }
+ candidateSource = new FileModelSource( candidateModel.getPomFile() );
+ }
+
+ //
+ // TODO:jvz Why isn't all this checking the job of the duty of the workspace resolver, we know that we
+ // have a model that is suitable, yet more checks are done here and the one for the version is problematic
+ // before because with parents as ranges it will never work in this scenario.
+ //
+
+ 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() ) || artifactId == null
+ || !artifactId.equals( parent.getArtifactId() ) )
+ {
+ StringBuilder buffer = new StringBuilder( 256 );
+ buffer.append( "'parent.relativePath'" );
+ if ( childModel != problems.getRootModel() )
+ {
+ buffer.append( " of POM " ).append( ModelProblemUtils.toSourceHint( childModel ) );
+ }
+ buffer.append( " points at " ).append( groupId ).append( ":" ).append( artifactId );
+ buffer.append( " instead of " ).append( parent.getGroupId() ).append( ":" );
+ buffer.append( parent.getArtifactId() ).append( ", please verify your project structure" );
+
+ problems.setSource( childModel );
+ problems.add( new ModelProblemCollectorRequest( Severity.WARNING, Version.BASE )
+ .setMessage( buffer.toString() ).setLocation( parent.getLocation( "" ) ) );
+ return null;
+ }
+
+ //
+ // Here we just need to know that a version is fine to use but this validation we can do in our workspace
+ // resolver.
+ //
+
+ /*
+ * if ( version == null || !version.equals( parent.getVersion() ) ) { return null; }
+ */
+
+ ModelData parentData = new ModelData( candidateSource, candidateModel, groupId, artifactId, version );
+
+ return parentData;
+ }
+
+ private ModelSource getParentPomFile( Model childModel, ModelSource source )
+ {
+ if ( !( source instanceof ModelSource2 ) )
+ {
+ return null;
+ }
+
+ String parentPath = childModel.getParent().getRelativePath();
+
+ if ( parentPath == null || parentPath.length() <= 0 )
+ {
+ return null;
+ }
+
+ return ( (ModelSource2) source ).getRelatedSource( parentPath );
+ }
+
+ private ModelData readParentExternally( Model childModel, ModelBuildingRequest request,
+ DefaultModelProblemCollector problems )
+ throws ModelBuildingException
+ {
+ problems.setSource( childModel );
+
+ Parent parent = childModel.getParent().clone();
+
+ String groupId = parent.getGroupId();
+ String artifactId = parent.getArtifactId();
+ String version = parent.getVersion();
+
+ ModelResolver modelResolver = request.getModelResolver();
+
+ if ( modelResolver == null )
+ {
+ throw new IllegalArgumentException( "no model resolver provided, cannot resolve parent POM "
+ + ModelProblemUtils.toId( groupId, artifactId, version ) + " for POM "
+ + ModelProblemUtils.toSourceHint( childModel ) );
+ }
+
+ ModelSource modelSource;
+ try
+ {
+ modelSource = modelResolver.resolveModel( parent );
+ }
+ catch ( UnresolvableModelException e )
+ {
+ StringBuilder buffer = new StringBuilder( 256 );
+ buffer.append( "Non-resolvable parent POM" );
+ if ( !containsCoordinates( e.getMessage(), groupId, artifactId, version ) )
+ {
+ buffer.append( " " ).append( ModelProblemUtils.toId( groupId, artifactId, version ) );
+ }
+ if ( childModel != problems.getRootModel() )
+ {
+ buffer.append( " for " ).append( ModelProblemUtils.toId( childModel ) );
+ }
+ buffer.append( ": " ).append( e.getMessage() );
+ if ( childModel.getProjectDirectory() != null )
+ {
+ if ( parent.getRelativePath() == null || parent.getRelativePath().length() <= 0 )
+ {
+ buffer.append( " and 'parent.relativePath' points at no local POM" );
+ }
+ else
+ {
+ buffer.append( " and 'parent.relativePath' points at wrong local POM" );
+ }
+ }
+
+ problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.BASE )
+ .setMessage( buffer.toString() ).setLocation( parent.getLocation( "" ) ).setException( e ) );
+ throw problems.newModelBuildingException();
+ }
+
+ ModelBuildingRequest lenientRequest = request;
+ if ( request.getValidationLevel() > ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0 )
+ {
+ lenientRequest = new FilterModelBuildingRequest( request )
+ {
+ @Override
+ public int getValidationLevel()
+ {
+ return ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0;
+ }
+ };
+ }
+
+ Model parentModel = readModel( modelSource, null, lenientRequest, problems );
+
+ if ( !parent.getVersion().equals( version ) )
+ {
+ if ( childModel.getVersion() == null )
+ {
+ problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.V31 )
+ .setMessage( "Version must be a constant" ).setLocation( childModel.getLocation( "" ) ) );
+
+ }
+ else
+ {
+ if ( childModel.getVersion().indexOf( "${" ) > -1 )
+ {
+ problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.V31 )
+ .setMessage( "Version must be a constant" )
+ .setLocation( childModel.getLocation( "version" ) ) );
+
+ }
+ }
+
+ // MNG-2199: What else to check here ?
+ }
+
+ ModelData parentData = new ModelData( modelSource, parentModel, parent.getGroupId(), parent.getArtifactId(),
+ parent.getVersion() );
+
+ return parentData;
+ }
+
+ private Model getSuperModel()
+ {
+ return superPomProvider.getSuperModel( "4.0.0" ).clone();
+ }
+
+ private void importDependencyManagement( Model model, ModelBuildingRequest request,
+ DefaultModelProblemCollector problems, Collection<String> importIds )
+ {
+ DependencyManagement depMngt = model.getDependencyManagement();
+
+ if ( depMngt == null )
+ {
+ return;
+ }
+
+ String importing = model.getGroupId() + ':' + model.getArtifactId() + ':' + model.getVersion();
+
+ importIds.add( importing );
+
+ final WorkspaceModelResolver workspaceResolver = request.getWorkspaceModelResolver();
+ final ModelResolver modelResolver = request.getModelResolver();
+
+ ModelBuildingRequest importRequest = null;
+
+ List<DependencyManagement> importMngts = null;
+
+ for ( Iterator<Dependency> it = depMngt.getDependencies().iterator(); it.hasNext(); )
+ {
+ Dependency dependency = it.next();
+
+ if ( !"pom".equals( dependency.getType() ) || !"import".equals( dependency.getScope() ) )
+ {
+ continue;
+ }
+
+ it.remove();
+
+ String groupId = dependency.getGroupId();
+ String artifactId = dependency.getArtifactId();
+ String version = dependency.getVersion();
+
+ if ( groupId == null || groupId.length() <= 0 )
+ {
+ problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
+ .setMessage( "'dependencyManagement.dependencies.dependency.groupId' for "
+ + dependency.getManagementKey() + " is missing." )
+ .setLocation( dependency.getLocation( "" ) ) );
+ continue;
+ }
+ if ( artifactId == null || artifactId.length() <= 0 )
+ {
+ problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
+ .setMessage( "'dependencyManagement.dependencies.dependency.artifactId' for "
+ + dependency.getManagementKey() + " is missing." )
+ .setLocation( dependency.getLocation( "" ) ) );
+ continue;
+ }
+ if ( version == null || version.length() <= 0 )
+ {
+ problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
+ .setMessage( "'dependencyManagement.dependencies.dependency.version' for "
+ + dependency.getManagementKey() + " is missing." )
+ .setLocation( dependency.getLocation( "" ) ) );
+ continue;
+ }
+
+ String imported = groupId + ':' + artifactId + ':' + version;
+
+ if ( importIds.contains( imported ) )
+ {
+ String message = "The dependencies of type=pom and with scope=import form a cycle: ";
+ for ( String modelId : importIds )
+ {
+ message += modelId + " -> ";
+ }
+ message += imported;
+ problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE ).setMessage( message ) );
+
+ continue;
+ }
+
+ DependencyManagement importMngt = getCache( request.getModelCache(), groupId, artifactId, version,
+ ModelCacheTag.IMPORT );
+
+ if ( importMngt == null )
+ {
+ if ( workspaceResolver == null && modelResolver == null )
+ {
+ throw new IllegalArgumentException( "no model resolver provided, cannot resolve import POM "
+ + ModelProblemUtils.toId( groupId, artifactId, version ) + " for POM "
+ + ModelProblemUtils.toSourceHint( model ) );
+ }
+
+ Model importModel = null;
+ if ( workspaceResolver != null )
+ {
+ try
+ {
+ importModel = workspaceResolver.resolveEffectiveModel( groupId, artifactId, version );
+ }
+ catch ( UnresolvableModelException e )
+ {
+ problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.BASE )
+ .setMessage( e.getMessage().toString() ).setException( e ) );
+ continue;
+ }
+ }
+
+ // no workspace resolver or workspace resolver returned null (i.e. model not in workspace)
+ if ( importModel == null )
+ {
+ final ModelSource importSource;
+ try
+ {
+ importSource = modelResolver.resolveModel( groupId, artifactId, version );
+ }
+ catch ( UnresolvableModelException e )
+ {
+ StringBuilder buffer = new StringBuilder( 256 );
+ buffer.append( "Non-resolvable import POM" );
+ if ( !containsCoordinates( e.getMessage(), groupId, artifactId, version ) )
+ {
+ buffer.append( " " ).append( ModelProblemUtils.toId( groupId, artifactId, version ) );
+ }
+ buffer.append( ": " ).append( e.getMessage() );
+
+ problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
+ .setMessage( buffer.toString() ).setLocation( dependency.getLocation( "" ) )
+ .setException( e ) );
+ continue;
+ }
+
+ if ( importRequest == null )
+ {
+ importRequest = new DefaultModelBuildingRequest();
+ importRequest.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL );
+ importRequest.setModelCache( request.getModelCache() );
+ importRequest.setSystemProperties( request.getSystemProperties() );
+ importRequest.setUserProperties( request.getUserProperties() );
+ importRequest.setLocationTracking( request.isLocationTracking() );
+ }
+
+ importRequest.setModelSource( importSource );
+ importRequest.setModelResolver( modelResolver.newCopy() );
+
+ final ModelBuildingResult importResult;
+ try
+ {
+ importResult = build( importRequest );
+ }
+ catch ( ModelBuildingException e )
+ {
+ problems.addAll( e.getProblems() );
+ continue;
+ }
+
+ problems.addAll( importResult.getProblems() );
+
+ importModel = importResult.getEffectiveModel();
+ }
+
+ importMngt = importModel.getDependencyManagement();
+
+ if ( importMngt == null )
+ {
+ importMngt = new DependencyManagement();
+ }
+
+ putCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT, importMngt );
+ }
+
+ if ( importMngts == null )
+ {
+ importMngts = new ArrayList<DependencyManagement>();
+ }
+
+ importMngts.add( importMngt );
+ }
+
+ importIds.remove( importing );
+
+ dependencyManagementImporter.importManagement( model, importMngts, request, problems );
+ }
+
+ private <T> void putCache( ModelCache modelCache, String groupId, String artifactId, String version,
+ ModelCacheTag<T> tag, T data )
+ {
+ if ( modelCache != null )
+ {
+ modelCache.put( groupId, artifactId, version, tag.getName(), tag.intoCache( data ) );
+ }
+ }
+
+ private <T> T getCache( ModelCache modelCache, String groupId, String artifactId, String version,
+ ModelCacheTag<T> tag )
+ {
+ if ( modelCache != null )
+ {
+ Object data = modelCache.get( groupId, artifactId, version, tag.getName() );
+ if ( data != null )
+ {
+ return tag.fromCache( tag.getType().cast( data ) );
+ }
+ }
+ return null;
+ }
+
+ private void fireEvent( Model model, ModelBuildingRequest request, ModelProblemCollector problems,
+ ModelBuildingEventCatapult catapult )
+ throws ModelBuildingException
+ {
+ ModelBuildingListener listener = request.getModelBuildingListener();
+
+ if ( listener != null )
+ {
+ ModelBuildingEvent event = new DefaultModelBuildingEvent( model, request, problems );
+
+ catapult.fire( listener, event );
+ }
+ }
+
+ private boolean containsCoordinates( String message, String groupId, String artifactId, String version )
+ {
+ return message != null && ( groupId == null || message.contains( groupId ) )
+ && ( artifactId == null || message.contains( artifactId ) )
+ && ( version == null || message.contains( version ) );
+ }
+
+ protected boolean hasModelErrors( ModelProblemCollectorExt problems )
+ {
+ if ( problems instanceof DefaultModelProblemCollector )
+ {
+ return ( (DefaultModelProblemCollector) problems ).hasErrors();
+ }
+ else
+ {
+ // the default execution path only knows the DefaultModelProblemCollector,
+ // only reason it's not in signature is because it's package private
+ throw new IllegalStateException();
+ }
+ }
+
+ protected boolean hasFatalErrors( ModelProblemCollectorExt problems )
+ {
+ if ( problems instanceof DefaultModelProblemCollector )
+ {
+ return ( (DefaultModelProblemCollector) problems ).hasFatalErrors();
+ }
+ else
+ {
+ // the default execution path only knows the DefaultModelProblemCollector,
+ // only reason it's not in signature is because it's package private
+ throw new IllegalStateException();
+ }
+ }
+
+}