mirror of https://github.com/apache/maven.git
[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 git-svn-id: https://svn.apache.org/repos/asf/maven/maven-3/trunk@934425 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
a315a9dac3
commit
7e5e5eb1da
|
@ -25,6 +25,8 @@ import org.apache.maven.plugin.MojoExecution;
|
|||
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()
|
||||
|
|
|
@ -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 "";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
* 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.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 BuiltLogItem
|
||||
{
|
||||
private final ExecutionPlanItem executionPlanItem;
|
||||
|
||||
private final MavenProject project;
|
||||
|
||||
private final long startTime;
|
||||
|
||||
private long endTime;
|
||||
|
||||
private final List<WaitLogEntry> waits = new ArrayList<WaitLogEntry>();
|
||||
|
||||
public BuiltLogItem( MavenProject project, ExecutionPlanItem executionPlanItem )
|
||||
{
|
||||
this.executionPlanItem = executionPlanItem;
|
||||
this.project = project;
|
||||
startTime = System.currentTimeMillis();
|
||||
|
||||
}
|
||||
|
||||
public void setComplete()
|
||||
{
|
||||
endTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void addWait( MavenProject upstreamProject, ExecutionPlanItem inSchedule, long startWait )
|
||||
{
|
||||
long now = System.currentTimeMillis();
|
||||
if ( ( now - startWait ) > 1 )
|
||||
{
|
||||
waits.add( new WaitLogEntry( upstreamProject, inSchedule, startWait, now ) );
|
||||
}
|
||||
}
|
||||
|
||||
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( executionPlanItem.getMojoExecution().getArtifactId() );
|
||||
for ( WaitLogEntry waitLogEntry : waits )
|
||||
{
|
||||
result.append( waitLogEntry.toString() );
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
class WaitLogEntry
|
||||
{
|
||||
private final ExecutionPlanItem executionPlanItem;
|
||||
|
||||
private final MavenProject upstreamProject;
|
||||
|
||||
private final long start;
|
||||
|
||||
private final long stop;
|
||||
|
||||
WaitLogEntry( MavenProject upstreamProject, ExecutionPlanItem executionPlanItem, long start, long stop )
|
||||
{
|
||||
this.upstreamProject = upstreamProject;
|
||||
this.executionPlanItem = executionPlanItem;
|
||||
this.start = start;
|
||||
this.stop = stop;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return upstreamProject.getName() + " " + executionPlanItem.getMojoExecution().getArtifactId() + ", wait=" +
|
||||
( stop - start );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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() )
|
||||
{
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
@ -69,6 +72,9 @@ public class LifecycleWeaveBuilder
|
|||
@Requirement
|
||||
private Logger logger;
|
||||
|
||||
@Requirement
|
||||
private LifecycleDependencyResolver lifecycleDependencyResolver;
|
||||
|
||||
@Requirement
|
||||
private ExecutionEventCatapult eventCatapult;
|
||||
|
||||
|
@ -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 )
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -59,7 +59,7 @@ public class LifecycleExecutionPlanCalculatorTest
|
|||
|
||||
// Maybe also make one with LifeCycleTasks
|
||||
|
||||
private LifecycleExecutionPlanCalculator createExecutionPlaceCalculator(
|
||||
public static LifecycleExecutionPlanCalculator createExecutionPlaceCalculator(
|
||||
MojoDescriptorCreator mojoDescriptorCreator )
|
||||
{
|
||||
LifecyclePluginResolver lifecyclePluginResolver =
|
||||
|
@ -69,7 +69,7 @@ public class LifecycleExecutionPlanCalculatorTest
|
|||
mojoDescriptorCreator, lifecyclePluginResolver );
|
||||
}
|
||||
|
||||
private MojoDescriptorCreator createMojoDescriptorCreator()
|
||||
public static MojoDescriptorCreator createMojoDescriptorCreator()
|
||||
{
|
||||
return new MojoDescriptorCreator( new PluginVersionResolverStub(), new BuildPluginManagerStub(),
|
||||
new PluginPrefixResolverStub() );
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -168,6 +168,7 @@ public class LifecycleExecutionPlanCalculatorStub
|
|||
MojoExecution result = new MojoExecution( plugin, goal, executionId );
|
||||
result.setConfiguration( new Xpp3Dom( executionId + "-" + goal ) );
|
||||
result.setMojoDescriptor( mojoDescriptor );
|
||||
result.setLifecyclePhase( mojoDescriptor.getPhase() );
|
||||
return result;
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue