mirror of https://github.com/apache/maven.git
MNG-5775 Make the project graph building code pluggable to allow for new/different implementations.
This commit is contained in:
parent
7997634209
commit
be3fb20032
|
@ -52,6 +52,7 @@ import org.eclipse.aether.impl.RemoteRepositoryManager;
|
|||
import org.eclipse.aether.impl.RepositoryEventDispatcher;
|
||||
import org.eclipse.aether.impl.VersionRangeResolver;
|
||||
import org.eclipse.aether.impl.VersionResolver;
|
||||
import org.eclipse.aether.repository.WorkspaceReader;
|
||||
import org.eclipse.aether.repository.WorkspaceRepository;
|
||||
import org.eclipse.aether.resolution.ArtifactDescriptorException;
|
||||
import org.eclipse.aether.resolution.ArtifactDescriptorPolicy;
|
||||
|
@ -215,7 +216,6 @@ public class DefaultArtifactDescriptorReader
|
|||
ArtifactDescriptorResult result = new ArtifactDescriptorResult( request );
|
||||
|
||||
Model model = loadPom( session, request, result );
|
||||
|
||||
if ( model != null )
|
||||
{
|
||||
Map<String, Object> config = session.getConfigProperties();
|
||||
|
@ -303,6 +303,18 @@ public class DefaultArtifactDescriptorReader
|
|||
}
|
||||
|
||||
Model model;
|
||||
|
||||
// hack: don't rebuild model if it was already loaded during reactor resolution
|
||||
final WorkspaceReader workspace = session.getWorkspaceReader();
|
||||
if ( workspace instanceof MavenWorkspaceReader )
|
||||
{
|
||||
model = ( (MavenWorkspaceReader) workspace ).findModel( pomArtifact );
|
||||
if ( model != null )
|
||||
{
|
||||
return model;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ModelBuildingRequest modelRequest = new DefaultModelBuildingRequest();
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package org.apache.maven.repository.internal;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
import org.eclipse.aether.artifact.Artifact;
|
||||
import org.eclipse.aether.repository.WorkspaceReader;
|
||||
|
||||
public interface MavenWorkspaceReader
|
||||
extends WorkspaceReader
|
||||
{
|
||||
|
||||
Model findModel( Artifact artifact );
|
||||
|
||||
}
|
|
@ -25,7 +25,6 @@ import java.util.Arrays;
|
|||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
|
@ -39,20 +38,15 @@ import org.apache.maven.execution.MavenExecutionRequest;
|
|||
import org.apache.maven.execution.MavenExecutionResult;
|
||||
import org.apache.maven.execution.MavenSession;
|
||||
import org.apache.maven.execution.ProjectDependencyGraph;
|
||||
import org.apache.maven.graph.GraphBuilder;
|
||||
import org.apache.maven.internal.aether.DefaultRepositorySystemSessionFactory;
|
||||
import org.apache.maven.lifecycle.internal.ExecutionEventCatapult;
|
||||
import org.apache.maven.lifecycle.internal.LifecycleStarter;
|
||||
import org.apache.maven.model.Plugin;
|
||||
import org.apache.maven.model.building.ModelProblem;
|
||||
import org.apache.maven.model.building.ModelProblemUtils;
|
||||
import org.apache.maven.model.building.ModelSource;
|
||||
import org.apache.maven.model.building.UrlModelSource;
|
||||
import org.apache.maven.model.building.Result;
|
||||
import org.apache.maven.plugin.LegacySupport;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.project.ProjectBuilder;
|
||||
import org.apache.maven.project.ProjectBuildingException;
|
||||
import org.apache.maven.project.ProjectBuildingRequest;
|
||||
import org.apache.maven.project.ProjectBuildingResult;
|
||||
import org.apache.maven.repository.LocalRepositoryNotAccessibleException;
|
||||
import org.apache.maven.session.scope.internal.SessionScope;
|
||||
import org.codehaus.plexus.PlexusContainer;
|
||||
|
@ -60,13 +54,13 @@ import org.codehaus.plexus.component.annotations.Component;
|
|||
import org.codehaus.plexus.component.annotations.Requirement;
|
||||
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
|
||||
import org.codehaus.plexus.logging.Logger;
|
||||
import org.codehaus.plexus.util.StringUtils;
|
||||
import org.codehaus.plexus.util.dag.CycleDetectedException;
|
||||
import org.eclipse.aether.DefaultRepositorySystemSession;
|
||||
import org.eclipse.aether.RepositorySystemSession;
|
||||
import org.eclipse.aether.repository.WorkspaceReader;
|
||||
import org.eclipse.aether.util.repository.ChainedWorkspaceReader;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
* @author Jason van Zyl
|
||||
*/
|
||||
|
@ -99,6 +93,9 @@ public class DefaultMaven
|
|||
@Requirement
|
||||
private DefaultRepositorySystemSessionFactory repositorySessionFactory;
|
||||
|
||||
@Requirement( hint = GraphBuilder.HINT )
|
||||
private GraphBuilder graphBuilder;
|
||||
|
||||
@Override
|
||||
public MavenExecutionResult execute( MavenExecutionRequest request )
|
||||
{
|
||||
|
@ -114,9 +111,18 @@ public class DefaultMaven
|
|||
}
|
||||
catch ( RuntimeException e )
|
||||
{
|
||||
result =
|
||||
addExceptionToResult( new DefaultMavenExecutionResult(), new InternalErrorException( "Internal error: "
|
||||
+ e, e ) );
|
||||
//TODO Hack to make the cycle detection the same for the new graph builder
|
||||
if ( e.getCause() instanceof ProjectCycleException )
|
||||
{
|
||||
result = addExceptionToResult( new DefaultMavenExecutionResult(), e.getCause() );
|
||||
}
|
||||
else
|
||||
{
|
||||
result = addExceptionToResult( new DefaultMavenExecutionResult(), new InternalErrorException(
|
||||
"Internal error: "
|
||||
+ e,
|
||||
e ) );
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -171,7 +177,8 @@ public class DefaultMaven
|
|||
}
|
||||
|
||||
//
|
||||
// We enter the session scope right after the MavenSession creation and before any of the AbstractLifecycleParticipant lookups
|
||||
// We enter the session scope right after the MavenSession creation and before any of the
|
||||
// AbstractLifecycleParticipant lookups
|
||||
// so that @SessionScoped components can be @Injected into AbstractLifecycleParticipants.
|
||||
//
|
||||
sessionScope.enter();
|
||||
|
@ -198,7 +205,8 @@ public class DefaultMaven
|
|||
{
|
||||
try
|
||||
{
|
||||
for ( AbstractMavenLifecycleParticipant listener : getLifecycleParticipants( Collections.<MavenProject>emptyList() ) )
|
||||
for ( AbstractMavenLifecycleParticipant listener : getLifecycleParticipants( Collections
|
||||
.<MavenProject>emptyList() ) )
|
||||
{
|
||||
listener.afterSessionStart( session );
|
||||
}
|
||||
|
@ -210,35 +218,14 @@ public class DefaultMaven
|
|||
|
||||
eventCatapult.fire( ExecutionEvent.Type.ProjectDiscoveryStarted, session, null );
|
||||
|
||||
List<MavenProject> projects;
|
||||
try
|
||||
Result<? extends ProjectDependencyGraph> graphResult = buildGraph( session, result );
|
||||
|
||||
if ( graphResult.hasErrors() )
|
||||
{
|
||||
projects = getProjectsForMavenReactor( session );
|
||||
//
|
||||
// Capture the full set of projects before any potential constraining is performed by --projects
|
||||
//
|
||||
session.setAllProjects( projects );
|
||||
return addExceptionToResult( result,
|
||||
Iterables.toArray( graphResult.getProblems(), ModelProblem.class )[0]
|
||||
.getException() );
|
||||
}
|
||||
catch ( ProjectBuildingException e )
|
||||
{
|
||||
return addExceptionToResult( result, e );
|
||||
}
|
||||
|
||||
validateProjects( projects );
|
||||
|
||||
//
|
||||
// This creates the graph and trims the projects down based on the user request using something like:
|
||||
//
|
||||
// -pl project0,project2 eclipse:eclipse
|
||||
//
|
||||
ProjectDependencyGraph projectDependencyGraph = createProjectDependencyGraph( projects, request, result, true );
|
||||
|
||||
if ( result.hasExceptions() )
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
session.setProjects( projectDependencyGraph.getSortedProjects() );
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -274,7 +261,7 @@ public class DefaultMaven
|
|||
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
try
|
||||
{
|
||||
for ( AbstractMavenLifecycleParticipant listener : getLifecycleParticipants( projects ) )
|
||||
for ( AbstractMavenLifecycleParticipant listener : getLifecycleParticipants( session.getProjects() ) )
|
||||
{
|
||||
Thread.currentThread().setContextClassLoader( listener.getClass().getClassLoader() );
|
||||
|
||||
|
@ -298,7 +285,15 @@ public class DefaultMaven
|
|||
// Note that participants may affect the topological order of the projects but it is
|
||||
// not expected that a participant will add or remove projects from the session.
|
||||
//
|
||||
projectDependencyGraph = createProjectDependencyGraph( session.getProjects(), request, result, false );
|
||||
|
||||
graphResult = buildGraph( session, result );
|
||||
|
||||
if ( graphResult.hasErrors() )
|
||||
{
|
||||
return addExceptionToResult( result,
|
||||
Iterables.toArray( graphResult.getProblems(), ModelProblem.class )[0]
|
||||
.getException() );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -307,10 +302,6 @@ public class DefaultMaven
|
|||
return result;
|
||||
}
|
||||
|
||||
session.setProjects( projectDependencyGraph.getSortedProjects() );
|
||||
|
||||
session.setProjectDependencyGraph( projectDependencyGraph );
|
||||
|
||||
result.setTopologicallySortedProjects( session.getProjects() );
|
||||
|
||||
result.setProject( session.getTopLevelProject() );
|
||||
|
@ -328,7 +319,7 @@ public class DefaultMaven
|
|||
{
|
||||
try
|
||||
{
|
||||
afterSessionEnd( projects, session );
|
||||
afterSessionEnd( session.getProjects(), session );
|
||||
}
|
||||
catch ( MavenExecutionException e )
|
||||
{
|
||||
|
@ -380,8 +371,7 @@ public class DefaultMaven
|
|||
|
||||
private Collection<AbstractMavenLifecycleParticipant> getLifecycleParticipants( Collection<MavenProject> projects )
|
||||
{
|
||||
Collection<AbstractMavenLifecycleParticipant> lifecycleListeners =
|
||||
new LinkedHashSet<AbstractMavenLifecycleParticipant>();
|
||||
Collection<AbstractMavenLifecycleParticipant> lifecycleListeners = new LinkedHashSet<AbstractMavenLifecycleParticipant>();
|
||||
|
||||
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
try
|
||||
|
@ -436,72 +426,22 @@ public class DefaultMaven
|
|||
return result;
|
||||
}
|
||||
|
||||
private List<MavenProject> getProjectsForMavenReactor( MavenSession session )
|
||||
throws ProjectBuildingException
|
||||
private void validateActivatedProfiles( List<MavenProject> projects, List<String> activeProfileIds )
|
||||
{
|
||||
MavenExecutionRequest request = session.getRequest();
|
||||
Collection<String> notActivatedProfileIds = new LinkedHashSet<String>( activeProfileIds );
|
||||
|
||||
request.getProjectBuildingRequest().setRepositorySession( session.getRepositorySession() );
|
||||
|
||||
List<MavenProject> projects = new ArrayList<MavenProject>();
|
||||
|
||||
// We have no POM file.
|
||||
//
|
||||
if ( request.getPom() == null )
|
||||
for ( MavenProject project : projects )
|
||||
{
|
||||
ModelSource modelSource = new UrlModelSource( DefaultMaven.class.getResource( "project/standalone.xml" ) );
|
||||
MavenProject project =
|
||||
projectBuilder.build( modelSource, request.getProjectBuildingRequest() ).getProject();
|
||||
project.setExecutionRoot( true );
|
||||
projects.add( project );
|
||||
request.setProjectPresent( false );
|
||||
return projects;
|
||||
}
|
||||
|
||||
List<File> files = Arrays.asList( request.getPom().getAbsoluteFile() );
|
||||
collectProjects( projects, files, request );
|
||||
return projects;
|
||||
}
|
||||
|
||||
private void collectProjects( List<MavenProject> projects, List<File> files, MavenExecutionRequest request )
|
||||
throws ProjectBuildingException
|
||||
for ( List<String> profileIds : project.getInjectedProfileIds().values() )
|
||||
{
|
||||
ProjectBuildingRequest projectBuildingRequest = request.getProjectBuildingRequest();
|
||||
|
||||
List<ProjectBuildingResult> results =
|
||||
projectBuilder.build( files, request.isRecursive(), projectBuildingRequest );
|
||||
|
||||
boolean problems = false;
|
||||
|
||||
for ( ProjectBuildingResult result : results )
|
||||
{
|
||||
projects.add( result.getProject() );
|
||||
|
||||
if ( !result.getProblems().isEmpty() && logger.isWarnEnabled() )
|
||||
{
|
||||
logger.warn( "" );
|
||||
logger.warn( "Some problems were encountered while building the effective model for "
|
||||
+ result.getProject().getId() );
|
||||
|
||||
for ( ModelProblem problem : result.getProblems() )
|
||||
{
|
||||
String loc = ModelProblemUtils.formatLocation( problem, result.getProjectId() );
|
||||
logger.warn( problem.getMessage() + ( StringUtils.isNotEmpty( loc ) ? " @ " + loc : "" ) );
|
||||
}
|
||||
|
||||
problems = true;
|
||||
notActivatedProfileIds.removeAll( profileIds );
|
||||
}
|
||||
}
|
||||
|
||||
if ( problems )
|
||||
for ( String notActivatedProfileId : notActivatedProfileIds )
|
||||
{
|
||||
logger.warn( "" );
|
||||
logger.warn( "It is highly recommended to fix these problems"
|
||||
+ " because they threaten the stability of your build." );
|
||||
logger.warn( "" );
|
||||
logger.warn( "For this reason, future Maven versions might no"
|
||||
+ " longer support building such malformed projects." );
|
||||
logger.warn( "" );
|
||||
logger.warn( "The requested profile \"" + notActivatedProfileId
|
||||
+ "\" could not be activated because it does not exist." );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -547,330 +487,36 @@ public class DefaultMaven
|
|||
return index;
|
||||
}
|
||||
|
||||
private void validateProjects( List<MavenProject> projects )
|
||||
private Result<? extends ProjectDependencyGraph> buildGraph( MavenSession session, MavenExecutionResult result )
|
||||
{
|
||||
Map<String, MavenProject> projectsMap = new HashMap<String, MavenProject>();
|
||||
|
||||
for ( MavenProject p : projects )
|
||||
Result<? extends ProjectDependencyGraph> graphResult = graphBuilder.build( session );
|
||||
for ( ModelProblem problem : graphResult.getProblems() )
|
||||
{
|
||||
String projectKey = ArtifactUtils.key( p.getGroupId(), p.getArtifactId(), p.getVersion() );
|
||||
|
||||
projectsMap.put( projectKey, p );
|
||||
if ( problem.getSeverity() == ModelProblem.Severity.WARNING )
|
||||
{
|
||||
logger.warn( problem.toString() );
|
||||
}
|
||||
|
||||
for ( MavenProject project : projects )
|
||||
else
|
||||
{
|
||||
// MNG-1911 / MNG-5572: Building plugins with extensions cannot be part of reactor
|
||||
for ( Plugin plugin : project.getBuildPlugins() )
|
||||
{
|
||||
if ( plugin.isExtensions() )
|
||||
{
|
||||
String pluginKey =
|
||||
ArtifactUtils.key( plugin.getGroupId(), plugin.getArtifactId(), plugin.getVersion() );
|
||||
|
||||
if ( projectsMap.containsKey( pluginKey ) )
|
||||
{
|
||||
logger.warn( project.getName() + " uses " + plugin.getKey()
|
||||
+ " as extensions, which is not possible within the same reactor build. "
|
||||
+ "This plugin was pulled from the local repository!" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateActivatedProfiles( List<MavenProject> projects, List<String> activeProfileIds )
|
||||
{
|
||||
Collection<String> notActivatedProfileIds = new LinkedHashSet<String>( activeProfileIds );
|
||||
|
||||
for ( MavenProject project : projects )
|
||||
{
|
||||
for ( List<String> profileIds : project.getInjectedProfileIds().values() )
|
||||
{
|
||||
notActivatedProfileIds.removeAll( profileIds );
|
||||
logger.error( problem.toString() );
|
||||
}
|
||||
}
|
||||
|
||||
for ( String notActivatedProfileId : notActivatedProfileIds )
|
||||
if ( !graphResult.hasErrors() )
|
||||
{
|
||||
logger.warn( "The requested profile \"" + notActivatedProfileId
|
||||
+ "\" could not be activated because it does not exist." );
|
||||
}
|
||||
ProjectDependencyGraph projectDependencyGraph = graphResult.get();
|
||||
session.setProjects( projectDependencyGraph.getSortedProjects() );
|
||||
session.setAllProjects( projectDependencyGraph.getSortedProjects() );
|
||||
session.setProjectDependencyGraph( projectDependencyGraph );
|
||||
}
|
||||
|
||||
@Deprecated // 5 January 2014
|
||||
return graphResult;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
// 5 January 2014
|
||||
protected Logger getLogger()
|
||||
{
|
||||
return logger;
|
||||
}
|
||||
|
||||
private ProjectDependencyGraph createProjectDependencyGraph( Collection<MavenProject> projects,
|
||||
MavenExecutionRequest request,
|
||||
MavenExecutionResult result, boolean trimming )
|
||||
{
|
||||
ProjectDependencyGraph projectDependencyGraph = null;
|
||||
|
||||
try
|
||||
{
|
||||
projectDependencyGraph = new DefaultProjectDependencyGraph( projects );
|
||||
|
||||
if ( trimming )
|
||||
{
|
||||
List<MavenProject> activeProjects = projectDependencyGraph.getSortedProjects();
|
||||
|
||||
activeProjects = trimSelectedProjects( activeProjects, projectDependencyGraph, request );
|
||||
activeProjects = trimExcludedProjects( activeProjects, request );
|
||||
activeProjects = trimResumedProjects( activeProjects, request );
|
||||
|
||||
if ( activeProjects.size() != projectDependencyGraph.getSortedProjects().size() )
|
||||
{
|
||||
projectDependencyGraph =
|
||||
new FilteredProjectDependencyGraph( projectDependencyGraph, activeProjects );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( CycleDetectedException e )
|
||||
{
|
||||
String message = "The projects in the reactor contain a cyclic reference: " + e.getMessage();
|
||||
|
||||
ProjectCycleException error = new ProjectCycleException( message, e );
|
||||
|
||||
addExceptionToResult( result, error );
|
||||
}
|
||||
catch ( org.apache.maven.project.DuplicateProjectException e )
|
||||
{
|
||||
addExceptionToResult( result, e );
|
||||
}
|
||||
catch ( MavenExecutionException e )
|
||||
{
|
||||
addExceptionToResult( result, e );
|
||||
}
|
||||
|
||||
return projectDependencyGraph;
|
||||
}
|
||||
|
||||
private List<MavenProject> trimSelectedProjects( List<MavenProject> projects, ProjectDependencyGraph graph,
|
||||
MavenExecutionRequest request )
|
||||
throws MavenExecutionException
|
||||
{
|
||||
List<MavenProject> result = projects;
|
||||
|
||||
if ( !request.getSelectedProjects().isEmpty() )
|
||||
{
|
||||
File reactorDirectory = null;
|
||||
if ( request.getBaseDirectory() != null )
|
||||
{
|
||||
reactorDirectory = new File( request.getBaseDirectory() );
|
||||
}
|
||||
|
||||
Collection<MavenProject> selectedProjects = new LinkedHashSet<MavenProject>( projects.size() );
|
||||
|
||||
for ( String selector : request.getSelectedProjects() )
|
||||
{
|
||||
MavenProject selectedProject = null;
|
||||
|
||||
for ( MavenProject project : projects )
|
||||
{
|
||||
if ( isMatchingProject( project, selector, reactorDirectory ) )
|
||||
{
|
||||
selectedProject = project;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( selectedProject != null )
|
||||
{
|
||||
selectedProjects.add( selectedProject );
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new MavenExecutionException( "Could not find the selected project in the reactor: "
|
||||
+ selector, request.getPom() );
|
||||
}
|
||||
}
|
||||
|
||||
boolean makeUpstream = false;
|
||||
boolean makeDownstream = false;
|
||||
|
||||
if ( MavenExecutionRequest.REACTOR_MAKE_UPSTREAM.equals( request.getMakeBehavior() ) )
|
||||
{
|
||||
makeUpstream = true;
|
||||
}
|
||||
else if ( MavenExecutionRequest.REACTOR_MAKE_DOWNSTREAM.equals( request.getMakeBehavior() ) )
|
||||
{
|
||||
makeDownstream = true;
|
||||
}
|
||||
else if ( MavenExecutionRequest.REACTOR_MAKE_BOTH.equals( request.getMakeBehavior() ) )
|
||||
{
|
||||
makeUpstream = true;
|
||||
makeDownstream = true;
|
||||
}
|
||||
else if ( StringUtils.isNotEmpty( request.getMakeBehavior() ) )
|
||||
{
|
||||
throw new MavenExecutionException( "Invalid reactor make behavior: " + request.getMakeBehavior(),
|
||||
request.getPom() );
|
||||
}
|
||||
|
||||
if ( makeUpstream || makeDownstream )
|
||||
{
|
||||
for ( MavenProject selectedProject : new ArrayList<MavenProject>( selectedProjects ) )
|
||||
{
|
||||
if ( makeUpstream )
|
||||
{
|
||||
selectedProjects.addAll( graph.getUpstreamProjects( selectedProject, true ) );
|
||||
}
|
||||
if ( makeDownstream )
|
||||
{
|
||||
selectedProjects.addAll( graph.getDownstreamProjects( selectedProject, true ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = new ArrayList<MavenProject>( selectedProjects.size() );
|
||||
|
||||
for ( MavenProject project : projects )
|
||||
{
|
||||
if ( selectedProjects.contains( project ) )
|
||||
{
|
||||
result.add( project );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<MavenProject> trimExcludedProjects( List<MavenProject> projects, MavenExecutionRequest request )
|
||||
throws MavenExecutionException
|
||||
{
|
||||
List<MavenProject> result = projects;
|
||||
|
||||
if ( !request.getExcludedProjects().isEmpty() )
|
||||
{
|
||||
File reactorDirectory = null;
|
||||
|
||||
if ( request.getBaseDirectory() != null )
|
||||
{
|
||||
reactorDirectory = new File( request.getBaseDirectory() );
|
||||
}
|
||||
|
||||
Collection<MavenProject> excludedProjects = new LinkedHashSet<MavenProject>( projects.size() );
|
||||
|
||||
for ( String selector : request.getExcludedProjects() )
|
||||
{
|
||||
MavenProject excludedProject = null;
|
||||
|
||||
for ( MavenProject project : projects )
|
||||
{
|
||||
if ( isMatchingProject( project, selector, reactorDirectory ) )
|
||||
{
|
||||
excludedProject = project;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( excludedProject != null )
|
||||
{
|
||||
excludedProjects.add( excludedProject );
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new MavenExecutionException( "Could not find the selected project in the reactor: "
|
||||
+ selector, request.getPom() );
|
||||
}
|
||||
}
|
||||
|
||||
result = new ArrayList<MavenProject>( projects.size() );
|
||||
for ( MavenProject project : projects )
|
||||
{
|
||||
if ( !excludedProjects.contains( project ) )
|
||||
{
|
||||
result.add( project );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<MavenProject> trimResumedProjects( List<MavenProject> projects, MavenExecutionRequest request )
|
||||
throws MavenExecutionException
|
||||
{
|
||||
List<MavenProject> result = projects;
|
||||
|
||||
if ( StringUtils.isNotEmpty( request.getResumeFrom() ) )
|
||||
{
|
||||
File reactorDirectory = null;
|
||||
if ( request.getBaseDirectory() != null )
|
||||
{
|
||||
reactorDirectory = new File( request.getBaseDirectory() );
|
||||
}
|
||||
|
||||
String selector = request.getResumeFrom();
|
||||
|
||||
result = new ArrayList<MavenProject>( projects.size() );
|
||||
|
||||
boolean resumed = false;
|
||||
|
||||
for ( MavenProject project : projects )
|
||||
{
|
||||
if ( !resumed && isMatchingProject( project, selector, reactorDirectory ) )
|
||||
{
|
||||
resumed = true;
|
||||
}
|
||||
|
||||
if ( resumed )
|
||||
{
|
||||
result.add( project );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !resumed )
|
||||
{
|
||||
throw new MavenExecutionException( "Could not find project to resume reactor build from: " + selector
|
||||
+ " vs " + projects, request.getPom() );
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isMatchingProject( MavenProject project, String selector, File reactorDirectory )
|
||||
{
|
||||
// [groupId]:artifactId
|
||||
if ( selector.indexOf( ':' ) >= 0 )
|
||||
{
|
||||
String id = ':' + project.getArtifactId();
|
||||
|
||||
if ( id.equals( selector ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
id = project.getGroupId() + id;
|
||||
|
||||
if ( id.equals( selector ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// relative path, e.g. "sub", "../sub" or "."
|
||||
else if ( reactorDirectory != null )
|
||||
{
|
||||
File selectedProject = new File( new File( reactorDirectory, selector ).toURI().normalize() );
|
||||
|
||||
if ( selectedProject.isFile() )
|
||||
{
|
||||
return selectedProject.equals( project.getFile() );
|
||||
}
|
||||
else if ( selectedProject.isDirectory() )
|
||||
{
|
||||
return selectedProject.equals( project.getBasedir() );
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,6 +27,11 @@ import org.codehaus.plexus.util.dag.CycleDetectedException;
|
|||
public class ProjectCycleException
|
||||
extends BuildFailureException
|
||||
{
|
||||
public ProjectCycleException( String message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
public ProjectCycleException( String message, CycleDetectedException cause )
|
||||
{
|
||||
super( message, cause );
|
||||
|
|
|
@ -34,9 +34,10 @@ import javax.inject.Named;
|
|||
|
||||
import org.apache.maven.artifact.ArtifactUtils;
|
||||
import org.apache.maven.execution.MavenSession;
|
||||
import org.apache.maven.model.Model;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.repository.internal.MavenWorkspaceReader;
|
||||
import org.eclipse.aether.artifact.Artifact;
|
||||
import org.eclipse.aether.repository.WorkspaceReader;
|
||||
import org.eclipse.aether.repository.WorkspaceRepository;
|
||||
import org.eclipse.aether.util.artifact.ArtifactIdUtils;
|
||||
|
||||
|
@ -49,7 +50,7 @@ import org.eclipse.aether.util.artifact.ArtifactIdUtils;
|
|||
@Named( ReactorReader.HINT )
|
||||
@SessionScoped
|
||||
class ReactorReader
|
||||
implements WorkspaceReader
|
||||
implements MavenWorkspaceReader
|
||||
{
|
||||
public static final String HINT = "reactor";
|
||||
|
||||
|
@ -136,6 +137,14 @@ class ReactorReader
|
|||
return Collections.unmodifiableList( versions );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Model findModel( Artifact artifact )
|
||||
{
|
||||
String projectKey = ArtifactUtils.key( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion() );
|
||||
MavenProject project = projectsByGAV.get( projectKey );
|
||||
return project == null ? null : project.getModel();
|
||||
}
|
||||
|
||||
//
|
||||
// Implementation
|
||||
//
|
||||
|
|
|
@ -272,6 +272,8 @@ public class MavenSession
|
|||
this.projectMap = projectMap;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/** @deprecated This appears to only be used in the ReactorReader and we can do any processing required there */
|
||||
public Map<String, MavenProject> getProjectMap()
|
||||
{
|
||||
return projectMap;
|
||||
|
@ -433,5 +435,4 @@ public class MavenSession
|
|||
}
|
||||
|
||||
/*end[MAVEN4]*/
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,487 @@
|
|||
package org.apache.maven.graph;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.maven.DefaultMaven;
|
||||
import org.apache.maven.MavenExecutionException;
|
||||
import org.apache.maven.ProjectCycleException;
|
||||
import org.apache.maven.artifact.ArtifactUtils;
|
||||
import org.apache.maven.execution.MavenExecutionRequest;
|
||||
import org.apache.maven.execution.MavenExecutionResult;
|
||||
import org.apache.maven.execution.MavenSession;
|
||||
import org.apache.maven.execution.ProjectDependencyGraph;
|
||||
import org.apache.maven.model.Plugin;
|
||||
import org.apache.maven.model.building.DefaultModelProblem;
|
||||
import org.apache.maven.model.building.ModelProblem;
|
||||
import org.apache.maven.model.building.ModelProblemUtils;
|
||||
import org.apache.maven.model.building.ModelSource;
|
||||
import org.apache.maven.model.building.Result;
|
||||
import org.apache.maven.model.building.UrlModelSource;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.project.ProjectBuilder;
|
||||
import org.apache.maven.project.ProjectBuildingException;
|
||||
import org.apache.maven.project.ProjectBuildingRequest;
|
||||
import org.apache.maven.project.ProjectBuildingResult;
|
||||
import org.codehaus.plexus.component.annotations.Component;
|
||||
import org.codehaus.plexus.component.annotations.Requirement;
|
||||
import org.codehaus.plexus.logging.Logger;
|
||||
import org.codehaus.plexus.util.StringUtils;
|
||||
import org.codehaus.plexus.util.dag.CycleDetectedException;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
@Component( role = GraphBuilder.class, hint = GraphBuilder.HINT )
|
||||
public class DefaultGraphBuilder
|
||||
implements GraphBuilder
|
||||
{
|
||||
@Requirement
|
||||
private Logger logger;
|
||||
|
||||
@Requirement
|
||||
protected ProjectBuilder projectBuilder;
|
||||
|
||||
@Override
|
||||
public Result<ProjectDependencyGraph> build( MavenSession session )
|
||||
{
|
||||
if ( session.getProjectDependencyGraph() != null )
|
||||
{
|
||||
return dependencyGraph( session, session.getProjects(), false );
|
||||
}
|
||||
|
||||
List<MavenProject> projects = session.getProjects();
|
||||
|
||||
if ( projects == null )
|
||||
{
|
||||
try
|
||||
{
|
||||
projects = getProjectsForMavenReactor( session );
|
||||
}
|
||||
catch ( ProjectBuildingException e )
|
||||
{
|
||||
return Result.error( Lists.newArrayList( new DefaultModelProblem( null, null, null, null, 0, 0, e ) ) );
|
||||
}
|
||||
|
||||
validateProjects( projects );
|
||||
|
||||
return dependencyGraph( session, projects, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
return dependencyGraph( session, projects, false );
|
||||
}
|
||||
}
|
||||
|
||||
private Result<ProjectDependencyGraph> dependencyGraph( MavenSession session, List<MavenProject> projects,
|
||||
boolean applyMakeBehaviour )
|
||||
{
|
||||
MavenExecutionRequest request = session.getRequest();
|
||||
|
||||
ProjectDependencyGraph projectDependencyGraph = null;
|
||||
|
||||
try
|
||||
{
|
||||
projectDependencyGraph = new DefaultProjectDependencyGraph( projects );
|
||||
|
||||
if ( applyMakeBehaviour )
|
||||
{
|
||||
List<MavenProject> activeProjects = projectDependencyGraph.getSortedProjects();
|
||||
|
||||
activeProjects = trimSelectedProjects( activeProjects, projectDependencyGraph, request );
|
||||
activeProjects = trimExcludedProjects( activeProjects, request );
|
||||
activeProjects = trimResumedProjects( activeProjects, request );
|
||||
|
||||
if ( activeProjects.size() != projectDependencyGraph.getSortedProjects().size() )
|
||||
{
|
||||
projectDependencyGraph = new FilteredProjectDependencyGraph( projectDependencyGraph, activeProjects );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( CycleDetectedException e )
|
||||
{
|
||||
String message = "The projects in the reactor contain a cyclic reference: " + e.getMessage();
|
||||
ProjectCycleException error = new ProjectCycleException( message, e );
|
||||
return Result.error( Lists.newArrayList( new DefaultModelProblem( null, null, null, null, 0, 0, error ) ) );
|
||||
}
|
||||
catch ( org.apache.maven.project.DuplicateProjectException e )
|
||||
{
|
||||
return Result.error( Lists.newArrayList( new DefaultModelProblem( null, null, null, null, 0, 0, e ) ) );
|
||||
}
|
||||
catch ( MavenExecutionException e )
|
||||
{
|
||||
return Result.error( Lists.newArrayList( new DefaultModelProblem( null, null, null, null, 0, 0, e ) ) );
|
||||
}
|
||||
|
||||
session.setProjects( projectDependencyGraph.getSortedProjects() );
|
||||
session.setProjectDependencyGraph( projectDependencyGraph );
|
||||
|
||||
return Result.success( projectDependencyGraph );
|
||||
}
|
||||
|
||||
private List<MavenProject> trimSelectedProjects( List<MavenProject> projects, ProjectDependencyGraph graph,
|
||||
MavenExecutionRequest request )
|
||||
throws MavenExecutionException
|
||||
{
|
||||
List<MavenProject> result = projects;
|
||||
|
||||
if ( !request.getSelectedProjects().isEmpty() )
|
||||
{
|
||||
File reactorDirectory = null;
|
||||
if ( request.getBaseDirectory() != null )
|
||||
{
|
||||
reactorDirectory = new File( request.getBaseDirectory() );
|
||||
}
|
||||
|
||||
Collection<MavenProject> selectedProjects = new LinkedHashSet<MavenProject>( projects.size() );
|
||||
|
||||
for ( String selector : request.getSelectedProjects() )
|
||||
{
|
||||
MavenProject selectedProject = null;
|
||||
|
||||
for ( MavenProject project : projects )
|
||||
{
|
||||
if ( isMatchingProject( project, selector, reactorDirectory ) )
|
||||
{
|
||||
selectedProject = project;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( selectedProject != null )
|
||||
{
|
||||
selectedProjects.add( selectedProject );
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new MavenExecutionException( "Could not find the selected project in the reactor: "
|
||||
+ selector, request.getPom() );
|
||||
}
|
||||
}
|
||||
|
||||
boolean makeUpstream = false;
|
||||
boolean makeDownstream = false;
|
||||
|
||||
if ( MavenExecutionRequest.REACTOR_MAKE_UPSTREAM.equals( request.getMakeBehavior() ) )
|
||||
{
|
||||
makeUpstream = true;
|
||||
}
|
||||
else if ( MavenExecutionRequest.REACTOR_MAKE_DOWNSTREAM.equals( request.getMakeBehavior() ) )
|
||||
{
|
||||
makeDownstream = true;
|
||||
}
|
||||
else if ( MavenExecutionRequest.REACTOR_MAKE_BOTH.equals( request.getMakeBehavior() ) )
|
||||
{
|
||||
makeUpstream = true;
|
||||
makeDownstream = true;
|
||||
}
|
||||
else if ( StringUtils.isNotEmpty( request.getMakeBehavior() ) )
|
||||
{
|
||||
throw new MavenExecutionException( "Invalid reactor make behavior: " + request.getMakeBehavior(),
|
||||
request.getPom() );
|
||||
}
|
||||
|
||||
if ( makeUpstream || makeDownstream )
|
||||
{
|
||||
for ( MavenProject selectedProject : new ArrayList<MavenProject>( selectedProjects ) )
|
||||
{
|
||||
if ( makeUpstream )
|
||||
{
|
||||
selectedProjects.addAll( graph.getUpstreamProjects( selectedProject, true ) );
|
||||
}
|
||||
if ( makeDownstream )
|
||||
{
|
||||
selectedProjects.addAll( graph.getDownstreamProjects( selectedProject, true ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = new ArrayList<MavenProject>( selectedProjects.size() );
|
||||
|
||||
for ( MavenProject project : projects )
|
||||
{
|
||||
if ( selectedProjects.contains( project ) )
|
||||
{
|
||||
result.add( project );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<MavenProject> trimExcludedProjects( List<MavenProject> projects, MavenExecutionRequest request )
|
||||
throws MavenExecutionException
|
||||
{
|
||||
List<MavenProject> result = projects;
|
||||
|
||||
if ( !request.getExcludedProjects().isEmpty() )
|
||||
{
|
||||
File reactorDirectory = null;
|
||||
|
||||
if ( request.getBaseDirectory() != null )
|
||||
{
|
||||
reactorDirectory = new File( request.getBaseDirectory() );
|
||||
}
|
||||
|
||||
Collection<MavenProject> excludedProjects = new LinkedHashSet<MavenProject>( projects.size() );
|
||||
|
||||
for ( String selector : request.getExcludedProjects() )
|
||||
{
|
||||
MavenProject excludedProject = null;
|
||||
|
||||
for ( MavenProject project : projects )
|
||||
{
|
||||
if ( isMatchingProject( project, selector, reactorDirectory ) )
|
||||
{
|
||||
excludedProject = project;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( excludedProject != null )
|
||||
{
|
||||
excludedProjects.add( excludedProject );
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new MavenExecutionException( "Could not find the selected project in the reactor: "
|
||||
+ selector, request.getPom() );
|
||||
}
|
||||
}
|
||||
|
||||
result = new ArrayList<MavenProject>( projects.size() );
|
||||
for ( MavenProject project : projects )
|
||||
{
|
||||
if ( !excludedProjects.contains( project ) )
|
||||
{
|
||||
result.add( project );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<MavenProject> trimResumedProjects( List<MavenProject> projects, MavenExecutionRequest request )
|
||||
throws MavenExecutionException
|
||||
{
|
||||
List<MavenProject> result = projects;
|
||||
|
||||
if ( StringUtils.isNotEmpty( request.getResumeFrom() ) )
|
||||
{
|
||||
File reactorDirectory = null;
|
||||
if ( request.getBaseDirectory() != null )
|
||||
{
|
||||
reactorDirectory = new File( request.getBaseDirectory() );
|
||||
}
|
||||
|
||||
String selector = request.getResumeFrom();
|
||||
|
||||
result = new ArrayList<MavenProject>( projects.size() );
|
||||
|
||||
boolean resumed = false;
|
||||
|
||||
for ( MavenProject project : projects )
|
||||
{
|
||||
if ( !resumed && isMatchingProject( project, selector, reactorDirectory ) )
|
||||
{
|
||||
resumed = true;
|
||||
}
|
||||
|
||||
if ( resumed )
|
||||
{
|
||||
result.add( project );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !resumed )
|
||||
{
|
||||
throw new MavenExecutionException( "Could not find project to resume reactor build from: " + selector
|
||||
+ " vs " + projects, request.getPom() );
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isMatchingProject( MavenProject project, String selector, File reactorDirectory )
|
||||
{
|
||||
// [groupId]:artifactId
|
||||
if ( selector.indexOf( ':' ) >= 0 )
|
||||
{
|
||||
String id = ':' + project.getArtifactId();
|
||||
|
||||
if ( id.equals( selector ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
id = project.getGroupId() + id;
|
||||
|
||||
if ( id.equals( selector ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// relative path, e.g. "sub", "../sub" or "."
|
||||
else if ( reactorDirectory != null )
|
||||
{
|
||||
File selectedProject = new File( new File( reactorDirectory, selector ).toURI().normalize() );
|
||||
|
||||
if ( selectedProject.isFile() )
|
||||
{
|
||||
return selectedProject.equals( project.getFile() );
|
||||
}
|
||||
else if ( selectedProject.isDirectory() )
|
||||
{
|
||||
return selectedProject.equals( project.getBasedir() );
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private MavenExecutionResult addExceptionToResult( MavenExecutionResult result, Throwable e )
|
||||
{
|
||||
if ( !result.getExceptions().contains( e ) )
|
||||
{
|
||||
result.addException( e );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Project collection
|
||||
//
|
||||
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private List<MavenProject> getProjectsForMavenReactor( MavenSession session )
|
||||
throws ProjectBuildingException
|
||||
{
|
||||
MavenExecutionRequest request = session.getRequest();
|
||||
|
||||
request.getProjectBuildingRequest().setRepositorySession( session.getRepositorySession() );
|
||||
|
||||
List<MavenProject> projects = new ArrayList<MavenProject>();
|
||||
|
||||
// We have no POM file.
|
||||
//
|
||||
if ( request.getPom() == null )
|
||||
{
|
||||
ModelSource modelSource = new UrlModelSource( DefaultMaven.class.getResource( "project/standalone.xml" ) );
|
||||
MavenProject project = projectBuilder.build( modelSource, request.getProjectBuildingRequest() )
|
||||
.getProject();
|
||||
project.setExecutionRoot( true );
|
||||
projects.add( project );
|
||||
request.setProjectPresent( false );
|
||||
return projects;
|
||||
}
|
||||
|
||||
List<File> files = Arrays.asList( request.getPom().getAbsoluteFile() );
|
||||
collectProjects( projects, files, request );
|
||||
return projects;
|
||||
}
|
||||
|
||||
private void collectProjects( List<MavenProject> projects, List<File> files, MavenExecutionRequest request )
|
||||
throws ProjectBuildingException
|
||||
{
|
||||
ProjectBuildingRequest projectBuildingRequest = request.getProjectBuildingRequest();
|
||||
|
||||
List<ProjectBuildingResult> results = projectBuilder.build( files, request.isRecursive(),
|
||||
projectBuildingRequest );
|
||||
|
||||
boolean problems = false;
|
||||
|
||||
for ( ProjectBuildingResult result : results )
|
||||
{
|
||||
projects.add( result.getProject() );
|
||||
|
||||
if ( !result.getProblems().isEmpty() && logger.isWarnEnabled() )
|
||||
{
|
||||
logger.warn( "" );
|
||||
logger.warn( "Some problems were encountered while building the effective model for "
|
||||
+ result.getProject().getId() );
|
||||
|
||||
for ( ModelProblem problem : result.getProblems() )
|
||||
{
|
||||
String loc = ModelProblemUtils.formatLocation( problem, result.getProjectId() );
|
||||
logger.warn( problem.getMessage() + ( StringUtils.isNotEmpty( loc ) ? " @ " + loc : "" ) );
|
||||
}
|
||||
|
||||
problems = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( problems )
|
||||
{
|
||||
logger.warn( "" );
|
||||
logger.warn( "It is highly recommended to fix these problems"
|
||||
+ " because they threaten the stability of your build." );
|
||||
logger.warn( "" );
|
||||
logger.warn( "For this reason, future Maven versions might no"
|
||||
+ " longer support building such malformed projects." );
|
||||
logger.warn( "" );
|
||||
}
|
||||
}
|
||||
|
||||
private void validateProjects( List<MavenProject> projects )
|
||||
{
|
||||
Map<String, MavenProject> projectsMap = new HashMap<String, MavenProject>();
|
||||
|
||||
for ( MavenProject p : projects )
|
||||
{
|
||||
String projectKey = ArtifactUtils.key( p.getGroupId(), p.getArtifactId(), p.getVersion() );
|
||||
|
||||
projectsMap.put( projectKey, p );
|
||||
}
|
||||
|
||||
for ( MavenProject project : projects )
|
||||
{
|
||||
// MNG-1911 / MNG-5572: Building plugins with extensions cannot be part of reactor
|
||||
for ( Plugin plugin : project.getBuildPlugins() )
|
||||
{
|
||||
if ( plugin.isExtensions() )
|
||||
{
|
||||
String pluginKey = ArtifactUtils.key( plugin.getGroupId(), plugin.getArtifactId(),
|
||||
plugin.getVersion() );
|
||||
|
||||
if ( projectsMap.containsKey( pluginKey ) )
|
||||
{
|
||||
logger.warn( project.getName() + " uses " + plugin.getKey()
|
||||
+ " as extensions, which is not possible within the same reactor build. "
|
||||
+ "This plugin was pulled from the local repository!" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package org.apache.maven;
|
||||
package org.apache.maven.graph;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
|
@ -36,7 +36,7 @@ import org.codehaus.plexus.util.dag.CycleDetectedException;
|
|||
*
|
||||
* @author Benjamin Bentmann
|
||||
*/
|
||||
class DefaultProjectDependencyGraph
|
||||
public class DefaultProjectDependencyGraph
|
||||
implements ProjectDependencyGraph
|
||||
{
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.apache.maven;
|
||||
package org.apache.maven.graph;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
@ -0,0 +1,31 @@
|
|||
package org.apache.maven.graph;
|
||||
|
||||
/*
|
||||
* 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.execution.MavenSession;
|
||||
import org.apache.maven.execution.ProjectDependencyGraph;
|
||||
import org.apache.maven.model.building.Result;
|
||||
|
||||
public interface GraphBuilder
|
||||
{
|
||||
String HINT = "graphBuilder";
|
||||
|
||||
Result<? extends ProjectDependencyGraph> build( MavenSession session );
|
||||
}
|
|
@ -37,7 +37,7 @@ import org.apache.maven.plugin.version.PluginVersionResolutionException;
|
|||
*
|
||||
* @author Benjamin Bentmann
|
||||
*/
|
||||
class DefaultModelBuildingListener
|
||||
public class DefaultModelBuildingListener
|
||||
extends AbstractModelBuildingListener
|
||||
{
|
||||
|
||||
|
|
|
@ -1171,7 +1171,7 @@ public class MavenProject
|
|||
return clone;
|
||||
}
|
||||
|
||||
protected void setModel( Model model )
|
||||
public void setModel( Model model )
|
||||
{
|
||||
this.model = model;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.util.Set;
|
|||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import org.apache.maven.model.Parent;
|
||||
import org.apache.maven.model.Repository;
|
||||
import org.apache.maven.model.building.FileModelSource;
|
||||
|
@ -55,7 +56,7 @@ import org.eclipse.aether.resolution.VersionRangeResult;
|
|||
*
|
||||
* @author Benjamin Bentmann
|
||||
*/
|
||||
class ProjectModelResolver
|
||||
public class ProjectModelResolver
|
||||
implements ModelResolver
|
||||
{
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package org.apache.maven;
|
||||
package org.apache.maven.graph;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.maven.execution.ProjectDependencyGraph;
|
|
@ -409,6 +409,11 @@ public class LifecycleExecutorTest
|
|||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public java.util.List<MavenProject> getAllSortedProjects()
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
} );
|
||||
|
||||
final List<String> log = new ArrayList<String>();
|
||||
|
|
|
@ -51,7 +51,10 @@
|
|||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-builder-support</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.sisu</groupId>
|
||||
<artifactId>org.eclipse.sisu.plexus</artifactId>
|
||||
|
|
|
@ -19,6 +19,10 @@ package org.apache.maven.model.building;
|
|||
* 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;
|
||||
|
@ -63,6 +67,7 @@ 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;
|
||||
|
@ -241,8 +246,8 @@ public class DefaultModelBuilder
|
|||
DefaultProfileActivationContext profileActivationContext = getProfileActivationContext( request );
|
||||
|
||||
problems.setSource( "(external profiles)" );
|
||||
List<Profile> activeExternalProfiles =
|
||||
profileSelector.getActiveProfiles( request.getProfiles(), profileActivationContext, problems );
|
||||
List<Profile> activeExternalProfiles = profileSelector.getActiveProfiles( request.getProfiles(),
|
||||
profileActivationContext, problems );
|
||||
|
||||
result.setActiveExternalProfiles( activeExternalProfiles );
|
||||
|
||||
|
@ -258,7 +263,11 @@ public class DefaultModelBuilder
|
|||
}
|
||||
|
||||
// read and validate raw model
|
||||
Model inputModel = readModel( request.getModelSource(), request.getPomFile(), request, problems );
|
||||
Model inputModel = request.getRawModel();
|
||||
if ( inputModel == null )
|
||||
{
|
||||
inputModel = readModel( request.getModelSource(), request.getPomFile(), request, problems );
|
||||
}
|
||||
|
||||
problems.setRootModel( inputModel );
|
||||
|
||||
|
@ -272,11 +281,12 @@ public class DefaultModelBuilder
|
|||
{
|
||||
lineage.add( currentData );
|
||||
|
||||
Model tmpModel = currentData.getModel();
|
||||
|
||||
Model rawModel = tmpModel.clone();
|
||||
Model rawModel = currentData.getModel();
|
||||
currentData.setRawModel( rawModel );
|
||||
|
||||
Model tmpModel = rawModel.clone();
|
||||
currentData.setModel( tmpModel );
|
||||
|
||||
problems.setSource( tmpModel );
|
||||
|
||||
// model normalization
|
||||
|
@ -284,8 +294,8 @@ public class DefaultModelBuilder
|
|||
|
||||
profileActivationContext.setProjectProperties( tmpModel.getProperties() );
|
||||
|
||||
List<Profile> activePomProfiles =
|
||||
profileSelector.getActiveProfiles( rawModel.getProfiles(), profileActivationContext, problems );
|
||||
List<Profile> activePomProfiles = profileSelector.getActiveProfiles( rawModel.getProfiles(),
|
||||
profileActivationContext, problems );
|
||||
currentData.setActiveProfiles( activePomProfiles );
|
||||
|
||||
Map<String, Activation> interpolatedActivations = getProfileActivations( rawModel, false );
|
||||
|
@ -320,13 +330,13 @@ public class DefaultModelBuilder
|
|||
}
|
||||
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.setGroupId( currentData.getRawModel().getGroupId() == null ? parentData.getGroupId()
|
||||
: currentData.getRawModel()
|
||||
.getGroupId() );
|
||||
|
||||
currentData.setVersion( currentData.getRawModel().getVersion() == null
|
||||
? parentData.getVersion()
|
||||
: currentData.getRawModel().getVersion() );
|
||||
currentData.setVersion( currentData.getRawModel().getVersion() == null ? parentData.getVersion()
|
||||
: currentData.getRawModel()
|
||||
.getVersion() );
|
||||
|
||||
currentData.setArtifactId( currentData.getRawModel().getArtifactId() );
|
||||
parentIds.add( currentData.getId() );
|
||||
|
@ -345,9 +355,8 @@ public class DefaultModelBuilder
|
|||
}
|
||||
message += parentData.getId();
|
||||
|
||||
problems.add(
|
||||
new ModelProblemCollectorRequest( ModelProblem.Severity.FATAL, ModelProblem.Version.BASE ).
|
||||
setMessage( message ) );
|
||||
problems.add( new ModelProblemCollectorRequest( ModelProblem.Severity.FATAL, ModelProblem.Version.BASE )
|
||||
.setMessage( message ) );
|
||||
|
||||
throw problems.newModelBuildingException();
|
||||
}
|
||||
|
@ -469,6 +478,23 @@ public class DefaultModelBuilder
|
|||
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
|
||||
|
@ -564,8 +590,7 @@ public class DefaultModelBuilder
|
|||
}
|
||||
}
|
||||
problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.BASE )
|
||||
.setMessage( "Non-readable POM " + modelSource.getLocation() + ": " + msg )
|
||||
.setException( e ) );
|
||||
.setMessage( "Non-readable POM " + modelSource.getLocation() + ": " + msg ).setException( e ) );
|
||||
throw problems.newModelBuildingException();
|
||||
}
|
||||
|
||||
|
@ -622,8 +647,7 @@ public class DefaultModelBuilder
|
|||
{
|
||||
problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
|
||||
.setMessage( "Invalid repository " + repository.getId() + ": " + e.getMessage() )
|
||||
.setLocation( repository.getLocation( "" ) )
|
||||
.setException( e ) );
|
||||
.setLocation( repository.getLocation( "" ) ).setException( e ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -675,7 +699,8 @@ public class DefaultModelBuilder
|
|||
if ( versions.get( key ) == null && managedVersions.get( key ) == null )
|
||||
{
|
||||
InputLocation location = plugins.get( key ).getLocation( "" );
|
||||
problems.add( new ModelProblemCollectorRequest( Severity.WARNING, Version.V20 )
|
||||
problems
|
||||
.add( new ModelProblemCollectorRequest( Severity.WARNING, Version.V20 )
|
||||
.setMessage( "'build.plugins.plugin.version' for " + key + " is missing." )
|
||||
.setLocation( location ) );
|
||||
}
|
||||
|
@ -817,7 +842,13 @@ public class DefaultModelBuilder
|
|||
DefaultModelProblemCollector problems )
|
||||
throws ModelBuildingException
|
||||
{
|
||||
ModelSource candidateSource = getParentPomFile( childModel, childSource );
|
||||
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 )
|
||||
{
|
||||
|
@ -830,7 +861,33 @@ public class DefaultModelBuilder
|
|||
pomFile = ( (FileModelSource) candidateSource ).getPomFile();
|
||||
}
|
||||
|
||||
Model candidateModel = readModel( candidateSource, pomFile, request, problems );
|
||||
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 )
|
||||
|
@ -844,8 +901,6 @@ public class DefaultModelBuilder
|
|||
version = candidateModel.getParent().getVersion();
|
||||
}
|
||||
|
||||
Parent parent = childModel.getParent();
|
||||
|
||||
if ( groupId == null || !groupId.equals( parent.getGroupId() ) || artifactId == null
|
||||
|| !artifactId.equals( parent.getArtifactId() ) )
|
||||
{
|
||||
|
@ -861,15 +916,19 @@ public class DefaultModelBuilder
|
|||
|
||||
problems.setSource( childModel );
|
||||
problems.add( new ModelProblemCollectorRequest( Severity.WARNING, Version.BASE )
|
||||
.setMessage( buffer.toString() )
|
||||
.setLocation( parent.getLocation( "" ) ) );
|
||||
return null;
|
||||
}
|
||||
if ( version == null || !version.equals( parent.getVersion() ) )
|
||||
{
|
||||
.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;
|
||||
|
@ -944,9 +1003,7 @@ public class DefaultModelBuilder
|
|||
}
|
||||
|
||||
problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.BASE )
|
||||
.setMessage( buffer.toString() )
|
||||
.setLocation( parent.getLocation( "" ) )
|
||||
.setException( e ) );
|
||||
.setMessage( buffer.toString() ).setLocation( parent.getLocation( "" ) ).setException( e ) );
|
||||
throw problems.newModelBuildingException();
|
||||
}
|
||||
|
||||
|
@ -969,18 +1026,17 @@ public class DefaultModelBuilder
|
|||
{
|
||||
if ( childModel.getVersion() == null )
|
||||
{
|
||||
problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.V31 ).
|
||||
setMessage( "Version must be a constant" ).
|
||||
setLocation( childModel.getLocation( "" ) ) );
|
||||
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" ) ) );
|
||||
problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.V31 )
|
||||
.setMessage( "Version must be a constant" )
|
||||
.setLocation( childModel.getLocation( "version" ) ) );
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1013,7 +1069,8 @@ public class DefaultModelBuilder
|
|||
|
||||
importIds.add( importing );
|
||||
|
||||
ModelResolver modelResolver = request.getModelResolver();
|
||||
final WorkspaceModelResolver workspaceResolver = request.getWorkspaceModelResolver();
|
||||
final ModelResolver modelResolver = request.getModelResolver();
|
||||
|
||||
ModelBuildingRequest importRequest = null;
|
||||
|
||||
|
@ -1074,19 +1131,37 @@ public class DefaultModelBuilder
|
|||
continue;
|
||||
}
|
||||
|
||||
DependencyManagement importMngt =
|
||||
getCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT );
|
||||
DependencyManagement importMngt = getCache( request.getModelCache(), groupId, artifactId, version,
|
||||
ModelCacheTag.IMPORT );
|
||||
|
||||
if ( importMngt == null )
|
||||
{
|
||||
if ( modelResolver == 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 ) );
|
||||
}
|
||||
|
||||
ModelSource importSource;
|
||||
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 );
|
||||
|
@ -1102,8 +1177,7 @@ public class DefaultModelBuilder
|
|||
buffer.append( ": " ).append( e.getMessage() );
|
||||
|
||||
problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
|
||||
.setMessage( buffer.toString() )
|
||||
.setLocation( dependency.getLocation( "" ) )
|
||||
.setMessage( buffer.toString() ).setLocation( dependency.getLocation( "" ) )
|
||||
.setException( e ) );
|
||||
continue;
|
||||
}
|
||||
|
@ -1121,7 +1195,7 @@ public class DefaultModelBuilder
|
|||
importRequest.setModelSource( importSource );
|
||||
importRequest.setModelResolver( modelResolver.newCopy() );
|
||||
|
||||
ModelBuildingResult importResult;
|
||||
final ModelBuildingResult importResult;
|
||||
try
|
||||
{
|
||||
importResult = build( importRequest );
|
||||
|
@ -1134,7 +1208,8 @@ public class DefaultModelBuilder
|
|||
|
||||
problems.addAll( importResult.getProblems() );
|
||||
|
||||
Model importModel = importResult.getEffectiveModel();
|
||||
importModel = importResult.getEffectiveModel();
|
||||
}
|
||||
|
||||
importMngt = importModel.getDependencyManagement();
|
||||
|
||||
|
|
|
@ -25,8 +25,10 @@ import java.util.Date;
|
|||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.maven.model.Model;
|
||||
import org.apache.maven.model.Profile;
|
||||
import org.apache.maven.model.resolution.ModelResolver;
|
||||
import org.apache.maven.model.resolution.WorkspaceModelResolver;
|
||||
|
||||
/**
|
||||
* Collects settings that control building of effective models.
|
||||
|
@ -37,6 +39,8 @@ public class DefaultModelBuildingRequest
|
|||
implements ModelBuildingRequest
|
||||
{
|
||||
|
||||
private Model rawModel;
|
||||
|
||||
private File pomFile;
|
||||
|
||||
private ModelSource modelSource;
|
||||
|
@ -67,6 +71,8 @@ public class DefaultModelBuildingRequest
|
|||
|
||||
private ModelCache modelCache;
|
||||
|
||||
private WorkspaceModelResolver workspaceResolver;
|
||||
|
||||
/**
|
||||
* Creates an empty request.
|
||||
*/
|
||||
|
@ -373,4 +379,30 @@ public class DefaultModelBuildingRequest
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Model getRawModel()
|
||||
{
|
||||
return rawModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelBuildingRequest setRawModel( Model rawModel )
|
||||
{
|
||||
this.rawModel = rawModel;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorkspaceModelResolver getWorkspaceModelResolver()
|
||||
{
|
||||
return workspaceResolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelBuildingRequest setWorkspaceModelResolver( WorkspaceModelResolver workspaceResolver )
|
||||
{
|
||||
this.workspaceResolver = workspaceResolver;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,8 +24,10 @@ import java.util.Date;
|
|||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.maven.model.Model;
|
||||
import org.apache.maven.model.Profile;
|
||||
import org.apache.maven.model.resolution.ModelResolver;
|
||||
import org.apache.maven.model.resolution.WorkspaceModelResolver;
|
||||
|
||||
/**
|
||||
* A model building request that delegates all methods invocations to another request, meant for easy transformations by
|
||||
|
@ -254,4 +256,30 @@ class FilterModelBuildingRequest
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Model getRawModel()
|
||||
{
|
||||
return request.getRawModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelBuildingRequest setRawModel( Model rawModel )
|
||||
{
|
||||
request.setRawModel( rawModel );
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorkspaceModelResolver getWorkspaceModelResolver()
|
||||
{
|
||||
return request.getWorkspaceModelResolver();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelBuildingRequest setWorkspaceModelResolver( WorkspaceModelResolver workspaceResolver )
|
||||
{
|
||||
request.setWorkspaceModelResolver( workspaceResolver );
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
|
@ -19,6 +19,10 @@ package org.apache.maven.model.building;
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.apache.maven.model.Model;
|
||||
|
||||
/**
|
||||
* Builds the effective model from a POM.
|
||||
*
|
||||
|
@ -51,4 +55,13 @@ public interface ModelBuilder
|
|||
ModelBuildingResult build( ModelBuildingRequest request, ModelBuildingResult result )
|
||||
throws ModelBuildingException;
|
||||
|
||||
/**
|
||||
* Performs only the part of {@link ModelBuilder#build(ModelBuildingRequest)} that loads the raw model
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
* @throws ModelBuildingException
|
||||
*/
|
||||
Result<? extends Model> buildRawModel( File pomFile, int validationLevel, boolean locationTracking );
|
||||
|
||||
}
|
||||
|
|
|
@ -24,8 +24,10 @@ import java.util.Date;
|
|||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.maven.model.Model;
|
||||
import org.apache.maven.model.Profile;
|
||||
import org.apache.maven.model.resolution.ModelResolver;
|
||||
import org.apache.maven.model.resolution.WorkspaceModelResolver;
|
||||
|
||||
/**
|
||||
* Collects settings that control the building of effective models.
|
||||
|
@ -62,6 +64,20 @@ public interface ModelBuildingRequest
|
|||
*/
|
||||
int VALIDATION_LEVEL_STRICT = VALIDATION_LEVEL_MAVEN_3_0;
|
||||
|
||||
/**
|
||||
* Gets the raw model to build. If not set, model source will be used to load raw model.
|
||||
*
|
||||
* @return The raw model to build or {@code null} if not set.
|
||||
*/
|
||||
Model getRawModel();
|
||||
|
||||
/**
|
||||
* Set raw model.
|
||||
*
|
||||
* @param model
|
||||
*/
|
||||
ModelBuildingRequest setRawModel( Model rawModel );
|
||||
|
||||
/**
|
||||
* Gets the source of the POM to process.
|
||||
*
|
||||
|
@ -315,4 +331,8 @@ public interface ModelBuildingRequest
|
|||
*/
|
||||
ModelBuildingRequest setModelCache( ModelCache modelCache );
|
||||
|
||||
WorkspaceModelResolver getWorkspaceModelResolver();
|
||||
|
||||
ModelBuildingRequest setWorkspaceModelResolver( WorkspaceModelResolver workspaceResolver );
|
||||
|
||||
}
|
|
@ -0,0 +1,255 @@
|
|||
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 com.google.common.base.Predicates.in;
|
||||
import static com.google.common.collect.Iterables.any;
|
||||
import static com.google.common.collect.Iterables.concat;
|
||||
import static com.google.common.collect.Iterables.transform;
|
||||
import static java.util.Collections.singleton;
|
||||
import static java.util.EnumSet.of;
|
||||
import static org.apache.maven.model.building.ModelProblem.Severity.ERROR;
|
||||
import static org.apache.maven.model.building.ModelProblem.Severity.FATAL;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.apache.maven.model.building.ModelProblem.Severity;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
* There are various forms of results that are represented by this class:
|
||||
* <ol>
|
||||
* <li>success - in which case only the model field is set
|
||||
* <li>success with warnings - model field + non-error model problems
|
||||
* <li>error - no model, but diagnostics
|
||||
* <li>error - (partial) model and diagnostics
|
||||
* </ol>
|
||||
* Could encode these variants as subclasses, but kept in one for now
|
||||
*
|
||||
* @author bbusjaeger
|
||||
* @param <T>
|
||||
*/
|
||||
public class Result<T>
|
||||
{
|
||||
|
||||
/**
|
||||
* Success without warnings
|
||||
*
|
||||
* @param model
|
||||
* @return
|
||||
*/
|
||||
public static <T> Result<T> success( T model )
|
||||
{
|
||||
return success( model, Collections.<ModelProblem>emptyList() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Success with warnings
|
||||
*
|
||||
* @param model
|
||||
* @param problems
|
||||
* @return
|
||||
*/
|
||||
public static <T> Result<T> success( T model, Iterable<? extends ModelProblem> problems )
|
||||
{
|
||||
assert !hasErrors( problems );
|
||||
return new Result<T>( false, model, problems );
|
||||
}
|
||||
|
||||
/**
|
||||
* Success with warnings
|
||||
*
|
||||
* @param model
|
||||
* @param results
|
||||
* @return
|
||||
*/
|
||||
public static <T> Result<T> success( T model, Result<?>... results )
|
||||
{
|
||||
return success( model, Iterables.concat( Iterables.transform( Arrays.asList( results ), GET_PROBLEMS ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Error with problems describing the cause
|
||||
*
|
||||
* @param problems
|
||||
* @return
|
||||
*/
|
||||
public static <T> Result<T> error( Iterable<? extends ModelProblem> problems )
|
||||
{
|
||||
return error( null, problems );
|
||||
}
|
||||
|
||||
public static <T> Result<T> error( T model )
|
||||
{
|
||||
return error( model, Collections.<ModelProblem>emptyList() );
|
||||
}
|
||||
|
||||
public static <T> Result<T> error( Result<?> result )
|
||||
{
|
||||
return error( result.getProblems() );
|
||||
}
|
||||
|
||||
public static <T> Result<T> error( Result<?>... results )
|
||||
{
|
||||
return error( Iterables.concat( Iterables.transform( Arrays.asList( results ), GET_PROBLEMS ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Error with partial result and problems describing the cause
|
||||
*
|
||||
* @param model
|
||||
* @param problems
|
||||
* @return
|
||||
*/
|
||||
public static <T> Result<T> error( T model, Iterable<? extends ModelProblem> problems )
|
||||
{
|
||||
return new Result<T>( true, model, problems );
|
||||
}
|
||||
|
||||
/**
|
||||
* New result - determine whether error or success by checking problems for errors
|
||||
*
|
||||
* @param model
|
||||
* @param problems
|
||||
* @return
|
||||
*/
|
||||
public static <T> Result<T> newResult( T model, Iterable<? extends ModelProblem> problems )
|
||||
{
|
||||
return new Result<T>( hasErrors( problems ), model, problems );
|
||||
}
|
||||
|
||||
/**
|
||||
* New result consisting of given result and new problem. Convenience for newResult(result.get(),
|
||||
* concat(result.getProblems(),problems)).
|
||||
*
|
||||
* @param result
|
||||
* @param problem
|
||||
* @return
|
||||
*/
|
||||
public static <T> Result<T> addProblem( Result<T> result, ModelProblem problem )
|
||||
{
|
||||
return addProblems( result, singleton( problem ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* New result that includes the given
|
||||
*
|
||||
* @param result
|
||||
* @param problems
|
||||
* @return
|
||||
*/
|
||||
public static <T> Result<T> addProblems( Result<T> result, Iterable<? extends ModelProblem> problems )
|
||||
{
|
||||
return new Result<T>( result.hasErrors() || hasErrors( problems ), result.get(), concat( result.getProblems(),
|
||||
problems ) );
|
||||
}
|
||||
|
||||
public static <T> Result<T> addProblems( Result<T> result, Result<?>... results )
|
||||
{
|
||||
return addProblems( result, Iterables.concat( Iterables.transform( Arrays.asList( results ), GET_PROBLEMS ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns the given results into a single result by combining problems and models into single collection.
|
||||
*
|
||||
* @param results
|
||||
* @return
|
||||
*/
|
||||
public static <T> Result<Iterable<T>> newResultSet( Iterable<? extends Result<? extends T>> results )
|
||||
{
|
||||
final boolean hasErrors = any( transform( results, new Function<Result<?>, Boolean>()
|
||||
{
|
||||
@Override
|
||||
public Boolean apply( Result<?> input )
|
||||
{
|
||||
return input.hasErrors();
|
||||
}
|
||||
} ), Predicates.equalTo( true ) );
|
||||
final Iterable<T> models = transform( results, new Function<Result<? extends T>, T>()
|
||||
{
|
||||
@Override
|
||||
public T apply( Result<? extends T> input )
|
||||
{
|
||||
return input.get();
|
||||
}
|
||||
} );
|
||||
final Iterable<ModelProblem> problems = concat( transform( results, GET_PROBLEMS ) );
|
||||
return new Result<Iterable<T>>( hasErrors, models, problems );
|
||||
}
|
||||
|
||||
// helper to determine if problems contain error
|
||||
private static boolean hasErrors( Iterable<? extends ModelProblem> problems )
|
||||
{
|
||||
return any( transform( problems, new Function<ModelProblem, Severity>()
|
||||
{
|
||||
@Override
|
||||
public Severity apply( ModelProblem input )
|
||||
{
|
||||
return input.getSeverity();
|
||||
}
|
||||
} ), in( of( ERROR, FATAL ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
|
||||
private final boolean errors;
|
||||
|
||||
private final T value;
|
||||
|
||||
private final Iterable<? extends ModelProblem> problems;
|
||||
|
||||
private Result( boolean errors, T model, Iterable<? extends ModelProblem> problems )
|
||||
{
|
||||
this.errors = errors;
|
||||
this.value = model;
|
||||
this.problems = problems;
|
||||
}
|
||||
|
||||
public Iterable<? extends ModelProblem> getProblems()
|
||||
{
|
||||
return problems;
|
||||
}
|
||||
|
||||
public T get()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean hasErrors()
|
||||
{
|
||||
return errors;
|
||||
}
|
||||
|
||||
private static final Function<Result<?>, Iterable<? extends ModelProblem>> GET_PROBLEMS =
|
||||
new Function<Result<?>, Iterable<? extends ModelProblem>>()
|
||||
{
|
||||
@Override
|
||||
public Iterable<? extends ModelProblem> apply( Result<?> input )
|
||||
{
|
||||
return input.getProblems();
|
||||
}
|
||||
};
|
||||
}
|
|
@ -77,6 +77,22 @@ public class UnresolvableModelException
|
|||
this.version = ( version != null ) ? version : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new exception with specified cause
|
||||
*
|
||||
* @param cause
|
||||
* @param groupId
|
||||
* @param artifactId
|
||||
* @param version
|
||||
*/
|
||||
public UnresolvableModelException( Throwable cause, String groupId, String artifactId, String version )
|
||||
{
|
||||
super( cause );
|
||||
this.groupId = groupId;
|
||||
this.artifactId = artifactId;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the group id of the unresolvable model.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package org.apache.maven.model.resolution;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
public interface WorkspaceModelResolver
|
||||
{
|
||||
|
||||
Model resolveRawModel( String groupId, String artifactId, String versionConstraint )
|
||||
throws UnresolvableModelException;
|
||||
|
||||
Model resolveEffectiveModel( String groupId, String artifactId, String versionConstraint )
|
||||
throws UnresolvableModelException;
|
||||
|
||||
}
|
|
@ -1466,12 +1466,18 @@
|
|||
<version>4.0.0+</version>
|
||||
<code>
|
||||
<![CDATA[
|
||||
private String managementKey;
|
||||
|
||||
/**
|
||||
* @return the management key as <code>groupId:artifactId:type</code>
|
||||
*/
|
||||
public String getManagementKey()
|
||||
{
|
||||
return groupId + ":" + artifactId + ":" + type + ( classifier != null ? ":" + classifier : "" );
|
||||
if ( managementKey == null )
|
||||
{
|
||||
managementKey = groupId + ":" + artifactId + ":" + type + ( classifier != null ? ":" + classifier : "" );
|
||||
}
|
||||
return managementKey;
|
||||
}
|
||||
]]>
|
||||
</code>
|
||||
|
|
Loading…
Reference in New Issue