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 javax.inject.Inject;
22  import javax.inject.Named;
23  import javax.inject.Singleton;
24  
25  import java.util.List;
26  import java.util.Map;
27  
28  import org.apache.maven.execution.ExecutionEvent;
29  import org.apache.maven.execution.MavenExecutionResult;
30  import org.apache.maven.execution.MavenSession;
31  import org.apache.maven.lifecycle.DefaultLifecycles;
32  import org.apache.maven.lifecycle.MissingProjectException;
33  import org.apache.maven.lifecycle.NoGoalSpecifiedException;
34  import org.apache.maven.lifecycle.internal.builder.Builder;
35  import org.apache.maven.lifecycle.internal.builder.BuilderNotFoundException;
36  import org.apache.maven.session.scope.internal.SessionScope;
37  import org.slf4j.Logger;
38  import org.slf4j.LoggerFactory;
39  
40  /**
41   * Starts the build life cycle
42   *
43   * @author Jason van Zyl
44   * @author Benjamin Bentmann
45   * @author Kristian Rosenvold
46   */
47  @Named
48  @Singleton
49  public class LifecycleStarter {
50      private final Logger logger = LoggerFactory.getLogger(getClass());
51  
52      private final ExecutionEventCatapult eventCatapult;
53  
54      private final DefaultLifecycles defaultLifeCycles;
55  
56      private final BuildListCalculator buildListCalculator;
57  
58      private final LifecycleDebugLogger lifecycleDebugLogger;
59  
60      private final LifecycleTaskSegmentCalculator lifecycleTaskSegmentCalculator;
61  
62      private final Map<String, Builder> builders;
63  
64      private final SessionScope sessionScope;
65  
66      @Inject
67      public LifecycleStarter(
68              ExecutionEventCatapult eventCatapult,
69              DefaultLifecycles defaultLifeCycles,
70              BuildListCalculator buildListCalculator,
71              LifecycleDebugLogger lifecycleDebugLogger,
72              LifecycleTaskSegmentCalculator lifecycleTaskSegmentCalculator,
73              Map<String, Builder> builders,
74              SessionScope sessionScope) {
75          this.eventCatapult = eventCatapult;
76          this.defaultLifeCycles = defaultLifeCycles;
77          this.buildListCalculator = buildListCalculator;
78          this.lifecycleDebugLogger = lifecycleDebugLogger;
79          this.lifecycleTaskSegmentCalculator = lifecycleTaskSegmentCalculator;
80          this.builders = builders;
81          this.sessionScope = sessionScope;
82      }
83  
84      public void execute(MavenSession session) {
85          eventCatapult.fire(ExecutionEvent.Type.SessionStarted, session, null);
86  
87          ReactorContext reactorContext = null;
88          ProjectBuildList projectBuilds = null;
89          MavenExecutionResult result = session.getResult();
90  
91          try {
92              if (buildExecutionRequiresProject(session) && projectIsNotPresent(session)) {
93                  throw new MissingProjectException("The goal you specified requires a project to execute"
94                          + " but there is no POM in this directory (" + session.getExecutionRootDirectory() + ")."
95                          + " Please verify you invoked Maven from the correct directory.");
96              }
97  
98              List<TaskSegment> taskSegments = lifecycleTaskSegmentCalculator.calculateTaskSegments(session);
99              projectBuilds = buildListCalculator.calculateProjectBuilds(session, taskSegments);
100 
101             if (projectBuilds.isEmpty()) {
102                 throw new NoGoalSpecifiedException("No goals have been specified for this build."
103                         + " You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or"
104                         + " <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>."
105                         + " Available lifecycle phases are: " + defaultLifeCycles.getLifecyclePhaseList() + ".");
106             }
107 
108             ProjectIndex projectIndex = new ProjectIndex(session.getProjects());
109 
110             if (logger.isDebugEnabled()) {
111                 lifecycleDebugLogger.debugReactorPlan(projectBuilds);
112             }
113 
114             ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
115             ReactorBuildStatus reactorBuildStatus = new ReactorBuildStatus(session.getProjectDependencyGraph());
116             reactorContext = new ReactorContext(result, projectIndex, oldContextClassLoader, reactorBuildStatus);
117 
118             String builderId = session.getRequest().getBuilderId();
119             Builder builder = builders.get(builderId);
120             if (builder == null) {
121                 throw new BuilderNotFoundException(
122                         String.format("The builder requested using id = %s cannot be" + " found", builderId));
123             }
124 
125             int degreeOfConcurrency = session.getRequest().getDegreeOfConcurrency();
126             if (degreeOfConcurrency > 1) {
127                 logger.info("");
128                 logger.info(String.format(
129                         "Using the %s implementation with a thread count of %d",
130                         builder.getClass().getSimpleName(), degreeOfConcurrency));
131             }
132             builder.build(session, reactorContext, projectBuilds, taskSegments, reactorBuildStatus);
133 
134         } catch (Exception e) {
135             result.addException(e);
136         } finally {
137             eventCatapult.fire(ExecutionEvent.Type.SessionEnded, session, null);
138         }
139     }
140 
141     private boolean buildExecutionRequiresProject(MavenSession session) {
142         return lifecycleTaskSegmentCalculator.requiresProject(session);
143     }
144 
145     private boolean projectIsNotPresent(MavenSession session) {
146         return !session.getRequest().isProjectPresent();
147     }
148 }