You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by jv...@apache.org on 2014/02/06 04:48:51 UTC

[2/3] git commit: MNG-5575: Separate distinct build strategies into their own new Builder implementation. The interface is not ideal yet, but gives us a cleaner separation of implementations and gives us a path forward.

MNG-5575: Separate distinct build strategies into their own new Builder implementation. The interface is not ideal yet, but gives us a cleaner
separation of implementations and gives us a path forward.


Project: http://git-wip-us.apache.org/repos/asf/maven/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven/commit/09961c31
Tree: http://git-wip-us.apache.org/repos/asf/maven/tree/09961c31
Diff: http://git-wip-us.apache.org/repos/asf/maven/diff/09961c31

Branch: refs/heads/master
Commit: 09961c3150b1a9ddaa88760d3a91f86542e5827d
Parents: 3bf568e
Author: Jason van Zyl <ja...@tesla.io>
Authored: Wed Feb 5 22:43:04 2014 -0500
Committer: Jason van Zyl <ja...@tesla.io>
Committed: Wed Feb 5 22:43:04 2014 -0500

----------------------------------------------------------------------
 MavenLifecyle.md                                |  45 ++
 .../maven/DefaultProjectDependencyGraph.java    |  10 +-
 .../execution/DefaultMavenExecutionRequest.java |  49 +-
 .../execution/DefaultMavenExecutionResult.java  |   8 +-
 .../maven/execution/MavenExecutionRequest.java  |  97 +++-
 .../maven/execution/MavenExecutionResult.java   |   1 -
 .../apache/maven/execution/MavenSession.java    |   1 +
 .../apache/maven/execution/ReactorManager.java  |   5 -
 .../maven/lifecycle/DefaultSchedules.java       |   2 +-
 .../lifecycle/internal/BuildListCalculator.java |   1 +
 .../lifecycle/internal/BuildThreadFactory.java  |  20 +
 ...DefaultLifecycleExecutionPlanCalculator.java |   1 +
 .../internal/LifecycleDebugLogger.java          |   1 +
 .../internal/LifecycleModuleBuilder.java        |   7 +-
 .../lifecycle/internal/LifecycleStarter.java    | 114 +---
 .../lifecycle/internal/ProjectBuildList.java    |  12 +
 .../maven/lifecycle/internal/ProjectIndex.java  |   1 +
 .../lifecycle/internal/ReactorBuildStatus.java  |   1 +
 .../lifecycle/internal/builder/Builder.java     |  28 +
 .../internal/builder/BuilderCommon.java         | 195 +++++++
 .../builder/BuilderNotFoundException.java       |   9 +
 .../ConcurrencyDependencyGraph.java             | 153 ++++++
 .../multithreaded/MultiThreadedBuilder.java     | 193 +++++++
 .../singlethreaded/SingleThreadedBuilder.java   |  46 ++
 .../internal/builder/weave/BuildLogItem.java    | 221 ++++++++
 .../builder/weave/ConcurrentBuildLogger.java    | 124 +++++
 .../builder/weave/CurrentPhaseForThread.java    |  44 ++
 .../builder/weave/ThreadLockedArtifact.java     | 320 ++++++++++++
 .../internal/builder/weave/WeaveBuilder.java    | 521 +++++++++++++++++++
 .../maven/lifecycle/MavenExecutionPlanTest.java |   1 +
 .../lifecycle/internal/BuilderCommonTest.java   |   2 +
 .../ConcurrencyDependencyGraphTest.java         |   1 +
 .../internal/ConcurrentBuildLoggerTest.java     |   7 +-
 .../internal/ExecutionPlanItemTest.java         |   1 +
 .../internal/LifecycleWeaveBuilderTest.java     |  11 +-
 .../lifecycle/internal/PhaseRecorderTest.java   |   1 +
 .../stub/ProjectDependencyGraphStub.java        |   1 +
 .../java/org/apache/maven/cli/CLIManager.java   |   3 +
 .../java/org/apache/maven/cli/MavenCli.java     |  41 +-
 .../maven/cli/event/ExecutionEventLogger.java   |   2 +-
 40 files changed, 2139 insertions(+), 162 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/MavenLifecyle.md
----------------------------------------------------------------------
diff --git a/MavenLifecyle.md b/MavenLifecyle.md
new file mode 100644
index 0000000..1007dea
--- /dev/null
+++ b/MavenLifecyle.md
@@ -0,0 +1,45 @@
+Maven (DefaultMaven) : doExecute
+ - add a build timestamp to the request properties
+ - validateLocalRepository: validate local repository (check to make sure it exists and is writable)
+ - newRepositorySession: create the RepositorySystemSession
+ - AbstractLifecycleParticipant.afterSessionStart
+ - event: ExecutionEvent.Type.ProjectDiscoveryStarted
+ - set the RepositorySystemSession in the ProjectBuildingRequest
+ - getProjectsForMavenReactor 
+   - this triggers the reading of all the POMs: (NOTE: this could be optimized looking at the POMs if they don't change)
+ - create the ReactorReader
+ - set RepositorySystemSession.setWorkspaceReader()
+ - make the RepositorySystemSession readonly
+ ? Can we remove all the @Deprecated methods from MavenSession (4 years, 7 months)
+ ? Can we make the MavenSession read-only, do we need a way to share state better 
+ - AbstractLifecycleParticipant.afterProjectsRead()
+ - lifecycleStarter.execute(session)
+ - validateProfiles (NOTE: why does this happen at the end?)
+
+# Things to document
+- How the ClassRealms are setup at each stage
+- Having meaningful visuals for the lifecycle and stages
+- explain forked executions
+- remove aggregators, and what are they exactly
+
+# Questions
+
+? forked executions
+? aggregators
+? All the different resolvers: project, plugin, lifecycle
+? Turn if all into JSR330
+
+# Things to refactor
+
+# Isolate project dependency downloads from build execution
+- project dependencies are resolved from the mojo executor
+- separate dependency resolution from build execution, right now they are intertwined
+  - if separated then a calculation can be made for the whole set of dependencies
+  - make sure dependency resolution works before the build executes
+  - not sure there would be much of a speed impact if one assumes the best speeds will happen when everything is downloaded and the
+    conflation of these modes and the complexity it creates is not worth it
+
+- turn all to JSR330 
+- use LifecycleModuleBuilder consistently instead of BuilderCommon
+- the MavenExecution is calculated in each of the builders instead of once, the implication of this is that project dependency resolution will happen in parallel which means the local repository needs to be safe, and resolution in general.
+- the weave builder uses BuilderCommon directly, should be used the same way the other builders work

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/DefaultProjectDependencyGraph.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/DefaultProjectDependencyGraph.java b/maven-core/src/main/java/org/apache/maven/DefaultProjectDependencyGraph.java
index 67ed340..adf85da 100644
--- a/maven-core/src/main/java/org/apache/maven/DefaultProjectDependencyGraph.java
+++ b/maven-core/src/main/java/org/apache/maven/DefaultProjectDependencyGraph.java
@@ -113,13 +113,15 @@ class DefaultProjectDependencyGraph
 
     private List<MavenProject> getProjects( Collection<String> projectIds )
     {
-        List<MavenProject> projects = new ArrayList<MavenProject>();
+        List<MavenProject> projects = new ArrayList<MavenProject>( projectIds.size() );
 
-        for ( MavenProject p : sorter.getSortedProjects() )
+        for ( String projectId : projectIds )
         {
-            if ( projectIds.contains( ProjectSorter.getId( p ) ) )
+            MavenProject project = sorter.getProjectMap().get( projectId );
+
+            if ( project != null )
             {
-                projects.add( p );
+                projects.add( project );
             }
         }
 

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java b/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java
index 9919a1e..11329d0 100644
--- a/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java
+++ b/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java
@@ -101,7 +101,7 @@ public class DefaultMavenExecutionRequest
     private String reactorFailureBehavior = REACTOR_FAIL_FAST;
 
     private List<String> selectedProjects;
-    
+
     private List<String> excludedProjects;
 
     private String resumeFrom;
@@ -134,13 +134,13 @@ public class DefaultMavenExecutionRequest
 
     private ExecutionListener executionListener;
 
-    private String threadCount;
+    private int degreeOfConcurrency = 1;
 
-    private boolean perCoreThreadCount;
+    private String builderId = "singlethreaded";
 
     /**
      * Suppress SNAPSHOT updates.
-     *
+     * 
      * @issue MNG-2681
      */
     private boolean noSnapshotUpdates;
@@ -169,8 +169,7 @@ public class DefaultMavenExecutionRequest
         copy.setUserSettingsFile( original.getUserSettingsFile() );
         copy.setGlobalSettingsFile( original.getGlobalSettingsFile() );
         copy.setUserToolchainsFile( original.getUserToolchainsFile() );
-        copy.setBaseDirectory( ( original.getBaseDirectory() != null )
-                               ? new File( original.getBaseDirectory() ) : null );
+        copy.setBaseDirectory( ( original.getBaseDirectory() != null ) ? new File( original.getBaseDirectory() ) : null );
         copy.setGoals( original.getGoals() );
         copy.setRecursive( original.isRecursive() );
         copy.setPom( original.getPom() );
@@ -260,7 +259,7 @@ public class DefaultMavenExecutionRequest
 
         return selectedProjects;
     }
-    
+
     public List<String> getExcludedProjects()
     {
         if ( excludedProjects == null )
@@ -981,7 +980,7 @@ public class DefaultMavenExecutionRequest
         return pluginArtifactRepositories;
     }
 
-    //TODO: this does not belong here.
+    // TODO: this does not belong here.
     public ProjectBuildingRequest getProjectBuildingRequest()
     {
         if ( projectBuildingRequest == null )
@@ -1046,29 +1045,14 @@ public class DefaultMavenExecutionRequest
         return this;
     }
 
-    public String getThreadCount()
-    {
-        return threadCount;
-    }
-
-    public void setThreadCount( String threadCount )
-    {
-        this.threadCount = threadCount;
-    }
-
-    public boolean isThreadConfigurationPresent()
-    {
-        return getThreadCount() != null;
-    }
-
-    public boolean isPerCoreThreadCount()
+    public void setDegreeOfConcurrency( final int degreeOfConcurrency )
     {
-        return perCoreThreadCount;
+        this.degreeOfConcurrency = degreeOfConcurrency;
     }
 
-    public void setPerCoreThreadCount( boolean perCoreThreadCount )
+    public int getDegreeOfConcurrency()
     {
-        this.perCoreThreadCount = perCoreThreadCount;
+        return degreeOfConcurrency;
     }
 
     public WorkspaceReader getWorkspaceReader()
@@ -1114,4 +1098,15 @@ public class DefaultMavenExecutionRequest
         this.useSimpleLocalRepositoryManager = useSimpleLocalRepositoryManager;
         return this;
     }
+
+    public MavenExecutionRequest setBuilderId( String builderId )
+    {
+        this.builderId = builderId;
+        return this;
+    }
+
+    public String getBuilderId()
+    {
+        return builderId;
+    }
 }

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionResult.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionResult.java b/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionResult.java
index cb22b38..115cd73 100644
--- a/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionResult.java
+++ b/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionResult.java
@@ -28,6 +28,8 @@ import java.util.concurrent.CopyOnWriteArrayList;
 import org.apache.maven.project.DependencyResolutionResult;
 import org.apache.maven.project.MavenProject;
 
+import com.google.common.collect.Maps;
+
 /** @author Jason van Zyl */
 public class DefaultMavenExecutionResult
     implements MavenExecutionResult
@@ -40,7 +42,7 @@ public class DefaultMavenExecutionResult
 
     private List<Throwable> exceptions = new CopyOnWriteArrayList<Throwable>();
 
-    private Map<MavenProject, BuildSummary> buildSummaries;
+    private Map<MavenProject, BuildSummary> buildSummaries = Maps.newIdentityHashMap();
 
     public MavenExecutionResult setProject( MavenProject project )
     {
@@ -63,7 +65,8 @@ public class DefaultMavenExecutionResult
 
     public List<MavenProject> getTopologicallySortedProjects()
     {
-        return null == topologicallySortedProjects ? Collections.<MavenProject> emptyList() : topologicallySortedProjects;
+        return null == topologicallySortedProjects ? Collections.<MavenProject> emptyList()
+                        : topologicallySortedProjects;
     }
 
     public DependencyResolutionResult getDependencyResolutionResult()
@@ -108,5 +111,4 @@ public class DefaultMavenExecutionResult
         }
         buildSummaries.put( summary.getProject(), summary );
     }
-
 }

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java b/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java
index 70b77e1..121e51a 100644
--- a/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java
+++ b/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java
@@ -91,14 +91,17 @@ public interface MavenExecutionRequest
 
     // Base directory
     MavenExecutionRequest setBaseDirectory( File basedir );
+
     String getBaseDirectory();
 
     // Timing (remove this)
     MavenExecutionRequest setStartTime( Date start );
+
     Date getStartTime();
 
     // Goals
     MavenExecutionRequest setGoals( List<String> goals );
+
     List<String> getGoals();
 
     // Properties
@@ -106,7 +109,7 @@ public interface MavenExecutionRequest
     /**
      * Sets the system properties to use for interpolation and profile activation. The system properties are collected
      * from the runtime environment like {@link System#getProperties()} and environment variables.
-     *
+     * 
      * @param systemProperties The system properties, may be {@code null}.
      * @return This request, never {@code null}.
      */
@@ -115,7 +118,7 @@ public interface MavenExecutionRequest
     /**
      * Gets the system properties to use for interpolation and profile activation. The system properties are collected
      * from the runtime environment like {@link System#getProperties()} and environment variables.
-     *
+     * 
      * @return The system properties, never {@code null}.
      */
     Properties getSystemProperties();
@@ -124,7 +127,7 @@ public interface MavenExecutionRequest
      * Sets the user properties to use for interpolation and profile activation. The user properties have been
      * configured directly by the user on his discretion, e.g. via the {@code -Dkey=value} parameter on the command
      * line.
-     *
+     * 
      * @param userProperties The user properties, may be {@code null}.
      * @return This request, never {@code null}.
      */
@@ -134,165 +137,219 @@ public interface MavenExecutionRequest
      * Gets the user properties to use for interpolation and profile activation. The user properties have been
      * configured directly by the user on his discretion, e.g. via the {@code -Dkey=value} parameter on the command
      * line.
-     *
+     * 
      * @return The user properties, never {@code null}.
      */
     Properties getUserProperties();
 
     // Reactor
     MavenExecutionRequest setReactorFailureBehavior( String failureBehavior );
+
     String getReactorFailureBehavior();
 
     MavenExecutionRequest setSelectedProjects( List<String> projects );
+
     List<String> getSelectedProjects();
-    
+
     /**
-     * 
      * @param projects the projects to exclude
      * @return this MavenExecutionRequest
      * @since 3.2
      */
     MavenExecutionRequest setExcludedProjects( List<String> projects );
+
     /**
-     * 
      * @return the excluded projects, never {@code null}
      * @since 3.2
      */
     List<String> getExcludedProjects();
 
     MavenExecutionRequest setResumeFrom( String project );
+
     String getResumeFrom();
 
     MavenExecutionRequest setMakeBehavior( String makeBehavior );
+
     String getMakeBehavior();
 
-    void setThreadCount( String threadCount );
-    String getThreadCount();
-    boolean isThreadConfigurationPresent();
-    void setPerCoreThreadCount( boolean perCoreThreadCount );
-    boolean isPerCoreThreadCount();
+    /**
+     * Set's the parallel degree of concurrency used by the build.
+     * 
+     * @param degreeOfConcurrency
+     */
+    public void setDegreeOfConcurrency( final int degreeOfConcurrency );
+
+    /**
+     * @return the degree of concurrency for the build.
+     */
+    public int getDegreeOfConcurrency();
 
     // Recursive (really to just process the top-level POM)
     MavenExecutionRequest setRecursive( boolean recursive );
+
     boolean isRecursive();
 
     MavenExecutionRequest setPom( File pom );
+
     File getPom();
 
     // Errors
     MavenExecutionRequest setShowErrors( boolean showErrors );
+
     boolean isShowErrors();
 
     // Transfer listeners
     MavenExecutionRequest setTransferListener( TransferListener transferListener );
+
     TransferListener getTransferListener();
 
     // Logging
     MavenExecutionRequest setLoggingLevel( int loggingLevel );
+
     int getLoggingLevel();
 
     // Update snapshots
     MavenExecutionRequest setUpdateSnapshots( boolean updateSnapshots );
+
     boolean isUpdateSnapshots();
 
     MavenExecutionRequest setNoSnapshotUpdates( boolean noSnapshotUpdates );
+
     boolean isNoSnapshotUpdates();
 
     // Checksum policy
     MavenExecutionRequest setGlobalChecksumPolicy( String globalChecksumPolicy );
+
     String getGlobalChecksumPolicy();
 
     // Local repository
     MavenExecutionRequest setLocalRepositoryPath( String localRepository );
+
     MavenExecutionRequest setLocalRepositoryPath( File localRepository );
+
     File getLocalRepositoryPath();
+
     MavenExecutionRequest setLocalRepository( ArtifactRepository repository );
+
     ArtifactRepository getLocalRepository();
 
     // Interactive
     MavenExecutionRequest setInteractiveMode( boolean interactive );
+
     boolean isInteractiveMode();
 
     // Offline
     MavenExecutionRequest setOffline( boolean offline );
+
     boolean isOffline();
 
     boolean isCacheTransferError();
+
     MavenExecutionRequest setCacheTransferError( boolean cacheTransferError );
 
     boolean isCacheNotFound();
+
     MavenExecutionRequest setCacheNotFound( boolean cacheNotFound );
 
     // Profiles
     List<Profile> getProfiles();
+
     MavenExecutionRequest addProfile( Profile profile );
+
     MavenExecutionRequest setProfiles( List<Profile> profiles );
+
     MavenExecutionRequest addActiveProfile( String profile );
+
     MavenExecutionRequest addActiveProfiles( List<String> profiles );
+
     MavenExecutionRequest setActiveProfiles( List<String> profiles );
+
     List<String> getActiveProfiles();
+
     MavenExecutionRequest addInactiveProfile( String profile );
+
     MavenExecutionRequest addInactiveProfiles( List<String> profiles );
+
     MavenExecutionRequest setInactiveProfiles( List<String> profiles );
+
     List<String> getInactiveProfiles();
 
     // Proxies
     List<Proxy> getProxies();
+
     MavenExecutionRequest setProxies( List<Proxy> proxies );
+
     MavenExecutionRequest addProxy( Proxy proxy );
 
     // Servers
     List<Server> getServers();
+
     MavenExecutionRequest setServers( List<Server> servers );
+
     MavenExecutionRequest addServer( Server server );
 
     // Mirrors
     List<Mirror> getMirrors();
+
     MavenExecutionRequest setMirrors( List<Mirror> mirrors );
+
     MavenExecutionRequest addMirror( Mirror mirror );
 
     // Plugin groups
     List<String> getPluginGroups();
+
     MavenExecutionRequest setPluginGroups( List<String> pluginGroups );
+
     MavenExecutionRequest addPluginGroup( String pluginGroup );
+
     MavenExecutionRequest addPluginGroups( List<String> pluginGroups );
 
     boolean isProjectPresent();
+
     MavenExecutionRequest setProjectPresent( boolean isProjectPresent );
 
     File getUserSettingsFile();
+
     MavenExecutionRequest setUserSettingsFile( File userSettingsFile );
 
     File getGlobalSettingsFile();
+
     MavenExecutionRequest setGlobalSettingsFile( File globalSettingsFile );
 
     MavenExecutionRequest addRemoteRepository( ArtifactRepository repository );
+
     MavenExecutionRequest addPluginArtifactRepository( ArtifactRepository repository );
 
     /**
      * Set a new list of remote repositories to use the execution request. This is necessary if you perform
      * transformations on the remote repositories being used. For example if you replace existing repositories with
      * mirrors then it's easier to just replace the whole list with a new list of transformed repositories.
-     *
+     * 
      * @param repositories
      * @return This request, never {@code null}.
      */
     MavenExecutionRequest setRemoteRepositories( List<ArtifactRepository> repositories );
+
     List<ArtifactRepository> getRemoteRepositories();
 
     MavenExecutionRequest setPluginArtifactRepositories( List<ArtifactRepository> repositories );
+
     List<ArtifactRepository> getPluginArtifactRepositories();
 
     MavenExecutionRequest setRepositoryCache( RepositoryCache repositoryCache );
+
     RepositoryCache getRepositoryCache();
 
     WorkspaceReader getWorkspaceReader();
+
     MavenExecutionRequest setWorkspaceReader( WorkspaceReader workspaceReader );
 
     File getUserToolchainsFile();
+
     MavenExecutionRequest setUserToolchainsFile( File userToolchainsFile );
 
     ExecutionListener getExecutionListener();
+
     MavenExecutionRequest setExecutionListener( ExecutionListener executionListener );
 
     ProjectBuildingRequest getProjectBuildingRequest();
@@ -307,4 +364,18 @@ public interface MavenExecutionRequest
      */
     MavenExecutionRequest setUseLegacyLocalRepository( boolean useLegacyLocalRepository );
 
+    /**
+     * Controls the {@link Builder} used by Maven by specification of the builder's id.
+     * 
+     * @since 3.2.0
+     */
+    MavenExecutionRequest setBuilderId( String builderId );
+
+    /**
+     * Controls the {@link Builder} used by Maven by specification of the builders id.
+     * 
+     * @since 3.2.0
+     */
+    String getBuilderId();
+
 }

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionResult.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionResult.java b/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionResult.java
index dd04665..8adc7ac 100644
--- a/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionResult.java
+++ b/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionResult.java
@@ -67,5 +67,4 @@ public interface MavenExecutionResult
      * @param summary The build summary to add, must not be {@code null}.
      */
     void addBuildSummary( BuildSummary summary );
-
 }

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java b/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java
index 214aed8..93a1c7a 100644
--- a/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java
+++ b/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java
@@ -254,6 +254,7 @@ public class MavenSession
         return request.getBaseDirectory();
     }
 
+    @Deprecated
     public boolean isUsingPOMsFromFilesystem()
     {
         return request.isProjectPresent();

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/execution/ReactorManager.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/execution/ReactorManager.java b/maven-core/src/main/java/org/apache/maven/execution/ReactorManager.java
index 97d5857..bf089ab 100644
--- a/maven-core/src/main/java/org/apache/maven/execution/ReactorManager.java
+++ b/maven-core/src/main/java/org/apache/maven/execution/ReactorManager.java
@@ -176,11 +176,6 @@ public class ReactorManager
         return sorter.getSortedProjects();
     }
 
-    public MavenProject getTopLevelProject()
-    {
-        return sorter.getTopLevelProject();
-    }
-
     public boolean hasBuildSuccess( MavenProject project )
     {
         return buildSuccessesByProject.containsKey( getProjectKey( project ) );

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultSchedules.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultSchedules.java b/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultSchedules.java
index b8ab35e..d583cc3 100644
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultSchedules.java
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultSchedules.java
@@ -19,8 +19,8 @@ package org.apache.maven.lifecycle;
  * under the License.
  */
 
-import org.apache.maven.lifecycle.internal.BuilderCommon;
 import org.apache.maven.lifecycle.internal.ExecutionPlanItem;
+import org.apache.maven.lifecycle.internal.builder.BuilderCommon;
 import org.apache.maven.plugin.MojoExecution;
 import org.apache.maven.project.MavenProject;
 

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/lifecycle/internal/BuildListCalculator.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/BuildListCalculator.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/BuildListCalculator.java
index 9c3a294..771385c 100644
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/BuildListCalculator.java
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/BuildListCalculator.java
@@ -20,6 +20,7 @@ package org.apache.maven.lifecycle.internal;
  */
 
 import org.apache.maven.execution.MavenSession;
+import org.apache.maven.lifecycle.internal.builder.BuilderCommon;
 import org.apache.maven.project.MavenProject;
 import org.codehaus.plexus.component.annotations.Component;
 

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/lifecycle/internal/BuildThreadFactory.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/BuildThreadFactory.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/BuildThreadFactory.java
new file mode 100644
index 0000000..eb54418
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/BuildThreadFactory.java
@@ -0,0 +1,20 @@
+package org.apache.maven.lifecycle.internal;
+
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Simple {@link ThreadFactory} implementation that ensures the corresponding threads have a meaningful name.
+ */
+public class BuildThreadFactory
+    implements ThreadFactory
+{
+    private final AtomicInteger ID = new AtomicInteger();
+
+    private String PREFIX = "BuilderThread";
+
+    public Thread newThread( Runnable r )
+    {
+        return new Thread( r, String.format( "%s %d", PREFIX, ID.getAndIncrement() ) );
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleExecutionPlanCalculator.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleExecutionPlanCalculator.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleExecutionPlanCalculator.java
index 58a7a62..52cf960 100644
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleExecutionPlanCalculator.java
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleExecutionPlanCalculator.java
@@ -36,6 +36,7 @@ import org.apache.maven.lifecycle.Lifecycle;
 import org.apache.maven.lifecycle.LifecycleNotFoundException;
 import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
 import org.apache.maven.lifecycle.MavenExecutionPlan;
+import org.apache.maven.lifecycle.internal.builder.BuilderCommon;
 import org.apache.maven.model.Plugin;
 import org.apache.maven.model.PluginExecution;
 import org.apache.maven.plugin.BuildPluginManager;

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDebugLogger.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDebugLogger.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDebugLogger.java
index 25a1e7d..521753c 100644
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDebugLogger.java
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDebugLogger.java
@@ -22,6 +22,7 @@ package org.apache.maven.lifecycle.internal;
 import org.apache.maven.execution.MavenSession;
 import org.apache.maven.execution.ProjectDependencyGraph;
 import org.apache.maven.lifecycle.MavenExecutionPlan;
+import org.apache.maven.lifecycle.internal.builder.BuilderCommon;
 import org.apache.maven.plugin.MojoExecution;
 import org.apache.maven.plugin.descriptor.MojoDescriptor;
 import org.apache.maven.project.MavenProject;

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleModuleBuilder.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleModuleBuilder.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleModuleBuilder.java
index bf2bb21..2b4ba0e 100644
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleModuleBuilder.java
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleModuleBuilder.java
@@ -29,6 +29,7 @@ import org.apache.maven.execution.MavenSession;
 import org.apache.maven.execution.ProjectExecutionEvent;
 import org.apache.maven.execution.ProjectExecutionListener;
 import org.apache.maven.lifecycle.MavenExecutionPlan;
+import org.apache.maven.lifecycle.internal.builder.BuilderCommon;
 import org.apache.maven.plugin.MojoExecution;
 import org.apache.maven.project.MavenProject;
 import org.codehaus.plexus.component.annotations.Component;
@@ -111,8 +112,7 @@ public class LifecycleModuleBuilder
             projectExecutionListener.afterProjectExecutionSuccess( new ProjectExecutionEvent( session, currentProject,
                                                                                               mojoExecutions ) );
 
-            reactorContext.getResult().addBuildSummary(
-                new BuildSuccess( currentProject, buildEndTime - buildStartTime ) );
+            reactorContext.getResult().addBuildSummary( new BuildSuccess( currentProject, buildEndTime - buildStartTime ) );
 
             eventCatapult.fire( ExecutionEvent.Type.ProjectSucceeded, session, null );
         }
@@ -120,7 +120,8 @@ public class LifecycleModuleBuilder
         {
             builderCommon.handleBuildError( reactorContext, rootSession, session, currentProject, e, buildStartTime );
 
-            projectExecutionListener.afterProjectExecutionFailure( new ProjectExecutionEvent( session, currentProject, e ) );
+            projectExecutionListener.afterProjectExecutionFailure( new ProjectExecutionEvent( session, currentProject,
+                                                                                              e ) );
         }
         finally
         {

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleStarter.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleStarter.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleStarter.java
index f77ebd1..e33a0f1 100644
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleStarter.java
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleStarter.java
@@ -19,25 +19,24 @@ package org.apache.maven.lifecycle.internal;
  * under the License.
  */
 
+import java.util.List;
+import java.util.Map;
+
 import org.apache.maven.execution.ExecutionEvent;
-import org.apache.maven.execution.MavenExecutionRequest;
 import org.apache.maven.execution.MavenExecutionResult;
 import org.apache.maven.execution.MavenSession;
 import org.apache.maven.lifecycle.DefaultLifecycles;
 import org.apache.maven.lifecycle.MissingProjectException;
 import org.apache.maven.lifecycle.NoGoalSpecifiedException;
+import org.apache.maven.lifecycle.internal.builder.Builder;
+import org.apache.maven.lifecycle.internal.builder.BuilderNotFoundException;
 import org.codehaus.plexus.component.annotations.Component;
 import org.codehaus.plexus.component.annotations.Requirement;
 import org.codehaus.plexus.logging.Logger;
 
-import java.util.List;
-import java.util.concurrent.CompletionService;
-import java.util.concurrent.ExecutorCompletionService;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.TimeUnit;
-
 /**
  * Starts the build life cycle
+ * 
  * @author Jason van Zyl
  * @author Benjamin Bentmann
  * @author Kristian Rosenvold
@@ -45,7 +44,6 @@ import java.util.concurrent.TimeUnit;
 @Component( role = LifecycleStarter.class )
 public class LifecycleStarter
 {
-
     @Requirement
     private ExecutionEventCatapult eventCatapult;
 
@@ -56,15 +54,6 @@ public class LifecycleStarter
     private Logger logger;
 
     @Requirement
-    private LifecycleModuleBuilder lifecycleModuleBuilder;
-
-    @Requirement
-    private LifecycleWeaveBuilder lifeCycleWeaveBuilder;
-
-    @Requirement
-    private LifecycleThreadedBuilder lifecycleThreadedBuilder;
-
-    @Requirement
     private BuildListCalculator buildListCalculator;
 
     @Requirement
@@ -74,30 +63,27 @@ public class LifecycleStarter
     private LifecycleTaskSegmentCalculator lifecycleTaskSegmentCalculator;
 
     @Requirement
-    private ThreadConfigurationService threadConfigService;
+    private Map<String, Builder> builders;
 
     public void execute( MavenSession session )
     {
         eventCatapult.fire( ExecutionEvent.Type.SessionStarted, session, null );
 
+        ReactorContext reactorContext = null;
+        ProjectBuildList projectBuilds = null;
         MavenExecutionResult result = session.getResult();
 
         try
         {
-            if ( !session.isUsingPOMsFromFilesystem() && lifecycleTaskSegmentCalculator.requiresProject( session ) )
+            if ( buildExecutionRequiresProject( session ) && projectIsNotPresent( session ) )
             {
                 throw new MissingProjectException( "The goal you specified requires a project to execute"
                     + " but there is no POM in this directory (" + session.getExecutionRootDirectory() + ")."
                     + " Please verify you invoked Maven from the correct directory." );
             }
 
-            final MavenExecutionRequest executionRequest = session.getRequest();
-            boolean isThreaded = executionRequest.isThreadConfigurationPresent();
-            session.setParallel( isThreaded );
-
             List<TaskSegment> taskSegments = lifecycleTaskSegmentCalculator.calculateTaskSegments( session );
-
-            ProjectBuildList projectBuilds = buildListCalculator.calculateProjectBuilds( session, taskSegments );
+            projectBuilds = buildListCalculator.calculateProjectBuilds( session, taskSegments );
 
             if ( projectBuilds.isEmpty() )
             {
@@ -115,52 +101,20 @@ public class LifecycleStarter
             }
 
             ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
-
             ReactorBuildStatus reactorBuildStatus = new ReactorBuildStatus( session.getProjectDependencyGraph() );
-            ReactorContext callableContext =
-                new ReactorContext( result, projectIndex, oldContextClassLoader, reactorBuildStatus );
+            reactorContext = new ReactorContext( result, projectIndex, oldContextClassLoader, reactorBuildStatus );
 
-            if ( isThreaded )
-            {
-                ExecutorService executor =
-                    threadConfigService.getExecutorService( executionRequest.getThreadCount(),
-                                                            executionRequest.isPerCoreThreadCount(),
-                                                            session.getProjects().size() );
-                try
-                {
-
-                    final boolean isWeaveMode = LifecycleWeaveBuilder.isWeaveMode( executionRequest );
-                    if ( isWeaveMode )
-                    {
-                        lifecycleDebugLogger.logWeavePlan( session );
-                        lifeCycleWeaveBuilder.build( projectBuilds, callableContext, taskSegments, session, executor,
-                                                     reactorBuildStatus );
-                    }
-                    else
-                    {
-                        ConcurrencyDependencyGraph analyzer =
-                            new ConcurrencyDependencyGraph( projectBuilds, session.getProjectDependencyGraph() );
-
-                        CompletionService<ProjectSegment> service =
-                            new ExecutorCompletionService<ProjectSegment>( executor );
-
-                        lifecycleThreadedBuilder.build( session, callableContext, projectBuilds, taskSegments, analyzer,
-                                                        service );
-                    }
-                }
-                finally
-                {
-                    executor.shutdown();
-                    // If the builder has terminated with an exception we want to catch any stray threads before going
-                    // to System.exit in the mavencli.
-                    executor.awaitTermination( 5, TimeUnit.SECONDS ) ;
-                }
-            }
-            else
+            String builderId = session.getRequest().getBuilderId();
+            Builder builder = builders.get( builderId );
+            if ( builder == null )
             {
-                singleThreadedBuild( session, callableContext, projectBuilds, taskSegments, reactorBuildStatus );
+                throw new BuilderNotFoundException( String.format( "The builder requested using id = %s cannot be found", builderId ) );
             }
 
+            logger.info( "" );
+            logger.info( String.format( "Using the builder %s", builder.getClass().getName() ) );
+            builder.build( session, reactorContext, projectBuilds, taskSegments, reactorBuildStatus );
+
         }
         catch ( Exception e )
         {
@@ -170,29 +124,13 @@ public class LifecycleStarter
         eventCatapult.fire( ExecutionEvent.Type.SessionEnded, session, null );
     }
 
-    private void singleThreadedBuild( MavenSession session, ReactorContext callableContext,
-                                      ProjectBuildList projectBuilds, List<TaskSegment> taskSegments,
-                                      ReactorBuildStatus reactorBuildStatus )
+    private boolean buildExecutionRequiresProject( MavenSession session )
     {
-        for ( TaskSegment taskSegment : taskSegments )
-        {
-            for ( ProjectSegment projectBuild : projectBuilds.getByTaskSegment( taskSegment ) )
-            {
-                try
-                {
-                    lifecycleModuleBuilder.buildProject( session, callableContext, projectBuild.getProject(),
-                                                         taskSegment );
-                    if ( reactorBuildStatus.isHalted() )
-                    {
-                        break;
-                    }
-                }
-                catch ( Exception e )
-                {
-                    break;  // Why are we just ignoring this exception? Are exceptions are being used for flow control
-                }
+        return lifecycleTaskSegmentCalculator.requiresProject( session );
+    }
 
-            }
-        }
+    private boolean projectIsNotPresent( MavenSession session )
+    {
+        return !session.getRequest().isProjectPresent();
     }
 }

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ProjectBuildList.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ProjectBuildList.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ProjectBuildList.java
index 011e5cd..acea697 100644
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ProjectBuildList.java
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ProjectBuildList.java
@@ -141,4 +141,16 @@ public class ProjectBuildList
     {
         return items.isEmpty();
     }
+
+    /**
+     * @return a set of all the projects managed by the build
+     */
+	public Set<MavenProject> getProjects() {
+		Set<MavenProject> projects = new HashSet<MavenProject>();
+		
+		for (ProjectSegment s : items) {
+			projects.add(s.getProject());
+		}
+		return projects;
+	}
 }

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ProjectIndex.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ProjectIndex.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ProjectIndex.java
index 254e868..3f78baf 100644
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ProjectIndex.java
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ProjectIndex.java
@@ -19,6 +19,7 @@ package org.apache.maven.lifecycle.internal;
  * under the License.
  */
 
+import org.apache.maven.lifecycle.internal.builder.BuilderCommon;
 import org.apache.maven.project.MavenProject;
 
 import java.util.HashMap;

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ReactorBuildStatus.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ReactorBuildStatus.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ReactorBuildStatus.java
index b4e13a4..eff4e92 100644
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ReactorBuildStatus.java
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ReactorBuildStatus.java
@@ -20,6 +20,7 @@ package org.apache.maven.lifecycle.internal;
  */
 
 import org.apache.maven.execution.ProjectDependencyGraph;
+import org.apache.maven.lifecycle.internal.builder.BuilderCommon;
 import org.apache.maven.project.MavenProject;
 
 import java.util.Collection;

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/Builder.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/Builder.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/Builder.java
new file mode 100644
index 0000000..d3a0440
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/Builder.java
@@ -0,0 +1,28 @@
+package org.apache.maven.lifecycle.internal.builder;
+
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.lifecycle.internal.ProjectBuildList;
+import org.apache.maven.lifecycle.internal.ReactorBuildStatus;
+import org.apache.maven.lifecycle.internal.ReactorContext;
+import org.apache.maven.lifecycle.internal.TaskSegment;
+
+/**
+ * This is provisional API and is very likely to change in the near future. If you implement a builder expect it to
+ * change. 
+ * 
+ * @author jvanzyl
+ *
+ */
+public interface Builder
+{
+    //
+    // Be nice to whittle this down to Session, maybe add task segments to the session. The session really is the 
+    // the place to store reactor related information.
+    //
+    public void build( MavenSession session, ReactorContext reactorContext, ProjectBuildList projectBuilds,
+                       List<TaskSegment> taskSegments, ReactorBuildStatus reactorBuildStatus )
+        throws ExecutionException, InterruptedException;
+} 

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/BuilderCommon.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/BuilderCommon.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/BuilderCommon.java
new file mode 100644
index 0000000..8110902
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/BuilderCommon.java
@@ -0,0 +1,195 @@
+package org.apache.maven.lifecycle.internal.builder;
+
+/*
+ * 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.InternalErrorException;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.execution.BuildFailure;
+import org.apache.maven.execution.ExecutionEvent;
+import org.apache.maven.execution.MavenExecutionRequest;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.lifecycle.LifecycleExecutionException;
+import org.apache.maven.lifecycle.LifecycleNotFoundException;
+import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
+import org.apache.maven.lifecycle.MavenExecutionPlan;
+import org.apache.maven.lifecycle.internal.ExecutionEventCatapult;
+import org.apache.maven.lifecycle.internal.LifecycleDebugLogger;
+import org.apache.maven.lifecycle.internal.LifecycleExecutionPlanCalculator;
+import org.apache.maven.lifecycle.internal.ReactorContext;
+import org.apache.maven.lifecycle.internal.TaskSegment;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.plugin.InvalidPluginDescriptorException;
+import org.apache.maven.plugin.MojoNotFoundException;
+import org.apache.maven.plugin.PluginDescriptorParsingException;
+import org.apache.maven.plugin.PluginNotFoundException;
+import org.apache.maven.plugin.PluginResolutionException;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
+import org.apache.maven.plugin.version.PluginVersionResolutionException;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.classworlds.realm.ClassRealm;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+import org.codehaus.plexus.logging.Logger;
+
+import java.util.Set;
+
+/**
+ * Common code that is shared by the LifecycleModuleBuilder and the LifeCycleWeaveBuilder
+ *
+ * @since 3.0
+ * @author Kristian Rosenvold
+ *         Builds one or more lifecycles for a full module
+ *         NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
+ */
+@Component( role = BuilderCommon.class )
+public class BuilderCommon
+{
+    @Requirement
+    private LifecycleDebugLogger lifecycleDebugLogger;
+
+    @Requirement
+    private LifecycleExecutionPlanCalculator lifeCycleExecutionPlanCalculator;
+
+    @Requirement
+    private ExecutionEventCatapult eventCatapult;
+
+    @Requirement
+    private Logger logger;
+
+
+    public BuilderCommon()
+    {
+    }
+
+    public BuilderCommon( LifecycleDebugLogger lifecycleDebugLogger,
+                          LifecycleExecutionPlanCalculator lifeCycleExecutionPlanCalculator, Logger logger )
+    {
+        this.lifecycleDebugLogger = lifecycleDebugLogger;
+        this.lifeCycleExecutionPlanCalculator = lifeCycleExecutionPlanCalculator;
+        this.logger = logger;
+    }
+
+    public MavenExecutionPlan resolveBuildPlan( MavenSession session, MavenProject project, TaskSegment taskSegment,
+                                                Set<Artifact> projectArtifacts )
+        throws PluginNotFoundException, PluginResolutionException, LifecyclePhaseNotFoundException,
+        PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException,
+        NoPluginFoundForPrefixException, LifecycleNotFoundException, PluginVersionResolutionException,
+        LifecycleExecutionException
+    {
+        MavenExecutionPlan executionPlan =
+            lifeCycleExecutionPlanCalculator.calculateExecutionPlan( session, project, taskSegment.getTasks() );
+
+        lifecycleDebugLogger.debugProjectPlan( project, executionPlan );
+
+        if ( session.getRequest().getDegreeOfConcurrency() > 1 )
+        {
+            final Set<Plugin> unsafePlugins = executionPlan.getNonThreadSafePlugins();
+            if ( !unsafePlugins.isEmpty()  && logger.isDebugEnabled() )
+            {
+                logger.warn( "*****************************************************************" );
+                logger.warn( "* Your build is requesting parallel execution, but project      *" );
+                logger.warn( "* contains the following plugin(s) that have goals not marked   *" );
+                logger.warn( "* as @threadSafe to support parallel building.                  *" );
+                logger.warn( "* While this /may/ work fine, please look for plugin updates    *" );
+                logger.warn( "* and/or request plugins be made thread-safe.                   *" );
+                logger.warn( "* If reporting an issue, report it against the plugin in        *" );
+                logger.warn( "* question, not against maven-core                              *" );
+                logger.warn( "*****************************************************************" );
+                if ( logger.isDebugEnabled() )
+                {
+                    final Set<MojoDescriptor> unsafeGoals = executionPlan.getNonThreadSafeMojos();
+                    logger.warn( "The following goals are not marked @threadSafe in " + project.getName() + ":" );
+                    for ( MojoDescriptor unsafeGoal : unsafeGoals )
+                    {
+                        logger.warn( unsafeGoal.getId() );
+                    }
+                }
+                else
+                {
+                    logger.warn( "The following plugins are not marked @threadSafe in " + project.getName() + ":" );
+                    for ( Plugin unsafePlugin : unsafePlugins )
+                    {
+                        logger.warn( unsafePlugin.getId() );
+                    }
+                    logger.warn( "Enable debug to see more precisely which goals are not marked @threadSafe." );
+                }
+                logger.warn( "*****************************************************************" );
+            }
+        }
+
+        return executionPlan;
+    }
+
+    public void handleBuildError( final ReactorContext buildContext, final MavenSession rootSession,
+                                  final MavenSession currentSession, final MavenProject mavenProject, Exception e,
+                                  final long buildStartTime )
+    {
+        if ( e instanceof RuntimeException )
+        {
+            e = new InternalErrorException( "Internal error: " + e, e );
+        }
+
+        buildContext.getResult().addException( e );
+
+        long buildEndTime = System.currentTimeMillis();
+
+        buildContext.getResult().addBuildSummary( new BuildFailure( mavenProject, buildEndTime - buildStartTime, e ) );
+
+        eventCatapult.fire( ExecutionEvent.Type.ProjectFailed, currentSession, null, e );
+
+        if ( MavenExecutionRequest.REACTOR_FAIL_NEVER.equals( rootSession.getReactorFailureBehavior() ) )
+        {
+            // continue the build
+        }
+        else if ( MavenExecutionRequest.REACTOR_FAIL_AT_END.equals( rootSession.getReactorFailureBehavior() ) )
+        {
+            // continue the build but ban all projects that depend on the failed one
+            buildContext.getReactorBuildStatus().blackList( mavenProject );
+        }
+        else if ( MavenExecutionRequest.REACTOR_FAIL_FAST.equals( rootSession.getReactorFailureBehavior() ) )
+        {
+            buildContext.getReactorBuildStatus().halt();
+        }
+        else
+        {
+            throw new IllegalArgumentException(
+                "invalid reactor failure behavior " + rootSession.getReactorFailureBehavior() );
+        }
+    }
+
+    public static void attachToThread( MavenProject currentProject )
+    {
+        ClassRealm projectRealm = currentProject.getClassRealm();
+        if ( projectRealm != null )
+        {
+            Thread.currentThread().setContextClassLoader( projectRealm );
+        }
+    }
+
+    // Todo: I'm really wondering where this method belongs; smells like it should be on MavenProject, but for some reason
+    // it isn't ? This localization is kind-of a code smell.
+
+    public static String getKey( MavenProject project )
+    {
+        return project.getGroupId() + ':' + project.getArtifactId() + ':' + project.getVersion();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/BuilderNotFoundException.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/BuilderNotFoundException.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/BuilderNotFoundException.java
new file mode 100644
index 0000000..a90c0d4
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/BuilderNotFoundException.java
@@ -0,0 +1,9 @@
+package org.apache.maven.lifecycle.internal.builder;
+
+public class BuilderNotFoundException extends Exception 
+{
+    public BuilderNotFoundException(String message) 
+    {
+        super(message);
+    }  
+}

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/ConcurrencyDependencyGraph.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/ConcurrencyDependencyGraph.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/ConcurrencyDependencyGraph.java
new file mode 100644
index 0000000..53be344
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/ConcurrencyDependencyGraph.java
@@ -0,0 +1,153 @@
+package org.apache.maven.lifecycle.internal.builder.multithreaded;
+
+/*
+ * 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.ProjectDependencyGraph;
+import org.apache.maven.lifecycle.internal.ProjectBuildList;
+import org.apache.maven.lifecycle.internal.ProjectSegment;
+import org.apache.maven.project.MavenProject;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Presents a view of the Dependency Graph that is suited for concurrent building.
+ * 
+ * @since 3.0
+ * @author Kristian Rosenvold
+ *         <p/>
+ *         NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
+ */
+public class ConcurrencyDependencyGraph
+{
+
+    private final ProjectBuildList projectBuilds;
+
+    private final ProjectDependencyGraph projectDependencyGraph;
+
+    private final HashSet<MavenProject> finishedProjects = new HashSet<MavenProject>();
+
+    public ConcurrencyDependencyGraph( ProjectBuildList projectBuilds, ProjectDependencyGraph projectDependencyGraph )
+    {
+        this.projectDependencyGraph = projectDependencyGraph;
+        this.projectBuilds = projectBuilds;
+    }
+
+    public int getNumberOfBuilds()
+    {
+        return projectBuilds.size();
+    }
+
+    /**
+     * Gets all the builds that have no reactor-dependencies
+     * 
+     * @return A list of all the initial builds
+     */
+
+    public List<MavenProject> getRootSchedulableBuilds()
+    {
+        List<MavenProject> result = new ArrayList<MavenProject>();
+        for ( ProjectSegment projectBuild : projectBuilds )
+        {
+            if ( projectDependencyGraph.getUpstreamProjects( projectBuild.getProject(), false ).size() == 0 )
+            {
+                result.add( projectBuild.getProject() );
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Marks the provided project as finished. Returns a list of
+     * 
+     * @param mavenProject The project
+     * @return The list of builds that are eligible for starting now that the provided project is done
+     */
+    public List<MavenProject> markAsFinished( MavenProject mavenProject )
+    {
+        finishedProjects.add( mavenProject );
+        return getSchedulableNewProcesses( mavenProject );
+    }
+
+    private List<MavenProject> getSchedulableNewProcesses( MavenProject finishedProject )
+    {
+        List<MavenProject> result = new ArrayList<MavenProject>();
+        // schedule dependent projects, if all of their requirements are met
+        for ( MavenProject dependentProject : projectDependencyGraph.getDownstreamProjects( finishedProject, false ) )
+        {
+            final List<MavenProject> upstreamProjects =
+                projectDependencyGraph.getUpstreamProjects( dependentProject, false );
+            if ( finishedProjects.containsAll( upstreamProjects ) )
+            {
+                result.add( dependentProject );
+            }
+        }
+        return result;
+    }
+
+    /**
+     * @return set of projects that have yet to be processed successfully by the build.
+     */
+    public Set<MavenProject> getUnfinishedProjects()
+    {
+        Set<MavenProject> unfinished = new HashSet<MavenProject>( projectBuilds.getProjects() );
+        unfinished.remove( finishedProjects );
+        return unfinished;
+    }
+
+    /**
+     * @return set of projects that have been successfully processed by the build.
+     */
+    protected Set<MavenProject> getFinishedProjects()
+    {
+        return finishedProjects;
+    }
+
+    protected ProjectBuildList getProjectBuilds()
+    {
+        return projectBuilds;
+    }
+
+    /**
+     * For the given {@link MavenProject} {@code p}, return all of {@code p}'s dependencies.
+     * 
+     * @param p
+     * @return List of prerequisite projects
+     */
+    protected List<MavenProject> getDependencies( MavenProject p )
+    {
+        return projectDependencyGraph.getUpstreamProjects( p, false );
+    }
+
+    /**
+     * For the given {@link MavenProject} {@code p} return {@code p}'s uncompleted dependencies.
+     * 
+     * @param p
+     * @return List of uncompleted prerequisite projects
+     */
+    public List<MavenProject> getActiveDependencies( MavenProject p )
+    {
+        List<MavenProject> activeDependencies = projectDependencyGraph.getUpstreamProjects( p, false );
+        activeDependencies.removeAll( finishedProjects );
+        return activeDependencies;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/MultiThreadedBuilder.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/MultiThreadedBuilder.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/MultiThreadedBuilder.java
new file mode 100644
index 0000000..b89aa0e
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/MultiThreadedBuilder.java
@@ -0,0 +1,193 @@
+package org.apache.maven.lifecycle.internal.builder.multithreaded;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CompletionService;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorCompletionService;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.lifecycle.internal.BuildThreadFactory;
+import org.apache.maven.lifecycle.internal.LifecycleModuleBuilder;
+import org.apache.maven.lifecycle.internal.ProjectBuildList;
+import org.apache.maven.lifecycle.internal.ProjectSegment;
+import org.apache.maven.lifecycle.internal.ReactorBuildStatus;
+import org.apache.maven.lifecycle.internal.ReactorContext;
+import org.apache.maven.lifecycle.internal.TaskSegment;
+import org.apache.maven.lifecycle.internal.ThreadOutputMuxer;
+import org.apache.maven.lifecycle.internal.builder.Builder;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+import org.codehaus.plexus.logging.Logger;
+
+/**
+ * Builds the full lifecycle in weave-mode (phase by phase as opposed to project-by-project)
+ * 
+ * @since 3.0
+ * @author Kristian Rosenvold
+ *         Builds one or more lifecycles for a full module
+ *         <p/>
+ *         NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
+ */
+@Component( role = Builder.class, hint = "multithreaded" )
+public class MultiThreadedBuilder implements Builder
+{
+
+    @Requirement
+    private Logger logger;
+
+    @Requirement
+    private LifecycleModuleBuilder lifecycleModuleBuilder;
+
+
+    public MultiThreadedBuilder()
+    {
+    }
+
+    @Override
+    public void build( MavenSession session, ReactorContext reactorContext, ProjectBuildList projectBuilds,
+                       List<TaskSegment> taskSegments, ReactorBuildStatus reactorBuildStatus )
+        throws ExecutionException, InterruptedException
+    {
+        ExecutorService executor = Executors.newFixedThreadPool(Math.min(session.getRequest().getDegreeOfConcurrency(), session.getProjects().size()), new BuildThreadFactory());
+        CompletionService<ProjectSegment> service = new ExecutorCompletionService<ProjectSegment>(executor);
+        ConcurrencyDependencyGraph analyzer = new ConcurrencyDependencyGraph(projectBuilds, session.getProjectDependencyGraph());
+        
+        // Currently disabled
+        ThreadOutputMuxer muxer = null; // new ThreadOutputMuxer( analyzer.getProjectBuilds(), System.out );
+
+        for ( TaskSegment taskSegment : taskSegments )
+        {
+            Map<MavenProject, ProjectSegment> projectBuildMap = projectBuilds.selectSegment( taskSegment );
+            try
+            {
+                multiThreadedProjectTaskSegmentBuild( analyzer, reactorContext, session, service, taskSegment,
+                                                      projectBuildMap, muxer );
+                if ( reactorContext.getReactorBuildStatus().isHalted() )
+                {
+                    break;
+                }
+            }
+            catch ( Exception e )
+            {
+                session.getResult().addException( e );
+                break;
+            }
+
+        }
+    }
+
+    private void multiThreadedProjectTaskSegmentBuild( ConcurrencyDependencyGraph analyzer,
+                                                       ReactorContext reactorContext, MavenSession rootSession,
+                                                       CompletionService<ProjectSegment> service,
+                                                       TaskSegment taskSegment,
+                                                       Map<MavenProject, ProjectSegment> projectBuildList,
+                                                       ThreadOutputMuxer muxer )
+    {
+
+        // schedule independent projects
+        for ( MavenProject mavenProject : analyzer.getRootSchedulableBuilds() )
+        {
+            ProjectSegment projectSegment = projectBuildList.get( mavenProject );
+            logger.debug( "Scheduling: " + projectSegment.getProject() );
+            Callable<ProjectSegment> cb =
+                createBuildCallable( rootSession, projectSegment, reactorContext, taskSegment, muxer );
+            service.submit( cb );
+        }
+
+        // for each finished project
+        for ( int i = 0; i < analyzer.getNumberOfBuilds(); i++ )
+        {
+            try
+            {
+                ProjectSegment projectBuild = service.take().get();
+                if ( reactorContext.getReactorBuildStatus().isHalted() )
+                {
+                    break;
+                }
+                final List<MavenProject> newItemsThatCanBeBuilt =
+                    analyzer.markAsFinished( projectBuild.getProject() );
+                for ( MavenProject mavenProject : newItemsThatCanBeBuilt )
+                {
+                    ProjectSegment scheduledDependent = projectBuildList.get( mavenProject );
+                    logger.debug( "Scheduling: " + scheduledDependent );
+                    Callable<ProjectSegment> cb =
+                        createBuildCallable( rootSession, scheduledDependent, reactorContext, taskSegment, muxer );
+                    service.submit( cb );
+                }
+            }
+            catch ( InterruptedException e )
+            {
+                rootSession.getResult().addException( e );
+                break;
+            }
+            catch ( ExecutionException e )
+            {
+                rootSession.getResult().addException( e );
+                break;
+            }
+        }
+
+        // cancel outstanding builds (if any)  - this can happen if an exception is thrown in above block
+
+        Future<ProjectSegment> unprocessed;
+        while ( ( unprocessed = service.poll() ) != null )
+        {
+            try
+            {
+                unprocessed.get();
+            }
+            catch ( InterruptedException e )
+            {
+                throw new RuntimeException( e );
+            }
+            catch ( ExecutionException e )
+            {
+                throw new RuntimeException( e );
+            }
+        }
+    }
+
+    private Callable<ProjectSegment> createBuildCallable( final MavenSession rootSession,
+                                                          final ProjectSegment projectBuild,
+                                                          final ReactorContext reactorContext,
+                                                          final TaskSegment taskSegment, final ThreadOutputMuxer muxer )
+    {
+        return new Callable<ProjectSegment>()
+        {
+            public ProjectSegment call()
+            {
+                // muxer.associateThreadWithProjectSegment( projectBuild );
+                lifecycleModuleBuilder.buildProject( projectBuild.getSession(), rootSession, reactorContext,
+                                                     projectBuild.getProject(), taskSegment );
+                // muxer.setThisModuleComplete( projectBuild );
+
+                return projectBuild;
+            }
+        };
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/singlethreaded/SingleThreadedBuilder.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/singlethreaded/SingleThreadedBuilder.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/singlethreaded/SingleThreadedBuilder.java
new file mode 100644
index 0000000..a6c9d03
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/singlethreaded/SingleThreadedBuilder.java
@@ -0,0 +1,46 @@
+package org.apache.maven.lifecycle.internal.builder.singlethreaded;
+
+import java.util.List;
+
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.lifecycle.internal.LifecycleModuleBuilder;
+import org.apache.maven.lifecycle.internal.ProjectBuildList;
+import org.apache.maven.lifecycle.internal.ProjectSegment;
+import org.apache.maven.lifecycle.internal.ReactorBuildStatus;
+import org.apache.maven.lifecycle.internal.ReactorContext;
+import org.apache.maven.lifecycle.internal.TaskSegment;
+import org.apache.maven.lifecycle.internal.builder.Builder;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+
+@Component( role = Builder.class, hint = "singlethreaded" )
+public class SingleThreadedBuilder
+    implements Builder
+{
+    @Requirement
+    private LifecycleModuleBuilder lifecycleModuleBuilder;
+
+    public void build( MavenSession session, ReactorContext reactorContext, ProjectBuildList projectBuilds,
+                       List<TaskSegment> taskSegments, ReactorBuildStatus reactorBuildStatus )
+    {
+        for ( TaskSegment taskSegment : taskSegments )
+        {
+            for ( ProjectSegment projectBuild : projectBuilds.getByTaskSegment( taskSegment ) )
+            {
+                try
+                {
+                    lifecycleModuleBuilder.buildProject( session, reactorContext, projectBuild.getProject(),
+                                                         taskSegment );
+                    if ( reactorBuildStatus.isHalted() )
+                    {
+                        break;
+                    }
+                }
+                catch ( Exception e )
+                {
+                    break; // Why are we just ignoring this exception? Are exceptions are being used for flow control
+                }
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/weave/BuildLogItem.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/weave/BuildLogItem.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/weave/BuildLogItem.java
new file mode 100644
index 0000000..9b5b321
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/weave/BuildLogItem.java
@@ -0,0 +1,221 @@
+package org.apache.maven.lifecycle.internal.builder.weave;
+
+/*
+ * 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.lifecycle.internal.ExecutionPlanItem;
+import org.apache.maven.project.MavenProject;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @since 3.0
+ * @author Kristian Rosenvold
+ *         NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
+ */
+public class BuildLogItem
+{
+    private final ExecutionPlanItem executionPlanItem;
+
+    private final MavenProject project;
+
+    private final long startTime;
+
+    private long endTime;
+
+    private final List<DependencyLogEntry> dependencies =
+        Collections.synchronizedList( new ArrayList<DependencyLogEntry>() );
+
+    public BuildLogItem( MavenProject project, ExecutionPlanItem executionPlanItem )
+    {
+        this.executionPlanItem = executionPlanItem;
+        this.project = project;
+        startTime = System.currentTimeMillis();
+
+    }
+
+
+    public MavenProject getProject()
+    {
+        return project;
+    }
+
+    public void setComplete()
+    {
+        endTime = System.currentTimeMillis();
+    }
+
+    public void addWait( MavenProject upstreamProject, ExecutionPlanItem inSchedule, long startWait )
+    {
+        long now = System.currentTimeMillis();
+        dependencies.add( new DependencyLogEntry( upstreamProject, inSchedule, startWait, now, null ) );
+    }
+
+    public void addDependency( MavenProject upstreamProject, String message )
+    {
+        dependencies.add( new DependencyLogEntry( upstreamProject, message ) );
+    }
+
+    public String toString( long rootStart )
+    {
+        StringBuilder result = new StringBuilder();
+        result.append( String.format( "%1d  %2d ", startTime - rootStart, endTime - rootStart ) );
+        result.append( project.getName() );
+        result.append( " " );
+        result.append( getMojoExecutionDescription( executionPlanItem ) );
+        if ( dependencies.size() > 0 )
+        {
+            result.append( "\n" );
+            for ( DependencyLogEntry waitLogEntry : dependencies )
+            {
+                result.append( "    " );
+                result.append( waitLogEntry.toString() );
+                result.append( "\n" );
+            }
+        }
+        return result.toString();
+    }
+
+
+    public Object toGraph( long rootStart )
+    {
+        StringBuilder result = new StringBuilder();
+        if ( dependencies.size() > 0 )
+        {
+            for ( DependencyLogEntry waitLogEntry : dependencies )
+            {
+                result.append( "        " );
+                result.append( nodeKey( project, executionPlanItem ) );
+                result.append( " ->   " );
+                result.append( waitLogEntry.toNodeKey() );
+                result.append( waitLogEntry.toNodeDescription( rootStart ) );
+                result.append( "\n" );
+            }
+        }
+        else
+        {
+            result.append( "        " );
+            result.append( nodeKey( project, executionPlanItem ) );
+            result.append( "\n" );
+        }
+        return result.toString();
+    }
+
+    private static String nodeKey( MavenProject mavenProject, ExecutionPlanItem executionPlanItem )
+    {
+        String key = mavenProject.getArtifactId();
+        if ( executionPlanItem != null )
+        {
+            key += "_" + getMojoExecutionDescription( executionPlanItem );
+        }
+        return key.replace( ".", "_" ).replace( ":", "_" );
+    }
+
+    private static String getMojoExecutionDescription( ExecutionPlanItem executionPlanItem )
+    {
+        if ( executionPlanItem.getMojoExecution() != null )
+        {
+            return executionPlanItem.getMojoExecution().getArtifactId() + getLifeCyclePhase( executionPlanItem );
+        }
+        else
+        {
+            return "";
+        }
+    }
+
+    private static String getLifeCyclePhase( ExecutionPlanItem executionPlanItem )
+    {
+        return executionPlanItem.getLifecyclePhase() != null ? "[" + executionPlanItem.getLifecyclePhase() + "]" : "";
+    }
+
+
+    class DependencyLogEntry
+    {
+        private final ExecutionPlanItem executionPlanItem;
+
+        private final MavenProject upstreamProject;
+
+        private final Long start;
+
+        private final Long stop;
+
+        private final String message;
+
+        DependencyLogEntry( MavenProject upstreamProject, ExecutionPlanItem executionPlanItem, Long start, Long stop,
+                            String message )
+        {
+            this.upstreamProject = upstreamProject;
+            this.executionPlanItem = executionPlanItem;
+            this.start = start;
+            this.stop = stop;
+            this.message = message;
+        }
+
+        DependencyLogEntry( MavenProject upstreamProject, String message )
+        {
+            this( upstreamProject, null, null, null, message );
+        }
+
+        public String toString()
+        {
+            return upstreamProject.getName() + ":" + getExecutionPlanItem() + getElapsed() + getMessage();
+        }
+
+        public String toNodeKey()
+        {
+            return nodeKey( upstreamProject, executionPlanItem );
+        }
+
+        public String toNodeDescription( long rootStart )
+        {
+            return "";
+        }
+
+
+        private String getMessage()
+        {
+            return message != null ? message : "";
+        }
+
+        private String getExecutionPlanItem()
+        {
+            if ( executionPlanItem != null )
+            {
+                return getMojoExecutionDescription( executionPlanItem );
+            }
+            else
+            {
+                return "";
+            }
+        }
+
+        private String getElapsed()
+        {
+            if ( start != null && stop != null )
+            {
+                long elapsed = stop - start;
+                return elapsed > 0 ? ", wait=" + elapsed : "";
+            }
+            return "";
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/weave/ConcurrentBuildLogger.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/weave/ConcurrentBuildLogger.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/weave/ConcurrentBuildLogger.java
new file mode 100644
index 0000000..2dcd348
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/weave/ConcurrentBuildLogger.java
@@ -0,0 +1,124 @@
+package org.apache.maven.lifecycle.internal.builder.weave;
+
+/*
+ * 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.lifecycle.internal.ExecutionPlanItem;
+import org.apache.maven.project.MavenProject;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Handles all concurrency-related logging.
+ * <p/>
+ * The logging/diagnostic needs of a concurrent build are different from a linear build. This
+ * delta required to analyze a concurrent build is located here.
+ * <p/>
+ * NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
+ * 
+ * @since 3.0
+ * @author Kristian Rosenvold
+ */
+public class ConcurrentBuildLogger
+{
+    private final long startTime;
+
+    private final Map<MavenProject, Thread> threadMap = new ConcurrentHashMap<MavenProject, Thread>();
+
+    public ConcurrentBuildLogger()
+    {
+        startTime = System.currentTimeMillis();
+    }
+
+
+    List<BuildLogItem> items = Collections.synchronizedList( new ArrayList<BuildLogItem>() );
+
+    public BuildLogItem createBuildLogItem( MavenProject project, ExecutionPlanItem current )
+    {
+        threadMap.put( project, Thread.currentThread() );
+        BuildLogItem result = new BuildLogItem( project, current );
+        items.add( result );
+        return result;
+    }
+
+    public String toString()
+    {
+        StringBuilder result = new StringBuilder();
+        for ( Map.Entry<MavenProject, Thread> mavenProjectThreadEntry : threadMap.entrySet() )
+        {
+            result.append( mavenProjectThreadEntry.getKey().getName() );
+            result.append( " ran on " );
+            result.append( mavenProjectThreadEntry.getValue().getName() );
+            result.append( "\n" );
+        }
+
+        for ( BuildLogItem builtLogItem : items )
+        {
+            result.append( builtLogItem.toString( startTime ) );
+            result.append( "\n" );
+        }
+        return result.toString();
+    }
+
+    public String toGraph()
+    {
+        StringBuilder result = new StringBuilder();
+
+        Map<MavenProject, Collection<BuildLogItem>> multiMap = new HashMap<MavenProject, Collection<BuildLogItem>>();
+        for ( BuildLogItem builtLogItem : items )
+        {
+            MavenProject project = builtLogItem.getProject();
+            Collection<BuildLogItem> bag = multiMap.get( project );
+            if ( bag == null )
+            {
+                bag = new ArrayList<BuildLogItem>();
+                multiMap.put( project, bag );
+            }
+            bag.add( builtLogItem );
+        }
+
+        result.append( "digraph build" );
+        result.append( " {\n " );
+
+        for ( MavenProject mavenProject : multiMap.keySet() )
+        {
+            final Collection<BuildLogItem> builtLogItems = multiMap.get( mavenProject );
+            result.append( "   subgraph " );
+            result.append( mavenProject.getArtifactId() );
+            result.append( "   {\n" );
+
+            for ( BuildLogItem builtLogItem : builtLogItems )
+            {
+                result.append( builtLogItem.toGraph( startTime ) );
+            }
+
+            result.append( "\n   }\n" );
+        }
+
+        result.append( "\n}\n " );
+        return result.toString();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/maven/blob/09961c31/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/weave/CurrentPhaseForThread.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/weave/CurrentPhaseForThread.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/weave/CurrentPhaseForThread.java
new file mode 100644
index 0000000..f52f4e0
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/weave/CurrentPhaseForThread.java
@@ -0,0 +1,44 @@
+package org.apache.maven.lifecycle.internal.builder.weave;
+
+/*
+ * 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.
+ */
+
+/**
+ * Knows the phase the current thread is executing.
+ * <p/>
+ * This class is used in weave-mode only , there may be better ways of doing this once the dust settles.
+ * 
+ * @since 3.0
+ * @author Kristian Rosenvold
+ */
+class CurrentPhaseForThread
+{
+    private static final InheritableThreadLocal<String> THREAD_PHASE = new InheritableThreadLocal<String>();
+
+    public static void setPhase( String phase )
+    {
+        THREAD_PHASE.set( phase );
+    }
+
+    public static boolean isPhase( String phase )
+    {
+        return phase.equals( THREAD_PHASE.get() );
+    }
+
+}