You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by kr...@apache.org on 2010/04/15 16:34:42 UTC

svn commit: r934425 - in /maven/maven-3/trunk/maven-core/src: main/java/org/apache/maven/lifecycle/ main/java/org/apache/maven/lifecycle/internal/ test/java/org/apache/maven/lifecycle/internal/ test/java/org/apache/maven/lifecycle/internal/stub/

Author: krosenvold
Date: Thu Apr 15 14:34:42 2010
New Revision: 934425

URL: http://svn.apache.org/viewvc?rev=934425&view=rev
Log:
[MNG-4633] Weave mode operational.

Replaced approximation-based algorithm for detecting upstream-mojo dependencies with
a proper phase based solution. Revised re-resolution strategy of reactor artifacts

There are a few minor performance inefficiencies (only in weave mode), that will be
sorted for beta-2.

Improved logging, and also added initial graphviz-format log output support

Added:
    maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/BuildLogItem.java   (with props)
    maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/lifecycle/internal/ConcurrentBuildLoggerTest.java   (with props)
Removed:
    maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/BuiltLogItem.java
Modified:
    maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/MavenExecutionPlan.java
    maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ConcurrentBuildLogger.java
    maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ExecutionPlanItem.java
    maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDebugLogger.java
    maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleWeaveBuilder.java
    maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/lifecycle/internal/LifecycleExecutionPlanCalculatorTest.java
    maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/lifecycle/internal/LifecycleWeaveBuilderTest.java
    maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/LifecycleExecutionPlanCalculatorStub.java

Modified: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/MavenExecutionPlan.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/MavenExecutionPlan.java?rev=934425&r1=934424&r2=934425&view=diff
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/MavenExecutionPlan.java (original)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/MavenExecutionPlan.java Thu Apr 15 14:34:42 2010
@@ -25,6 +25,8 @@ import org.apache.maven.plugin.MojoExecu
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -64,7 +66,7 @@ public class MavenExecutionPlan
     private final Map<String, ExecutionPlanItem> lastMojoExecutionForAllPhases;
 
 
-    final List<String> phases;
+    final List<String> phasesInExecutionPlan;
 
     public MavenExecutionPlan( Set<String> requiredDependencyResolutionScopes,
                                Set<String> requiredDependencyCollectionScopes, List<ExecutionPlanItem> planItem,
@@ -73,61 +75,43 @@ public class MavenExecutionPlan
         this.requiredDependencyResolutionScopes = requiredDependencyResolutionScopes;
         this.requiredDependencyCollectionScopes = requiredDependencyCollectionScopes;
         this.planItem = planItem;
-        lastMojoExecutionForAllPhases = new HashMap<String, ExecutionPlanItem>();
+        lastMojoExecutionForAllPhases = new LinkedHashMap<String, ExecutionPlanItem>();
 
-        String firstPhasePreset = getFirstPhasePresentInPlan();
-
-        List<String> phases = null;
+        LinkedHashSet<String> totalPhaseSet = new LinkedHashSet<String>();
         if ( defaultLifecycles != null )
         {
-            final Lifecycle lifecycle = defaultLifecycles.get( firstPhasePreset );
-            if ( lifecycle != null )
+            for ( String phase : getDistinctPhasesInOrderOfExecutionPlanAppearance( planItem ) )
             {
-                phases = lifecycle.getPhases();
+                final Lifecycle lifecycle = defaultLifecycles.get( phase );
+                if ( lifecycle != null )
+                {
+                    totalPhaseSet.addAll( lifecycle.getPhases() );
+                }
             }
         }
-        this.phases = phases;
+        this.phasesInExecutionPlan = new ArrayList<String>( totalPhaseSet );
 
         Map<String, ExecutionPlanItem> lastInExistingPhases = new HashMap<String, ExecutionPlanItem>();
         for ( ExecutionPlanItem executionPlanItem : getExecutionPlanItems() )
         {
-            final String phaseName = executionPlanItem.getLifecyclePhase();
-            if ( phaseName != null )
-            {
-                lastInExistingPhases.put( phaseName, executionPlanItem );
-            }
+            lastInExistingPhases.put( executionPlanItem.getLifecyclePhase(), executionPlanItem );
         }
 
         ExecutionPlanItem lastSeenExecutionPlanItem = null;
-        ExecutionPlanItem forThis;
+        ExecutionPlanItem forThisPhase;
 
-        if ( phases != null )
+        for ( String phase : totalPhaseSet )
         {
-            for ( String phase : phases )
+            forThisPhase = lastInExistingPhases.get( phase );
+            if ( forThisPhase != null )
             {
-                forThis = lastInExistingPhases.get( phase );
-                if ( forThis != null )
-                {
-                    lastSeenExecutionPlanItem = forThis;
-                }
-                lastMojoExecutionForAllPhases.put( phase, lastSeenExecutionPlanItem );
-
+                lastSeenExecutionPlanItem = forThisPhase;
             }
+            lastMojoExecutionForAllPhases.put( phase, lastSeenExecutionPlanItem );
+
         }
 
-    }
 
-    private String getFirstPhasePresentInPlan()
-    {
-        for ( ExecutionPlanItem executionPlanItem : getExecutionPlanItems() )
-        {
-            final String phase = executionPlanItem.getLifecyclePhase();
-            if ( phase != null )
-            {
-                return phase;
-            }
-        }
-        return null;
     }
 
 
@@ -146,15 +130,7 @@ public class MavenExecutionPlan
      */
     public ExecutionPlanItem findLastInPhase( String requestedPhase )
     {
-        ExecutionPlanItem result = lastMojoExecutionForAllPhases.get( requestedPhase );
-        int i = phases.indexOf( requestedPhase );
-        while ( result == null && i > 0 )
-        {
-            final String previousPhase = phases.get( --i );
-            result = lastMojoExecutionForAllPhases.get( previousPhase );
-
-        }
-        return result;
+        return lastMojoExecutionForAllPhases.get( requestedPhase );
     }
 
     private List<ExecutionPlanItem> getExecutionPlanItems()
@@ -162,6 +138,22 @@ public class MavenExecutionPlan
         return planItem;
     }
 
+
+    private static Iterable<String> getDistinctPhasesInOrderOfExecutionPlanAppearance(
+        List<ExecutionPlanItem> planItems )
+    {
+        LinkedHashSet<String> result = new LinkedHashSet<String>();
+        for ( ExecutionPlanItem executionPlanItem : planItems )
+        {
+            final String phase = executionPlanItem.getLifecyclePhase();
+            if ( !result.contains( phase ) )
+            {
+                result.add( phase );
+            }
+        }
+        return result;
+    }
+
     public void forceAllComplete()
     {
         for ( ExecutionPlanItem executionPlanItem : getExecutionPlanItems() )
@@ -170,6 +162,20 @@ public class MavenExecutionPlan
         }
     }
 
+    public void waitUntilAllDone()
+        throws InterruptedException
+    {
+        for ( ExecutionPlanItem executionPlanItem : getExecutionPlanItems() )
+        {
+            executionPlanItem.waitUntilDone();
+        }
+    }
+
+    public boolean containsPhase( String phase )
+    {
+        return phasesInExecutionPlan.contains( phase );
+    }
+
     public Set<String> getRequiredResolutionScopes()
     {
         return requiredDependencyResolutionScopes;
@@ -191,6 +197,7 @@ public class MavenExecutionPlan
     }
 
     // Used by m2e but will be removed, really. 
+
     @SuppressWarnings({"UnusedDeclaration"})
     @Deprecated
     public List<MojoExecution> getExecutions()

Added: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/BuildLogItem.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/BuildLogItem.java?rev=934425&view=auto
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/BuildLogItem.java (added)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/BuildLogItem.java Thu Apr 15 14:34:42 2010
@@ -0,0 +1,214 @@
+/*
+ * 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.
+ */
+package org.apache.maven.lifecycle.internal;
+
+import org.apache.maven.project.MavenProject;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @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 "";
+        }
+    }
+
+}

Propchange: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/BuildLogItem.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ConcurrentBuildLogger.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ConcurrentBuildLogger.java?rev=934425&r1=934424&r2=934425&view=diff
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ConcurrentBuildLogger.java (original)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ConcurrentBuildLogger.java Thu Apr 15 14:34:42 2010
@@ -14,9 +14,12 @@
  */
 package org.apache.maven.lifecycle.internal;
 
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
 import org.apache.maven.project.MavenProject;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -44,12 +47,12 @@ public class ConcurrentBuildLogger
     }
 
 
-    List<BuiltLogItem> items = Collections.synchronizedList( new ArrayList<BuiltLogItem>() );
+    List<BuildLogItem> items = Collections.synchronizedList( new ArrayList<BuildLogItem>() );
 
-    public BuiltLogItem createBuildLogItem( MavenProject project, ExecutionPlanItem current )
+    public BuildLogItem createBuildLogItem( MavenProject project, ExecutionPlanItem current )
     {
         threadMap.put( project, Thread.currentThread() );
-        BuiltLogItem result = new BuiltLogItem( project, current );
+        BuildLogItem result = new BuildLogItem( project, current );
         items.add( result );
         return result;
     }
@@ -65,11 +68,44 @@ public class ConcurrentBuildLogger
             result.append( "\n" );
         }
 
-        for ( BuiltLogItem builtLogItem : items )
+        for ( BuildLogItem builtLogItem : items )
         {
             result.append( builtLogItem.toString( startTime ) );
             result.append( "\n" );
         }
         return result.toString();
     }
+
+    public String toGraph()
+    {
+        StringBuilder result = new StringBuilder();
+
+        Multimap<MavenProject, BuildLogItem> multiMap = ArrayListMultimap.create();
+        for ( BuildLogItem builtLogItem : items )
+        {
+            multiMap.put( builtLogItem.getProject(), 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();
+    }
+
 }

Modified: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ExecutionPlanItem.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ExecutionPlanItem.java?rev=934425&r1=934424&r2=934425&view=diff
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ExecutionPlanItem.java (original)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ExecutionPlanItem.java Thu Apr 15 14:34:42 2010
@@ -52,11 +52,6 @@ public class ExecutionPlanItem
 
     public String getLifecyclePhase()
     {
-        final MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
-        if ( mojoDescriptor.getPhase() != null )
-        {
-            return mojoDescriptor.getPhase();
-        }
         return mojoExecution.getLifecyclePhase();
     }
 
@@ -110,18 +105,6 @@ public class ExecutionPlanItem
         return schedule;
     }
 
-    public boolean hasSchedule( Schedule other )
-    {
-        if ( getSchedule() != null && !getSchedule().isMissingPhase() )
-        {
-            if ( other.getPhase().equals( getSchedule().getPhase() ) )
-            {
-                return true;
-            }
-        }
-        return false;
-    }
-
     public Plugin getPlugin()
     {
         final MojoDescriptor mojoDescriptor = getMojoExecution().getMojoDescriptor();

Modified: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDebugLogger.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDebugLogger.java?rev=934425&r1=934424&r2=934425&view=diff
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDebugLogger.java (original)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDebugLogger.java Thu Apr 15 14:34:42 2010
@@ -142,7 +142,7 @@ public class LifecycleDebugLogger
         }
 
         final ProjectDependencyGraph dependencyGraph = session.getProjectDependencyGraph();
-        logger.info( "=== WEAVE CONCURRENCY BUILD PLAN ================================================" );
+        logger.info( "=== WEAVE CONCURRENCY BUILD PLAN ======================================" );
         for ( MavenProject mavenProject : dependencyGraph.getSortedProjects() )
         {
 

Modified: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleWeaveBuilder.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleWeaveBuilder.java?rev=934425&r1=934424&r2=934425&view=diff
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleWeaveBuilder.java (original)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleWeaveBuilder.java Thu Apr 15 14:34:42 2010
@@ -14,6 +14,8 @@
  */
 package org.apache.maven.lifecycle.internal;
 
+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;
@@ -33,6 +35,7 @@ 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;
@@ -70,6 +73,9 @@ public class LifecycleWeaveBuilder
     private Logger logger;
 
     @Requirement
+    private LifecycleDependencyResolver lifecycleDependencyResolver;
+
+    @Requirement
     private ExecutionEventCatapult eventCatapult;
 
     private final Map<MavenProject, MavenExecutionPlan> executionPlans =
@@ -82,6 +88,7 @@ public class LifecycleWeaveBuilder
     }
 
     public LifecycleWeaveBuilder( MojoExecutor mojoExecutor, BuilderCommon builderCommon, Logger logger,
+                                  LifecycleDependencyResolver lifecycleDependencyResolver,
                                   ExecutionEventCatapult eventCatapult )
     {
         this.mojoExecutor = mojoExecutor;
@@ -118,7 +125,8 @@ public class LifecycleWeaveBuilder
                         final Callable<ProjectSegment> projectBuilder =
                             createCallableForBuildingOneFullModule( buildContext, session, reactorBuildStatus,
                                                                     executionPlan, projectBuild, muxer,
-                                                                    dependencyContext, concurrentBuildLogger );
+                                                                    dependencyContext, concurrentBuildLogger,
+                                                                    projectBuilds );
 
                         futures.add( service.submit( projectBuilder ) );
                     }
@@ -150,7 +158,8 @@ public class LifecycleWeaveBuilder
                                                                              final ProjectSegment projectBuild,
                                                                              final ThreadOutputMuxer muxer,
                                                                              final DependencyContext dependencyContext,
-                                                                             final ConcurrentBuildLogger concurrentBuildLogger )
+                                                                             final ConcurrentBuildLogger concurrentBuildLogger,
+                                                                             final ProjectBuildList projectBuilds )
     {
         return new Callable<ProjectSegment>()
         {
@@ -178,7 +187,7 @@ public class LifecycleWeaveBuilder
                     {
                         PhaseRecorder phaseRecorder = new PhaseRecorder( projectBuild.getProject() );
 
-                        BuiltLogItem builtLogItem =
+                        BuildLogItem builtLogItem =
                             concurrentBuildLogger.createBuildLogItem( projectBuild.getProject(), current );
                         final Schedule schedule = current.getSchedule();
 
@@ -202,6 +211,9 @@ public class LifecycleWeaveBuilder
                         ExecutionPlanItem nextPlanItem = planItems.hasNext() ? planItems.next() : null;
                         if ( nextPlanItem != null )
                         {
+
+                            boolean mustReResolved = false;
+
                             final Schedule scheduleOfNext = nextPlanItem.getSchedule();
                             if ( scheduleOfNext == null || !scheduleOfNext.isParallel() )
                             {
@@ -210,14 +222,52 @@ public class LifecycleWeaveBuilder
                                     final MavenExecutionPlan upstreamPlan = executionPlans.get( upstreamProject );
                                     final String nextPhase = nextPlanItem.getLifecyclePhase();
                                     final ExecutionPlanItem inSchedule = upstreamPlan.findLastInPhase( nextPhase );
+
                                     if ( inSchedule != null )
                                     {
+                                        if ( upstreamPhaseModifiesArtifactResolutionState( inSchedule ) )
+                                        {
+                                            String key = ArtifactUtils.key( upstreamProject.getGroupId(),
+                                                                            upstreamProject.getArtifactId(),
+                                                                            upstreamProject.getVersion() );
+                                            final Set<Artifact> deps =
+                                                projectBuild.getProject().getDependencyArtifacts();
+                                            for ( Artifact dep : deps )
+                                            {
+                                                String depKey =
+                                                    ArtifactUtils.key( dep.getGroupId(), dep.getArtifactId(),
+                                                                       dep.getVersion() );
+                                                if ( key.equals( depKey ) )
+                                                {
+                                                    dep.setResolved( false );
+                                                    mustReResolved = true;
+                                                }
+                                            }
+                                        }
                                         long startWait = System.currentTimeMillis();
                                         inSchedule.waitUntilDone();
                                         builtLogItem.addWait( upstreamProject, inSchedule, 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" );
+                                    }
                                 }
                             }
+                            if ( mustReResolved )
+                            {
+                                lifecycleDependencyResolver.resolveDependencies( false, projectBuild.getProject(),
+                                                                                 projectBuild.getSession(),
+                                                                                 executionPlan );
+                            }
                         }
                         current = nextPlanItem;
                     }
@@ -246,6 +296,12 @@ public class LifecycleWeaveBuilder
         };
     }
 
+    private boolean upstreamPhaseModifiesArtifactResolutionState( ExecutionPlanItem inSchedule )
+    {
+        final String phase = inSchedule.getLifecyclePhase();
+        return "install".equals( phase ) || "compile".equals( phase ) || "test-compile".equals( phase );
+    }
+
     private void buildExecutionPlanItem( ReactorContext reactorContext, ExecutionPlanItem node,
                                          ProjectSegment projectBuild, DependencyContext dependencyContext,
                                          PhaseRecorder phaseRecorder )

Added: maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/lifecycle/internal/ConcurrentBuildLoggerTest.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/lifecycle/internal/ConcurrentBuildLoggerTest.java?rev=934425&view=auto
==============================================================================
--- maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/lifecycle/internal/ConcurrentBuildLoggerTest.java (added)
+++ maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/lifecycle/internal/ConcurrentBuildLoggerTest.java Thu Apr 15 14:34:42 2010
@@ -0,0 +1,73 @@
+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.MavenExecutionPlan;
+import org.apache.maven.lifecycle.internal.stub.ProjectDependencyGraphStub;
+import org.apache.maven.project.MavenProject;
+
+import java.util.Iterator;
+
+/**
+ * @author Kristian Rosenvold
+ */
+public class ConcurrentBuildLoggerTest
+    extends TestCase
+{
+    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.indexOf( "digraph" ) >= 0 );
+    }
+}

Propchange: maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/lifecycle/internal/ConcurrentBuildLoggerTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/lifecycle/internal/LifecycleExecutionPlanCalculatorTest.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/lifecycle/internal/LifecycleExecutionPlanCalculatorTest.java?rev=934425&r1=934424&r2=934425&view=diff
==============================================================================
--- maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/lifecycle/internal/LifecycleExecutionPlanCalculatorTest.java (original)
+++ maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/lifecycle/internal/LifecycleExecutionPlanCalculatorTest.java Thu Apr 15 14:34:42 2010
@@ -59,7 +59,7 @@ public class LifecycleExecutionPlanCalcu
 
     // Maybe also make one with LifeCycleTasks
 
-    private LifecycleExecutionPlanCalculator createExecutionPlaceCalculator(
+    public static LifecycleExecutionPlanCalculator createExecutionPlaceCalculator(
         MojoDescriptorCreator mojoDescriptorCreator )
     {
         LifecyclePluginResolver lifecyclePluginResolver =
@@ -69,7 +69,7 @@ public class LifecycleExecutionPlanCalcu
                                                          mojoDescriptorCreator, lifecyclePluginResolver );
     }
 
-    private MojoDescriptorCreator createMojoDescriptorCreator()
+    public static MojoDescriptorCreator createMojoDescriptorCreator()
     {
         return new MojoDescriptorCreator( new PluginVersionResolverStub(), new BuildPluginManagerStub(),
                                           new PluginPrefixResolverStub() );

Modified: maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/lifecycle/internal/LifecycleWeaveBuilderTest.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/lifecycle/internal/LifecycleWeaveBuilderTest.java?rev=934425&r1=934424&r2=934425&view=diff
==============================================================================
--- maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/lifecycle/internal/LifecycleWeaveBuilderTest.java (original)
+++ maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/lifecycle/internal/LifecycleWeaveBuilderTest.java Thu Apr 15 14:34:42 2010
@@ -122,7 +122,8 @@ public class LifecycleWeaveBuilderTest
         final LoggerStub loggerStub = new LoggerStub();
         final LifecycleDependencyResolver lifecycleDependencyResolver =
             new LifecycleDependencyResolver( new ProjectDependenciesResolverStub(), loggerStub );
-        return new LifecycleWeaveBuilder( mojoExecutor, builderCommon, loggerStub, new ExecutionEventCatapultStub() );
+        return new LifecycleWeaveBuilder( mojoExecutor, builderCommon, loggerStub, lifecycleDependencyResolver,
+                                          new ExecutionEventCatapultStub() );
     }
 
     private BuilderCommon getBuilderCommon()

Modified: maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/LifecycleExecutionPlanCalculatorStub.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/LifecycleExecutionPlanCalculatorStub.java?rev=934425&r1=934424&r2=934425&view=diff
==============================================================================
--- maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/LifecycleExecutionPlanCalculatorStub.java (original)
+++ maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/LifecycleExecutionPlanCalculatorStub.java Thu Apr 15 14:34:42 2010
@@ -168,6 +168,7 @@ public class LifecycleExecutionPlanCalcu
         MojoExecution result = new MojoExecution( plugin, goal, executionId );
         result.setConfiguration( new Xpp3Dom( executionId + "-" + goal ) );
         result.setMojoDescriptor( mojoDescriptor );
+        result.setLifecyclePhase(  mojoDescriptor.getPhase() );
         return result;
 
     }