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/08 13:29:09 UTC
svn commit: r931884 [4/7] - in /maven/maven-3/trunk:
maven-compat/src/test/java/org/apache/maven/project/
maven-core/src/main/java/org/apache/maven/
maven-core/src/main/java/org/apache/maven/artifact/repository/
maven-core/src/main/java/org/apache/mave...
Added: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleExecutionPlanCalculatorImpl.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleExecutionPlanCalculatorImpl.java?rev=931884&view=auto
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleExecutionPlanCalculatorImpl.java (added)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleExecutionPlanCalculatorImpl.java Thu Apr 8 11:29:07 2010
@@ -0,0 +1,673 @@
+/*
+ * 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.artifact.repository.DefaultRepositoryRequest;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.lifecycle.*;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.model.PluginExecution;
+import org.apache.maven.plugin.*;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+import org.apache.maven.plugin.descriptor.Parameter;
+import org.apache.maven.plugin.descriptor.PluginDescriptor;
+import org.apache.maven.plugin.lifecycle.Execution;
+import org.apache.maven.plugin.lifecycle.Phase;
+import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
+import org.apache.maven.plugin.version.PluginVersionResolutionException;
+import org.apache.maven.plugin.version.PluginVersionResolver;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+import org.codehaus.plexus.util.StringUtils;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * @author Benjamin Bentmann
+ * @author Kristian Rosenvold (Extract class)
+ * <p/>
+ * NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
+ */
+@Component(role = LifecycleExecutionPlanCalculator.class)
+public class LifecycleExecutionPlanCalculatorImpl
+ implements LifecycleExecutionPlanCalculator
+{
+ @Requirement
+ private PluginVersionResolver pluginVersionResolver;
+
+ @Requirement
+ private BuildPluginManager pluginManager;
+
+ @Requirement
+ private DefaultLifecycles defaultLifeCycles;
+
+ @Requirement
+ private MojoDescriptorCreator mojoDescriptorCreator;
+
+ @Requirement
+ private LifecyclePluginResolver lifecyclePluginResolver;
+
+ @SuppressWarnings({"UnusedDeclaration"})
+ public LifecycleExecutionPlanCalculatorImpl()
+ {
+ }
+
+ public LifecycleExecutionPlanCalculatorImpl( BuildPluginManager pluginManager, DefaultLifecycles defaultLifeCycles,
+ MojoDescriptorCreator mojoDescriptorCreator,
+ LifecyclePluginResolver lifecyclePluginResolver )
+ {
+ this.pluginManager = pluginManager;
+ this.defaultLifeCycles = defaultLifeCycles;
+ this.mojoDescriptorCreator = mojoDescriptorCreator;
+ this.lifecyclePluginResolver = lifecyclePluginResolver;
+ }
+
+ public MavenExecutionPlan calculateExecutionPlan( MavenSession session, MavenProject project, List<Object> tasks )
+ throws PluginNotFoundException, PluginResolutionException, LifecyclePhaseNotFoundException,
+ PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException,
+ NoPluginFoundForPrefixException, LifecycleNotFoundException, PluginVersionResolutionException
+ {
+ Set<String> requiredDependencyResolutionScopes = new TreeSet<String>();
+ Set<String> requiredDependencyCollectionScopes = new TreeSet<String>();
+
+ final List<MojoExecution> executions =
+ calculateExecutionPlan( session, project, tasks, requiredDependencyResolutionScopes,
+ requiredDependencyCollectionScopes );
+ final List<ExecutionPlanItem> planItem = defaultLifeCycles.createExecutionPlanItem( project, executions );
+
+ return new MavenExecutionPlan( requiredDependencyResolutionScopes, requiredDependencyCollectionScopes,
+ planItem );
+
+
+ }
+
+ public List<MojoExecution> calculateExecutionPlan( MavenSession session, MavenProject project, List<Object> tasks,
+ Set<String> requiredDependencyResolutionScopes,
+ Set<String> requiredDependencyCollectionScopes )
+ throws PluginNotFoundException, PluginResolutionException, LifecyclePhaseNotFoundException,
+ PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException,
+ NoPluginFoundForPrefixException, LifecycleNotFoundException, PluginVersionResolutionException
+ {
+ lifecyclePluginResolver.resolveMissingPluginVersions( project, session );
+
+ List<MojoExecution> mojoExecutions = new ArrayList<MojoExecution>();
+
+ for ( Object task : tasks )
+ {
+ if ( task instanceof GoalTask )
+ {
+ String pluginGoal = ( (GoalTask) task ).pluginGoal;
+
+ MojoDescriptor mojoDescriptor = mojoDescriptorCreator.getMojoDescriptor( pluginGoal, session, project );
+
+ MojoExecution mojoExecution =
+ new MojoExecution( mojoDescriptor, "default-cli", MojoExecution.Source.CLI );
+
+ mojoExecutions.add( mojoExecution );
+ }
+ else if ( task instanceof LifecycleTask )
+ {
+ String lifecyclePhase = ( (LifecycleTask) task ).getLifecyclePhase();
+
+ Map<String, List<MojoExecution>> phaseToMojoMapping =
+ calculateLifecycleMappings( session, project, lifecyclePhase );
+
+ for ( List<MojoExecution> mojoExecutionsFromLifecycle : phaseToMojoMapping.values() )
+ {
+ mojoExecutions.addAll( mojoExecutionsFromLifecycle );
+ }
+ }
+ else
+ {
+ throw new IllegalStateException( "unexpected task " + task );
+ }
+ }
+
+ for ( MojoExecution mojoExecution : mojoExecutions )
+ {
+ MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
+
+ if ( mojoDescriptor == null )
+ {
+ mojoDescriptor = pluginManager.getMojoDescriptor( mojoExecution.getPlugin(), mojoExecution.getGoal(),
+ DefaultRepositoryRequest.getRepositoryRequest(
+ session, project ) );
+
+ mojoExecution.setMojoDescriptor( mojoDescriptor );
+ }
+
+ populateMojoExecutionConfiguration( project, mojoExecution,
+ MojoExecution.Source.CLI.equals( mojoExecution.getSource() ) );
+
+ finalizeMojoConfiguration( mojoExecution );
+
+ calculateForkedExecutions( mojoExecution, session, project, new HashSet<MojoDescriptor>() );
+
+ collectDependencyRequirements( requiredDependencyResolutionScopes, requiredDependencyCollectionScopes,
+ mojoExecution );
+ }
+
+ return mojoExecutions;
+ }
+
+ private static void collectDependencyRequirements( Collection<String> requiredDependencyResolutionScopes,
+ Collection<String> requiredDependencyCollectionScopes,
+ MojoExecution mojoExecution )
+ {
+ MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
+
+ String requiredDependencyResolutionScope = mojoDescriptor.getDependencyResolutionRequired();
+
+ if ( StringUtils.isNotEmpty( requiredDependencyResolutionScope ) )
+ {
+ requiredDependencyResolutionScopes.add( requiredDependencyResolutionScope );
+ }
+
+ String requiredDependencyCollectionScope = mojoDescriptor.getDependencyCollectionRequired();
+
+ if ( StringUtils.isNotEmpty( requiredDependencyCollectionScope ) )
+ {
+ requiredDependencyCollectionScopes.add( requiredDependencyCollectionScope );
+ }
+
+ for ( List<MojoExecution> forkedExecutions : mojoExecution.getForkedExecutions().values() )
+ {
+ for ( MojoExecution forkedExecution : forkedExecutions )
+ {
+ collectDependencyRequirements( requiredDependencyResolutionScopes, requiredDependencyCollectionScopes,
+ forkedExecution );
+ }
+ }
+ }
+
+
+ private Map<String, List<MojoExecution>> calculateLifecycleMappings( MavenSession session, MavenProject project,
+ String lifecyclePhase )
+ throws LifecyclePhaseNotFoundException, PluginNotFoundException, PluginResolutionException,
+ PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException
+ {
+ /*
+ * Determine the lifecycle that corresponds to the given phase.
+ */
+
+ Lifecycle lifecycle = defaultLifeCycles.get( lifecyclePhase );
+
+ if ( lifecycle == null )
+ {
+ throw new LifecyclePhaseNotFoundException(
+ "Unknown lifecycle phase \"" + lifecyclePhase + "\". You must specify a valid lifecycle phase" +
+ " or a goal in the format <plugin-prefix>:<goal> or" +
+ " <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: " +
+ defaultLifeCycles.getLifecyclePhaseList() + ".", lifecyclePhase );
+ }
+
+ /*
+ * Initialize mapping from lifecycle phase to bound mojos. The key set of this map denotes the phases the caller
+ * is interested in, i.e. all phases up to and including the specified phase.
+ */
+
+ Map<String, Map<Integer, List<MojoExecution>>> mappings =
+ new LinkedHashMap<String, Map<Integer, List<MojoExecution>>>();
+
+ for ( String phase : lifecycle.getPhases() )
+ {
+ Map<Integer, List<MojoExecution>> phaseBindings = new TreeMap<Integer, List<MojoExecution>>();
+
+ mappings.put( phase, phaseBindings );
+
+ if ( phase.equals( lifecyclePhase ) )
+ {
+ break;
+ }
+ }
+
+ /*
+ * Grab plugin executions that are bound to the selected lifecycle phases from project. The effective model of
+ * the project already contains the plugin executions induced by the project's packaging type. Remember, all
+ * phases of interest and only those are in the lifecyle mapping, if a phase has no value in the map, we are not
+ * interested in any of the executions bound to it.
+ */
+
+ for ( Plugin plugin : project.getBuild().getPlugins() )
+ {
+ for ( PluginExecution execution : plugin.getExecutions() )
+ {
+ // if the phase is specified then I don't have to go fetch the plugin yet and pull it down
+ // to examine the phase it is associated to.
+ if ( execution.getPhase() != null )
+ {
+ Map<Integer, List<MojoExecution>> phaseBindings = mappings.get( execution.getPhase() );
+ if ( phaseBindings != null )
+ {
+ for ( String goal : execution.getGoals() )
+ {
+ MojoExecution mojoExecution = new MojoExecution( plugin, goal, execution.getId() );
+ mojoExecution.setLifecyclePhase( execution.getPhase() );
+ addMojoExecution( phaseBindings, mojoExecution, execution.getPriority() );
+ }
+ }
+ }
+ // if not then i need to grab the mojo descriptor and look at the phase that is specified
+ else
+ {
+ for ( String goal : execution.getGoals() )
+ {
+ MojoDescriptor mojoDescriptor = pluginManager.getMojoDescriptor( plugin, goal,
+ DefaultRepositoryRequest.getRepositoryRequest(
+ session, project ) );
+
+ Map<Integer, List<MojoExecution>> phaseBindings = mappings.get( mojoDescriptor.getPhase() );
+ if ( phaseBindings != null )
+ {
+ MojoExecution mojoExecution = new MojoExecution( mojoDescriptor, execution.getId() );
+ mojoExecution.setLifecyclePhase( mojoDescriptor.getPhase() );
+ addMojoExecution( phaseBindings, mojoExecution, execution.getPriority() );
+ }
+ }
+ }
+ }
+ }
+
+ Map<String, List<MojoExecution>> lifecycleMappings = new LinkedHashMap<String, List<MojoExecution>>();
+
+ for ( Map.Entry<String, Map<Integer, List<MojoExecution>>> entry : mappings.entrySet() )
+ {
+ List<MojoExecution> mojoExecutions = new ArrayList<MojoExecution>();
+
+ for ( List<MojoExecution> executions : entry.getValue().values() )
+ {
+ mojoExecutions.addAll( executions );
+ }
+
+ lifecycleMappings.put( entry.getKey(), mojoExecutions );
+ }
+
+ return lifecycleMappings;
+ }
+
+ private void addMojoExecution( Map<Integer, List<MojoExecution>> phaseBindings, MojoExecution mojoExecution,
+ int priority )
+ {
+ List<MojoExecution> mojoExecutions = phaseBindings.get( priority );
+
+ if ( mojoExecutions == null )
+ {
+ mojoExecutions = new ArrayList<MojoExecution>();
+ phaseBindings.put( priority, mojoExecutions );
+ }
+
+ mojoExecutions.add( mojoExecution );
+ }
+
+ private void populateMojoExecutionConfiguration( MavenProject project, MojoExecution mojoExecution,
+ boolean allowPluginLevelConfig )
+ {
+ String g = mojoExecution.getGroupId();
+
+ String a = mojoExecution.getArtifactId();
+
+ Plugin plugin = findPlugin( g, a, project.getBuildPlugins() );
+
+ if ( plugin == null && project.getPluginManagement() != null )
+ {
+ plugin = findPlugin( g, a, project.getPluginManagement().getPlugins() );
+ }
+
+ if ( plugin != null )
+ {
+ PluginExecution pluginExecution =
+ findPluginExecution( mojoExecution.getExecutionId(), plugin.getExecutions() );
+
+ Xpp3Dom pomConfiguration = null;
+
+ if ( pluginExecution != null )
+ {
+ pomConfiguration = (Xpp3Dom) pluginExecution.getConfiguration();
+ }
+ else if ( allowPluginLevelConfig )
+ {
+ pomConfiguration = (Xpp3Dom) plugin.getConfiguration();
+ }
+
+ Xpp3Dom mojoConfiguration = ( pomConfiguration != null ) ? new Xpp3Dom( pomConfiguration ) : null;
+
+ mojoConfiguration = Xpp3Dom.mergeXpp3Dom( mojoExecution.getConfiguration(), mojoConfiguration );
+
+ mojoExecution.setConfiguration( mojoConfiguration );
+ }
+ }
+
+ private Plugin findPlugin( String groupId, String artifactId, Collection<Plugin> plugins )
+ {
+ for ( Plugin plugin : plugins )
+ {
+ if ( artifactId.equals( plugin.getArtifactId() ) && groupId.equals( plugin.getGroupId() ) )
+ {
+ return plugin;
+ }
+ }
+
+ return null;
+ }
+
+ private PluginExecution findPluginExecution( String executionId, Collection<PluginExecution> executions )
+ {
+ if ( StringUtils.isNotEmpty( executionId ) )
+ {
+ for ( PluginExecution execution : executions )
+ {
+ if ( executionId.equals( execution.getId() ) )
+ {
+ return execution;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Post-processes the effective configuration for the specified mojo execution. This step discards all parameters
+ * from the configuration that are not applicable to the mojo and injects the default values for any missing
+ * parameters.
+ *
+ * @param mojoExecution The mojo execution whose configuration should be finalized, must not be {@code null}.
+ */
+ private void finalizeMojoConfiguration( MojoExecution mojoExecution )
+ {
+ MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
+
+ Xpp3Dom executionConfiguration = mojoExecution.getConfiguration();
+ if ( executionConfiguration == null )
+ {
+ executionConfiguration = new Xpp3Dom( "configuration" );
+ }
+
+ Xpp3Dom defaultConfiguration = getMojoConfiguration( mojoDescriptor );
+
+ Xpp3Dom finalConfiguration = new Xpp3Dom( "configuration" );
+
+ if ( mojoDescriptor.getParameters() != null )
+ {
+ for ( Parameter parameter : mojoDescriptor.getParameters() )
+ {
+ Xpp3Dom parameterConfiguration = executionConfiguration.getChild( parameter.getName() );
+
+ if ( parameterConfiguration == null )
+ {
+ parameterConfiguration = executionConfiguration.getChild( parameter.getAlias() );
+ }
+
+ Xpp3Dom parameterDefaults = defaultConfiguration.getChild( parameter.getName() );
+
+ parameterConfiguration =
+ Xpp3Dom.mergeXpp3Dom( parameterConfiguration, parameterDefaults, Boolean.TRUE );
+
+ if ( parameterConfiguration != null )
+ {
+ parameterConfiguration = new Xpp3Dom( parameterConfiguration, parameter.getName() );
+
+ if ( StringUtils.isEmpty( parameterConfiguration.getAttribute( "implementation" ) ) &&
+ StringUtils.isNotEmpty( parameter.getImplementation() ) )
+ {
+ parameterConfiguration.setAttribute( "implementation", parameter.getImplementation() );
+ }
+
+ finalConfiguration.addChild( parameterConfiguration );
+ }
+ }
+ }
+
+ mojoExecution.setConfiguration( finalConfiguration );
+ }
+
+ private Xpp3Dom getMojoConfiguration( MojoDescriptor mojoDescriptor )
+ {
+ return MojoDescriptorCreator.convert( mojoDescriptor );
+ }
+
+ private void calculateForkedExecutions( MojoExecution mojoExecution, MavenSession session, MavenProject project,
+ Collection<MojoDescriptor> alreadyForkedExecutions )
+ throws MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
+ PluginDescriptorParsingException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
+ LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException
+ {
+ MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
+
+ if ( !mojoDescriptor.isForking() )
+ {
+ return;
+ }
+
+ if ( !alreadyForkedExecutions.add( mojoDescriptor ) )
+ {
+ return;
+ }
+
+ List<MavenProject> forkedProjects =
+ LifecycleDependencyResolver.getProjects( project, session, mojoDescriptor.isAggregator() );
+
+ for ( MavenProject forkedProject : forkedProjects )
+ {
+ List<MojoExecution> forkedExecutions;
+
+ if ( StringUtils.isNotEmpty( mojoDescriptor.getExecutePhase() ) )
+ {
+ forkedExecutions =
+ calculateForkedLifecycle( mojoExecution, session, forkedProject, alreadyForkedExecutions );
+ }
+ else
+ {
+ forkedExecutions =
+ calculateForkedGoal( mojoExecution, session, forkedProject, alreadyForkedExecutions );
+ }
+
+ mojoExecution.setForkedExecutions( BuilderCommon.getKey( forkedProject ), forkedExecutions );
+ }
+
+ alreadyForkedExecutions.remove( mojoDescriptor );
+ }
+
+ private List<MojoExecution> calculateForkedLifecycle( MojoExecution mojoExecution, MavenSession session,
+ MavenProject project,
+ Collection<MojoDescriptor> alreadyForkedExecutions )
+ throws MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
+ PluginDescriptorParsingException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
+ LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException
+ {
+ MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
+
+ String forkedPhase = mojoDescriptor.getExecutePhase();
+
+ Map<String, List<MojoExecution>> lifecycleMappings =
+ calculateLifecycleMappings( session, project, forkedPhase );
+
+ for ( List<MojoExecution> forkedExecutions : lifecycleMappings.values() )
+ {
+ for ( MojoExecution forkedExecution : forkedExecutions )
+ {
+ if ( forkedExecution.getMojoDescriptor() == null )
+ {
+ MojoDescriptor forkedMojoDescriptor =
+ pluginManager.getMojoDescriptor( forkedExecution.getPlugin(), forkedExecution.getGoal(),
+ DefaultRepositoryRequest.getRepositoryRequest( session,
+ project ) );
+
+ forkedExecution.setMojoDescriptor( forkedMojoDescriptor );
+ }
+
+ populateMojoExecutionConfiguration( project, forkedExecution, false );
+ }
+ }
+
+ injectLifecycleOverlay( lifecycleMappings, mojoExecution, session, project );
+
+ List<MojoExecution> mojoExecutions = new ArrayList<MojoExecution>();
+
+ for ( List<MojoExecution> forkedExecutions : lifecycleMappings.values() )
+ {
+ for ( MojoExecution forkedExecution : forkedExecutions )
+ {
+ if ( !alreadyForkedExecutions.contains( forkedExecution.getMojoDescriptor() ) )
+ {
+ finalizeMojoConfiguration( forkedExecution );
+
+ calculateForkedExecutions( forkedExecution, session, project, alreadyForkedExecutions );
+
+ mojoExecutions.add( forkedExecution );
+ }
+ }
+ }
+
+ return mojoExecutions;
+ }
+
+ private void injectLifecycleOverlay( Map<String, List<MojoExecution>> lifecycleMappings,
+ MojoExecution mojoExecution, MavenSession session, MavenProject project )
+ throws PluginDescriptorParsingException, LifecycleNotFoundException, MojoNotFoundException,
+ PluginNotFoundException, PluginResolutionException, NoPluginFoundForPrefixException,
+ InvalidPluginDescriptorException, PluginVersionResolutionException
+ {
+ MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
+
+ PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
+
+ String forkedLifecycle = mojoDescriptor.getExecuteLifecycle();
+
+ if ( StringUtils.isEmpty( forkedLifecycle ) )
+ {
+ return;
+ }
+
+ org.apache.maven.plugin.lifecycle.Lifecycle lifecycleOverlay;
+
+ try
+ {
+ lifecycleOverlay = pluginDescriptor.getLifecycleMapping( forkedLifecycle );
+ }
+ catch ( IOException e )
+ {
+ throw new PluginDescriptorParsingException( pluginDescriptor.getPlugin(), pluginDescriptor.getSource(), e );
+ }
+ catch ( XmlPullParserException e )
+ {
+ throw new PluginDescriptorParsingException( pluginDescriptor.getPlugin(), pluginDescriptor.getSource(), e );
+ }
+
+ if ( lifecycleOverlay == null )
+ {
+ throw new LifecycleNotFoundException( forkedLifecycle );
+ }
+
+ for ( Phase phase : lifecycleOverlay.getPhases() )
+ {
+ List<MojoExecution> forkedExecutions = lifecycleMappings.get( phase.getId() );
+
+ if ( forkedExecutions != null )
+ {
+ for ( Execution execution : phase.getExecutions() )
+ {
+ for ( String goal : execution.getGoals() )
+ {
+ MojoDescriptor forkedMojoDescriptor;
+
+ if ( goal.indexOf( ':' ) < 0 )
+ {
+ forkedMojoDescriptor = pluginDescriptor.getMojo( goal );
+ if ( forkedMojoDescriptor == null )
+ {
+ throw new MojoNotFoundException( goal, pluginDescriptor );
+ }
+ }
+ else
+ {
+ forkedMojoDescriptor = mojoDescriptorCreator.getMojoDescriptor( goal, session, project );
+ }
+
+ MojoExecution forkedExecution =
+ new MojoExecution( forkedMojoDescriptor, mojoExecution.getExecutionId() );
+
+ Xpp3Dom forkedConfiguration = (Xpp3Dom) execution.getConfiguration();
+
+ forkedExecution.setConfiguration( forkedConfiguration );
+
+ populateMojoExecutionConfiguration( project, forkedExecution, true );
+
+ forkedExecutions.add( forkedExecution );
+ }
+ }
+
+ Xpp3Dom phaseConfiguration = (Xpp3Dom) phase.getConfiguration();
+
+ if ( phaseConfiguration != null )
+ {
+ for ( MojoExecution forkedExecution : forkedExecutions )
+ {
+ Xpp3Dom forkedConfiguration = forkedExecution.getConfiguration();
+
+ forkedConfiguration = Xpp3Dom.mergeXpp3Dom( phaseConfiguration, forkedConfiguration );
+
+ forkedExecution.setConfiguration( forkedConfiguration );
+ }
+ }
+ }
+ }
+ }
+ // org.apache.maven.plugins:maven-remote-resources-plugin:1.0:process
+ //TODO: take repo mans into account as one may be aggregating prefixes of many
+ //TODO: collect at the root of the repository, read the one at the root, and fetch remote if something is missing
+ // or the user forces the issue
+
+ private List<MojoExecution> calculateForkedGoal( MojoExecution mojoExecution, MavenSession session,
+ MavenProject project,
+ Collection<MojoDescriptor> alreadyForkedExecutions )
+ throws MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
+ PluginDescriptorParsingException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
+ LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException
+ {
+ MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
+
+ PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
+
+ String forkedGoal = mojoDescriptor.getExecuteGoal();
+
+ MojoDescriptor forkedMojoDescriptor = pluginDescriptor.getMojo( forkedGoal );
+ if ( forkedMojoDescriptor == null )
+ {
+ throw new MojoNotFoundException( forkedGoal, pluginDescriptor );
+ }
+
+ if ( alreadyForkedExecutions.contains( forkedMojoDescriptor ) )
+ {
+ return Collections.emptyList();
+ }
+
+ MojoExecution forkedExecution = new MojoExecution( forkedMojoDescriptor, forkedGoal );
+
+ populateMojoExecutionConfiguration( project, forkedExecution, true );
+
+ finalizeMojoConfiguration( forkedExecution );
+
+ calculateForkedExecutions( forkedExecution, session, project, alreadyForkedExecutions );
+
+ return Collections.singletonList( forkedExecution );
+ }
+
+
+}
Propchange: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleExecutionPlanCalculatorImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleModuleBuilder.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleModuleBuilder.java?rev=931884&view=auto
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleModuleBuilder.java (added)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleModuleBuilder.java Thu Apr 8 11:29:07 2010
@@ -0,0 +1,96 @@
+/*
+ * 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.execution.BuildSuccess;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.lifecycle.DefaultLifecycleExecutor;
+import org.apache.maven.lifecycle.LifecycleEventCatapult;
+import org.apache.maven.lifecycle.MavenExecutionPlan;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+
+/**
+ * Builds one or more lifecycles for a full module
+ *
+ * @author Benjamin Bentmann
+ * @author Jason van Zyl
+ * @author Kristian Rosenvold (extracted class)
+ * <p/>
+ * NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
+ */
+@Component(role = LifecycleModuleBuilder.class)
+public class LifecycleModuleBuilder
+{
+ @Requirement
+ private MojoExecutor mojoExecutor;
+
+ @Requirement
+ private BuilderCommon builderCommon;
+
+ public void buildProject( MavenSession session, ReactorContext reactorContext, MavenProject currentProject,
+ TaskSegment taskSegment )
+ {
+ buildProject( session, session, reactorContext, currentProject, taskSegment );
+ }
+
+ public void buildProject( MavenSession session, MavenSession rootSession, ReactorContext reactorContext,
+ MavenProject currentProject, TaskSegment taskSegment )
+ {
+ boolean isAggregating = taskSegment.isAggregating();
+
+ session.setCurrentProject( currentProject );
+
+ long buildStartTime = System.currentTimeMillis();
+
+ try
+ {
+
+ if ( reactorContext.getReactorBuildStatus().isHaltedOrBlacklisted( currentProject ) )
+ {
+ DefaultLifecycleExecutor.fireEvent( session, null, LifecycleEventCatapult.PROJECT_SKIPPED );
+ return;
+ }
+
+ DefaultLifecycleExecutor.fireEvent( session, null, LifecycleEventCatapult.PROJECT_STARTED );
+
+ BuilderCommon.attachToThread( currentProject );
+ MavenExecutionPlan executionPlan = builderCommon.resolveBuildPlan( session, currentProject, taskSegment );
+
+ DependencyContext dependencyContext = new DependencyContext( executionPlan, isAggregating );
+ mojoExecutor.execute( session, executionPlan.getMojoExecutions(), reactorContext.getProjectIndex(),
+ dependencyContext );
+
+ long buildEndTime = System.currentTimeMillis();
+
+ reactorContext.getResult().addBuildSummary(
+ new BuildSuccess( currentProject, buildEndTime - buildStartTime ) );
+
+ DefaultLifecycleExecutor.fireEvent( session, null, LifecycleEventCatapult.PROJECT_SUCCEEDED );
+ }
+ catch ( Exception e )
+ {
+ BuilderCommon.handleBuildError( reactorContext, rootSession, currentProject, e, buildStartTime );
+ }
+ finally
+ {
+ session.setCurrentProject( null );
+
+ Thread.currentThread().setContextClassLoader( reactorContext.getOriginalContextClassLoader() );
+ }
+ }
+}
\ No newline at end of file
Propchange: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleModuleBuilder.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecyclePluginAnalyzerImpl.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecyclePluginAnalyzerImpl.java?rev=931884&view=auto
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecyclePluginAnalyzerImpl.java (added)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecyclePluginAnalyzerImpl.java Thu Apr 8 11:29:07 2010
@@ -0,0 +1,161 @@
+/*
+ * 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.lifecycle.DefaultLifecycles;
+import org.apache.maven.lifecycle.LifeCyclePluginAnalyzer;
+import org.apache.maven.lifecycle.Lifecycle;
+import org.apache.maven.lifecycle.mapping.LifecycleMapping;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.model.PluginExecution;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+import org.codehaus.plexus.logging.Logger;
+import org.codehaus.plexus.util.StringUtils;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Benjamin Bentmann
+ * @author Jason van Zyl
+ * @author jdcasey
+ * @author Kristian Rosenvold (extracted class only)
+ * <p/>
+ * NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
+ */
+@Component(role = LifecyclePluginAnalyzerImpl.class)
+public class LifecyclePluginAnalyzerImpl
+ implements LifeCyclePluginAnalyzer
+{
+ @Requirement
+ private Map<String, LifecycleMapping> lifecycleMappings;
+
+ @Requirement
+ private DefaultLifecycles defaultLifeCycles;
+
+ @Requirement
+ private Logger logger;
+
+
+ public LifecyclePluginAnalyzerImpl()
+ {
+ }
+
+ // These methods deal with construction intact Plugin object that look like they come from a standard
+ // <plugin/> block in a Maven POM. We have to do some wiggling to pull the sources of information
+ // together and this really shows the problem of constructing a sensible default configuration but
+ // it's all encapsulated here so it appears normalized to the POM builder.
+
+ // We are going to take the project packaging and find all plugin in the default lifecycle and create
+ // fully populated Plugin objects, including executions with goals and default configuration taken
+ // from the plugin.xml inside a plugin.
+ //
+
+ public Set<Plugin> getPluginsBoundByDefaultToAllLifecycles( String packaging )
+ {
+ if ( logger.isDebugEnabled() )
+ {
+ logger.debug( "Looking up lifecyle mappings for packaging " + packaging + " from " +
+ Thread.currentThread().getContextClassLoader() );
+ }
+
+ LifecycleMapping lifecycleMappingForPackaging = lifecycleMappings.get( packaging );
+
+ if ( lifecycleMappingForPackaging == null )
+ {
+ return null;
+ }
+
+ Map<Plugin, Plugin> plugins = new LinkedHashMap<Plugin, Plugin>();
+
+ for ( Lifecycle lifecycle : defaultLifeCycles.getLifeCycles() )
+ {
+ org.apache.maven.lifecycle.mapping.Lifecycle lifecycleConfiguration =
+ lifecycleMappingForPackaging.getLifecycles().get( lifecycle.getId() );
+
+ Map<String, String> phaseToGoalMapping = null;
+
+ if ( lifecycleConfiguration != null )
+ {
+ phaseToGoalMapping = lifecycleConfiguration.getPhases();
+ }
+ else if ( lifecycle.getDefaultPhases() != null )
+ {
+ phaseToGoalMapping = lifecycle.getDefaultPhases();
+ }
+
+ if ( phaseToGoalMapping != null )
+ {
+ // These are of the form:
+ //
+ // compile -> org.apache.maven.plugins:maven-compiler-plugin:compile[,gid:aid:goal,...]
+ //
+ for ( Map.Entry<String, String> goalsForLifecyclePhase : phaseToGoalMapping.entrySet() )
+ {
+ String phase = goalsForLifecyclePhase.getKey();
+ String goals = goalsForLifecyclePhase.getValue();
+ if ( goals != null )
+ {
+ parseLifecyclePhaseDefinitions( plugins, phase, goals );
+ }
+ }
+ }
+ }
+
+ return plugins.keySet();
+ }
+
+ private void parseLifecyclePhaseDefinitions( Map<Plugin, Plugin> plugins, String phase, String goals )
+ {
+ String[] mojos = StringUtils.split( goals, "," );
+
+ for ( int i = 0; i < mojos.length; i++ )
+ {
+ // either <groupId>:<artifactId>:<goal> or <groupId>:<artifactId>:<version>:<goal>
+ String goal = mojos[i].trim();
+ String[] p = StringUtils.split( goal, ":" );
+
+ PluginExecution execution = new PluginExecution();
+ execution.setId( "default-" + p[p.length - 1] );
+ execution.setPhase( phase );
+ execution.setPriority( i - mojos.length );
+ execution.getGoals().add( p[p.length - 1] );
+
+ Plugin plugin = new Plugin();
+ plugin.setGroupId( p[0] );
+ plugin.setArtifactId( p[1] );
+ if ( p.length >= 4 )
+ {
+ plugin.setVersion( p[2] );
+ }
+
+ Plugin existing = plugins.get( plugin );
+ if ( existing != null )
+ {
+ plugin = existing;
+ }
+ else
+ {
+ plugins.put( plugin, plugin );
+ }
+
+ plugin.getExecutions().add( execution );
+ }
+ }
+
+
+}
Propchange: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecyclePluginAnalyzerImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecyclePluginResolver.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecyclePluginResolver.java?rev=931884&view=auto
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecyclePluginResolver.java (added)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecyclePluginResolver.java Thu Apr 8 11:29:07 2010
@@ -0,0 +1,86 @@
+/*
+ * 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.execution.MavenSession;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.model.PluginManagement;
+import org.apache.maven.plugin.version.DefaultPluginVersionRequest;
+import org.apache.maven.plugin.version.PluginVersionRequest;
+import org.apache.maven.plugin.version.PluginVersionResolutionException;
+import org.apache.maven.plugin.version.PluginVersionResolver;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Benjamin Bentmann
+ * @author Kristian Rosenvold (Extract class)
+ * <p/>
+ * NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
+ */
+@Component(role = LifecyclePluginResolver.class)
+public class LifecyclePluginResolver
+{
+ @Requirement
+ private PluginVersionResolver pluginVersionResolver;
+
+
+ public LifecyclePluginResolver( PluginVersionResolver pluginVersionResolver )
+ {
+ this.pluginVersionResolver = pluginVersionResolver;
+ }
+
+ @SuppressWarnings({"UnusedDeclaration"})
+ public LifecyclePluginResolver()
+ {
+ }
+
+ public void resolveMissingPluginVersions( MavenProject project, MavenSession session )
+ throws PluginVersionResolutionException
+ {
+ Map<String, String> versions = new HashMap<String, String>();
+
+ for ( Plugin plugin : project.getBuildPlugins() )
+ {
+ if ( plugin.getVersion() == null )
+ {
+ PluginVersionRequest request = new DefaultPluginVersionRequest( plugin, session );
+ plugin.setVersion( pluginVersionResolver.resolve( request ).getVersion() );
+ }
+ versions.put( plugin.getKey(), plugin.getVersion() );
+ }
+
+ PluginManagement pluginManagement = project.getPluginManagement();
+ if ( pluginManagement != null )
+ {
+ for ( Plugin plugin : pluginManagement.getPlugins() )
+ {
+ if ( plugin.getVersion() == null )
+ {
+ plugin.setVersion( versions.get( plugin.getKey() ) );
+ if ( plugin.getVersion() == null )
+ {
+ PluginVersionRequest request = new DefaultPluginVersionRequest( plugin, session );
+ plugin.setVersion( pluginVersionResolver.resolve( request ).getVersion() );
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
Propchange: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecyclePluginResolver.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleTask.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleTask.java?rev=931884&view=auto
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleTask.java (added)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleTask.java Thu Apr 8 11:29:07 2010
@@ -0,0 +1,45 @@
+/*
+ * 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;
+
+/**
+ * A task that is a lifecycle
+ * <p/>
+ * NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
+ *
+ * @author Benjamin Bentmann
+ */
+public final class LifecycleTask
+{
+
+ private final String lifecyclePhase;
+
+ public LifecycleTask( String lifecyclePhase )
+ {
+ this.lifecyclePhase = lifecyclePhase;
+ }
+
+ @Override
+ public String toString()
+ {
+ return getLifecyclePhase();
+ }
+
+ public String getLifecyclePhase()
+ {
+ return lifecyclePhase;
+ }
+}
Propchange: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleTask.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleTaskSegmentCalculator.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleTaskSegmentCalculator.java?rev=931884&view=auto
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleTaskSegmentCalculator.java (added)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleTaskSegmentCalculator.java Thu Apr 8 11:29:07 2010
@@ -0,0 +1,44 @@
+/*
+ * 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.execution.MavenSession;
+import org.apache.maven.plugin.*;
+import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
+import org.apache.maven.plugin.version.PluginVersionResolutionException;
+
+import java.util.List;
+
+/**
+ * Calculates the task segments in the build
+ *
+ * @author Benjamin Bentmann
+ * @author Jason van Zyl
+ * @author jdcasey
+ * @author Kristian Rosenvold (extracted interface)
+ * <p/>
+ * NOTE: This interface is not part of any public api and can be changed or deleted without prior notice.
+ */
+
+public interface LifecycleTaskSegmentCalculator
+{
+ List<TaskSegment> calculateTaskSegments( MavenSession session, List<String> tasks )
+ throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
+ MojoNotFoundException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
+ PluginVersionResolutionException;
+
+ public boolean requiresProject( MavenSession session );
+
+}
Propchange: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleTaskSegmentCalculator.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleTaskSegmentCalculatorImpl.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleTaskSegmentCalculatorImpl.java?rev=931884&view=auto
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleTaskSegmentCalculatorImpl.java (added)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleTaskSegmentCalculatorImpl.java Thu Apr 8 11:29:07 2010
@@ -0,0 +1,122 @@
+/*
+ * 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.execution.MavenSession;
+import org.apache.maven.plugin.*;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
+import org.apache.maven.plugin.version.PluginVersionResolutionException;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Calculates the task segments in the build
+ *
+ * @author Benjamin Bentmann
+ * @author Jason van Zyl
+ * @author jdcasey
+ * @author Kristian Rosenvold (extracted class)
+ * <p/>
+ * NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
+ */
+
+@Component(role = LifecycleTaskSegmentCalculator.class)
+public class LifecycleTaskSegmentCalculatorImpl
+ implements LifecycleTaskSegmentCalculator
+{
+ @Requirement
+ private MojoDescriptorCreator mojoDescriptorCreator;
+
+ @Requirement
+ private LifecyclePluginResolver lifecyclePluginResolver;
+
+ public LifecycleTaskSegmentCalculatorImpl()
+ {
+ }
+
+ public List<TaskSegment> calculateTaskSegments( MavenSession session, List<String> tasks )
+ throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
+ MojoNotFoundException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
+ PluginVersionResolutionException
+ {
+ List<TaskSegment> taskSegments = new ArrayList<TaskSegment>( tasks.size() );
+
+ TaskSegment currentSegment = null;
+
+ for ( String task : tasks )
+ {
+ if ( isGoalSpecification( task ) )
+ {
+ // "pluginPrefix:goal" or "groupId:artifactId[:version]:goal"
+
+ lifecyclePluginResolver.resolveMissingPluginVersions( session.getTopLevelProject(), session );
+
+ MojoDescriptor mojoDescriptor =
+ mojoDescriptorCreator.getMojoDescriptor( task, session, session.getTopLevelProject() );
+
+ boolean aggregating = mojoDescriptor.isAggregator() || !mojoDescriptor.isProjectRequired();
+
+ if ( currentSegment == null || currentSegment.isAggregating() != aggregating )
+ {
+ currentSegment = new TaskSegment( aggregating );
+ taskSegments.add( currentSegment );
+ }
+
+ currentSegment.getTasks().add( new GoalTask( task ) );
+ }
+ else
+ {
+ // lifecycle phase
+
+ if ( currentSegment == null || currentSegment.isAggregating() )
+ {
+ currentSegment = new TaskSegment( false );
+ taskSegments.add( currentSegment );
+ }
+
+ currentSegment.getTasks().add( new LifecycleTask( task ) );
+ }
+ }
+
+ return taskSegments;
+ }
+
+ public boolean requiresProject( MavenSession session )
+ {
+ List<String> goals = session.getGoals();
+ if ( goals != null )
+ {
+ for ( String goal : goals )
+ {
+ if ( !isGoalSpecification( goal ) )
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+
+ private boolean isGoalSpecification( String task )
+ {
+ return task.indexOf( ':' ) >= 0;
+ }
+
+}
\ No newline at end of file
Propchange: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleTaskSegmentCalculatorImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleThreadedBuilder.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleThreadedBuilder.java?rev=931884&view=auto
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleThreadedBuilder.java (added)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleThreadedBuilder.java Thu Apr 8 11:29:07 2010
@@ -0,0 +1,173 @@
+/*
+ * 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.execution.MavenSession;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+import org.codehaus.plexus.logging.Logger;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CompletionService;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+/**
+ * Builds the full lifecycle in weave-mode (phase by phase as opposed to project-by-project)
+ *
+ * @author Kristian Rosenvold
+ * Builds one or more lifecycles for a full module
+ * <p/>
+ * NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
+ */
+@Component(role = LifecycleThreadedBuilder.class)
+public class LifecycleThreadedBuilder
+{
+
+
+ @Requirement
+ private Logger logger;
+
+ @Requirement
+ private LifecycleModuleBuilder lifecycleModuleBuilder;
+
+
+ @SuppressWarnings({"UnusedDeclaration"})
+ public LifecycleThreadedBuilder()
+ {
+ }
+
+ public void build( MavenSession session, ReactorContext reactorContext, ProjectBuildList projectBuilds,
+ List<TaskSegment> currentTaskSegment, ConcurrencyDependencyGraph analyzer,
+ CompletionService<ProjectSegment> service )
+ {
+
+ // Currently disabled
+ ThreadOutputMuxer muxer = null; // new ThreadOutputMuxer( analyzer.getProjectBuilds(), System.out );
+
+ for ( TaskSegment taskSegment : currentTaskSegment )
+ {
+ Map<MavenProject, ProjectSegment> projectBuildMap = projectBuilds.selectSegment( taskSegment );
+ try
+ {
+ multiThreadedProjectTaskSegmentBuild( analyzer, reactorContext, session, service, taskSegment, projectBuildMap, muxer );
+ if ( reactorContext.getReactorBuildStatus().isHalted() )
+ {
+ break;
+ }
+
+ if ( reactorContext.getReactorBuildStatus().isHalted() )
+ {
+ break;
+ }
+ }
+ catch ( Exception e )
+ {
+ break; // Why are we just ignoring this exception? Are exceptions are being used for flow control
+ }
+
+ }
+ }
+
+ private void multiThreadedProjectTaskSegmentBuild( ConcurrencyDependencyGraph analyzer,
+ ReactorContext reactorContext, MavenSession rootSession,
+ CompletionService<ProjectSegment> service,
+ TaskSegment taskSegment, Map<MavenProject, ProjectSegment> projectBuildList,
+ ThreadOutputMuxer muxer )
+ {
+
+ // schedule independent projects
+ for ( MavenProject mavenProject : analyzer.getRootSchedulableBuilds() )
+ {
+ ProjectSegment projectSegment = projectBuildList.get( mavenProject );
+ logger.debug( "Scheduling: " + projectSegment.getProject() );
+ Callable<ProjectSegment> cb =
+ createBuildCallable( rootSession, projectSegment, reactorContext, taskSegment, muxer );
+ service.submit( cb );
+ }
+
+ // for each finished project
+ for ( int i = 0; i < analyzer.getNumberOfBuilds(); i++ )
+ {
+ try
+ {
+ ProjectSegment projectBuild = service.take().get();
+ if ( reactorContext.getReactorBuildStatus().isHalted() )
+ {
+ break;
+ }
+ final List<MavenProject> newItemsThatCanBeBuilt =
+ analyzer.markAsFinished( projectBuild.getProject() );
+ for ( MavenProject mavenProject : newItemsThatCanBeBuilt )
+ {
+ ProjectSegment scheduledDependent = projectBuildList.get( mavenProject );
+ logger.debug( "Scheduling: " + scheduledDependent );
+ Callable<ProjectSegment> cb =
+ createBuildCallable( rootSession, scheduledDependent, reactorContext, taskSegment, muxer );
+ service.submit( cb );
+ }
+ }
+ catch ( InterruptedException e )
+ {
+ break;
+ }
+ catch ( ExecutionException e )
+ {
+ break;
+ }
+ }
+
+ // cancel outstanding builds (if any) - this can happen if an exception is thrown in above block
+
+ Future<ProjectSegment> unprocessed;
+ while ( ( unprocessed = service.poll() ) != null )
+ {
+ try
+ {
+ unprocessed.get();
+ }
+ catch ( InterruptedException e )
+ {
+ throw new RuntimeException( e );
+ }
+ catch ( ExecutionException e )
+ {
+ throw new RuntimeException( e );
+ }
+ }
+ }
+
+ private Callable<ProjectSegment> createBuildCallable( final MavenSession rootSession,
+ final ProjectSegment projectBuild,
+ final ReactorContext reactorContext,
+ final TaskSegment taskSegment, final ThreadOutputMuxer muxer )
+ {
+ return new Callable<ProjectSegment>()
+ {
+ public ProjectSegment call()
+ {
+ // muxer.associateThreadWithProjectSegment( projectBuild );
+ lifecycleModuleBuilder.buildProject( projectBuild.getSession(), rootSession, reactorContext,
+ projectBuild.getProject(), taskSegment );
+ // muxer.setThisModuleComplete( projectBuild );
+
+ return projectBuild;
+ }
+ };
+ }
+}
\ No newline at end of file
Propchange: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleThreadedBuilder.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: 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=931884&view=auto
==============================================================================
--- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleWeaveBuilder.java (added)
+++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleWeaveBuilder.java Thu Apr 8 11:29:07 2010
@@ -0,0 +1,306 @@
+/*
+ * 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.execution.BuildSuccess;
+import org.apache.maven.execution.MavenExecutionRequest;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.lifecycle.*;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+import org.codehaus.plexus.logging.Logger;
+
+import java.util.*;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CompletionService;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+/**
+ * Builds the full lifecycle in weave-mode (phase by phase as opposed to project-by-project)
+ * <p/>
+ * NOTE: Weave mode is still experimental. It may be either promoted to first class citizen
+ * at some later point in time, and it may also be removed entirely. Weave mode has much more aggressive
+ * concurrency behaviour than regular threaded mode, and as such is still under test wrt cross platform stability.
+ * <p/>
+ * To remove weave mode from m3, the following should be removed:
+ * ExecutionPlanItem.schedule w/setters and getters
+ * DefaultLifeCycles.getScheduling() and all its use
+ * ReactorArtifactRepository has a reference to isWeave too.
+ * This class and its usage
+ *
+ * @author Kristian Rosenvold
+ * Builds one or more lifecycles for a full module
+ * <p/>
+ * NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
+ */
+@Component(role = LifecycleWeaveBuilder.class)
+public class LifecycleWeaveBuilder
+{
+ @Requirement
+ private MojoExecutor mojoExecutor;
+
+ @Requirement
+ private BuilderCommon builderCommon;
+
+ @Requirement
+ private Logger logger;
+
+ @Requirement
+ private LifecycleDependencyResolver lifecycleDependencyResolver;
+
+
+ private final Map<MavenProject, MavenExecutionPlan> executionPlans =
+ Collections.synchronizedMap( new HashMap<MavenProject, MavenExecutionPlan>() );
+
+
+ @SuppressWarnings({"UnusedDeclaration"})
+ public LifecycleWeaveBuilder()
+ {
+ }
+
+ public LifecycleWeaveBuilder( MojoExecutor mojoExecutor, BuilderCommon builderCommon, Logger logger,
+ LifecycleDependencyResolver lifecycleDependencyResolver )
+ {
+ this.mojoExecutor = mojoExecutor;
+ this.builderCommon = builderCommon;
+ this.logger = logger;
+ this.lifecycleDependencyResolver = lifecycleDependencyResolver;
+ }
+
+ public void build( ProjectBuildList projectBuilds, ReactorContext buildContext, List<TaskSegment> taskSegments,
+ MavenSession session, CompletionService<ProjectSegment> service, ReactorBuildStatus reactorBuildStatus )
+ throws ExecutionException, InterruptedException
+ {
+ ConcurrentBuildLogger concurrentBuildLogger = new ConcurrentBuildLogger();
+ try
+ {
+ final List<Future<ProjectSegment>> futures = new ArrayList<Future<ProjectSegment>>();
+
+ for ( TaskSegment taskSegment : taskSegments )
+ {
+ ProjectBuildList segmentChunks = projectBuilds.getByTaskSegment( taskSegment );
+ ThreadOutputMuxer muxer = null; // new ThreadOutputMuxer( segmentChunks, System.out );
+ for ( ProjectSegment projectBuild : segmentChunks )
+ {
+ try
+ {
+ MavenExecutionPlan executionPlan =
+ builderCommon.resolveBuildPlan( projectBuild.getSession(), projectBuild.getProject(),
+ projectBuild.getTaskSegment() );
+ executionPlans.put( projectBuild.getProject(), executionPlan );
+ DependencyContext dependencyContext =
+ new DependencyContext( executionPlan, projectBuild.getTaskSegment().isAggregating() );
+
+ final Callable<ProjectSegment> projectBuilder =
+ createCallableForBuildingOneFullModule( buildContext, session, reactorBuildStatus,
+ executionPlan, projectBuild, muxer,
+ dependencyContext, concurrentBuildLogger,
+ projectBuilds );
+
+ futures.add( service.submit( projectBuilder ) );
+ }
+ catch ( Exception e )
+ {
+ throw new ExecutionException( e );
+ }
+ }
+
+ for ( Future<ProjectSegment> buildFuture : futures )
+ {
+ buildFuture.get(); // At this point, this build *is* finished.
+ // Do not leak threads past here or evil gremlins will get you!
+ }
+ futures.clear();
+ }
+ }
+ finally
+ {
+ projectBuilds.closeAll();
+ }
+ logger.info( concurrentBuildLogger.toString() );
+ }
+
+ private Callable<ProjectSegment> createCallableForBuildingOneFullModule( final ReactorContext reactorContext,
+ final MavenSession rootSession,
+ final ReactorBuildStatus reactorBuildStatus,
+ final MavenExecutionPlan executionPlan,
+ final ProjectSegment projectBuild,
+ final ThreadOutputMuxer muxer,
+ final DependencyContext dependencyContext,
+ final ConcurrentBuildLogger concurrentBuildLogger,
+ final ProjectBuildList projectBuilds )
+ {
+ return new Callable<ProjectSegment>()
+ {
+ public ProjectSegment call()
+ throws Exception
+ {
+ Iterator<ExecutionPlanItem> planItems = executionPlan.iterator();
+ ExecutionPlanItem current = planItems.hasNext() ? planItems.next() : null;
+ long buildStartTime = System.currentTimeMillis();
+
+ //muxer.associateThreadWithProjectSegment( projectBuild );
+
+ if ( reactorBuildStatus.isHaltedOrBlacklisted( projectBuild.getProject() ) )
+ {
+ DefaultLifecycleExecutor.fireEvent( projectBuild.getSession(), null,
+ LifecycleEventCatapult.PROJECT_SKIPPED );
+ return null;
+ }
+
+ DefaultLifecycleExecutor.fireEvent( projectBuild.getSession(), null,
+ LifecycleEventCatapult.PROJECT_STARTED );
+
+ boolean packagePhaseSeen = false;
+ boolean runBAbyRun = false;
+ try
+ {
+ while ( current != null && !reactorBuildStatus.isHalted() &&
+ !reactorBuildStatus.isBlackListed( projectBuild.getProject() ) )
+ {
+ final String phase = current.getMojoExecution().getMojoDescriptor().getPhase();
+ PhaseRecorder phaseRecorder = new PhaseRecorder( projectBuild.getProject() );
+
+ if ( !packagePhaseSeen && phase != null && phase.equals( "package" ) )
+ {
+ // Re-resolve. A bit of a kludge ATM
+ packagePhaseSeen = true;
+ lifecycleDependencyResolver.reResolveReactorArtifacts( projectBuilds, false,
+ projectBuild.getProject(),
+ projectBuild.getSession(),
+ executionPlan );
+
+ }
+
+ BuiltLogItem builtLogItem =
+ concurrentBuildLogger.createBuildLogItem( projectBuild.getProject(), current );
+ final Schedule schedule = current.getSchedule();
+
+ if ( schedule != null && schedule.isMojoSynchronized() )
+ {
+ synchronized ( current.getPlugin() )
+ {
+ buildExecutionPlanItem( reactorContext, current, projectBuild, dependencyContext,
+ phaseRecorder );
+ }
+ }
+ else
+ {
+ buildExecutionPlanItem( reactorContext, current, projectBuild, dependencyContext,
+ phaseRecorder );
+ }
+
+ current.setComplete();
+ builtLogItem.setComplete();
+
+ ExecutionPlanItem next = planItems.hasNext() ? planItems.next() : null;
+ if ( next != null )
+ {
+ final Schedule scheduleOfNext = next.getSchedule();
+ if ( !runBAbyRun && ( scheduleOfNext == null || !scheduleOfNext.isParallel() ) )
+ {
+ for ( MavenProject upstreamProject : projectBuild.getImmediateUpstreamProjects() )
+ {
+ final MavenExecutionPlan upstreamPlan = executionPlans.get( upstreamProject );
+ final ExecutionPlanItem inSchedule = upstreamPlan.findLastInPhase( next );
+ if ( inSchedule != null )
+ {
+ long startWait = System.currentTimeMillis();
+ inSchedule.waitUntilDone();
+ builtLogItem.addWait( upstreamProject, inSchedule, startWait );
+ }
+ }
+ }
+ }
+ current = next;
+
+ if ( packagePhaseSeen && !runBAbyRun )
+ {
+ runBAbyRun = true;
+ }
+ }
+
+ final long wallClockTime = System.currentTimeMillis() - buildStartTime;
+ final BuildSuccess summary =
+ new BuildSuccess( projectBuild.getProject(), wallClockTime ); // - waitingTime
+ reactorContext.getResult().addBuildSummary( summary );
+ DefaultLifecycleExecutor.fireEvent( projectBuild.getSession(), null,
+ LifecycleEventCatapult.PROJECT_SUCCEEDED );
+
+ }
+ catch ( Exception e )
+ {
+ BuilderCommon.handleBuildError( reactorContext, rootSession, projectBuild.getProject(), e,
+ buildStartTime );
+ }
+ finally
+ {
+ if ( current != null )
+ {
+ executionPlan.forceAllComplete();
+ }
+ // muxer.setThisModuleComplete( projectBuild );
+ }
+ return null;
+ }
+ };
+ }
+
+ private void buildExecutionPlanItem( ReactorContext reactorContext, ExecutionPlanItem node,
+ ProjectSegment projectBuild, DependencyContext dependencyContext,
+ PhaseRecorder phaseRecorder )
+ throws LifecycleExecutionException
+ {
+
+ MavenProject currentProject = projectBuild.getProject();
+
+ long buildStartTime = System.currentTimeMillis();
+
+ MavenSession sessionForThisModule = projectBuild.getSession();
+ try
+ {
+
+ if ( reactorContext.getReactorBuildStatus().isHaltedOrBlacklisted( currentProject ) )
+ {
+ return;
+ }
+
+ BuilderCommon.attachToThread( currentProject );
+
+ mojoExecutor.execute( sessionForThisModule, node.getMojoExecution(), reactorContext.getProjectIndex(),
+ dependencyContext, phaseRecorder );
+
+ final BuildSuccess summary =
+ new BuildSuccess( currentProject, System.currentTimeMillis() - buildStartTime );
+ reactorContext.getResult().addBuildSummary( summary );
+ }
+ finally
+ {
+ Thread.currentThread().setContextClassLoader( reactorContext.getOriginalContextClassLoader() );
+ }
+ }
+
+ public static boolean isWeaveMode( MavenExecutionRequest request )
+ {
+ return "true".equals( request.getUserProperties().getProperty( "maven3.weaveMode" ) );
+ }
+
+ public static void setWeaveMode( Properties properties )
+ {
+ properties.setProperty( "maven3.weaveMode", "true" );
+ }
+}
\ No newline at end of file
Propchange: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleWeaveBuilder.java
------------------------------------------------------------------------------
svn:eol-style = native