diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/MavenExecutionPlan.java b/maven-core/src/main/java/org/apache/maven/lifecycle/MavenExecutionPlan.java index 882f349d64..3a9123fe7f 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/MavenExecutionPlan.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/MavenExecutionPlan.java @@ -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 lastMojoExecutionForAllPhases; - final List phases; + final List phasesInExecutionPlan; public MavenExecutionPlan( Set requiredDependencyResolutionScopes, Set requiredDependencyCollectionScopes, List planItem, @@ -73,61 +75,43 @@ public class MavenExecutionPlan this.requiredDependencyResolutionScopes = requiredDependencyResolutionScopes; this.requiredDependencyCollectionScopes = requiredDependencyCollectionScopes; this.planItem = planItem; - lastMojoExecutionForAllPhases = new HashMap(); + lastMojoExecutionForAllPhases = new LinkedHashMap(); - String firstPhasePreset = getFirstPhasePresentInPlan(); - - List phases = null; + LinkedHashSet totalPhaseSet = new LinkedHashSet(); 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( totalPhaseSet ); Map lastInExistingPhases = new HashMap(); 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 getExecutionPlanItems() @@ -162,6 +138,22 @@ public class MavenExecutionPlan return planItem; } + + private static Iterable getDistinctPhasesInOrderOfExecutionPlanAppearance( + List planItems ) + { + LinkedHashSet result = new LinkedHashSet(); + 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 getRequiredResolutionScopes() { return requiredDependencyResolutionScopes; @@ -191,6 +197,7 @@ public class MavenExecutionPlan } // Used by m2e but will be removed, really. + @SuppressWarnings({"UnusedDeclaration"}) @Deprecated public List getExecutions() diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/BuildLogItem.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/BuildLogItem.java new file mode 100644 index 0000000000..5754bb67cb --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/BuildLogItem.java @@ -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 dependencies = + Collections.synchronizedList( new ArrayList() ); + + 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 ""; + } + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/BuiltLogItem.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/BuiltLogItem.java deleted file mode 100644 index 600bf50b28..0000000000 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/BuiltLogItem.java +++ /dev/null @@ -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 waits = new ArrayList(); - - 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 ); - } - } -} diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ConcurrentBuildLogger.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ConcurrentBuildLogger.java index 5616339f5e..e0a71e3d51 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ConcurrentBuildLogger.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ConcurrentBuildLogger.java @@ -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 items = Collections.synchronizedList( new ArrayList() ); + List items = Collections.synchronizedList( new ArrayList() ); - 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 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 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(); + } + } diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ExecutionPlanItem.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ExecutionPlanItem.java index 55f0bf976b..d4b0d87fcb 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ExecutionPlanItem.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/ExecutionPlanItem.java @@ -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(); diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDebugLogger.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDebugLogger.java index 6c6f63344a..eaba163f4c 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDebugLogger.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDebugLogger.java @@ -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() ) { diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleWeaveBuilder.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleWeaveBuilder.java index 70821fbf75..1f0647dc11 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleWeaveBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleWeaveBuilder.java @@ -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 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() { @@ -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 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 ) 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 new file mode 100644 index 0000000000..f89c282b5d --- /dev/null +++ b/maven-core/src/test/java/org/apache/maven/lifecycle/internal/ConcurrentBuildLoggerTest.java @@ -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 planItemIterator = executionPlan.iterator(); + final BuildLogItem a1 = concurrentBuildLogger.createBuildLogItem( A, planItemIterator.next() ); + + final BuildLogItem a2 = concurrentBuildLogger.createBuildLogItem( A, planItemIterator.next() ); + + final Iterator 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 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 ); + } +} diff --git a/maven-core/src/test/java/org/apache/maven/lifecycle/internal/LifecycleExecutionPlanCalculatorTest.java b/maven-core/src/test/java/org/apache/maven/lifecycle/internal/LifecycleExecutionPlanCalculatorTest.java index a0c2fac6bb..57f79386e4 100644 --- a/maven-core/src/test/java/org/apache/maven/lifecycle/internal/LifecycleExecutionPlanCalculatorTest.java +++ b/maven-core/src/test/java/org/apache/maven/lifecycle/internal/LifecycleExecutionPlanCalculatorTest.java @@ -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() ); 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 index 11c0dca873..cddc1be891 100644 --- 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 @@ -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() diff --git a/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/LifecycleExecutionPlanCalculatorStub.java b/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/LifecycleExecutionPlanCalculatorStub.java index 6e9e997bfd..4a460c8106 100644 --- a/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/LifecycleExecutionPlanCalculatorStub.java +++ b/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/LifecycleExecutionPlanCalculatorStub.java @@ -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; }