mirror of https://github.com/apache/maven.git
MNG-5444 fixed building MavenProject from ModelSource
To maintain compatibility with (the extremely unlikely) existing implementations of ModelSource, the new API methods are provided via optional ModelSource2 interface. Updated javadoc to encourage use of the new API. Signed-off-by: Igor Fedorenko <igor@ifedorenko.com>
This commit is contained in:
parent
ef06aab96d
commit
9b58a3cfdc
|
@ -24,6 +24,7 @@ import java.util.List;
|
||||||
|
|
||||||
import org.apache.maven.artifact.Artifact;
|
import org.apache.maven.artifact.Artifact;
|
||||||
import org.apache.maven.model.building.ModelSource;
|
import org.apache.maven.model.building.ModelSource;
|
||||||
|
import org.apache.maven.model.building.ModelSource2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds in-memory descriptions of projects.
|
* Builds in-memory descriptions of projects.
|
||||||
|
@ -74,6 +75,8 @@ public interface ProjectBuilder
|
||||||
* @param request The project building request that holds further parameters, must not be {@code null}.
|
* @param request The project building request that holds further parameters, must not be {@code null}.
|
||||||
* @return The result of the project building, never {@code null}.
|
* @return The result of the project building, never {@code null}.
|
||||||
* @throws ProjectBuildingException If the project descriptor could not be successfully built.
|
* @throws ProjectBuildingException If the project descriptor could not be successfully built.
|
||||||
|
*
|
||||||
|
* @see ModelSource2
|
||||||
*/
|
*/
|
||||||
ProjectBuildingResult build( ModelSource modelSource, ProjectBuildingRequest request )
|
ProjectBuildingResult build( ModelSource modelSource, ProjectBuildingRequest request )
|
||||||
throws ProjectBuildingException;
|
throws ProjectBuildingException;
|
||||||
|
|
|
@ -24,6 +24,8 @@ import java.util.Properties;
|
||||||
|
|
||||||
import org.apache.maven.AbstractCoreMavenComponentTestCase;
|
import org.apache.maven.AbstractCoreMavenComponentTestCase;
|
||||||
import org.apache.maven.execution.MavenSession;
|
import org.apache.maven.execution.MavenSession;
|
||||||
|
import org.apache.maven.model.building.FileModelSource;
|
||||||
|
import org.apache.maven.model.building.ModelSource;
|
||||||
|
|
||||||
public class ProjectBuilderTest
|
public class ProjectBuilderTest
|
||||||
extends AbstractCoreMavenComponentTestCase
|
extends AbstractCoreMavenComponentTestCase
|
||||||
|
@ -49,4 +51,18 @@ public class ProjectBuilderTest
|
||||||
|
|
||||||
project.getCompileClasspathElements();
|
project.getCompileClasspathElements();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testBuildFromModelSource()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
File pomFile = new File( "src/test/resources/projects/modelsource/module01/pom.xml" );
|
||||||
|
MavenSession mavenSession = createMavenSession( pomFile );
|
||||||
|
ProjectBuildingRequest configuration = new DefaultProjectBuildingRequest();
|
||||||
|
configuration.setRepositorySession( mavenSession.getRepositorySession() );
|
||||||
|
ModelSource modelSource = new FileModelSource( pomFile );
|
||||||
|
ProjectBuildingResult result =
|
||||||
|
lookup( org.apache.maven.project.ProjectBuilder.class ).build( modelSource, configuration );
|
||||||
|
|
||||||
|
assertNotNull( result.getProject().getParentFile() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>test.readparent</groupId>
|
||||||
|
<artifactId>local-parent</artifactId>
|
||||||
|
<version>1.0</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>module01</artifactId>
|
||||||
|
</project>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>test.readparent</groupId>
|
||||||
|
<artifactId>local-parent</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<version>1.0</version>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module>module</module>
|
||||||
|
</modules>
|
||||||
|
|
||||||
|
</project>
|
|
@ -257,8 +257,8 @@ public class DefaultModelBuilder
|
||||||
|
|
||||||
problems.setRootModel( inputModel );
|
problems.setRootModel( inputModel );
|
||||||
|
|
||||||
ModelData resultData = new ModelData( inputModel );
|
ModelData resultData = new ModelData( request.getModelSource(), inputModel );
|
||||||
ModelData superData = new ModelData( getSuperModel() );
|
ModelData superData = new ModelData( null, getSuperModel() );
|
||||||
|
|
||||||
Collection<String> parentIds = new LinkedHashSet<String>();
|
Collection<String> parentIds = new LinkedHashSet<String>();
|
||||||
parentIds.add( ModelProblemUtils.toId( inputModel ) );
|
parentIds.add( ModelProblemUtils.toId( inputModel ) );
|
||||||
|
@ -304,7 +304,7 @@ public class DefaultModelBuilder
|
||||||
|
|
||||||
configureResolver( request.getModelResolver(), tmpModel, problems );
|
configureResolver( request.getModelResolver(), tmpModel, problems );
|
||||||
|
|
||||||
currentData = readParent( tmpModel, request, problems );
|
currentData = readParent( tmpModel, currentData.getSource(), request, problems );
|
||||||
|
|
||||||
if ( currentData == null )
|
if ( currentData == null )
|
||||||
{
|
{
|
||||||
|
@ -644,7 +644,7 @@ public class DefaultModelBuilder
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ModelData readParent( Model childModel, ModelBuildingRequest request,
|
private ModelData readParent( Model childModel, ModelSource childSource, ModelBuildingRequest request,
|
||||||
DefaultModelProblemCollector problems )
|
DefaultModelProblemCollector problems )
|
||||||
throws ModelBuildingException
|
throws ModelBuildingException
|
||||||
{
|
{
|
||||||
|
@ -662,7 +662,7 @@ public class DefaultModelBuilder
|
||||||
|
|
||||||
if ( parentData == null )
|
if ( parentData == null )
|
||||||
{
|
{
|
||||||
parentData = readParentLocally( childModel, request, problems );
|
parentData = readParentLocally( childModel, childSource, request, problems );
|
||||||
|
|
||||||
if ( parentData == null )
|
if ( parentData == null )
|
||||||
{
|
{
|
||||||
|
@ -683,9 +683,10 @@ public class DefaultModelBuilder
|
||||||
File pomFile = parentData.getModel().getPomFile();
|
File pomFile = parentData.getModel().getPomFile();
|
||||||
if ( pomFile != null )
|
if ( pomFile != null )
|
||||||
{
|
{
|
||||||
File expectedParentFile = getParentPomFile( childModel );
|
ModelSource expectedParentSource = getParentPomFile( childModel, childSource );
|
||||||
|
|
||||||
if ( !pomFile.equals( expectedParentFile ) )
|
if ( expectedParentSource instanceof ModelSource2
|
||||||
|
&& !pomFile.toURI().equals( ( (ModelSource2) expectedParentSource ).getLocationURI() ) )
|
||||||
{
|
{
|
||||||
parentData = readParentExternally( childModel, request, problems );
|
parentData = readParentExternally( childModel, request, problems );
|
||||||
}
|
}
|
||||||
|
@ -710,18 +711,24 @@ public class DefaultModelBuilder
|
||||||
return parentData;
|
return parentData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ModelData readParentLocally( Model childModel, ModelBuildingRequest request,
|
private ModelData readParentLocally( Model childModel, ModelSource childSource, ModelBuildingRequest request,
|
||||||
DefaultModelProblemCollector problems )
|
DefaultModelProblemCollector problems )
|
||||||
throws ModelBuildingException
|
throws ModelBuildingException
|
||||||
{
|
{
|
||||||
File pomFile = getParentPomFile( childModel );
|
ModelSource candidateSource = getParentPomFile( childModel, childSource );
|
||||||
|
|
||||||
if ( pomFile == null || !pomFile.isFile() )
|
if ( candidateSource == null )
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Model candidateModel = readModel( null, pomFile, request, problems );
|
File pomFile = null;
|
||||||
|
if ( candidateSource instanceof FileModelSource )
|
||||||
|
{
|
||||||
|
pomFile = ( (FileModelSource) candidateSource ).getPomFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
Model candidateModel = readModel( candidateSource, pomFile, request, problems );
|
||||||
|
|
||||||
String groupId = candidateModel.getGroupId();
|
String groupId = candidateModel.getGroupId();
|
||||||
if ( groupId == null && candidateModel.getParent() != null )
|
if ( groupId == null && candidateModel.getParent() != null )
|
||||||
|
@ -761,16 +768,14 @@ public class DefaultModelBuilder
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelData parentData = new ModelData( candidateModel, groupId, artifactId, version );
|
ModelData parentData = new ModelData( candidateSource, candidateModel, groupId, artifactId, version );
|
||||||
|
|
||||||
return parentData;
|
return parentData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private File getParentPomFile( Model childModel )
|
private ModelSource getParentPomFile( Model childModel, ModelSource source )
|
||||||
{
|
{
|
||||||
File projectDirectory = childModel.getProjectDirectory();
|
if ( !( source instanceof ModelSource2 ) )
|
||||||
|
|
||||||
if ( projectDirectory == null )
|
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -782,16 +787,7 @@ public class DefaultModelBuilder
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
parentPath = parentPath.replace( '\\', File.separatorChar ).replace( '/', File.separatorChar );
|
return ( (ModelSource2) source ).getRelatedSource( parentPath );
|
||||||
|
|
||||||
File pomFile = new File( new File( projectDirectory, parentPath ).toURI().normalize() );
|
|
||||||
|
|
||||||
if ( pomFile.isDirectory() )
|
|
||||||
{
|
|
||||||
pomFile = modelProcessor.locatePom( pomFile );
|
|
||||||
}
|
|
||||||
|
|
||||||
return pomFile;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ModelData readParentExternally( Model childModel, ModelBuildingRequest request,
|
private ModelData readParentExternally( Model childModel, ModelBuildingRequest request,
|
||||||
|
@ -867,7 +863,7 @@ public class DefaultModelBuilder
|
||||||
|
|
||||||
Model parentModel = readModel( modelSource, null, lenientRequest, problems );
|
Model parentModel = readModel( modelSource, null, lenientRequest, problems );
|
||||||
|
|
||||||
ModelData parentData = new ModelData( parentModel, groupId, artifactId, version );
|
ModelData parentData = new ModelData( modelSource, parentModel, groupId, artifactId, version );
|
||||||
|
|
||||||
return parentData;
|
return parentData;
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,8 +109,12 @@ public class DefaultModelBuildingRequest
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModelSource getModelSource()
|
public synchronized ModelSource getModelSource()
|
||||||
{
|
{
|
||||||
|
if ( modelSource == null && pomFile != null )
|
||||||
|
{
|
||||||
|
modelSource = new FileModelSource( pomFile );
|
||||||
|
}
|
||||||
return modelSource;
|
return modelSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wraps an ordinary {@link File} as a model source.
|
* Wraps an ordinary {@link File} as a model source.
|
||||||
|
@ -30,10 +31,9 @@ import java.io.InputStream;
|
||||||
* @author Benjamin Bentmann
|
* @author Benjamin Bentmann
|
||||||
*/
|
*/
|
||||||
public class FileModelSource
|
public class FileModelSource
|
||||||
implements ModelSource
|
implements ModelSource2
|
||||||
{
|
{
|
||||||
|
private final File pomFile;
|
||||||
private File pomFile;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new model source backed by the specified file.
|
* Creates a new model source backed by the specified file.
|
||||||
|
@ -76,4 +76,28 @@ public class FileModelSource
|
||||||
return getLocation();
|
return getLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ModelSource2 getRelatedSource( String relPath )
|
||||||
|
{
|
||||||
|
relPath = relPath.replace( '\\', File.separatorChar ).replace( '/', File.separatorChar );
|
||||||
|
|
||||||
|
File relatedPom = new File( pomFile.getParentFile(), relPath );
|
||||||
|
|
||||||
|
if ( relatedPom.isDirectory() )
|
||||||
|
{
|
||||||
|
// TODO figure out how to reuse ModelLocator.locatePom(File) here
|
||||||
|
relatedPom = new File( relatedPom, "pom.xml" );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( relatedPom.isFile() && relatedPom.canRead() )
|
||||||
|
{
|
||||||
|
return new FileModelSource( new File( relatedPom.toURI().normalize() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public URI getLocationURI()
|
||||||
|
{
|
||||||
|
return pomFile.toURI();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ interface ModelCacheTag<T>
|
||||||
public ModelData intoCache( ModelData data )
|
public ModelData intoCache( ModelData data )
|
||||||
{
|
{
|
||||||
Model model = ( data.getModel() != null ) ? data.getModel().clone() : null;
|
Model model = ( data.getModel() != null ) ? data.getModel().clone() : null;
|
||||||
return new ModelData( model, data.getGroupId(), data.getArtifactId(), data.getVersion() );
|
return new ModelData( data.getSource(), model, data.getGroupId(), data.getArtifactId(), data.getVersion() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModelData fromCache( ModelData data )
|
public ModelData fromCache( ModelData data )
|
||||||
|
|
|
@ -32,6 +32,7 @@ import org.apache.maven.model.Profile;
|
||||||
*/
|
*/
|
||||||
class ModelData
|
class ModelData
|
||||||
{
|
{
|
||||||
|
private final ModelSource source;
|
||||||
|
|
||||||
private Model model;
|
private Model model;
|
||||||
|
|
||||||
|
@ -50,8 +51,9 @@ class ModelData
|
||||||
*
|
*
|
||||||
* @param model The model to wrap, may be {@code null}.
|
* @param model The model to wrap, may be {@code null}.
|
||||||
*/
|
*/
|
||||||
public ModelData( Model model )
|
public ModelData( ModelSource source, Model model )
|
||||||
{
|
{
|
||||||
|
this.source = source;
|
||||||
this.model = model;
|
this.model = model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,14 +65,20 @@ class ModelData
|
||||||
* @param artifactId The effective artifact identifier of the model, may be {@code null}.
|
* @param artifactId The effective artifact identifier of the model, may be {@code null}.
|
||||||
* @param version The effective version of the model, may be {@code null}.
|
* @param version The effective version of the model, may be {@code null}.
|
||||||
*/
|
*/
|
||||||
public ModelData( Model model, String groupId, String artifactId, String version )
|
public ModelData( ModelSource source, Model model, String groupId, String artifactId, String version )
|
||||||
{
|
{
|
||||||
|
this.source = source;
|
||||||
this.model = model;
|
this.model = model;
|
||||||
setGroupId( groupId );
|
setGroupId( groupId );
|
||||||
setArtifactId( artifactId );
|
setArtifactId( artifactId );
|
||||||
setVersion( version );
|
setVersion( version );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ModelSource getSource()
|
||||||
|
{
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the model being wrapped.
|
* Gets the model being wrapped.
|
||||||
*
|
*
|
||||||
|
|
|
@ -24,8 +24,12 @@ import java.io.InputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides access to the contents of a POM independently of the backing store (e.g. file system, database, memory).
|
* Provides access to the contents of a POM independently of the backing store (e.g. file system, database, memory).
|
||||||
|
* <p>
|
||||||
|
* This interface does not support loading of parent POM(s) from the same backing store, integrators are strongly
|
||||||
|
* encouraged to implement {@link ModelSource2} instead of implementing this interface directly.
|
||||||
*
|
*
|
||||||
* @author Benjamin Bentmann
|
* @author Benjamin Bentmann
|
||||||
|
* @see ModelSource2
|
||||||
*/
|
*/
|
||||||
public interface ModelSource
|
public interface ModelSource
|
||||||
{
|
{
|
||||||
|
|
|
@ -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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to the contents of a POM independently of the backing store (e.g. file system, database, memory).
|
||||||
|
* <p>
|
||||||
|
* Unlike {@link ModelSource}, this interface supports loading of parent POM(s) from the same backing store and allows
|
||||||
|
* construction of MavenProject instances without the need to have parent POM(s) available from local or remote
|
||||||
|
* repositories.
|
||||||
|
* <p>
|
||||||
|
* ModelSource2 instances are cached in {@link ModelBuildingRequest#getModelCache()}. Implementations must guarantee
|
||||||
|
* that the connection to the backing store remains active until request's {@link ModelCache} is discarded or flushed.
|
||||||
|
*/
|
||||||
|
public interface ModelSource2
|
||||||
|
extends ModelSource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns model source identified by a path relative to this model source POM. Implementation <strong>MUST</strong>
|
||||||
|
* be able to accept <code>relPath</code> parameter values that
|
||||||
|
* <ul>
|
||||||
|
* <li>use either / or \ file path separator</li>
|
||||||
|
* <li>have .. parent directory references</li>
|
||||||
|
* <li>point either at file or directory, in the latter case POM file name 'pom.xml' needs to be used by the
|
||||||
|
* requested model source.</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param relPath is the path of the requested model source relative to this model source POM.
|
||||||
|
* @return related model source or <code>null</code> if no such model source.
|
||||||
|
*/
|
||||||
|
ModelSource2 getRelatedSource( String relPath );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns location of the POM, never <code>null</code>.
|
||||||
|
*/
|
||||||
|
URI getLocationURI();
|
||||||
|
}
|
Loading…
Reference in New Issue