1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.lifecycle.internal.builder;
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.Set;
27 import java.util.stream.Collectors;
28
29 import org.apache.maven.artifact.Artifact;
30 import org.apache.maven.execution.BuildFailure;
31 import org.apache.maven.execution.ExecutionEvent;
32 import org.apache.maven.execution.MavenExecutionRequest;
33 import org.apache.maven.execution.MavenSession;
34 import org.apache.maven.internal.MultilineMessageHelper;
35 import org.apache.maven.lifecycle.LifecycleExecutionException;
36 import org.apache.maven.lifecycle.LifecycleNotFoundException;
37 import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
38 import org.apache.maven.lifecycle.MavenExecutionPlan;
39 import org.apache.maven.lifecycle.internal.DefaultLifecyclePluginAnalyzer;
40 import org.apache.maven.lifecycle.internal.ExecutionEventCatapult;
41 import org.apache.maven.lifecycle.internal.LifecycleDebugLogger;
42 import org.apache.maven.lifecycle.internal.LifecycleExecutionPlanCalculator;
43 import org.apache.maven.lifecycle.internal.ReactorContext;
44 import org.apache.maven.lifecycle.internal.TaskSegment;
45 import org.apache.maven.model.Plugin;
46 import org.apache.maven.plugin.InvalidPluginDescriptorException;
47 import org.apache.maven.plugin.MojoExecution;
48 import org.apache.maven.plugin.MojoNotFoundException;
49 import org.apache.maven.plugin.PluginDescriptorParsingException;
50 import org.apache.maven.plugin.PluginNotFoundException;
51 import org.apache.maven.plugin.PluginResolutionException;
52 import org.apache.maven.plugin.descriptor.MojoDescriptor;
53 import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
54 import org.apache.maven.plugin.version.PluginVersionResolutionException;
55 import org.apache.maven.project.MavenProject;
56 import org.codehaus.plexus.classworlds.realm.ClassRealm;
57 import org.slf4j.Logger;
58 import org.slf4j.LoggerFactory;
59
60
61
62
63
64
65
66
67
68 @Named
69 @Singleton
70 public class BuilderCommon {
71 private final Logger logger;
72 private final LifecycleDebugLogger lifecycleDebugLogger;
73 private final LifecycleExecutionPlanCalculator lifeCycleExecutionPlanCalculator;
74 private final ExecutionEventCatapult eventCatapult;
75
76 @Inject
77 public BuilderCommon(
78 LifecycleDebugLogger lifecycleDebugLogger,
79 LifecycleExecutionPlanCalculator lifeCycleExecutionPlanCalculator,
80 ExecutionEventCatapult eventCatapult) {
81 this.logger = LoggerFactory.getLogger(getClass());
82 this.lifecycleDebugLogger = lifecycleDebugLogger;
83 this.lifeCycleExecutionPlanCalculator = lifeCycleExecutionPlanCalculator;
84 this.eventCatapult = eventCatapult;
85 }
86
87
88
89
90 BuilderCommon(
91 LifecycleDebugLogger lifecycleDebugLogger,
92 LifecycleExecutionPlanCalculator lifeCycleExecutionPlanCalculator,
93 ExecutionEventCatapult eventCatapult,
94 Logger logger) {
95 this.lifecycleDebugLogger = lifecycleDebugLogger;
96 this.lifeCycleExecutionPlanCalculator = lifeCycleExecutionPlanCalculator;
97 this.eventCatapult = eventCatapult;
98 this.logger = logger;
99 }
100
101 public MavenExecutionPlan resolveBuildPlan(
102 MavenSession session, MavenProject project, TaskSegment taskSegment, Set<Artifact> projectArtifacts)
103 throws PluginNotFoundException, PluginResolutionException, LifecyclePhaseNotFoundException,
104 PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException,
105 NoPluginFoundForPrefixException, LifecycleNotFoundException, PluginVersionResolutionException,
106 LifecycleExecutionException {
107 MavenExecutionPlan executionPlan =
108 lifeCycleExecutionPlanCalculator.calculateExecutionPlan(session, project, taskSegment.getTasks());
109
110 lifecycleDebugLogger.debugProjectPlan(project, executionPlan);
111
112 if (session.getRequest().getDegreeOfConcurrency() > 1
113 && session.getProjects().size() > 1) {
114 final Set<Plugin> unsafePlugins = executionPlan.getNonThreadSafePlugins();
115 if (!unsafePlugins.isEmpty()) {
116 for (String s : MultilineMessageHelper.format(
117 "Your build is requesting parallel execution, but this project contains the following "
118 + "plugin(s) that have goals not marked as thread-safe to support parallel execution.",
119 "While this /may/ work fine, please look for plugin updates and/or "
120 + "request plugins be made thread-safe.",
121 "If reporting an issue, report it against the plugin in question, not against Apache Maven.")) {
122 logger.warn(s);
123 }
124 if (logger.isDebugEnabled()) {
125 final Set<MojoDescriptor> unsafeGoals = executionPlan.getNonThreadSafeMojos();
126 logger.warn("The following goals are not marked as thread-safe in " + project.getName() + ":");
127 for (MojoDescriptor unsafeGoal : unsafeGoals) {
128 logger.warn(" " + unsafeGoal.getId());
129 }
130 } else {
131 logger.warn("The following plugins are not marked as thread-safe in " + project.getName() + ":");
132 for (Plugin unsafePlugin : unsafePlugins) {
133 logger.warn(" " + unsafePlugin.getId());
134 }
135 logger.warn("");
136 logger.warn("Enable verbose output (-X) to see precisely which goals are not marked as"
137 + " thread-safe.");
138 }
139 logger.warn(MultilineMessageHelper.separatorLine());
140 }
141 }
142
143 final String defaulModelId = DefaultLifecyclePluginAnalyzer.DEFAULTLIFECYCLEBINDINGS_MODELID;
144
145 List<String> unversionedPlugins = executionPlan.getMojoExecutions().stream()
146 .map(MojoExecution::getPlugin)
147 .filter(p -> p.getLocation("version") != null
148 && p.getLocation("version").getSource() != null
149 && defaulModelId.equals(
150 p.getLocation("version").getSource().getModelId()))
151 .distinct()
152 .map(Plugin::getArtifactId)
153 .collect(Collectors.toList());
154
155 if (!unversionedPlugins.isEmpty()) {
156 logger.warn("Version not locked for default bindings plugins " + unversionedPlugins
157 + ", you should define versions in pluginManagement section of your " + "pom.xml or parent");
158 }
159
160 return executionPlan;
161 }
162
163 public void handleBuildError(
164 final ReactorContext buildContext,
165 final MavenSession rootSession,
166 final MavenSession currentSession,
167 final MavenProject mavenProject,
168 Throwable t,
169 final long buildStartTime) {
170
171 long buildEndTime = System.currentTimeMillis();
172 buildContext.getResult().addException(t);
173 buildContext.getResult().addBuildSummary(new BuildFailure(mavenProject, buildEndTime - buildStartTime, t));
174
175
176 if (t instanceof Exception && !(t instanceof RuntimeException)) {
177 eventCatapult.fire(ExecutionEvent.Type.ProjectFailed, currentSession, null, (Exception) t);
178 }
179
180
181 if (t instanceof RuntimeException || !(t instanceof Exception)) {
182
183
184 buildContext.getReactorBuildStatus().halt();
185 } else if (MavenExecutionRequest.REACTOR_FAIL_NEVER.equals(rootSession.getReactorFailureBehavior())) {
186
187 } else if (MavenExecutionRequest.REACTOR_FAIL_AT_END.equals(rootSession.getReactorFailureBehavior())) {
188
189 buildContext.getReactorBuildStatus().blackList(mavenProject);
190 } else if (MavenExecutionRequest.REACTOR_FAIL_FAST.equals(rootSession.getReactorFailureBehavior())) {
191 buildContext.getReactorBuildStatus().halt();
192 } else {
193 logger.error("invalid reactor failure behavior " + rootSession.getReactorFailureBehavior());
194 buildContext.getReactorBuildStatus().halt();
195 }
196 }
197
198 public static void attachToThread(MavenProject currentProject) {
199 ClassRealm projectRealm = currentProject.getClassRealm();
200 if (projectRealm != null) {
201 Thread.currentThread().setContextClassLoader(projectRealm);
202 }
203 }
204
205
206
207
208 public static String getKey(MavenProject project) {
209 return project.getGroupId() + ':' + project.getArtifactId() + ':' + project.getVersion();
210 }
211 }