View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.lifecycle.internal;
20  
21  import java.util.List;
22  import java.util.Map;
23  import javax.inject.Inject;
24  import javax.inject.Named;
25  import javax.inject.Singleton;
26  import org.apache.maven.execution.ExecutionEvent;
27  import org.apache.maven.execution.MavenExecutionResult;
28  import org.apache.maven.execution.MavenSession;
29  import org.apache.maven.lifecycle.DefaultLifecycles;
30  import org.apache.maven.lifecycle.MissingProjectException;
31  import org.apache.maven.lifecycle.NoGoalSpecifiedException;
32  import org.apache.maven.lifecycle.internal.builder.Builder;
33  import org.apache.maven.lifecycle.internal.builder.BuilderNotFoundException;
34  import org.apache.maven.session.scope.internal.SessionScope;
35  import org.slf4j.Logger;
36  import org.slf4j.LoggerFactory;
37  
38  /**
39   * Starts the build life cycle
40   *
41   * @author Jason van Zyl
42   * @author Benjamin Bentmann
43   * @author Kristian Rosenvold
44   */
45  @Named
46  @Singleton
47  public class LifecycleStarter {
48      private final Logger logger = LoggerFactory.getLogger(getClass());
49  
50      private final ExecutionEventCatapult eventCatapult;
51  
52      private final DefaultLifecycles defaultLifeCycles;
53  
54      private final BuildListCalculator buildListCalculator;
55  
56      private final LifecycleDebugLogger lifecycleDebugLogger;
57  
58      private final LifecycleTaskSegmentCalculator lifecycleTaskSegmentCalculator;
59  
60      private final Map<String, Builder> builders;
61  
62      private final SessionScope sessionScope;
63  
64      @Inject
65      public LifecycleStarter(
66              ExecutionEventCatapult eventCatapult,
67              DefaultLifecycles defaultLifeCycles,
68              BuildListCalculator buildListCalculator,
69              LifecycleDebugLogger lifecycleDebugLogger,
70              LifecycleTaskSegmentCalculator lifecycleTaskSegmentCalculator,
71              Map<String, Builder> builders,
72              SessionScope sessionScope) {
73          this.eventCatapult = eventCatapult;
74          this.defaultLifeCycles = defaultLifeCycles;
75          this.buildListCalculator = buildListCalculator;
76          this.lifecycleDebugLogger = lifecycleDebugLogger;
77          this.lifecycleTaskSegmentCalculator = lifecycleTaskSegmentCalculator;
78          this.builders = builders;
79          this.sessionScope = sessionScope;
80      }
81  
82      public void execute(MavenSession session) {
83          eventCatapult.fire(ExecutionEvent.Type.SessionStarted, session, null);
84  
85          ReactorContext reactorContext = null;
86          ProjectBuildList projectBuilds = null;
87          MavenExecutionResult result = session.getResult();
88  
89          try {
90              if (buildExecutionRequiresProject(session) && projectIsNotPresent(session)) {
91                  throw new MissingProjectException("The goal you specified requires a project to execute"
92                          + " but there is no POM in this directory (" + session.getExecutionRootDirectory() + ")."
93                          + " Please verify you invoked Maven from the correct directory.");
94              }
95  
96              List<TaskSegment> taskSegments = lifecycleTaskSegmentCalculator.calculateTaskSegments(session);
97              projectBuilds = buildListCalculator.calculateProjectBuilds(session, taskSegments);
98  
99              if (projectBuilds.isEmpty()) {
100                 throw new NoGoalSpecifiedException("No goals have been specified for this build."
101                         + " You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or"
102                         + " <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>."
103                         + " Available lifecycle phases are: " + defaultLifeCycles.getLifecyclePhaseList() + ".");
104             }
105 
106             ProjectIndex projectIndex = new ProjectIndex(session.getProjects());
107 
108             if (logger.isDebugEnabled()) {
109                 lifecycleDebugLogger.debugReactorPlan(projectBuilds);
110             }
111 
112             ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
113             ReactorBuildStatus reactorBuildStatus = new ReactorBuildStatus(session.getProjectDependencyGraph());
114             reactorContext = new ReactorContext(result, projectIndex, oldContextClassLoader, reactorBuildStatus);
115 
116             String builderId = session.getRequest().getBuilderId();
117             Builder builder = builders.get(builderId);
118             if (builder == null) {
119                 throw new BuilderNotFoundException(
120                         String.format("The builder requested using id = %s cannot be" + " found", builderId));
121             }
122 
123             int degreeOfConcurrency = session.getRequest().getDegreeOfConcurrency();
124             if (degreeOfConcurrency > 1) {
125                 logger.info("");
126                 logger.info(String.format(
127                         "Using the %s implementation with a thread count of %d",
128                         builder.getClass().getSimpleName(), degreeOfConcurrency));
129             }
130             builder.build(session, reactorContext, projectBuilds, taskSegments, reactorBuildStatus);
131 
132         } catch (Exception e) {
133             result.addException(e);
134         } finally {
135             eventCatapult.fire(ExecutionEvent.Type.SessionEnded, session, null);
136         }
137     }
138 
139     private boolean buildExecutionRequiresProject(MavenSession session) {
140         return lifecycleTaskSegmentCalculator.requiresProject(session);
141     }
142 
143     private boolean projectIsNotPresent(MavenSession session) {
144         return !session.getRequest().isProjectPresent();
145     }
146 }