mirror of https://github.com/apache/maven.git
o Introduced model cache to avoid repeated building of models that can occur multiple times during a reactor build (e.g. parents and imported POMs)
git-svn-id: https://svn.apache.org/repos/asf/maven/components/trunk@797959 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
b2a9420e63
commit
57f82d7694
|
@ -424,11 +424,28 @@ public class DefaultModelBuilder
|
||||||
|
|
||||||
if ( parent != null )
|
if ( parent != null )
|
||||||
{
|
{
|
||||||
parentData = readParentLocally( childModel, request, problems );
|
String groupId = parent.getGroupId();
|
||||||
|
String artifactId = parent.getArtifactId();
|
||||||
|
String version = parent.getVersion();
|
||||||
|
|
||||||
|
parentData = getCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.RAW );
|
||||||
|
|
||||||
if ( parentData == null )
|
if ( parentData == null )
|
||||||
{
|
{
|
||||||
parentData = readParentExternally( childModel, request, problems );
|
parentData = readParentLocally( childModel, request, problems );
|
||||||
|
|
||||||
|
if ( parentData == null )
|
||||||
|
{
|
||||||
|
parentData = readParentExternally( childModel, request, problems );
|
||||||
|
}
|
||||||
|
|
||||||
|
putCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.RAW, parentData );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parentData =
|
||||||
|
new ModelData( ModelUtils.cloneModel( parentData.getModel() ), parentData.getGroupId(),
|
||||||
|
parentData.getArtifactId(), parentData.getVersion() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -497,23 +514,27 @@ public class DefaultModelBuilder
|
||||||
{
|
{
|
||||||
Parent parent = childModel.getParent();
|
Parent parent = childModel.getParent();
|
||||||
|
|
||||||
|
String groupId = parent.getGroupId();
|
||||||
|
String artifactId = parent.getArtifactId();
|
||||||
|
String version = parent.getVersion();
|
||||||
|
|
||||||
ModelResolver modelResolver = request.getModelResolver();
|
ModelResolver modelResolver = request.getModelResolver();
|
||||||
|
|
||||||
if ( modelResolver == null )
|
if ( modelResolver == null )
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException( "no model resolver provided, cannot resolve parent POM "
|
throw new IllegalArgumentException( "no model resolver provided, cannot resolve parent POM "
|
||||||
+ toId( parent ) + " for POM " + toSourceHint( childModel ) );
|
+ toId( groupId, artifactId, version ) + " for POM " + toSourceHint( childModel ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelSource modelSource;
|
ModelSource modelSource;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
modelSource = modelResolver.resolveModel( parent.getGroupId(), parent.getArtifactId(), parent.getVersion() );
|
modelSource = modelResolver.resolveModel( groupId, artifactId, version );
|
||||||
}
|
}
|
||||||
catch ( UnresolvableModelException e )
|
catch ( UnresolvableModelException e )
|
||||||
{
|
{
|
||||||
problems.add( new ModelProblem( "Non-resolvable parent POM " + toId( parent ) + " for POM "
|
problems.add( new ModelProblem( "Non-resolvable parent POM " + toId( groupId, artifactId, version )
|
||||||
+ toSourceHint( childModel ) + ": " + e.getMessage(), ModelProblem.Severity.FATAL,
|
+ " for POM " + toSourceHint( childModel ) + ": " + e.getMessage(), ModelProblem.Severity.FATAL,
|
||||||
toSourceHint( childModel ), e ) );
|
toSourceHint( childModel ), e ) );
|
||||||
throw new ModelBuildingException( problems );
|
throw new ModelBuildingException( problems );
|
||||||
}
|
}
|
||||||
|
@ -557,60 +578,95 @@ public class DefaultModelBuilder
|
||||||
|
|
||||||
it.remove();
|
it.remove();
|
||||||
|
|
||||||
if ( modelResolver == null )
|
String groupId = dependency.getGroupId();
|
||||||
{
|
String artifactId = dependency.getArtifactId();
|
||||||
throw new IllegalArgumentException( "no model resolver provided, cannot resolve import POM "
|
String version = dependency.getVersion();
|
||||||
+ toId( dependency ) + " for POM " + toSourceHint( model ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
ModelSource importSource;
|
Model importModel =
|
||||||
try
|
getCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.EFFECTIVE );
|
||||||
{
|
|
||||||
importSource =
|
|
||||||
modelResolver.resolveModel( dependency.getGroupId(), dependency.getArtifactId(),
|
|
||||||
dependency.getVersion() );
|
|
||||||
}
|
|
||||||
catch ( UnresolvableModelException e )
|
|
||||||
{
|
|
||||||
problems.add( new ModelProblem( "Non-resolvable import POM " + toId( dependency ) + " for POM "
|
|
||||||
+ toSourceHint( model ) + ": " + e.getMessage(), ModelProblem.Severity.ERROR,
|
|
||||||
toSourceHint( model ), e ) );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( importRequest == null )
|
if ( importModel == null )
|
||||||
{
|
{
|
||||||
importRequest = new DefaultModelBuildingRequest();
|
if ( modelResolver == null )
|
||||||
importRequest.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL );
|
{
|
||||||
|
throw new IllegalArgumentException( "no model resolver provided, cannot resolve import POM "
|
||||||
|
+ toId( groupId, artifactId, version ) + " for POM " + toSourceHint( model ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelSource importSource;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
importSource = modelResolver.resolveModel( groupId, artifactId, version );
|
||||||
|
}
|
||||||
|
catch ( UnresolvableModelException e )
|
||||||
|
{
|
||||||
|
problems.add( new ModelProblem( "Non-resolvable import POM " + toId( groupId, artifactId, version )
|
||||||
|
+ " for POM " + toSourceHint( model ) + ": " + e.getMessage(), ModelProblem.Severity.ERROR,
|
||||||
|
toSourceHint( model ), e ) );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( importRequest == null )
|
||||||
|
{
|
||||||
|
importRequest = new DefaultModelBuildingRequest();
|
||||||
|
importRequest.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL );
|
||||||
|
}
|
||||||
|
|
||||||
|
importRequest.setModelSource( importSource );
|
||||||
|
importRequest.setModelResolver( modelResolver.newCopy() );
|
||||||
|
|
||||||
|
ModelBuildingResult importResult;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
importResult = build( importRequest );
|
||||||
|
}
|
||||||
|
catch ( ModelBuildingException e )
|
||||||
|
{
|
||||||
|
problems.addAll( e.getProblems() );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
problems.addAll( importResult.getProblems() );
|
||||||
|
|
||||||
|
importModel = importResult.getEffectiveModel();
|
||||||
|
|
||||||
|
putCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.EFFECTIVE, importModel );
|
||||||
}
|
}
|
||||||
|
else
|
||||||
importRequest.setModelSource( importSource );
|
|
||||||
importRequest.setModelResolver( modelResolver.newCopy() );
|
|
||||||
|
|
||||||
ModelBuildingResult importResult;
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
importResult = build( importRequest );
|
importModel = ModelUtils.cloneModel( importModel );
|
||||||
}
|
}
|
||||||
catch ( ModelBuildingException e )
|
|
||||||
{
|
|
||||||
problems.addAll( e.getProblems() );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
problems.addAll( importResult.getProblems() );
|
|
||||||
|
|
||||||
if ( importModels == null )
|
if ( importModels == null )
|
||||||
{
|
{
|
||||||
importModels = new ArrayList<Model>();
|
importModels = new ArrayList<Model>();
|
||||||
}
|
}
|
||||||
|
|
||||||
importModels.add( importResult.getEffectiveModel() );
|
importModels.add( importModel );
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencyManagementImporter.importManagement( model, importModels, request );
|
dependencyManagementImporter.importManagement( model, importModels, request );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(), data );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T getCache( ModelCache modelCache, String groupId, String artifactId, String version,
|
||||||
|
ModelCacheTag<T> tag )
|
||||||
|
{
|
||||||
|
if ( modelCache != null )
|
||||||
|
{
|
||||||
|
return tag.getType().cast( modelCache.get( groupId, artifactId, version, tag.getName() ) );
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private void fireBuildExtensionsAssembled( Model model, ModelBuildingRequest request, List<ModelProblem> problems )
|
private void fireBuildExtensionsAssembled( Model model, ModelBuildingRequest request, List<ModelProblem> problems )
|
||||||
throws ModelBuildingException
|
throws ModelBuildingException
|
||||||
{
|
{
|
||||||
|
@ -669,16 +725,6 @@ public class DefaultModelBuilder
|
||||||
return toId( groupId, artifactId, version );
|
return toId( groupId, artifactId, version );
|
||||||
}
|
}
|
||||||
|
|
||||||
private String toId( Parent parent )
|
|
||||||
{
|
|
||||||
return toId( parent.getGroupId(), parent.getArtifactId(), parent.getVersion() );
|
|
||||||
}
|
|
||||||
|
|
||||||
private String toId( Dependency dependency )
|
|
||||||
{
|
|
||||||
return toId( dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion() );
|
|
||||||
}
|
|
||||||
|
|
||||||
private String toId( String groupId, String artifactId, String version )
|
private String toId( String groupId, String artifactId, String version )
|
||||||
{
|
{
|
||||||
StringBuilder buffer = new StringBuilder( 96 );
|
StringBuilder buffer = new StringBuilder( 96 );
|
||||||
|
|
|
@ -61,6 +61,8 @@ public class DefaultModelBuildingRequest
|
||||||
|
|
||||||
private List<ModelBuildingListener> modelBuildingListeners;
|
private List<ModelBuildingListener> modelBuildingListeners;
|
||||||
|
|
||||||
|
private ModelCache modelCache;
|
||||||
|
|
||||||
public File getPomFile()
|
public File getPomFile()
|
||||||
{
|
{
|
||||||
return pomFile;
|
return pomFile;
|
||||||
|
@ -279,4 +281,16 @@ public class DefaultModelBuildingRequest
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ModelCache getModelCache()
|
||||||
|
{
|
||||||
|
return this.modelCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefaultModelBuildingRequest setModelCache( ModelCache modelCache )
|
||||||
|
{
|
||||||
|
this.modelCache = modelCache;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -262,4 +262,20 @@ public interface ModelBuildingRequest
|
||||||
*/
|
*/
|
||||||
ModelBuildingRequest setModelBuildingListeners( List<? extends ModelBuildingListener> modelBuildingListeners );
|
ModelBuildingRequest setModelBuildingListeners( List<? extends ModelBuildingListener> modelBuildingListeners );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the model cache to use for reuse of previously built models.
|
||||||
|
*
|
||||||
|
* @return The model cache or {@code null} if not set.
|
||||||
|
*/
|
||||||
|
ModelCache getModelCache();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the model cache to use for reuse of previously built models. This is an optional component that serves
|
||||||
|
* performance optimizations.
|
||||||
|
*
|
||||||
|
* @param modelCache The model cache to use, may be {@code null}.
|
||||||
|
* @return This request, never {@code null}.
|
||||||
|
*/
|
||||||
|
ModelBuildingRequest setModelCache( ModelCache modelCache );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Caches auxiliary data used during model building like already processed raw/effective models. The data in the cache
|
||||||
|
* is meant for exclusive consumption by the model builder and is opaque to the cache implementation. The cache key is
|
||||||
|
* formed by a combination of group id, artifact id, version and tag. The first three components generally refer to the
|
||||||
|
* identify of a model. The tag allows for further classification of the associated data on the sole discretion of the
|
||||||
|
* model builder.
|
||||||
|
*
|
||||||
|
* @author Benjamin Bentmann
|
||||||
|
*/
|
||||||
|
public interface ModelCache
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Puts the specified data into the cache.
|
||||||
|
*
|
||||||
|
* @param groupId The group id of the cache record, must not be {@code null}.
|
||||||
|
* @param artifactId The artifact id of the cache record, must not be {@code null}.
|
||||||
|
* @param version The version of the cache record, must not be {@code null}.
|
||||||
|
* @param tag The tag of the cache record, must not be {@code null}.
|
||||||
|
* @param data The data to store in the cache, must not be {@code null}.
|
||||||
|
*/
|
||||||
|
void put( String groupId, String artifactId, String version, String tag, Object data );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the specified data from the cache.
|
||||||
|
*
|
||||||
|
* @param groupId The group id of the cache record, must not be {@code null}.
|
||||||
|
* @param artifactId The artifact id of the cache record, must not be {@code null}.
|
||||||
|
* @param version The version of the cache record, must not be {@code null}.
|
||||||
|
* @param tag The tag of the cache record, must not be {@code null}.
|
||||||
|
* @return The requested data or {@code null} if none was present in the cache.
|
||||||
|
*/
|
||||||
|
Object get( String groupId, String artifactId, String version, String tag );
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
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 org.apache.maven.model.Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes a tag used by the model builder to access a {@link ModelCache}. This interface simply aggregates a name and
|
||||||
|
* a class to provide some type safety when working with the otherwise untyped cache.
|
||||||
|
*
|
||||||
|
* @author Benjamin Bentmann
|
||||||
|
* @param <T> The type of data associated with the tag.
|
||||||
|
*/
|
||||||
|
interface ModelCacheTag<T>
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of the tag.
|
||||||
|
*
|
||||||
|
* @return The name of the tag, must not be {@code null}.
|
||||||
|
*/
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the type of data associated with this tag.
|
||||||
|
*
|
||||||
|
* @return The type of data, must not be {@code null}.
|
||||||
|
*/
|
||||||
|
Class<T> getType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tag used to denote raw model data.
|
||||||
|
*/
|
||||||
|
public static final ModelCacheTag<ModelData> RAW = new ModelCacheTag<ModelData>()
|
||||||
|
{
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return "raw";
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<ModelData> getType()
|
||||||
|
{
|
||||||
|
return ModelData.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tag used to denote an effective model.
|
||||||
|
*/
|
||||||
|
public static final ModelCacheTag<Model> EFFECTIVE = new ModelCacheTag<Model>()
|
||||||
|
{
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return "effective";
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<Model> getType()
|
||||||
|
{
|
||||||
|
return Model.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue