001package org.apache.maven.lifecycle.internal;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.util.List;
023import java.util.Map;
024
025import org.apache.maven.execution.ExecutionEvent;
026import org.apache.maven.execution.MavenExecutionResult;
027import org.apache.maven.execution.MavenSession;
028import org.apache.maven.lifecycle.DefaultLifecycles;
029import org.apache.maven.lifecycle.MissingProjectException;
030import org.apache.maven.lifecycle.NoGoalSpecifiedException;
031import org.apache.maven.lifecycle.internal.builder.Builder;
032import org.apache.maven.lifecycle.internal.builder.BuilderNotFoundException;
033import org.codehaus.plexus.component.annotations.Component;
034import org.codehaus.plexus.component.annotations.Requirement;
035import org.codehaus.plexus.logging.Logger;
036
037/**
038 * Starts the build life cycle
039 * 
040 * @author Jason van Zyl
041 * @author Benjamin Bentmann
042 * @author Kristian Rosenvold
043 */
044@Component( role = LifecycleStarter.class )
045public class LifecycleStarter
046{
047    @Requirement
048    private ExecutionEventCatapult eventCatapult;
049
050    @Requirement
051    private DefaultLifecycles defaultLifeCycles;
052
053    @Requirement
054    private Logger logger;
055
056    @Requirement
057    private BuildListCalculator buildListCalculator;
058
059    @Requirement
060    private LifecycleDebugLogger lifecycleDebugLogger;
061
062    @Requirement
063    private LifecycleTaskSegmentCalculator lifecycleTaskSegmentCalculator;
064
065    @Requirement
066    private Map<String, Builder> builders;
067
068    public void execute( MavenSession session )
069    {
070        eventCatapult.fire( ExecutionEvent.Type.SessionStarted, session, null );
071
072        ReactorContext reactorContext = null;
073        ProjectBuildList projectBuilds = null;
074        MavenExecutionResult result = session.getResult();
075
076        try
077        {
078            if ( buildExecutionRequiresProject( session ) && projectIsNotPresent( session ) )
079            {
080                throw new MissingProjectException( "The goal you specified requires a project to execute"
081                    + " but there is no POM in this directory (" + session.getExecutionRootDirectory() + ")."
082                    + " Please verify you invoked Maven from the correct directory." );
083            }
084
085            List<TaskSegment> taskSegments = lifecycleTaskSegmentCalculator.calculateTaskSegments( session );
086            projectBuilds = buildListCalculator.calculateProjectBuilds( session, taskSegments );
087
088            if ( projectBuilds.isEmpty() )
089            {
090                throw new NoGoalSpecifiedException( "No goals have been specified for this build."
091                    + " You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or"
092                    + " <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>."
093                    + " Available lifecycle phases are: " + defaultLifeCycles.getLifecyclePhaseList() + "." );
094            }
095
096            ProjectIndex projectIndex = new ProjectIndex( session.getProjects() );
097
098            if ( logger.isDebugEnabled() )
099            {
100                lifecycleDebugLogger.debugReactorPlan( projectBuilds );
101            }
102
103            ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
104            ReactorBuildStatus reactorBuildStatus = new ReactorBuildStatus( session.getProjectDependencyGraph() );
105            reactorContext = new ReactorContext( result, projectIndex, oldContextClassLoader, reactorBuildStatus );
106
107            String builderId = session.getRequest().getBuilderId();
108            Builder builder = builders.get( builderId );
109            if ( builder == null )
110            {
111                throw new BuilderNotFoundException( String.format( "The builder requested using id = %s cannot be found", builderId ) );
112            }
113
114            int degreeOfConcurrency = session.getRequest().getDegreeOfConcurrency();
115            if ( degreeOfConcurrency >= 2 )
116            {
117                logger.info( "" );
118                logger.info( String.format( "Using the %s implementation with a thread count of %d", builder.getClass().getSimpleName(), degreeOfConcurrency ) );
119            }
120            builder.build( session, reactorContext, projectBuilds, taskSegments, reactorBuildStatus );
121
122        }
123        catch ( Exception e )
124        {
125            result.addException( e );
126        }
127        finally
128        {
129            eventCatapult.fire( ExecutionEvent.Type.SessionEnded, session, null );
130        }
131    }
132
133    private boolean buildExecutionRequiresProject( MavenSession session )
134    {
135        return lifecycleTaskSegmentCalculator.requiresProject( session );
136    }
137
138    private boolean projectIsNotPresent( MavenSession session )
139    {
140        return !session.getRequest().isProjectPresent();
141    }
142}