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 22:44:03 UTC

[1/2] git commit: Remove weave mode building from the core

Updated Branches:
  refs/heads/master ccc7cb3ab -> 097cc8d25


Remove weave mode building from the core


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

Branch: refs/heads/master
Commit: 0c5678fa89485bbfa64746c5378100cf2bef2113
Parents: ccc7cb3
Author: Jason van Zyl <ja...@tesla.io>
Authored: Thu Feb 6 16:27:15 2014 -0500
Committer: Jason van Zyl <ja...@tesla.io>
Committed: Thu Feb 6 16:27:15 2014 -0500

----------------------------------------------------------------------
 .../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 -------------------
 .../internal/ConcurrentBuildLoggerTest.java     |  77 ---
 .../internal/LifecycleWeaveBuilderTest.java     | 142 -----
 .../java/org/apache/maven/cli/MavenCli.java     |   9 +-
 8 files changed, 1 insertion(+), 1457 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/maven/blob/0c5678fa/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
deleted file mode 100644
index 9b5b321..0000000
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/weave/BuildLogItem.java
+++ /dev/null
@@ -1,221 +0,0 @@
-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/0c5678fa/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
deleted file mode 100644
index 2dcd348..0000000
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/weave/ConcurrentBuildLogger.java
+++ /dev/null
@@ -1,124 +0,0 @@
-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/0c5678fa/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
deleted file mode 100644
index f52f4e0..0000000
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/weave/CurrentPhaseForThread.java
+++ /dev/null
@@ -1,44 +0,0 @@
-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() );
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/maven/blob/0c5678fa/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/weave/ThreadLockedArtifact.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/weave/ThreadLockedArtifact.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/weave/ThreadLockedArtifact.java
deleted file mode 100644
index 7a0e117..0000000
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/weave/ThreadLockedArtifact.java
+++ /dev/null
@@ -1,320 +0,0 @@
-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.artifact.Artifact;
-import org.apache.maven.artifact.handler.ArtifactHandler;
-import org.apache.maven.artifact.metadata.ArtifactMetadata;
-import org.apache.maven.artifact.repository.ArtifactRepository;
-import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
-import org.apache.maven.artifact.versioning.ArtifactVersion;
-import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
-import org.apache.maven.artifact.versioning.VersionRange;
-
-import java.io.File;
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-
-/**
- * An artifact that conditionally suspends on getFile for anything but the thread it is locked to.
- * 
- * @since 3.0
- */
-class ThreadLockedArtifact
-    implements Artifact
-{
-    private final Artifact real;
-
-    private final CountDownLatch artifactLocked = new CountDownLatch( 1 );
-
-    ThreadLockedArtifact( Artifact real )
-    {
-        this.real = real;
-    }
-
-    public boolean hasReal()
-    {
-        return real != null
-            && ( !( real instanceof ThreadLockedArtifact ) || ( (ThreadLockedArtifact) real ).hasReal() );
-    }
-
-    public String getGroupId()
-    {
-        return real.getGroupId();
-    }
-
-    public String getArtifactId()
-    {
-        return real.getArtifactId();
-    }
-
-    public String getVersion()
-    {
-        return real.getVersion();
-    }
-
-    public void setVersion( String version )
-    {
-        real.setVersion( version );
-    }
-
-    public String getScope()
-    {
-        return real.getScope();
-    }
-
-    public String getType()
-    {
-        return real.getType();
-    }
-
-    public String getClassifier()
-    {
-        return real.getClassifier();
-    }
-
-    public boolean hasClassifier()
-    {
-        return real.hasClassifier();
-    }
-
-    private static final InheritableThreadLocal<ThreadLockedArtifact> THREAD_ARTIFACT =
-        new InheritableThreadLocal<ThreadLockedArtifact>();
-
-    public void attachToThread()
-    {
-        THREAD_ARTIFACT.set( this );
-    }
-
-    public File getFile()
-    {
-        final ThreadLockedArtifact lockedArtifact = THREAD_ARTIFACT.get();
-        if ( lockedArtifact != null && this != lockedArtifact && mustLock() )
-        {
-            try
-            {
-                artifactLocked.await();
-            }
-            catch ( InterruptedException e )
-            {
-                // Ignore and go on to real.getFile();
-            }
-        }
-        return real.getFile();
-    }
-
-    private boolean mustLock()
-    {
-        boolean dontNeedLock = CurrentPhaseForThread.isPhase( "compile" ) || CurrentPhaseForThread.isPhase( "test" );
-        return !dontNeedLock;
-    }
-
-    public void setFile( File destination )
-    {
-        if ( destination != null && destination.exists() && destination.isFile() )
-        {
-            artifactLocked.countDown();
-        }
-        real.setFile( destination );
-    }
-
-    public String getBaseVersion()
-    {
-        return real.getBaseVersion();
-    }
-
-    public void setBaseVersion( String baseVersion )
-    {
-        real.setBaseVersion( baseVersion );
-    }
-
-    public String getId()
-    {
-        return real.getId();
-    }
-
-    public String getDependencyConflictId()
-    {
-        return real.getDependencyConflictId();
-    }
-
-    public void addMetadata( ArtifactMetadata metadata )
-    {
-        real.addMetadata( metadata );
-    }
-
-    public Collection<ArtifactMetadata> getMetadataList()
-    {
-        return real.getMetadataList();
-    }
-
-    public void setRepository( ArtifactRepository remoteRepository )
-    {
-        real.setRepository( remoteRepository );
-    }
-
-    public ArtifactRepository getRepository()
-    {
-        return real.getRepository();
-    }
-
-    public void updateVersion( String version, ArtifactRepository localRepository )
-    {
-        real.updateVersion( version, localRepository );
-    }
-
-    public String getDownloadUrl()
-    {
-        return real.getDownloadUrl();
-    }
-
-    public void setDownloadUrl( String downloadUrl )
-    {
-        real.setDownloadUrl( downloadUrl );
-    }
-
-    public ArtifactFilter getDependencyFilter()
-    {
-        return real.getDependencyFilter();
-    }
-
-    public void setDependencyFilter( ArtifactFilter artifactFilter )
-    {
-        real.setDependencyFilter( artifactFilter );
-    }
-
-    public ArtifactHandler getArtifactHandler()
-    {
-        return real.getArtifactHandler();
-    }
-
-    public List<String> getDependencyTrail()
-    {
-        return real.getDependencyTrail();
-    }
-
-    public void setDependencyTrail( List<String> dependencyTrail )
-    {
-        real.setDependencyTrail( dependencyTrail );
-    }
-
-    public void setScope( String scope )
-    {
-        real.setScope( scope );
-    }
-
-    public VersionRange getVersionRange()
-    {
-        return real.getVersionRange();
-    }
-
-    public void setVersionRange( VersionRange newRange )
-    {
-        real.setVersionRange( newRange );
-    }
-
-    public void selectVersion( String version )
-    {
-        real.selectVersion( version );
-    }
-
-    public void setGroupId( String groupId )
-    {
-        real.setGroupId( groupId );
-    }
-
-    public void setArtifactId( String artifactId )
-    {
-        real.setArtifactId( artifactId );
-    }
-
-    public boolean isSnapshot()
-    {
-        return real.isSnapshot();
-    }
-
-    public void setResolved( boolean resolved )
-    {
-        real.setResolved( resolved );
-    }
-
-    public boolean isResolved()
-    {
-        return real.isResolved();
-    }
-
-    public void setResolvedVersion( String version )
-    {
-        real.setResolvedVersion( version );
-    }
-
-    public void setArtifactHandler( ArtifactHandler handler )
-    {
-        real.setArtifactHandler( handler );
-    }
-
-    public boolean isRelease()
-    {
-        return real.isRelease();
-    }
-
-    public void setRelease( boolean release )
-    {
-        real.setRelease( release );
-    }
-
-    public List<ArtifactVersion> getAvailableVersions()
-    {
-        return real.getAvailableVersions();
-    }
-
-    public void setAvailableVersions( List<ArtifactVersion> versions )
-    {
-        real.setAvailableVersions( versions );
-    }
-
-    public boolean isOptional()
-    {
-        return real.isOptional();
-    }
-
-    public void setOptional( boolean optional )
-    {
-        real.setOptional( optional );
-    }
-
-    public ArtifactVersion getSelectedVersion()
-        throws OverConstrainedVersionException
-    {
-        return real.getSelectedVersion();
-    }
-
-    public boolean isSelectedVersionKnown()
-        throws OverConstrainedVersionException
-    {
-        return real.isSelectedVersionKnown();
-    }
-
-    public int compareTo( Artifact o )
-    {
-        return real.compareTo( o );
-    }
-}

http://git-wip-us.apache.org/repos/asf/maven/blob/0c5678fa/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/weave/WeaveBuilder.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/weave/WeaveBuilder.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/weave/WeaveBuilder.java
deleted file mode 100644
index 193eca6..0000000
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/weave/WeaveBuilder.java
+++ /dev/null
@@ -1,521 +0,0 @@
-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.artifact.Artifact;
-import org.apache.maven.artifact.ArtifactUtils;
-import org.apache.maven.execution.BuildSuccess;
-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.MavenExecutionPlan;
-import org.apache.maven.lifecycle.Schedule;
-import org.apache.maven.lifecycle.internal.BuildThreadFactory;
-import org.apache.maven.lifecycle.internal.DependencyContext;
-import org.apache.maven.lifecycle.internal.ExecutionEventCatapult;
-import org.apache.maven.lifecycle.internal.ExecutionPlanItem;
-import org.apache.maven.lifecycle.internal.LifecycleDebugLogger;
-import org.apache.maven.lifecycle.internal.MojoExecutor;
-import org.apache.maven.lifecycle.internal.PhaseRecorder;
-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.apache.maven.lifecycle.internal.builder.BuilderCommon;
-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;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-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 java.util.concurrent.TimeUnit;
-
-/**
- * Builds the full lifecycle in weave-mode (phase by phase as opposed to project-by-project)
- * <p/>
- * NOTE: Weave mode is still experimental. It may be either promoted to first class citizen at some later point in time,
- * and it may also be removed entirely. Weave mode has much more aggressive concurrency behaviour than regular threaded
- * mode, and as such is still under test wrt cross platform stability.
- * <p/>
- * To remove weave mode from m3, the following should be removed: ExecutionPlanItem.schedule w/setters and getters
- * DefaultLifeCycles.getScheduling() and all its use ReactorArtifactRepository has a reference to isWeave too. This
- * class and its usage
- * 
- * @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 = "weave" )
-public class WeaveBuilder
-    implements Builder
-{
-
-    @Requirement
-    private MojoExecutor mojoExecutor;
-
-    @Requirement
-    private BuilderCommon builderCommon;
-
-    @Requirement
-    private Logger logger;
-
-    @Requirement
-    private ExecutionEventCatapult eventCatapult;
-
-    @Requirement
-    private LifecycleDebugLogger lifecycleDebugLogger;
-
-    private Map<MavenProject, MavenExecutionPlan> executionPlans = new HashMap<MavenProject, MavenExecutionPlan>();
-
-    public WeaveBuilder()
-    {
-    }
-
-    public WeaveBuilder( MojoExecutor mojoExecutor, BuilderCommon builderCommon, Logger logger,
-                                  ExecutionEventCatapult eventCatapult, LifecycleDebugLogger lifecycleDebugLogger )
-    {
-        this.mojoExecutor = mojoExecutor;
-        this.builderCommon = builderCommon;
-        this.logger = logger;
-        this.eventCatapult = eventCatapult;
-        this.lifecycleDebugLogger = lifecycleDebugLogger;
-    }
-
-    public void build( MavenSession session, ReactorContext buildContext, ProjectBuildList projectBuilds,
-                       List<TaskSegment> taskSegments, ReactorBuildStatus reactorBuildStatus )
-        throws ExecutionException, InterruptedException
-    {
-        lifecycleDebugLogger.logWeavePlan( session );
-                
-        ExecutorService executor =
-                        Executors.newFixedThreadPool( Math.min( session.getRequest().getDegreeOfConcurrency(),
-                                                                session.getProjects().size() ), new BuildThreadFactory() );
-
-        try
-        {
-
-            ConcurrentBuildLogger concurrentBuildLogger = new ConcurrentBuildLogger();
-            CompletionService<ProjectSegment> service = new ExecutorCompletionService<ProjectSegment>( executor );
-
-            try
-            {
-                for ( MavenProject mavenProject : session.getProjects() )
-                {
-                    Artifact mainArtifact = mavenProject.getArtifact();
-                    if ( mainArtifact != null && !( mainArtifact instanceof ThreadLockedArtifact ) )
-                    {
-                        ThreadLockedArtifact threadLockedArtifact = new ThreadLockedArtifact( mainArtifact );
-                        mavenProject.setArtifact( threadLockedArtifact );
-                    }
-                }
-
-                final List<Future<ProjectSegment>> futures = new ArrayList<Future<ProjectSegment>>();
-                final Map<ProjectSegment, Future<MavenExecutionPlan>> plans =
-                    new HashMap<ProjectSegment, Future<MavenExecutionPlan>>();
-
-                for ( TaskSegment taskSegment : taskSegments )
-                {
-                    ProjectBuildList segmentChunks = projectBuilds.getByTaskSegment( taskSegment );
-                    Set<Artifact> projectArtifacts = new HashSet<Artifact>();
-                    for ( ProjectSegment segmentChunk : segmentChunks )
-                    {
-                        Artifact artifact = segmentChunk.getProject().getArtifact();
-                        if ( artifact != null )
-                        {
-                            projectArtifacts.add( artifact );
-                        }
-                    }
-                    for ( ProjectSegment projectBuild : segmentChunks )
-                    {
-                        plans.put( projectBuild, executor.submit( createEPFuture( projectBuild, projectArtifacts ) ) );
-                    }
-
-                    for ( ProjectSegment projectSegment : plans.keySet() )
-                    {
-                        executionPlans.put( projectSegment.getProject(), plans.get( projectSegment ).get() );
-
-                    }
-                    for ( ProjectSegment projectBuild : segmentChunks )
-                    {
-                        try
-                        {
-                            final MavenExecutionPlan executionPlan = plans.get( projectBuild ).get();
-
-                            DependencyContext dependencyContext =
-                                mojoExecutor.newDependencyContext( session, executionPlan.getMojoExecutions() );
-
-                            final Callable<ProjectSegment> projectBuilder =
-                                createCallableForBuildingOneFullModule( buildContext, session, reactorBuildStatus,
-                                                                        executionPlan, projectBuild, dependencyContext,
-                                                                        concurrentBuildLogger );
-
-                            futures.add( service.submit( projectBuilder ) );
-                        }
-                        catch ( Exception e )
-                        {
-                            throw new ExecutionException( e );
-                        }
-                    }
-
-                    for ( Future<ProjectSegment> buildFuture : futures )
-                    {
-                        buildFuture.get(); // At this point, this build *is* finished.
-                        // Do not leak threads past here or evil gremlins will get you!
-                    }
-                    futures.clear();
-                }
-            }
-            finally
-            {
-                projectBuilds.closeAll();
-            }
-            logger.info( concurrentBuildLogger.toString() );
-        }
-        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 );
-        }
-    }
-
-    private Callable<MavenExecutionPlan> createEPFuture( final ProjectSegment projectSegment,
-                                                         final Set<Artifact> projectArtifacts )
-    {
-        return new Callable<MavenExecutionPlan>()
-        {
-            public MavenExecutionPlan call()
-                throws Exception
-            {
-                return builderCommon.resolveBuildPlan( projectSegment.getSession(), projectSegment.getProject(),
-                                                       projectSegment.getTaskSegment(), projectArtifacts );
-            }
-        };
-    }
-
-    private Callable<ProjectSegment> createCallableForBuildingOneFullModule( final ReactorContext reactorContext,
-                                                                             final MavenSession rootSession,
-                                                                             final ReactorBuildStatus reactorBuildStatus,
-                                                                             final MavenExecutionPlan executionPlan,
-                                                                             final ProjectSegment projectBuild,
-                                                                             final DependencyContext dependencyContext,
-                                                                             final ConcurrentBuildLogger concurrentBuildLogger )
-    {
-        return new Callable<ProjectSegment>()
-        {
-            public ProjectSegment call()
-                throws Exception
-            {
-                Iterator<ExecutionPlanItem> planItems = executionPlan.iterator();
-                ExecutionPlanItem current = planItems.hasNext() ? planItems.next() : null;
-                ThreadLockedArtifact threadLockedArtifact =
-                    (ThreadLockedArtifact) projectBuild.getProject().getArtifact();
-                if ( threadLockedArtifact != null )
-                {
-                    threadLockedArtifact.attachToThread();
-                }
-                long buildStartTime = System.currentTimeMillis();
-
-                // muxer.associateThreadWithProjectSegment( projectBuild );
-
-                if ( reactorBuildStatus.isHaltedOrBlacklisted( projectBuild.getProject() ) )
-                {
-                    eventCatapult.fire( ExecutionEvent.Type.ProjectSkipped, projectBuild.getSession(), null );
-                    return null;
-                }
-
-                eventCatapult.fire( ExecutionEvent.Type.ProjectStarted, projectBuild.getSession(), null );
-
-                Collection<ArtifactLink> dependencyLinks = getUpstreamReactorDependencies( projectBuild );
-
-                try
-                {
-                    PhaseRecorder phaseRecorder = new PhaseRecorder( projectBuild.getProject() );
-                    long totalMojoTime = 0;
-                    long mojoStart;
-                    while ( current != null && !reactorBuildStatus.isHaltedOrBlacklisted( projectBuild.getProject() ) )
-                    {
-
-                        BuildLogItem builtLogItem =
-                            concurrentBuildLogger.createBuildLogItem( projectBuild.getProject(), current );
-                        final Schedule schedule = current.getSchedule();
-
-                        mojoStart = System.currentTimeMillis();
-                        buildExecutionPlanItem( current, phaseRecorder, schedule, reactorContext, projectBuild,
-                                                dependencyContext );
-                        totalMojoTime += ( System.currentTimeMillis() - mojoStart );
-
-                        current.setComplete();
-                        builtLogItem.setComplete();
-
-                        ExecutionPlanItem nextPlanItem = planItems.hasNext() ? planItems.next() : null;
-                        if ( nextPlanItem != null && phaseRecorder.isDifferentPhase( nextPlanItem.getMojoExecution() ) )
-                        {
-
-                            final Schedule scheduleOfNext = nextPlanItem.getSchedule();
-                            if ( scheduleOfNext == null || !scheduleOfNext.isParallel() )
-                            {
-                                waitForAppropriateUpstreamExecutionsToFinish( builtLogItem, nextPlanItem, projectBuild,
-                                                                              scheduleOfNext );
-                            }
-
-                            for ( ArtifactLink dependencyLink : dependencyLinks )
-                            {
-                                dependencyLink.resolveFromUpstream();
-                            }
-                        }
-                        current = nextPlanItem;
-                    }
-
-                    final BuildSuccess summary = new BuildSuccess( projectBuild.getProject(), totalMojoTime ); // -
-                                                                                                               // waitingTime
-                    reactorContext.getResult().addBuildSummary( summary );
-                    eventCatapult.fire( ExecutionEvent.Type.ProjectSucceeded, projectBuild.getSession(), null );
-                }
-                catch ( Exception e )
-                {
-                    builderCommon.handleBuildError( reactorContext, rootSession, projectBuild.getSession(),
-                                                    projectBuild.getProject(), e, buildStartTime );
-                }
-                finally
-                {
-                    if ( current != null )
-                    {
-                        executionPlan.forceAllComplete();
-                    }
-                    // muxer.setThisModuleComplete( projectBuild );
-                }
-                return null;
-            }
-
-        };
-    }
-
-    private void waitForAppropriateUpstreamExecutionsToFinish( BuildLogItem builtLogItem,
-                                                               ExecutionPlanItem nextPlanItem,
-                                                               ProjectSegment projectBuild, Schedule scheduleOfNext )
-        throws InterruptedException
-    {
-        for ( MavenProject upstreamProject : projectBuild.getImmediateUpstreamProjects() )
-        {
-            final MavenExecutionPlan upstreamPlan = executionPlans.get( upstreamProject );
-            final String nextPhase =
-                scheduleOfNext != null && scheduleOfNext.hasUpstreamPhaseDefined() ? scheduleOfNext.getUpstreamPhase()
-                                : nextPlanItem.getLifecyclePhase();
-            final ExecutionPlanItem upstream = upstreamPlan.findLastInPhase( nextPhase );
-
-            if ( upstream != null )
-            {
-                long startWait = System.currentTimeMillis();
-                upstream.waitUntilDone();
-                builtLogItem.addWait( upstreamProject, upstream, startWait );
-            }
-            else if ( !upstreamPlan.containsPhase( nextPhase ) )
-            {
-                // Still a bit of a kludge; if we cannot connect in a sensible way to
-                // the upstream build plan we just revert to waiting for it all to
-                // complete. Real problem is per-mojo phase->lifecycle mapping
-                builtLogItem.addDependency( upstreamProject, "No phase tracking possible " );
-                upstreamPlan.waitUntilAllDone();
-            }
-            else
-            {
-                builtLogItem.addDependency( upstreamProject, "No schedule" );
-            }
-        }
-    }
-
-    private Collection<ArtifactLink> getUpstreamReactorDependencies( ProjectSegment projectBuild )
-    {
-        Collection<ArtifactLink> result = new ArrayList<ArtifactLink>();
-        for ( MavenProject upstreamProject : projectBuild.getTransitiveUpstreamProjects() )
-        {
-            Artifact upStreamArtifact = upstreamProject.getArtifact();
-            if ( upStreamArtifact != null )
-            {
-                Artifact dependencyArtifact = findDependency( projectBuild.getProject(), upStreamArtifact );
-                if ( dependencyArtifact != null )
-                {
-                    result.add( new ArtifactLink( dependencyArtifact, upStreamArtifact ) );
-                }
-            }
-
-            Artifact upStreamTestScopedArtifact = findTestScopedArtifact( upstreamProject );
-            if ( upStreamTestScopedArtifact != null )
-            {
-                Artifact dependencyArtifact = findDependency( projectBuild.getProject(), upStreamArtifact );
-                if ( dependencyArtifact != null )
-                {
-                    result.add( new ArtifactLink( dependencyArtifact, upStreamTestScopedArtifact ) );
-                }
-            }
-        }
-        return result;
-    }
-
-    private Artifact findTestScopedArtifact( MavenProject upstreamProject )
-    {
-        if ( upstreamProject == null )
-        {
-            return null;
-        }
-
-        List<Artifact> artifactList = upstreamProject.getAttachedArtifacts();
-        for ( Artifact artifact : artifactList )
-        {
-            if ( Artifact.SCOPE_TEST.equals( artifact.getScope() ) )
-            {
-                return artifact;
-            }
-        }
-        return null;
-    }
-
-    private static boolean isThreadLockedAndEmpty( Artifact artifact )
-    {
-        return artifact instanceof ThreadLockedArtifact && !( (ThreadLockedArtifact) artifact ).hasReal();
-    }
-
-    private static Artifact findDependency( MavenProject project, Artifact upStreamArtifact )
-    {
-        if ( upStreamArtifact == null || isThreadLockedAndEmpty( upStreamArtifact ) )
-        {
-            return null;
-        }
-
-        String key =
-            ArtifactUtils.key( upStreamArtifact.getGroupId(), upStreamArtifact.getArtifactId(),
-                               upStreamArtifact.getVersion() );
-        final Set<Artifact> deps = project.getDependencyArtifacts();
-        for ( Artifact dep : deps )
-        {
-            String depKey = ArtifactUtils.key( dep.getGroupId(), dep.getArtifactId(), dep.getVersion() );
-            if ( key.equals( depKey ) )
-            {
-                return dep;
-            }
-        }
-        return null;
-
-    }
-
-    private void buildExecutionPlanItem( ExecutionPlanItem current, PhaseRecorder phaseRecorder, Schedule schedule,
-                                         ReactorContext reactorContext, ProjectSegment projectBuild,
-                                         DependencyContext dependencyContext )
-        throws LifecycleExecutionException
-    {
-        if ( schedule != null && schedule.isMojoSynchronized() )
-        {
-            synchronized ( current.getPlugin() )
-            {
-                buildExecutionPlanItem( reactorContext, current, projectBuild, dependencyContext, phaseRecorder );
-            }
-        }
-        else
-        {
-            buildExecutionPlanItem( reactorContext, current, projectBuild, dependencyContext, phaseRecorder );
-        }
-    }
-
-    private void buildExecutionPlanItem( ReactorContext reactorContext, ExecutionPlanItem node,
-                                         ProjectSegment projectBuild, DependencyContext dependencyContext,
-                                         PhaseRecorder phaseRecorder )
-        throws LifecycleExecutionException
-    {
-
-        MavenProject currentProject = projectBuild.getProject();
-
-        long buildStartTime = System.currentTimeMillis();
-
-        CurrentPhaseForThread.setPhase( node.getLifecyclePhase() );
-
-        MavenSession sessionForThisModule = projectBuild.getSession();
-        try
-        {
-
-            if ( reactorContext.getReactorBuildStatus().isHaltedOrBlacklisted( currentProject ) )
-            {
-                return;
-            }
-
-            BuilderCommon.attachToThread( currentProject );
-
-            mojoExecutor.execute( sessionForThisModule, node.getMojoExecution(), reactorContext.getProjectIndex(),
-                                  dependencyContext, phaseRecorder );
-
-            final BuildSuccess summary = new BuildSuccess( currentProject, System.currentTimeMillis() - buildStartTime );
-            reactorContext.getResult().addBuildSummary( summary );
-        }
-        finally
-        {
-            Thread.currentThread().setContextClassLoader( reactorContext.getOriginalContextClassLoader() );
-        }
-    }
-
-    public static boolean isWeaveMode( MavenExecutionRequest request )
-    {
-        return "true".equals( request.getUserProperties().getProperty( "maven3.weaveMode" ) );
-    }
-
-    public static void setWeaveMode( Properties properties )
-    {
-        properties.setProperty( "maven3.weaveMode", "true" );
-    }
-
-    static class ArtifactLink
-    {
-        private final Artifact artifactInThis;
-
-        private final Artifact upstream;
-
-        ArtifactLink( Artifact artifactInThis, Artifact upstream )
-        {
-            this.artifactInThis = artifactInThis;
-            this.upstream = upstream;
-        }
-
-        public void resolveFromUpstream()
-        {
-            artifactInThis.setFile( upstream.getFile() );
-            artifactInThis.setRepository( upstream.getRepository() );
-            artifactInThis.setResolved( true ); // Or maybe upstream.isResolved()....
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/maven/blob/0c5678fa/maven-core/src/test/java/org/apache/maven/lifecycle/internal/ConcurrentBuildLoggerTest.java
----------------------------------------------------------------------
diff --git a/maven-core/src/test/java/org/apache/maven/lifecycle/internal/ConcurrentBuildLoggerTest.java b/maven-core/src/test/java/org/apache/maven/lifecycle/internal/ConcurrentBuildLoggerTest.java
deleted file mode 100644
index 5a7e105..0000000
--- a/maven-core/src/test/java/org/apache/maven/lifecycle/internal/ConcurrentBuildLoggerTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package org.apache.maven.lifecycle.internal;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-import java.util.Iterator;
-
-import junit.framework.TestCase;
-
-import org.apache.maven.execution.MavenSession;
-import org.apache.maven.lifecycle.MavenExecutionPlan;
-import org.apache.maven.lifecycle.internal.builder.weave.BuildLogItem;
-import org.apache.maven.lifecycle.internal.builder.weave.ConcurrentBuildLogger;
-import org.apache.maven.lifecycle.internal.stub.ProjectDependencyGraphStub;
-import org.apache.maven.project.MavenProject;
-
-/**
- * @author Kristian Rosenvold
- */
-public class ConcurrentBuildLoggerTest
-    extends TestCase
-{
-    @SuppressWarnings( "unused" )
-    public void testToGraph()
-        throws Exception
-    {
-        ConcurrentBuildLogger concurrentBuildLogger = new ConcurrentBuildLogger();
-
-        MojoDescriptorCreator mojoDescriptorCreator =
-            LifecycleExecutionPlanCalculatorTest.createMojoDescriptorCreator();
-        LifecycleExecutionPlanCalculator lifecycleExecutionPlanCalculator =
-            LifecycleExecutionPlanCalculatorTest.createExecutionPlaceCalculator( mojoDescriptorCreator );
-
-        MavenProject A = ProjectDependencyGraphStub.B;
-        MavenProject B = ProjectDependencyGraphStub.C;
-
-        final MavenSession session1 = ProjectDependencyGraphStub.getMavenSession( A );
-
-        final GoalTask goalTask1 = new GoalTask( "compiler:compile" );
-        final GoalTask goalTask2 = new GoalTask( "surefire:test" );
-        final TaskSegment taskSegment1 = new TaskSegment( false, goalTask1, goalTask2 );
-
-        MavenExecutionPlan executionPlan =
-            lifecycleExecutionPlanCalculator.calculateExecutionPlan( session1, A, taskSegment1.getTasks() );
-
-        MavenExecutionPlan executionPlan2 =
-            lifecycleExecutionPlanCalculator.calculateExecutionPlan( session1, B, taskSegment1.getTasks() );
-
-        final Iterator<ExecutionPlanItem> planItemIterator = executionPlan.iterator();
-        final BuildLogItem a1 = concurrentBuildLogger.createBuildLogItem( A, planItemIterator.next() );
-
-        final BuildLogItem a2 = concurrentBuildLogger.createBuildLogItem( A, planItemIterator.next() );
-
-        final Iterator<ExecutionPlanItem> plan2ItemIterator = executionPlan.iterator();
-        final BuildLogItem b1 = concurrentBuildLogger.createBuildLogItem( B, plan2ItemIterator.next() );
-        final BuildLogItem b2 = concurrentBuildLogger.createBuildLogItem( B, plan2ItemIterator.next() );
-
-        b1.addDependency( A, "Project dependency" );
-        final Iterator<ExecutionPlanItem> aPlan = executionPlan.iterator();
-        b1.addWait( A, aPlan.next(), System.currentTimeMillis() );
-        b2.addWait( A, aPlan.next(), System.currentTimeMillis() );
-        final String response = concurrentBuildLogger.toGraph();
-        assertTrue( response.contains( "digraph" ) );
-    }
-}

http://git-wip-us.apache.org/repos/asf/maven/blob/0c5678fa/maven-core/src/test/java/org/apache/maven/lifecycle/internal/LifecycleWeaveBuilderTest.java
----------------------------------------------------------------------
diff --git a/maven-core/src/test/java/org/apache/maven/lifecycle/internal/LifecycleWeaveBuilderTest.java b/maven-core/src/test/java/org/apache/maven/lifecycle/internal/LifecycleWeaveBuilderTest.java
deleted file mode 100644
index 44f2311..0000000
--- a/maven-core/src/test/java/org/apache/maven/lifecycle/internal/LifecycleWeaveBuilderTest.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package org.apache.maven.lifecycle.internal;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-import junit.framework.TestCase;
-
-import org.apache.maven.execution.DefaultMavenExecutionResult;
-import org.apache.maven.execution.MavenExecutionResult;
-import org.apache.maven.execution.MavenSession;
-import org.apache.maven.lifecycle.LifecycleNotFoundException;
-import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
-import org.apache.maven.lifecycle.internal.builder.BuilderCommon;
-import org.apache.maven.lifecycle.internal.builder.weave.WeaveBuilder;
-import org.apache.maven.lifecycle.internal.stub.ExecutionEventCatapultStub;
-import org.apache.maven.lifecycle.internal.stub.LifecycleExecutionPlanCalculatorStub;
-import org.apache.maven.lifecycle.internal.stub.LifecycleTaskSegmentCalculatorStub;
-import org.apache.maven.lifecycle.internal.stub.LoggerStub;
-import org.apache.maven.lifecycle.internal.stub.MojoExecutorStub;
-import org.apache.maven.lifecycle.internal.stub.ProjectDependencyGraphStub;
-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.prefix.NoPluginFoundForPrefixException;
-import org.apache.maven.plugin.version.PluginVersionResolutionException;
-
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorCompletionService;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-/**
- * @author Kristian Rosenvold
- */
-public class LifecycleWeaveBuilderTest
-    extends TestCase
-{
-
-/*    public void testBuildProjectSynchronously()
-        throws Exception
-    {
-        final CompletionService<ProjectSegment> service = new CompletionServiceStub( true );
-        final ProjectBuildList projectBuildList = runWithCompletionService( service );
-        assertEquals( "Expect all tasks to be scheduled", projectBuildList.size(),
-                      ( (CompletionServiceStub) service ).size() );
-    }
-  */
-
-    @SuppressWarnings( "unused" )
-    public void testBuildProjectThreaded()
-        throws Exception
-    {
-        ExecutorService executor = Executors.newFixedThreadPool( 10 );
-        ExecutorCompletionService<ProjectSegment> service = new ExecutorCompletionService<ProjectSegment>( executor );
-        runWithCompletionService( executor );
-        executor.shutdown();
-    }
-
-    @SuppressWarnings( "unused" )
-    public void testBuildProjectThreadedAggressive()
-        throws Exception
-    {
-        ExecutorService executor = Executors.newFixedThreadPool( 10 );
-        ExecutorCompletionService<ProjectSegment> service = new ExecutorCompletionService<ProjectSegment>( executor );
-        runWithCompletionService( executor );
-        executor.shutdown();
-    }
-
-    private ProjectBuildList runWithCompletionService( ExecutorService service )
-        throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
-        MojoNotFoundException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
-        PluginVersionResolutionException, LifecyclePhaseNotFoundException, LifecycleNotFoundException,
-        ExecutionException, InterruptedException
-    {
-        final ClassLoader loader = Thread.currentThread().getContextClassLoader();
-        try
-        {
-            BuildListCalculator buildListCalculator = new BuildListCalculator();
-            final MavenSession session = ProjectDependencyGraphStub.getMavenSession();
-            List<TaskSegment> taskSegments = getTaskSegmentCalculator().calculateTaskSegments( session );
-            ProjectBuildList projectBuildList = buildListCalculator.calculateProjectBuilds( session, taskSegments );
-
-            final MojoExecutorStub mojoExecutorStub = new MojoExecutorStub();
-            final WeaveBuilder builder = getWeaveBuilder( mojoExecutorStub );
-            final ReactorContext buildContext = createBuildContext( session );
-            ReactorBuildStatus reactorBuildStatus = new ReactorBuildStatus( session.getProjectDependencyGraph() );
-            builder.build( session, buildContext, projectBuildList, taskSegments, reactorBuildStatus );
-
-            LifecycleExecutionPlanCalculatorStub lifecycleExecutionPlanCalculatorStub =
-                new LifecycleExecutionPlanCalculatorStub();
-            final int expected = lifecycleExecutionPlanCalculatorStub.getNumberOfExceutions( projectBuildList );
-            assertEquals( "All executions should be scheduled", expected, mojoExecutorStub.executions.size() );
-            return projectBuildList;
-        }
-        finally
-        {
-            Thread.currentThread().setContextClassLoader( loader );
-        }
-    }
-
-
-    private static LifecycleTaskSegmentCalculator getTaskSegmentCalculator()
-    {
-        return new LifecycleTaskSegmentCalculatorStub();
-    }
-
-    private ReactorContext createBuildContext( MavenSession session )
-    {
-        MavenExecutionResult mavenExecutionResult = new DefaultMavenExecutionResult();
-        ReactorBuildStatus reactorBuildStatus = new ReactorBuildStatus( session.getProjectDependencyGraph() );
-        return new ReactorContext( mavenExecutionResult, null, null, reactorBuildStatus );
-    }
-
-    private WeaveBuilder getWeaveBuilder( MojoExecutor mojoExecutor )
-    {
-        final BuilderCommon builderCommon = getBuilderCommon();
-        final LoggerStub loggerStub = new LoggerStub();
-        return new WeaveBuilder( mojoExecutor, builderCommon, loggerStub, new ExecutionEventCatapultStub(), new LifecycleDebugLogger( loggerStub ) );
-    }
-
-    private BuilderCommon getBuilderCommon()
-    {
-        final LifecycleDebugLogger logger = new LifecycleDebugLogger( new LoggerStub() );
-        return new BuilderCommon( logger, new LifecycleExecutionPlanCalculatorStub(),
-                                  new LoggerStub() );
-    }
-}

http://git-wip-us.apache.org/repos/asf/maven/blob/0c5678fa/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
----------------------------------------------------------------------
diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
index 8ee2830..79871df 100644
--- a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
+++ b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
@@ -1087,14 +1087,7 @@ public class MavenCli
         
         if ( threadConfiguration != null )
         {
-            if ( threadConfiguration.contains( "W" ) )
-            {
-                request.setBuilderId( "weave" );
-            }
-            else 
-            {
-                request.setBuilderId( "multithreaded" );
-            }
+            request.setBuilderId( "multithreaded" );
             
             int threads =
                 threadConfiguration.contains( "C" ) ? Integer.valueOf( threadConfiguration.replace( "C", "" ) )


[2/2] git commit: Move ThreadOutputMuxer to sit along with the multithreaded Builder implementation

Posted by jv...@apache.org.
Move ThreadOutputMuxer to sit along with the multithreaded Builder implementation


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

Branch: refs/heads/master
Commit: 097cc8d25f9261434c6de5e449ca442e45044d00
Parents: 0c5678f
Author: Jason van Zyl <ja...@tesla.io>
Authored: Thu Feb 6 16:39:15 2014 -0500
Committer: Jason van Zyl <ja...@tesla.io>
Committed: Thu Feb 6 16:39:15 2014 -0500

----------------------------------------------------------------------
 .../lifecycle/internal/ProjectBuildList.java    |   2 +-
 .../lifecycle/internal/ThreadOutputMuxer.java   | 474 ------------------
 .../multithreaded/MultiThreadedBuilder.java     |   1 -
 .../multithreaded/ThreadOutputMuxer.java        | 477 +++++++++++++++++++
 .../internal/ThreadOutputMuxerTest.java         | 163 -------
 .../multithreaded/ThreadOutputMuxerTest.java    | 167 +++++++
 6 files changed, 645 insertions(+), 639 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/maven/blob/097cc8d2/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 acea697..ee596ec 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
@@ -119,7 +119,7 @@ public class ProjectBuildList
         return items.size();
     }
 
-    ProjectSegment get( int index )
+    public ProjectSegment get( int index )
     {
         return items.get( index );
     }

http://git-wip-us.apache.org/repos/asf/maven/blob/097cc8d2/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ThreadOutputMuxer.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ThreadOutputMuxer.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ThreadOutputMuxer.java
deleted file mode 100644
index 0fde6d8..0000000
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ThreadOutputMuxer.java
+++ /dev/null
@@ -1,474 +0,0 @@
-package org.apache.maven.lifecycle.internal;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @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.
- *         This class in particular may spontaneusly self-combust and be replaced by a plexus-compliant thread aware
- *         logger implementation at any time.
- */
-@SuppressWarnings( { "SynchronizationOnLocalVariableOrMethodParameter" } )
-public class ThreadOutputMuxer
-{
-    private final Iterator<ProjectSegment> projects;
-
-    private final ThreadLocal<ProjectSegment> projectBuildThreadLocal = new ThreadLocal<ProjectSegment>();
-
-    private final Map<ProjectSegment, ByteArrayOutputStream> streams =
-        new HashMap<ProjectSegment, ByteArrayOutputStream>();
-
-    private final Map<ProjectSegment, PrintStream> printStreams = new HashMap<ProjectSegment, PrintStream>();
-
-    private final ByteArrayOutputStream defaultOutputStreamForUnknownData = new ByteArrayOutputStream();
-
-    private final PrintStream defaultPringStream = new PrintStream( defaultOutputStreamForUnknownData );
-
-    private final Set<ProjectSegment> completedBuilds = Collections.synchronizedSet( new HashSet<ProjectSegment>() );
-
-    private volatile ProjectSegment currentBuild;
-
-    private final PrintStream originalSystemOUtStream;
-
-    private final ConsolePrinter printer;
-
-    /**
-     * A simple but safe solution for printing to the console.
-     */
-
-    class ConsolePrinter
-        implements Runnable
-    {
-        public volatile boolean running;
-
-        private final ProjectBuildList projectBuildList;
-
-        ConsolePrinter( ProjectBuildList projectBuildList )
-        {
-            this.projectBuildList = projectBuildList;
-        }
-
-        public void run()
-        {
-            running = true;
-            for ( ProjectSegment projectBuild : projectBuildList )
-            {
-                final PrintStream projectStream = printStreams.get( projectBuild );
-                ByteArrayOutputStream projectOs = streams.get( projectBuild );
-
-                do
-                {
-                    synchronized ( projectStream )
-                    {
-                        try
-                        {
-                            projectStream.wait( 100 );
-                        }
-                        catch ( InterruptedException e )
-                        {
-                            throw new RuntimeException( e );
-                        }
-                        try
-                        {
-                            projectOs.writeTo( originalSystemOUtStream );
-                        }
-                        catch ( IOException e )
-                        {
-                            throw new RuntimeException( e );
-                        }
-
-                        projectOs.reset();
-                    }
-                }
-                while ( !completedBuilds.contains( projectBuild ) );
-            }
-            running = false;
-        }
-
-        /*
-        Wait until we are sure the print-stream thread is running.
-         */
-
-        public void waitUntilRunning( boolean expect )
-        {
-            while ( !running == expect )
-            {
-                try
-                {
-                    Thread.sleep( 10 );
-                }
-                catch ( InterruptedException e )
-                {
-                    throw new RuntimeException( e );
-                }
-            }
-        }
-    }
-
-    public ThreadOutputMuxer( ProjectBuildList segmentChunks, PrintStream originalSystemOut )
-    {
-        projects = segmentChunks.iterator();
-        for ( ProjectSegment segmentChunk : segmentChunks )
-        {
-            final ByteArrayOutputStream value = new ByteArrayOutputStream();
-            streams.put( segmentChunk, value );
-            printStreams.put( segmentChunk, new PrintStream( value ) );
-        }
-        setNext();
-        this.originalSystemOUtStream = originalSystemOut;
-        System.setOut( new ThreadBoundPrintStream( this.originalSystemOUtStream ) );
-        printer = new ConsolePrinter( segmentChunks );
-        new Thread( printer ).start();
-        printer.waitUntilRunning( true );
-    }
-
-    public void close()
-    {
-        printer.waitUntilRunning( false );
-        System.setOut( this.originalSystemOUtStream );
-    }
-
-    private void setNext()
-    {
-        currentBuild = projects.hasNext() ? projects.next() : null;
-    }
-
-    private boolean ownsRealOutputStream( ProjectSegment projectBuild )
-    {
-        return projectBuild.equals( currentBuild );
-    }
-
-    private PrintStream getThreadBoundPrintStream()
-    {
-        ProjectSegment threadProject = projectBuildThreadLocal.get();
-        if ( threadProject == null )
-        {
-            return defaultPringStream;
-        }
-        if ( ownsRealOutputStream( threadProject ) )
-        {
-            return originalSystemOUtStream;
-        }
-        return printStreams.get( threadProject );
-    }
-
-    public void associateThreadWithProjectSegment( ProjectSegment projectBuild )
-    {
-        projectBuildThreadLocal.set( projectBuild );
-    }
-
-    public void setThisModuleComplete( ProjectSegment projectBuild )
-    {
-        completedBuilds.add( projectBuild );
-        PrintStream stream = printStreams.get( projectBuild );
-        synchronized ( stream )
-        {
-            stream.notifyAll();
-        }
-        disconnectThreadFromProject();
-    }
-
-    private void disconnectThreadFromProject()
-    {
-        projectBuildThreadLocal.remove();
-    }
-
-    private class ThreadBoundPrintStream
-        extends PrintStream
-    {
-
-        public ThreadBoundPrintStream( PrintStream systemOutStream )
-        {
-            super( systemOutStream );
-        }
-
-        private PrintStream getOutputStreamForCurrentThread()
-        {
-            return getThreadBoundPrintStream();
-        }
-
-        @Override
-        public void println()
-        {
-            final PrintStream currentStream = getOutputStreamForCurrentThread();
-            synchronized ( currentStream )
-            {
-                currentStream.println();
-                currentStream.notifyAll();
-            }
-        }
-
-        @Override
-        public void print( char c )
-        {
-            final PrintStream currentStream = getOutputStreamForCurrentThread();
-            synchronized ( currentStream )
-            {
-                currentStream.print( c );
-                currentStream.notifyAll();
-            }
-        }
-
-        @Override
-        public void println( char x )
-        {
-            final PrintStream currentStream = getOutputStreamForCurrentThread();
-            synchronized ( currentStream )
-            {
-                currentStream.println( x );
-                currentStream.notifyAll();
-            }
-        }
-
-        @Override
-        public void print( double d )
-        {
-            final PrintStream currentStream = getOutputStreamForCurrentThread();
-            synchronized ( currentStream )
-            {
-                currentStream.print( d );
-                currentStream.notifyAll();
-            }
-        }
-
-        @Override
-        public void println( double x )
-        {
-            final PrintStream currentStream = getOutputStreamForCurrentThread();
-            synchronized ( currentStream )
-            {
-                currentStream.println( x );
-                currentStream.notifyAll();
-            }
-        }
-
-        @Override
-        public void print( float f )
-        {
-            final PrintStream currentStream = getOutputStreamForCurrentThread();
-            synchronized ( currentStream )
-            {
-                currentStream.print( f );
-                currentStream.notifyAll();
-            }
-        }
-
-        @Override
-        public void println( float x )
-        {
-            final PrintStream currentStream = getOutputStreamForCurrentThread();
-            synchronized ( currentStream )
-            {
-                currentStream.println( x );
-                currentStream.notifyAll();
-            }
-        }
-
-        @Override
-        public void print( int i )
-        {
-            final PrintStream currentStream = getOutputStreamForCurrentThread();
-            synchronized ( currentStream )
-            {
-                currentStream.print( i );
-                currentStream.notifyAll();
-            }
-        }
-
-        @Override
-        public void println( int x )
-        {
-            final PrintStream currentStream = getOutputStreamForCurrentThread();
-            synchronized ( currentStream )
-            {
-                currentStream.println( x );
-                currentStream.notifyAll();
-            }
-        }
-
-        @Override
-        public void print( long l )
-        {
-            final PrintStream currentStream = getOutputStreamForCurrentThread();
-            synchronized ( currentStream )
-            {
-                currentStream.print( l );
-                currentStream.notifyAll();
-            }
-        }
-
-        @Override
-        public void println( long x )
-        {
-            final PrintStream currentStream = getOutputStreamForCurrentThread();
-            synchronized ( currentStream )
-            {
-                currentStream.print( x );
-                currentStream.notifyAll();
-            }
-        }
-
-        @Override
-        public void print( boolean b )
-        {
-            final PrintStream currentStream = getOutputStreamForCurrentThread();
-            synchronized ( currentStream )
-            {
-                currentStream.print( b );
-                currentStream.notifyAll();
-            }
-        }
-
-        @Override
-        public void println( boolean x )
-        {
-            final PrintStream currentStream = getOutputStreamForCurrentThread();
-            synchronized ( currentStream )
-            {
-                currentStream.print( x );
-                currentStream.notifyAll();
-            }
-        }
-
-        @Override
-        public void print( char s[] )
-        {
-            final PrintStream currentStream = getOutputStreamForCurrentThread();
-            synchronized ( currentStream )
-            {
-                currentStream.print( s );
-                currentStream.notifyAll();
-            }
-        }
-
-        @Override
-        public void println( char x[] )
-        {
-            final PrintStream currentStream = getOutputStreamForCurrentThread();
-            synchronized ( currentStream )
-            {
-                currentStream.print( x );
-                currentStream.notifyAll();
-            }
-        }
-
-        @Override
-        public void print( Object obj )
-        {
-            final PrintStream currentStream = getOutputStreamForCurrentThread();
-            synchronized ( currentStream )
-            {
-                currentStream.print( obj );
-                currentStream.notifyAll();
-            }
-        }
-
-        @Override
-        public void println( Object x )
-        {
-            final PrintStream currentStream = getOutputStreamForCurrentThread();
-            synchronized ( currentStream )
-            {
-                currentStream.println( x );
-                currentStream.notifyAll();
-            }
-        }
-
-        @Override
-        public void print( String s )
-        {
-            final PrintStream currentStream = getOutputStreamForCurrentThread();
-            synchronized ( currentStream )
-            {
-                currentStream.print( s );
-                currentStream.notifyAll();
-            }
-        }
-
-        @Override
-        public void println( String x )
-        {
-            final PrintStream currentStream = getOutputStreamForCurrentThread();
-            synchronized ( currentStream )
-            {
-                currentStream.println( x );
-                currentStream.notifyAll();
-            }
-        }
-
-        @Override
-        public void write( byte b[], int off, int len )
-        {
-            final PrintStream currentStream = getOutputStreamForCurrentThread();
-            synchronized ( currentStream )
-            {
-                currentStream.write( b, off, len );
-                currentStream.notifyAll();
-            }
-        }
-
-        @Override
-        public void close()
-        {
-            getOutputStreamForCurrentThread().close();
-        }
-
-        @Override
-        public void flush()
-        {
-            getOutputStreamForCurrentThread().flush();
-        }
-
-        @Override
-        public void write( int b )
-        {
-            final PrintStream currentStream = getOutputStreamForCurrentThread();
-            synchronized ( currentStream )
-            {
-                currentStream.write( b );
-                currentStream.notifyAll();
-            }
-        }
-
-        @Override
-        public void write( byte b[] )
-            throws IOException
-        {
-            final PrintStream currentStream = getOutputStreamForCurrentThread();
-            synchronized ( currentStream )
-            {
-                currentStream.write( b );
-                currentStream.notifyAll();
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/maven/blob/097cc8d2/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
index b89aa0e..c0104ef 100644
--- 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
@@ -37,7 +37,6 @@ 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;

http://git-wip-us.apache.org/repos/asf/maven/blob/097cc8d2/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/ThreadOutputMuxer.java
----------------------------------------------------------------------
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/ThreadOutputMuxer.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/ThreadOutputMuxer.java
new file mode 100644
index 0000000..8f1f493
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/ThreadOutputMuxer.java
@@ -0,0 +1,477 @@
+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.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.maven.lifecycle.internal.ProjectBuildList;
+import org.apache.maven.lifecycle.internal.ProjectSegment;
+
+/**
+ * @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.
+ *         This class in particular may spontaneusly self-combust and be replaced by a plexus-compliant thread aware
+ *         logger implementation at any time.
+ */
+@SuppressWarnings( { "SynchronizationOnLocalVariableOrMethodParameter" } )
+public class ThreadOutputMuxer
+{
+    private final Iterator<ProjectSegment> projects;
+
+    private final ThreadLocal<ProjectSegment> projectBuildThreadLocal = new ThreadLocal<ProjectSegment>();
+
+    private final Map<ProjectSegment, ByteArrayOutputStream> streams =
+        new HashMap<ProjectSegment, ByteArrayOutputStream>();
+
+    private final Map<ProjectSegment, PrintStream> printStreams = new HashMap<ProjectSegment, PrintStream>();
+
+    private final ByteArrayOutputStream defaultOutputStreamForUnknownData = new ByteArrayOutputStream();
+
+    private final PrintStream defaultPringStream = new PrintStream( defaultOutputStreamForUnknownData );
+
+    private final Set<ProjectSegment> completedBuilds = Collections.synchronizedSet( new HashSet<ProjectSegment>() );
+
+    private volatile ProjectSegment currentBuild;
+
+    private final PrintStream originalSystemOUtStream;
+
+    private final ConsolePrinter printer;
+
+    /**
+     * A simple but safe solution for printing to the console.
+     */
+
+    class ConsolePrinter
+        implements Runnable
+    {
+        public volatile boolean running;
+
+        private final ProjectBuildList projectBuildList;
+
+        ConsolePrinter( ProjectBuildList projectBuildList )
+        {
+            this.projectBuildList = projectBuildList;
+        }
+
+        public void run()
+        {
+            running = true;
+            for ( ProjectSegment projectBuild : projectBuildList )
+            {
+                final PrintStream projectStream = printStreams.get( projectBuild );
+                ByteArrayOutputStream projectOs = streams.get( projectBuild );
+
+                do
+                {
+                    synchronized ( projectStream )
+                    {
+                        try
+                        {
+                            projectStream.wait( 100 );
+                        }
+                        catch ( InterruptedException e )
+                        {
+                            throw new RuntimeException( e );
+                        }
+                        try
+                        {
+                            projectOs.writeTo( originalSystemOUtStream );
+                        }
+                        catch ( IOException e )
+                        {
+                            throw new RuntimeException( e );
+                        }
+
+                        projectOs.reset();
+                    }
+                }
+                while ( !completedBuilds.contains( projectBuild ) );
+            }
+            running = false;
+        }
+
+        /*
+        Wait until we are sure the print-stream thread is running.
+         */
+
+        public void waitUntilRunning( boolean expect )
+        {
+            while ( !running == expect )
+            {
+                try
+                {
+                    Thread.sleep( 10 );
+                }
+                catch ( InterruptedException e )
+                {
+                    throw new RuntimeException( e );
+                }
+            }
+        }
+    }
+
+    public ThreadOutputMuxer( ProjectBuildList segmentChunks, PrintStream originalSystemOut )
+    {
+        projects = segmentChunks.iterator();
+        for ( ProjectSegment segmentChunk : segmentChunks )
+        {
+            final ByteArrayOutputStream value = new ByteArrayOutputStream();
+            streams.put( segmentChunk, value );
+            printStreams.put( segmentChunk, new PrintStream( value ) );
+        }
+        setNext();
+        this.originalSystemOUtStream = originalSystemOut;
+        System.setOut( new ThreadBoundPrintStream( this.originalSystemOUtStream ) );
+        printer = new ConsolePrinter( segmentChunks );
+        new Thread( printer ).start();
+        printer.waitUntilRunning( true );
+    }
+
+    public void close()
+    {
+        printer.waitUntilRunning( false );
+        System.setOut( this.originalSystemOUtStream );
+    }
+
+    private void setNext()
+    {
+        currentBuild = projects.hasNext() ? projects.next() : null;
+    }
+
+    private boolean ownsRealOutputStream( ProjectSegment projectBuild )
+    {
+        return projectBuild.equals( currentBuild );
+    }
+
+    private PrintStream getThreadBoundPrintStream()
+    {
+        ProjectSegment threadProject = projectBuildThreadLocal.get();
+        if ( threadProject == null )
+        {
+            return defaultPringStream;
+        }
+        if ( ownsRealOutputStream( threadProject ) )
+        {
+            return originalSystemOUtStream;
+        }
+        return printStreams.get( threadProject );
+    }
+
+    public void associateThreadWithProjectSegment( ProjectSegment projectBuild )
+    {
+        projectBuildThreadLocal.set( projectBuild );
+    }
+
+    public void setThisModuleComplete( ProjectSegment projectBuild )
+    {
+        completedBuilds.add( projectBuild );
+        PrintStream stream = printStreams.get( projectBuild );
+        synchronized ( stream )
+        {
+            stream.notifyAll();
+        }
+        disconnectThreadFromProject();
+    }
+
+    private void disconnectThreadFromProject()
+    {
+        projectBuildThreadLocal.remove();
+    }
+
+    private class ThreadBoundPrintStream
+        extends PrintStream
+    {
+
+        public ThreadBoundPrintStream( PrintStream systemOutStream )
+        {
+            super( systemOutStream );
+        }
+
+        private PrintStream getOutputStreamForCurrentThread()
+        {
+            return getThreadBoundPrintStream();
+        }
+
+        @Override
+        public void println()
+        {
+            final PrintStream currentStream = getOutputStreamForCurrentThread();
+            synchronized ( currentStream )
+            {
+                currentStream.println();
+                currentStream.notifyAll();
+            }
+        }
+
+        @Override
+        public void print( char c )
+        {
+            final PrintStream currentStream = getOutputStreamForCurrentThread();
+            synchronized ( currentStream )
+            {
+                currentStream.print( c );
+                currentStream.notifyAll();
+            }
+        }
+
+        @Override
+        public void println( char x )
+        {
+            final PrintStream currentStream = getOutputStreamForCurrentThread();
+            synchronized ( currentStream )
+            {
+                currentStream.println( x );
+                currentStream.notifyAll();
+            }
+        }
+
+        @Override
+        public void print( double d )
+        {
+            final PrintStream currentStream = getOutputStreamForCurrentThread();
+            synchronized ( currentStream )
+            {
+                currentStream.print( d );
+                currentStream.notifyAll();
+            }
+        }
+
+        @Override
+        public void println( double x )
+        {
+            final PrintStream currentStream = getOutputStreamForCurrentThread();
+            synchronized ( currentStream )
+            {
+                currentStream.println( x );
+                currentStream.notifyAll();
+            }
+        }
+
+        @Override
+        public void print( float f )
+        {
+            final PrintStream currentStream = getOutputStreamForCurrentThread();
+            synchronized ( currentStream )
+            {
+                currentStream.print( f );
+                currentStream.notifyAll();
+            }
+        }
+
+        @Override
+        public void println( float x )
+        {
+            final PrintStream currentStream = getOutputStreamForCurrentThread();
+            synchronized ( currentStream )
+            {
+                currentStream.println( x );
+                currentStream.notifyAll();
+            }
+        }
+
+        @Override
+        public void print( int i )
+        {
+            final PrintStream currentStream = getOutputStreamForCurrentThread();
+            synchronized ( currentStream )
+            {
+                currentStream.print( i );
+                currentStream.notifyAll();
+            }
+        }
+
+        @Override
+        public void println( int x )
+        {
+            final PrintStream currentStream = getOutputStreamForCurrentThread();
+            synchronized ( currentStream )
+            {
+                currentStream.println( x );
+                currentStream.notifyAll();
+            }
+        }
+
+        @Override
+        public void print( long l )
+        {
+            final PrintStream currentStream = getOutputStreamForCurrentThread();
+            synchronized ( currentStream )
+            {
+                currentStream.print( l );
+                currentStream.notifyAll();
+            }
+        }
+
+        @Override
+        public void println( long x )
+        {
+            final PrintStream currentStream = getOutputStreamForCurrentThread();
+            synchronized ( currentStream )
+            {
+                currentStream.print( x );
+                currentStream.notifyAll();
+            }
+        }
+
+        @Override
+        public void print( boolean b )
+        {
+            final PrintStream currentStream = getOutputStreamForCurrentThread();
+            synchronized ( currentStream )
+            {
+                currentStream.print( b );
+                currentStream.notifyAll();
+            }
+        }
+
+        @Override
+        public void println( boolean x )
+        {
+            final PrintStream currentStream = getOutputStreamForCurrentThread();
+            synchronized ( currentStream )
+            {
+                currentStream.print( x );
+                currentStream.notifyAll();
+            }
+        }
+
+        @Override
+        public void print( char s[] )
+        {
+            final PrintStream currentStream = getOutputStreamForCurrentThread();
+            synchronized ( currentStream )
+            {
+                currentStream.print( s );
+                currentStream.notifyAll();
+            }
+        }
+
+        @Override
+        public void println( char x[] )
+        {
+            final PrintStream currentStream = getOutputStreamForCurrentThread();
+            synchronized ( currentStream )
+            {
+                currentStream.print( x );
+                currentStream.notifyAll();
+            }
+        }
+
+        @Override
+        public void print( Object obj )
+        {
+            final PrintStream currentStream = getOutputStreamForCurrentThread();
+            synchronized ( currentStream )
+            {
+                currentStream.print( obj );
+                currentStream.notifyAll();
+            }
+        }
+
+        @Override
+        public void println( Object x )
+        {
+            final PrintStream currentStream = getOutputStreamForCurrentThread();
+            synchronized ( currentStream )
+            {
+                currentStream.println( x );
+                currentStream.notifyAll();
+            }
+        }
+
+        @Override
+        public void print( String s )
+        {
+            final PrintStream currentStream = getOutputStreamForCurrentThread();
+            synchronized ( currentStream )
+            {
+                currentStream.print( s );
+                currentStream.notifyAll();
+            }
+        }
+
+        @Override
+        public void println( String x )
+        {
+            final PrintStream currentStream = getOutputStreamForCurrentThread();
+            synchronized ( currentStream )
+            {
+                currentStream.println( x );
+                currentStream.notifyAll();
+            }
+        }
+
+        @Override
+        public void write( byte b[], int off, int len )
+        {
+            final PrintStream currentStream = getOutputStreamForCurrentThread();
+            synchronized ( currentStream )
+            {
+                currentStream.write( b, off, len );
+                currentStream.notifyAll();
+            }
+        }
+
+        @Override
+        public void close()
+        {
+            getOutputStreamForCurrentThread().close();
+        }
+
+        @Override
+        public void flush()
+        {
+            getOutputStreamForCurrentThread().flush();
+        }
+
+        @Override
+        public void write( int b )
+        {
+            final PrintStream currentStream = getOutputStreamForCurrentThread();
+            synchronized ( currentStream )
+            {
+                currentStream.write( b );
+                currentStream.notifyAll();
+            }
+        }
+
+        @Override
+        public void write( byte b[] )
+            throws IOException
+        {
+            final PrintStream currentStream = getOutputStreamForCurrentThread();
+            synchronized ( currentStream )
+            {
+                currentStream.write( b );
+                currentStream.notifyAll();
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven/blob/097cc8d2/maven-core/src/test/java/org/apache/maven/lifecycle/internal/ThreadOutputMuxerTest.java
----------------------------------------------------------------------
diff --git a/maven-core/src/test/java/org/apache/maven/lifecycle/internal/ThreadOutputMuxerTest.java b/maven-core/src/test/java/org/apache/maven/lifecycle/internal/ThreadOutputMuxerTest.java
deleted file mode 100644
index f040566..0000000
--- a/maven-core/src/test/java/org/apache/maven/lifecycle/internal/ThreadOutputMuxerTest.java
+++ /dev/null
@@ -1,163 +0,0 @@
-package org.apache.maven.lifecycle.internal;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-import junit.framework.TestCase;
-import org.apache.maven.execution.MavenSession;
-import org.apache.maven.lifecycle.LifecycleNotFoundException;
-import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
-import org.apache.maven.lifecycle.internal.stub.ProjectDependencyGraphStub;
-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.prefix.NoPluginFoundForPrefixException;
-import org.apache.maven.plugin.version.PluginVersionResolutionException;
-
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CompletionService;
-import java.util.concurrent.ExecutorCompletionService;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-
-/**
- * @author Kristian Rosenvold
- */
-public class ThreadOutputMuxerTest
-    extends TestCase
-{
-
-    final String paid = "Paid";
-
-    final String in = "In";
-
-    final String full = "Full";
-
-    public void testSingleThreaded()
-        throws Exception
-    {
-        ProjectBuildList src = getProjectBuildList();
-        ProjectBuildList projectBuildList =
-            new ProjectBuildList( Arrays.asList( src.get( 0 ), src.get( 1 ), src.get( 2 ) ) );
-
-        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
-        PrintStream systemOut = new PrintStream( byteArrayOutputStream );
-        ThreadOutputMuxer threadOutputMuxer = new ThreadOutputMuxer( projectBuildList, systemOut );
-
-        threadOutputMuxer.associateThreadWithProjectSegment( projectBuildList.get( 0 ) );
-        System.out.print( paid );  // No, this does not print to system.out. It's part of the test
-        assertEquals( paid.length(), byteArrayOutputStream.size() );
-        threadOutputMuxer.associateThreadWithProjectSegment( projectBuildList.get( 1 ) );
-        System.out.print( in );  // No, this does not print to system.out. It's part of the test
-        assertEquals( paid.length(), byteArrayOutputStream.size() );
-        threadOutputMuxer.associateThreadWithProjectSegment( projectBuildList.get( 2 ) );
-        System.out.print( full ); // No, this does not print to system.out. It's part of the test
-        assertEquals( paid.length(), byteArrayOutputStream.size() );
-
-        threadOutputMuxer.setThisModuleComplete( projectBuildList.get( 0 ) );
-        threadOutputMuxer.setThisModuleComplete( projectBuildList.get( 1 ) );
-        threadOutputMuxer.setThisModuleComplete( projectBuildList.get( 2 ) );
-        threadOutputMuxer.close();
-        assertEquals( ( paid + in + full ).length(), byteArrayOutputStream.size() );
-    }
-
-    public void testMultiThreaded()
-        throws Exception
-    {
-        ProjectBuildList projectBuildList = getProjectBuildList();
-
-        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
-        PrintStream systemOut = new PrintStream( byteArrayOutputStream );
-        final ThreadOutputMuxer threadOutputMuxer = new ThreadOutputMuxer( projectBuildList, systemOut );
-
-        final List<String> stringList =
-            Arrays.asList( "Thinkin", "of", "a", "master", "plan", "Cuz", "ain’t", "nuthin", "but", "sweat", "inside",
-                           "my", "hand" );
-        Iterator<String> lyrics = stringList.iterator();
-
-        ExecutorService executor = Executors.newFixedThreadPool( 10 );
-        CompletionService<ProjectSegment> service = new ExecutorCompletionService<ProjectSegment>( executor );
-
-        List<Future<ProjectSegment>> futures = new ArrayList<Future<ProjectSegment>>();
-        for ( ProjectSegment projectBuild : projectBuildList )
-        {
-            final Future<ProjectSegment> buildFuture =
-                service.submit( new Outputter( threadOutputMuxer, projectBuild, lyrics.next() ) );
-            futures.add( buildFuture );
-        }
-
-        for ( Future<ProjectSegment> future : futures )
-        {
-            future.get();
-        }
-        int expectedLength = 0;
-        for ( int i = 0; i < projectBuildList.size(); i++ )
-        {
-            expectedLength += stringList.get( i ).length();
-        }
-
-        threadOutputMuxer.close();
-        final byte[] bytes = byteArrayOutputStream.toByteArray();
-        String result = new String( bytes );
-        assertEquals( result, expectedLength, bytes.length );
-
-
-    }
-
-    class Outputter
-        implements Callable<ProjectSegment>
-    {
-        private final ThreadOutputMuxer threadOutputMuxer;
-
-        private final ProjectSegment item;
-
-        private final String response;
-
-        Outputter( ThreadOutputMuxer threadOutputMuxer, ProjectSegment item, String response )
-        {
-            this.threadOutputMuxer = threadOutputMuxer;
-            this.item = item;
-            this.response = response;
-        }
-
-        public ProjectSegment call()
-            throws Exception
-        {
-            threadOutputMuxer.associateThreadWithProjectSegment( item );
-            System.out.print( response );
-            threadOutputMuxer.setThisModuleComplete( item );
-            return item;
-        }
-    }
-
-
-    private ProjectBuildList getProjectBuildList()
-        throws InvalidPluginDescriptorException, PluginVersionResolutionException, PluginDescriptorParsingException,
-        NoPluginFoundForPrefixException, MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
-        LifecyclePhaseNotFoundException, LifecycleNotFoundException
-    {
-        final MavenSession session = ProjectDependencyGraphStub.getMavenSession();
-        return ProjectDependencyGraphStub.getProjectBuildList( session );
-    }
-}

http://git-wip-us.apache.org/repos/asf/maven/blob/097cc8d2/maven-core/src/test/java/org/apache/maven/lifecycle/internal/builder/multithreaded/ThreadOutputMuxerTest.java
----------------------------------------------------------------------
diff --git a/maven-core/src/test/java/org/apache/maven/lifecycle/internal/builder/multithreaded/ThreadOutputMuxerTest.java b/maven-core/src/test/java/org/apache/maven/lifecycle/internal/builder/multithreaded/ThreadOutputMuxerTest.java
new file mode 100644
index 0000000..dc75a94
--- /dev/null
+++ b/maven-core/src/test/java/org/apache/maven/lifecycle/internal/builder/multithreaded/ThreadOutputMuxerTest.java
@@ -0,0 +1,167 @@
+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 junit.framework.TestCase;
+
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.lifecycle.LifecycleNotFoundException;
+import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
+import org.apache.maven.lifecycle.internal.ProjectBuildList;
+import org.apache.maven.lifecycle.internal.ProjectSegment;
+import org.apache.maven.lifecycle.internal.builder.multithreaded.ThreadOutputMuxer;
+import org.apache.maven.lifecycle.internal.stub.ProjectDependencyGraphStub;
+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.prefix.NoPluginFoundForPrefixException;
+import org.apache.maven.plugin.version.PluginVersionResolutionException;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CompletionService;
+import java.util.concurrent.ExecutorCompletionService;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+/**
+ * @author Kristian Rosenvold
+ */
+public class ThreadOutputMuxerTest
+    extends TestCase
+{
+
+    final String paid = "Paid";
+
+    final String in = "In";
+
+    final String full = "Full";
+
+    public void testSingleThreaded()
+        throws Exception
+    {
+        ProjectBuildList src = getProjectBuildList();
+        ProjectBuildList projectBuildList =
+            new ProjectBuildList( Arrays.asList( src.get( 0 ), src.get( 1 ), src.get( 2 ) ) );
+
+        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+        PrintStream systemOut = new PrintStream( byteArrayOutputStream );
+        ThreadOutputMuxer threadOutputMuxer = new ThreadOutputMuxer( projectBuildList, systemOut );
+
+        threadOutputMuxer.associateThreadWithProjectSegment( projectBuildList.get( 0 ) );
+        System.out.print( paid );  // No, this does not print to system.out. It's part of the test
+        assertEquals( paid.length(), byteArrayOutputStream.size() );
+        threadOutputMuxer.associateThreadWithProjectSegment( projectBuildList.get( 1 ) );
+        System.out.print( in );  // No, this does not print to system.out. It's part of the test
+        assertEquals( paid.length(), byteArrayOutputStream.size() );
+        threadOutputMuxer.associateThreadWithProjectSegment( projectBuildList.get( 2 ) );
+        System.out.print( full ); // No, this does not print to system.out. It's part of the test
+        assertEquals( paid.length(), byteArrayOutputStream.size() );
+
+        threadOutputMuxer.setThisModuleComplete( projectBuildList.get( 0 ) );
+        threadOutputMuxer.setThisModuleComplete( projectBuildList.get( 1 ) );
+        threadOutputMuxer.setThisModuleComplete( projectBuildList.get( 2 ) );
+        threadOutputMuxer.close();
+        assertEquals( ( paid + in + full ).length(), byteArrayOutputStream.size() );
+    }
+
+    public void testMultiThreaded()
+        throws Exception
+    {
+        ProjectBuildList projectBuildList = getProjectBuildList();
+
+        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+        PrintStream systemOut = new PrintStream( byteArrayOutputStream );
+        final ThreadOutputMuxer threadOutputMuxer = new ThreadOutputMuxer( projectBuildList, systemOut );
+
+        final List<String> stringList =
+            Arrays.asList( "Thinkin", "of", "a", "master", "plan", "Cuz", "ain’t", "nuthin", "but", "sweat", "inside",
+                           "my", "hand" );
+        Iterator<String> lyrics = stringList.iterator();
+
+        ExecutorService executor = Executors.newFixedThreadPool( 10 );
+        CompletionService<ProjectSegment> service = new ExecutorCompletionService<ProjectSegment>( executor );
+
+        List<Future<ProjectSegment>> futures = new ArrayList<Future<ProjectSegment>>();
+        for ( ProjectSegment projectBuild : projectBuildList )
+        {
+            final Future<ProjectSegment> buildFuture =
+                service.submit( new Outputter( threadOutputMuxer, projectBuild, lyrics.next() ) );
+            futures.add( buildFuture );
+        }
+
+        for ( Future<ProjectSegment> future : futures )
+        {
+            future.get();
+        }
+        int expectedLength = 0;
+        for ( int i = 0; i < projectBuildList.size(); i++ )
+        {
+            expectedLength += stringList.get( i ).length();
+        }
+
+        threadOutputMuxer.close();
+        final byte[] bytes = byteArrayOutputStream.toByteArray();
+        String result = new String( bytes );
+        assertEquals( result, expectedLength, bytes.length );
+
+
+    }
+
+    class Outputter
+        implements Callable<ProjectSegment>
+    {
+        private final ThreadOutputMuxer threadOutputMuxer;
+
+        private final ProjectSegment item;
+
+        private final String response;
+
+        Outputter( ThreadOutputMuxer threadOutputMuxer, ProjectSegment item, String response )
+        {
+            this.threadOutputMuxer = threadOutputMuxer;
+            this.item = item;
+            this.response = response;
+        }
+
+        public ProjectSegment call()
+            throws Exception
+        {
+            threadOutputMuxer.associateThreadWithProjectSegment( item );
+            System.out.print( response );
+            threadOutputMuxer.setThisModuleComplete( item );
+            return item;
+        }
+    }
+
+
+    private ProjectBuildList getProjectBuildList()
+        throws InvalidPluginDescriptorException, PluginVersionResolutionException, PluginDescriptorParsingException,
+        NoPluginFoundForPrefixException, MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
+        LifecyclePhaseNotFoundException, LifecycleNotFoundException
+    {
+        final MavenSession session = ProjectDependencyGraphStub.getMavenSession();
+        return ProjectDependencyGraphStub.getProjectBuildList( session );
+    }
+}