mirror of https://github.com/apache/maven.git
o Enabled model cache
git-svn-id: https://svn.apache.org/repos/asf/maven/components/trunk@799470 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
147c7a6955
commit
c2078c65b1
|
@ -301,7 +301,9 @@ public class DefaultProjectBuilder
|
||||||
|
|
||||||
ReactorModelPool reactorModelPool = new ReactorModelPool();
|
ReactorModelPool reactorModelPool = new ReactorModelPool();
|
||||||
|
|
||||||
boolean errors = build( results, interimResults, pomFiles, recursive, config, reactorModelPool );
|
ReactorModelCache modelCache = new ReactorModelCache();
|
||||||
|
|
||||||
|
boolean errors = build( results, interimResults, pomFiles, recursive, config, reactorModelPool, modelCache );
|
||||||
|
|
||||||
for ( InterimResult interimResult : interimResults )
|
for ( InterimResult interimResult : interimResults )
|
||||||
{
|
{
|
||||||
|
@ -344,17 +346,19 @@ public class DefaultProjectBuilder
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean build( List<ProjectBuildingResult> results, List<InterimResult> interimResults, List<File> pomFiles,
|
private boolean build( List<ProjectBuildingResult> results, List<InterimResult> interimResults,
|
||||||
boolean recursive, ProjectBuildingRequest config, ReactorModelPool reactorModelPool )
|
List<File> pomFiles, boolean recursive, ProjectBuildingRequest config,
|
||||||
|
ReactorModelPool reactorModelPool, ReactorModelCache modelCache )
|
||||||
{
|
{
|
||||||
boolean errors = false;
|
boolean errors = false;
|
||||||
|
|
||||||
for ( File pomFile : pomFiles )
|
for ( File pomFile : pomFiles )
|
||||||
{
|
{
|
||||||
ModelBuildingRequest request = getModelBuildingRequest( config, reactorModelPool );
|
ModelBuildingRequest request = getModelBuildingRequest( config, reactorModelPool );
|
||||||
|
|
||||||
request.setPomFile( pomFile );
|
request.setPomFile( pomFile );
|
||||||
request.setTwoPhaseBuilding( true );
|
request.setTwoPhaseBuilding( true );
|
||||||
|
request.setModelCache( modelCache );
|
||||||
|
|
||||||
DefaultModelBuildingListener listener = new DefaultModelBuildingListener( projectBuildingHelper, config );
|
DefaultModelBuildingListener listener = new DefaultModelBuildingListener( projectBuildingHelper, config );
|
||||||
request.setModelBuildingListeners( Arrays.asList( listener ) );
|
request.setModelBuildingListeners( Arrays.asList( listener ) );
|
||||||
|
@ -421,7 +425,8 @@ public class DefaultProjectBuilder
|
||||||
}
|
}
|
||||||
|
|
||||||
errors =
|
errors =
|
||||||
build( results, interimResults, moduleFiles, recursive, config, reactorModelPool ) || errors;
|
build( results, interimResults, moduleFiles, recursive, config, reactorModelPool, modelCache )
|
||||||
|
|| errors;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch ( ModelBuildingException e )
|
catch ( ModelBuildingException e )
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
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.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.maven.model.building.ModelCache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple model cache used to accelerate model building during a reactor build.
|
||||||
|
*
|
||||||
|
* @author Benjamin Bentmann
|
||||||
|
*/
|
||||||
|
class ReactorModelCache
|
||||||
|
implements ModelCache
|
||||||
|
{
|
||||||
|
|
||||||
|
private final Map<CacheKey, Object> models = new HashMap<CacheKey, Object>( 256 );
|
||||||
|
|
||||||
|
public Object get( String groupId, String artifactId, String version, String tag )
|
||||||
|
{
|
||||||
|
return models.get( new CacheKey( groupId, artifactId, version, tag ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put( String groupId, String artifactId, String version, String tag, Object data )
|
||||||
|
{
|
||||||
|
models.put( new CacheKey( groupId, artifactId, version, tag ), data );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class CacheKey
|
||||||
|
{
|
||||||
|
|
||||||
|
private final String groupId;
|
||||||
|
|
||||||
|
private final String artifactId;
|
||||||
|
|
||||||
|
private final String version;
|
||||||
|
|
||||||
|
private final String tag;
|
||||||
|
|
||||||
|
private final int hashCode;
|
||||||
|
|
||||||
|
public CacheKey( String groupId, String artifactId, String version, String tag )
|
||||||
|
{
|
||||||
|
this.groupId = ( groupId != null ) ? groupId : "";
|
||||||
|
this.artifactId = ( artifactId != null ) ? artifactId : "";
|
||||||
|
this.version = ( version != null ) ? version : "";
|
||||||
|
this.tag = ( tag != null ) ? tag : "";
|
||||||
|
|
||||||
|
int hash = 17;
|
||||||
|
hash = hash * 31 + this.groupId.hashCode();
|
||||||
|
hash = hash * 31 + this.artifactId.hashCode();
|
||||||
|
hash = hash * 31 + this.version.hashCode();
|
||||||
|
hash = hash * 31 + this.tag.hashCode();
|
||||||
|
hashCode = hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals( Object obj )
|
||||||
|
{
|
||||||
|
if ( this == obj )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !( obj instanceof CacheKey ) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CacheKey that = (CacheKey) obj;
|
||||||
|
|
||||||
|
return artifactId.equals( that.artifactId ) && groupId.equals( that.groupId )
|
||||||
|
&& version.equals( that.version ) && tag.equals( that.tag );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode()
|
||||||
|
{
|
||||||
|
return hashCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -237,9 +237,6 @@ public class DefaultModelBuilder
|
||||||
throw new ModelBuildingException( problems );
|
throw new ModelBuildingException( problems );
|
||||||
}
|
}
|
||||||
|
|
||||||
putCache( request.getModelCache(), resultModel.getGroupId(), resultModel.getArtifactId(),
|
|
||||||
resultModel.getVersion(), ModelCacheTag.EFFECTIVE, resultModel );
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,9 +446,23 @@ public class DefaultModelBuilder
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
parentData =
|
/*
|
||||||
new ModelData( ModelUtils.cloneModel( parentData.getModel() ), parentData.getGroupId(),
|
* NOTE: This is a sanity check of the cache hit. If the cached parent POM was locally resolved, the
|
||||||
parentData.getArtifactId(), parentData.getVersion() );
|
* 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 )
|
||||||
|
{
|
||||||
|
File expectedParentFile = getParentPomFile( childModel );
|
||||||
|
|
||||||
|
if ( !pomFile.equals( expectedParentFile ) )
|
||||||
|
{
|
||||||
|
parentData = readParentExternally( childModel, request, problems );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -465,20 +476,9 @@ public class DefaultModelBuilder
|
||||||
private ModelData readParentLocally( Model childModel, ModelBuildingRequest request, List<ModelProblem> problems )
|
private ModelData readParentLocally( Model childModel, ModelBuildingRequest request, List<ModelProblem> problems )
|
||||||
throws ModelBuildingException
|
throws ModelBuildingException
|
||||||
{
|
{
|
||||||
File projectDirectory = childModel.getProjectDirectory();
|
File pomFile = getParentPomFile( childModel );
|
||||||
if ( projectDirectory == null )
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Parent parent = childModel.getParent();
|
if ( pomFile == null || !pomFile.isFile() )
|
||||||
|
|
||||||
File pomFile = new File( new File( projectDirectory, parent.getRelativePath() ).toURI().normalize() );
|
|
||||||
if ( pomFile.isDirectory() )
|
|
||||||
{
|
|
||||||
pomFile = new File( pomFile, "pom.xml" );
|
|
||||||
}
|
|
||||||
if ( !pomFile.isFile() )
|
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -497,6 +497,8 @@ public class DefaultModelBuilder
|
||||||
version = candidateModel.getParent().getVersion();
|
version = candidateModel.getParent().getVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Parent parent = childModel.getParent();
|
||||||
|
|
||||||
if ( groupId == null || !groupId.equals( parent.getGroupId() ) )
|
if ( groupId == null || !groupId.equals( parent.getGroupId() ) )
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
|
@ -515,6 +517,27 @@ public class DefaultModelBuilder
|
||||||
return parentData;
|
return parentData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private File getParentPomFile( Model childModel )
|
||||||
|
{
|
||||||
|
File projectDirectory = childModel.getProjectDirectory();
|
||||||
|
|
||||||
|
if ( projectDirectory == null )
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String parentPath = childModel.getParent().getRelativePath();
|
||||||
|
|
||||||
|
File pomFile = new File( new File( projectDirectory, parentPath ).toURI().normalize() );
|
||||||
|
|
||||||
|
if ( pomFile.isDirectory() )
|
||||||
|
{
|
||||||
|
pomFile = new File( pomFile, "pom.xml" );
|
||||||
|
}
|
||||||
|
|
||||||
|
return pomFile;
|
||||||
|
}
|
||||||
|
|
||||||
private ModelData readParentExternally( Model childModel, ModelBuildingRequest request, List<ModelProblem> problems )
|
private ModelData readParentExternally( Model childModel, ModelBuildingRequest request, List<ModelProblem> problems )
|
||||||
throws ModelBuildingException
|
throws ModelBuildingException
|
||||||
{
|
{
|
||||||
|
@ -588,12 +611,10 @@ public class DefaultModelBuilder
|
||||||
String artifactId = dependency.getArtifactId();
|
String artifactId = dependency.getArtifactId();
|
||||||
String version = dependency.getVersion();
|
String version = dependency.getVersion();
|
||||||
|
|
||||||
DependencyManagement importMngt;
|
DependencyManagement importMngt =
|
||||||
|
getCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT );
|
||||||
|
|
||||||
Model importModel =
|
if ( importMngt == null )
|
||||||
getCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.EFFECTIVE );
|
|
||||||
|
|
||||||
if ( importModel == null )
|
|
||||||
{
|
{
|
||||||
if ( modelResolver == null )
|
if ( modelResolver == null )
|
||||||
{
|
{
|
||||||
|
@ -636,18 +657,16 @@ public class DefaultModelBuilder
|
||||||
|
|
||||||
problems.addAll( importResult.getProblems() );
|
problems.addAll( importResult.getProblems() );
|
||||||
|
|
||||||
importModel = importResult.getEffectiveModel();
|
Model importModel = importResult.getEffectiveModel();
|
||||||
|
|
||||||
importMngt = importModel.getDependencyManagement();
|
importMngt = importModel.getDependencyManagement();
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
importMngt = ModelUtils.cloneDependencyManagement( importModel.getDependencyManagement() );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( importMngt == null )
|
if ( importMngt == null )
|
||||||
{
|
{
|
||||||
continue;
|
importMngt = new DependencyManagement();
|
||||||
|
}
|
||||||
|
|
||||||
|
putCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT, importMngt );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( importMngts == null )
|
if ( importMngts == null )
|
||||||
|
@ -666,7 +685,7 @@ public class DefaultModelBuilder
|
||||||
{
|
{
|
||||||
if ( modelCache != null )
|
if ( modelCache != null )
|
||||||
{
|
{
|
||||||
modelCache.put( groupId, artifactId, version, tag.getName(), data );
|
modelCache.put( groupId, artifactId, version, tag.getName(), tag.intoCache( data ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -675,7 +694,11 @@ public class DefaultModelBuilder
|
||||||
{
|
{
|
||||||
if ( modelCache != null )
|
if ( modelCache != null )
|
||||||
{
|
{
|
||||||
return tag.getType().cast( modelCache.get( groupId, artifactId, version, tag.getName() ) );
|
Object data = modelCache.get( groupId, artifactId, version, tag.getName() );
|
||||||
|
if ( data != null )
|
||||||
|
{
|
||||||
|
return tag.fromCache( tag.getType().cast( data ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,12 @@ package org.apache.maven.model.building;
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import org.apache.maven.model.DependencyManagement;
|
||||||
import org.apache.maven.model.Model;
|
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
|
* Describes a tag used by the model builder to access a {@link ModelCache}. This interface basically aggregates a name
|
||||||
* a class to provide some type safety when working with the otherwise untyped cache.
|
* and a class to provide some type safety when working with the otherwise untyped cache.
|
||||||
*
|
*
|
||||||
* @author Benjamin Bentmann
|
* @author Benjamin Bentmann
|
||||||
* @param <T> The type of data associated with the tag.
|
* @param <T> The type of data associated with the tag.
|
||||||
|
@ -45,6 +46,24 @@ interface ModelCacheTag<T>
|
||||||
*/
|
*/
|
||||||
Class<T> getType();
|
Class<T> getType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a copy of the data suitable for storage in the cache. The original data to store can be mutated after the
|
||||||
|
* cache is populated but the state of the cache must not change so we need to make a copy.
|
||||||
|
*
|
||||||
|
* @param data The data to store in the cache, must not be {@code null}.
|
||||||
|
* @return The data being stored in the cache, never {@code null}.
|
||||||
|
*/
|
||||||
|
T intoCache( T data );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a copy of the data suitable for retrieval from the cache. The retrieved data can be mutated after the
|
||||||
|
* cache is queried but the state of the cache must not change so we need to make a copy.
|
||||||
|
*
|
||||||
|
* @param data The data to retrieve from the cache, must not be {@code null}.
|
||||||
|
* @return The data being retrieved from the cache, never {@code null}.
|
||||||
|
*/
|
||||||
|
T fromCache( T data );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The tag used to denote raw model data.
|
* The tag used to denote raw model data.
|
||||||
*/
|
*/
|
||||||
|
@ -61,24 +80,45 @@ interface ModelCacheTag<T>
|
||||||
return ModelData.class;
|
return ModelData.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ModelData intoCache( ModelData data )
|
||||||
|
{
|
||||||
|
Model model = ModelUtils.cloneModel( data.getModel() );
|
||||||
|
return new ModelData( model, data.getGroupId(), data.getArtifactId(), data.getVersion() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModelData fromCache( ModelData data )
|
||||||
|
{
|
||||||
|
return intoCache( data );
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The tag used to denote an effective model.
|
* The tag used to denote an effective dependency management section from an imported model.
|
||||||
*/
|
*/
|
||||||
public static final ModelCacheTag<Model> EFFECTIVE = new ModelCacheTag<Model>()
|
public static final ModelCacheTag<DependencyManagement> IMPORT = new ModelCacheTag<DependencyManagement>()
|
||||||
{
|
{
|
||||||
|
|
||||||
public String getName()
|
public String getName()
|
||||||
{
|
{
|
||||||
return "effective";
|
return "import";
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class<Model> getType()
|
public Class<DependencyManagement> getType()
|
||||||
{
|
{
|
||||||
return Model.class;
|
return DependencyManagement.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DependencyManagement intoCache( DependencyManagement data )
|
||||||
|
{
|
||||||
|
return ModelUtils.cloneDependencyManagement( data );
|
||||||
|
};
|
||||||
|
|
||||||
|
public DependencyManagement fromCache( DependencyManagement data )
|
||||||
|
{
|
||||||
|
return intoCache( data );
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue