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