[MNG-4224] maven lifecycle participant

Submitted by: Igor Fedorenko

git-svn-id: https://svn.apache.org/repos/asf/maven/components/trunk@789993 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Benjamin Bentmann 2009-06-30 22:36:30 +00:00
parent e0d29fe6a3
commit accb45543f
9 changed files with 306 additions and 22 deletions

View File

@ -0,0 +1,54 @@
package org.apache.maven;
/*
* 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;
/**
* Allows core extensions to participate in build lifecycle.
*
* All callback methods (will) follow beforeXXX/afterXXX naming pattern to
* indicate at what lifecycle point it is being called.
*
*/
public abstract class AbstractMavenLifecycleParticipant
{
/**
* Invoked after all MavenProject instances have been created.
*
* This callback is intended to allow extensions to manipulate MavenProjects
* before they are sorted and actual build execution starts.
*/
public void afterProjectsRead( MavenSession session ) throws MavenExecutionException
{
// do nothing
}
/**
* Invoked after MavenSession instance has been created.
*
* This callback is intended to allow extensions to inject execution properties,
* activate profiles and perform similar tasks that affect MavenProject
* instance construction.
*/
public void afterSessionStart( MavenSession session ) throws MavenExecutionException
{
// do nothing
}
}

View File

@ -22,7 +22,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
@ -46,6 +45,7 @@ import org.apache.maven.repository.DelegatingLocalArtifactRepository;
import org.codehaus.plexus.PlexusContainer;
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.Os;
import org.codehaus.plexus.util.StringUtils;
@ -86,13 +86,24 @@ public class DefaultMaven
DelegatingLocalArtifactRepository delegatingLocalArtifactRepository = new DelegatingLocalArtifactRepository( request.getLocalRepository() );
request.setLocalRepository( delegatingLocalArtifactRepository );
MavenSession session;
MavenSession session = new MavenSession( container, request, result);
Map<String,MavenProject> projects;
try
{
for ( AbstractMavenLifecycleParticipant listener : getLifecycleParticipants() )
{
listener.afterSessionStart( session );
}
}
catch ( MavenExecutionException e )
{
return processResult( result, e );
}
//TODO: optimize for the single project or no project
List<MavenProject> projects;
try
{
projects = getProjectsForMavenReactor( request );
@ -101,7 +112,7 @@ public class DefaultMaven
if ( projects.isEmpty() )
{
MavenProject project = projectBuilder.buildStandaloneSuperProject( request.getProjectBuildingRequest() );
projects.put( ArtifactUtils.key( project.getGroupId(), project.getArtifactId(), project.getVersion() ), project );
projects.add( project );
request.setProjectPresent( false );
}
}
@ -113,12 +124,28 @@ public class DefaultMaven
{
return processResult( result, e );
}
session.setProjects( projects );
try
{
for ( AbstractMavenLifecycleParticipant listener : getLifecycleParticipants() )
{
listener.afterProjectsRead( session );
}
}
catch ( MavenExecutionException e )
{
return processResult( result, e );
}
try
{
ProjectSorter projectSorter = new ProjectSorter( projects.values() );
session = new MavenSession( container, request, result, projectSorter.getSortedProjects() );
ProjectSorter projectSorter = new ProjectSorter( session.getProjects() );
projects = projectSorter.getSortedProjects();
session.setProjects( projects );
}
catch ( CycleDetectedException e )
{
@ -132,14 +159,20 @@ public class DefaultMaven
{
return processResult( result, e );
}
// Desired order of precedence for local artifact repositories
//
// Reactor
// Workspace
// User Local Repository
delegatingLocalArtifactRepository.setBuildReactor( new ReactorArtifactRepository( projects ) );
try
{
delegatingLocalArtifactRepository.setBuildReactor( new ReactorArtifactRepository( getProjectMap( session.getProjects() ) ) );
}
catch ( MavenExecutionException e )
{
return processResult( result, e );
}
if ( result.hasExceptions() )
{
@ -162,6 +195,22 @@ public class DefaultMaven
return result;
}
private List<AbstractMavenLifecycleParticipant> getLifecycleParticipants()
{
// TODO injection of component lists does not work
List<AbstractMavenLifecycleParticipant> lifecycleListeners;
try
{
lifecycleListeners = container.lookupList( AbstractMavenLifecycleParticipant.class );
}
catch ( ComponentLookupException e1 )
{
// this is just silly, lookupList should return an empty list!
lifecycleListeners = new ArrayList<AbstractMavenLifecycleParticipant>();
}
return lifecycleListeners;
}
private MavenExecutionResult processResult( MavenExecutionResult result, Exception e )
{
ExceptionHandler handler = new DefaultExceptionHandler();
@ -175,14 +224,14 @@ public class DefaultMaven
return result;
}
protected Map<String,MavenProject> getProjectsForMavenReactor( MavenExecutionRequest request )
private List<MavenProject> getProjectsForMavenReactor( MavenExecutionRequest request )
throws MavenExecutionException, ProjectBuildingException
{
// We have no POM file.
//
if ( request.getPom() == null || !request.getPom().exists() )
{
return new HashMap<String,MavenProject>();
return new ArrayList<MavenProject>();
}
List<File> files = Arrays.asList( request.getPom().getAbsoluteFile() );
@ -191,6 +240,12 @@ public class DefaultMaven
collectProjects( projects, files, request );
return projects;
}
private Map<String, MavenProject> getProjectMap( List<MavenProject> projects )
throws org.apache.maven.DuplicateProjectException
{
Map<String, MavenProject> index = new LinkedHashMap<String, MavenProject>();
Map<String, List<File>> collisions = new LinkedHashMap<String, List<File>>();

View File

@ -31,7 +31,6 @@ import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuildingRequest;
import org.apache.maven.settings.Settings;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.util.dag.CycleDetectedException;
/**
* @author Jason van Zyl
@ -55,25 +54,37 @@ public class MavenSession
private MavenProject topLevelProject;
@Deprecated
public MavenSession( PlexusContainer container, MavenExecutionRequest request, MavenExecutionResult result, MavenProject project )
throws CycleDetectedException, DuplicateProjectException
{
this( container, request, result, Arrays.asList( new MavenProject[]{ project } ) );
}
@Deprecated
public MavenSession( PlexusContainer container, MavenExecutionRequest request, MavenExecutionResult result, List<MavenProject> projects )
throws CycleDetectedException, DuplicateProjectException
{
this.container = container;
this.request = request;
this.result = result;
setProjects( projects );
}
public MavenSession( PlexusContainer container, MavenExecutionRequest request, MavenExecutionResult result )
{
this.container = container;
this.request = request;
this.result = result;
}
public void setProjects( List<MavenProject> projects )
{
//TODO: Current for testing classes creating the session
if ( projects.size() > 0 )
{
this.currentProject = projects.get( 0 );
this.topLevelProject = projects.get( 0 );
}
this.projects = projects;
this.projects = projects;
}
@Deprecated

View File

@ -806,7 +806,10 @@ public class DefaultLifecycleExecutor
{
String phase = goalsForLifecyclePhase.getKey();
String goals = goalsForLifecyclePhase.getValue();
parseLifecyclePhaseDefinitions( plugins, phase, goals );
if ( goals != null )
{
parseLifecyclePhaseDefinitions( plugins, phase, goals );
}
}
}
else if ( lifecycle.getDefaultPhases() != null )

View File

@ -222,7 +222,7 @@ public class DefaultPluginManager
}
}
private PluginDescriptor parsebuildPluginDescriptor( InputStream is )
public PluginDescriptor parsebuildPluginDescriptor( InputStream is )
throws IOException, PlexusConfigurationException
{
PluginDescriptor pluginDescriptor;

View File

@ -164,7 +164,9 @@ public class MavenProject
private RepositorySystem repositorySystem;
private File parentFile;
private Map<String, Object> context;
//
public MavenProject()
@ -1966,4 +1968,41 @@ public class MavenProject
{
return groupId + ":" + artifactId + ":" + version;
}
/**
* Sets the value of the context value of this project identified
* by the given key. If the supplied value is <code>null</code>,
* the context value is removed from this project.
*
* Context values are intended to allow core extensions to associate
* derived state with project instances.
*/
public void setContextValue( String key, Object value )
{
if ( context == null )
{
context = new HashMap<String, Object>();
}
if ( value != null )
{
context.put( key, value );
}
else
{
context.remove( key );
}
}
/**
* Returns context value of this project associated with the given key
* or null if this project has no such value.
*/
public Object getContextValue( String key )
{
if ( context == null )
{
return null;
}
return context.get( key );
}
}

View File

@ -0,0 +1,111 @@
package org.apache.maven;
/*
* 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.io.IOException;
import java.util.ArrayList;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenExecutionResult;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Dependency;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.ComponentDescriptor;
public class MavenLifecycleParticipantTest
extends AbstractCoreMavenComponentTestCase
{
private static final String INJECTED_ARTIFACT_ID = "injected";
public static class InjectDependencyLifecycleListener
extends AbstractMavenLifecycleParticipant
{
@Override
public void afterProjectsRead( MavenSession session )
{
MavenProject project = session.getProjects().get( 0 );
Dependency dependency = new Dependency();
dependency.setArtifactId( INJECTED_ARTIFACT_ID );
dependency.setGroupId( "foo" );
dependency.setVersion( "1.2.3" );
dependency.setScope( "system" );
try
{
dependency.setSystemPath( new File(
"src/test/projects/lifecycle-executor/project-with-additional-lifecycle-elements/pom.xml" ).getCanonicalPath() );
}
catch ( IOException e )
{
throw new RuntimeException( e );
}
project.getModel().addDependency( dependency );
}
@Override
public void afterSessionStart( MavenSession session )
{
session.getExecutionProperties().setProperty( "injected", "bar" );
}
}
@Override
protected void setupContainer()
{
super.setupContainer();
}
@Override
protected String getProjectsDirectory()
{
return "src/test/projects/lifecycle-listener";
}
public void testDependencyInjection()
throws Exception
{
PlexusContainer container = getContainer();
ComponentDescriptor cd =
new ComponentDescriptor( InjectDependencyLifecycleListener.class, container.getContainerRealm() );
cd.setRoleClass( AbstractMavenLifecycleParticipant.class );
container.addComponentDescriptor( cd );
Maven maven = container.lookup( Maven.class );
File pom = getProject( "lifecycle-listener-dependency-injection" );
MavenExecutionRequest request = createMavenExecutionRequest( pom );
MavenExecutionResult result = maven.execute( request );
assertFalse( result.hasExceptions() );
MavenProject project = result.getProject();
assertEquals( "bar", project.getProperties().getProperty( "foo" ) );
ArrayList<Artifact> artifacts = new ArrayList<Artifact>( project.getArtifacts() );
assertEquals( 1, artifacts.size() );
assertEquals( INJECTED_ARTIFACT_ID, artifacts.get( 0 ).getArtifactId() );
}
}

View File

@ -6,7 +6,6 @@ import org.apache.maven.exception.ExceptionHandler;
import org.apache.maven.exception.ExceptionSummary;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenExecutionResult;
import org.apache.maven.execution.MavenSession;
import org.codehaus.plexus.component.annotations.Requirement;
public class MavenTest

View File

@ -0,0 +1,12 @@
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.maven.lifecycle-listener.test</groupId>
<artifactId>simple</artifactId>
<version>1.0</version>
<properties>
<foo>${injected}</foo>
</properties>
</project>