1 package org.apache.maven.lifecycle.internal;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.artifact.Artifact;
23 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
24 import org.apache.maven.artifact.resolver.filter.CumulativeScopeArtifactFilter;
25 import org.apache.maven.execution.ExecutionEvent;
26 import org.apache.maven.execution.MavenSession;
27 import org.apache.maven.lifecycle.LifecycleExecutionException;
28 import org.apache.maven.lifecycle.MissingProjectException;
29 import org.apache.maven.plugin.BuildPluginManager;
30 import org.apache.maven.plugin.MavenPluginManager;
31 import org.apache.maven.plugin.MojoExecution;
32 import org.apache.maven.plugin.MojoExecutionException;
33 import org.apache.maven.plugin.MojoFailureException;
34 import org.apache.maven.plugin.PluginConfigurationException;
35 import org.apache.maven.plugin.PluginIncompatibleException;
36 import org.apache.maven.plugin.PluginManagerException;
37 import org.apache.maven.plugin.descriptor.MojoDescriptor;
38 import org.apache.maven.project.MavenProject;
39 import org.codehaus.plexus.component.annotations.Component;
40 import org.codehaus.plexus.component.annotations.Requirement;
41 import org.codehaus.plexus.util.StringUtils;
42
43 import java.util.ArrayList;
44 import java.util.Arrays;
45 import java.util.Collection;
46 import java.util.Collections;
47 import java.util.List;
48 import java.util.Map;
49 import java.util.Set;
50 import java.util.TreeSet;
51
52
53
54
55
56
57
58
59
60
61
62 @Component( role = MojoExecutor.class )
63 public class MojoExecutor
64 {
65
66 @Requirement
67 private BuildPluginManager pluginManager;
68
69 @Requirement
70 private MavenPluginManager mavenPluginManager;
71
72 @Requirement
73 private LifecycleDependencyResolver lifeCycleDependencyResolver;
74
75 @Requirement
76 private ExecutionEventCatapult eventCatapult;
77
78 public MojoExecutor()
79 {
80 }
81
82 public DependencyContext newDependencyContext( MavenSession session, List<MojoExecution> mojoExecutions )
83 {
84 Set<String> scopesToCollect = new TreeSet<>();
85 Set<String> scopesToResolve = new TreeSet<>();
86
87 collectDependencyRequirements( scopesToResolve, scopesToCollect, mojoExecutions );
88
89 return new DependencyContext( session.getCurrentProject(), scopesToCollect, scopesToResolve );
90 }
91
92 private void collectDependencyRequirements( Set<String> scopesToResolve, Set<String> scopesToCollect,
93 Collection<MojoExecution> mojoExecutions )
94 {
95 for ( MojoExecution mojoExecution : mojoExecutions )
96 {
97 MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
98
99 scopesToResolve.addAll( toScopes( mojoDescriptor.getDependencyResolutionRequired() ) );
100
101 scopesToCollect.addAll( toScopes( mojoDescriptor.getDependencyCollectionRequired() ) );
102 }
103 }
104
105 private Collection<String> toScopes( String classpath )
106 {
107 if ( StringUtils.isNotEmpty( classpath ) )
108 {
109 if ( Artifact.SCOPE_COMPILE.equals( classpath ) )
110 {
111 return Arrays.asList( Artifact.SCOPE_COMPILE, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_PROVIDED );
112 }
113 else if ( Artifact.SCOPE_RUNTIME.equals( classpath ) )
114 {
115 return Arrays.asList( Artifact.SCOPE_COMPILE, Artifact.SCOPE_RUNTIME );
116 }
117 else if ( Artifact.SCOPE_COMPILE_PLUS_RUNTIME.equals( classpath ) )
118 {
119 return Arrays.asList( Artifact.SCOPE_COMPILE, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_PROVIDED,
120 Artifact.SCOPE_RUNTIME );
121 }
122 else if ( Artifact.SCOPE_RUNTIME_PLUS_SYSTEM.equals( classpath ) )
123 {
124 return Arrays.asList( Artifact.SCOPE_COMPILE, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_RUNTIME );
125 }
126 else if ( Artifact.SCOPE_TEST.equals( classpath ) )
127 {
128 return Arrays.asList( Artifact.SCOPE_COMPILE, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_PROVIDED,
129 Artifact.SCOPE_RUNTIME, Artifact.SCOPE_TEST );
130 }
131 }
132 return Collections.emptyList();
133 }
134
135 public void execute( MavenSession session, List<MojoExecution> mojoExecutions, ProjectIndex projectIndex )
136 throws LifecycleExecutionException
137
138 {
139 DependencyContext dependencyContext = newDependencyContext( session, mojoExecutions );
140
141 PhaseRecorder phaseRecorder = new PhaseRecorder( session.getCurrentProject() );
142
143 for ( MojoExecution mojoExecution : mojoExecutions )
144 {
145 execute( session, mojoExecution, projectIndex, dependencyContext, phaseRecorder );
146 }
147 }
148
149 public void execute( MavenSession session, MojoExecution mojoExecution, ProjectIndex projectIndex,
150 DependencyContext dependencyContext, PhaseRecorder phaseRecorder )
151 throws LifecycleExecutionException
152 {
153 execute( session, mojoExecution, projectIndex, dependencyContext );
154 phaseRecorder.observeExecution( mojoExecution );
155 }
156
157 private void execute( MavenSession session, MojoExecution mojoExecution, ProjectIndex projectIndex,
158 DependencyContext dependencyContext )
159 throws LifecycleExecutionException
160 {
161 MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
162
163 try
164 {
165 mavenPluginManager.checkRequiredMavenVersion( mojoDescriptor.getPluginDescriptor() );
166 }
167 catch ( PluginIncompatibleException e )
168 {
169 throw new LifecycleExecutionException( mojoExecution, session.getCurrentProject(), e );
170 }
171
172 if ( mojoDescriptor.isProjectRequired() && !session.getRequest().isProjectPresent() )
173 {
174 Throwable cause = new MissingProjectException(
175 "Goal requires a project to execute" + " but there is no POM in this directory ("
176 + session.getExecutionRootDirectory() + ")."
177 + " Please verify you invoked Maven from the correct directory." );
178 throw new LifecycleExecutionException( mojoExecution, null, cause );
179 }
180
181 if ( mojoDescriptor.isOnlineRequired() && session.isOffline() )
182 {
183 if ( MojoExecution.Source.CLI.equals( mojoExecution.getSource() ) )
184 {
185 Throwable cause = new IllegalStateException(
186 "Goal requires online mode for execution" + " but Maven is currently offline." );
187 throw new LifecycleExecutionException( mojoExecution, session.getCurrentProject(), cause );
188 }
189 else
190 {
191 eventCatapult.fire( ExecutionEvent.Type.MojoSkipped, session, mojoExecution );
192
193 return;
194 }
195 }
196
197 List<MavenProject> forkedProjects = executeForkedExecutions( mojoExecution, session, projectIndex );
198
199 ensureDependenciesAreResolved( mojoDescriptor, session, dependencyContext );
200
201 eventCatapult.fire( ExecutionEvent.Type.MojoStarted, session, mojoExecution );
202
203 try
204 {
205 try
206 {
207 pluginManager.executeMojo( session, mojoExecution );
208 }
209 catch ( MojoFailureException | PluginManagerException | PluginConfigurationException
210 | MojoExecutionException e )
211 {
212 throw new LifecycleExecutionException( mojoExecution, session.getCurrentProject(), e );
213 }
214
215 eventCatapult.fire( ExecutionEvent.Type.MojoSucceeded, session, mojoExecution );
216 }
217 catch ( LifecycleExecutionException e )
218 {
219 eventCatapult.fire( ExecutionEvent.Type.MojoFailed, session, mojoExecution, e );
220
221 throw e;
222 }
223 finally
224 {
225 for ( MavenProject forkedProject : forkedProjects )
226 {
227 forkedProject.setExecutionProject( null );
228 }
229 }
230 }
231
232 public void ensureDependenciesAreResolved( MojoDescriptor mojoDescriptor, MavenSession session,
233 DependencyContext dependencyContext )
234 throws LifecycleExecutionException
235
236 {
237 MavenProject project = dependencyContext.getProject();
238 boolean aggregating = mojoDescriptor.isAggregator();
239
240 if ( dependencyContext.isResolutionRequiredForCurrentProject() )
241 {
242 Collection<String> scopesToCollect = dependencyContext.getScopesToCollectForCurrentProject();
243 Collection<String> scopesToResolve = dependencyContext.getScopesToResolveForCurrentProject();
244
245 lifeCycleDependencyResolver.resolveProjectDependencies( project, scopesToCollect, scopesToResolve, session,
246 aggregating, Collections.<Artifact>emptySet() );
247
248 dependencyContext.synchronizeWithProjectState();
249 }
250
251 if ( aggregating )
252 {
253 Collection<String> scopesToCollect = toScopes( mojoDescriptor.getDependencyCollectionRequired() );
254 Collection<String> scopesToResolve = toScopes( mojoDescriptor.getDependencyResolutionRequired() );
255
256 if ( dependencyContext.isResolutionRequiredForAggregatedProjects( scopesToCollect, scopesToResolve ) )
257 {
258 for ( MavenProject aggregatedProject : session.getProjects() )
259 {
260 if ( aggregatedProject != project )
261 {
262 lifeCycleDependencyResolver.resolveProjectDependencies( aggregatedProject, scopesToCollect,
263 scopesToResolve, session, aggregating,
264 Collections.<Artifact>emptySet() );
265 }
266 }
267 }
268 }
269
270 ArtifactFilter artifactFilter = getArtifactFilter( mojoDescriptor );
271 List<MavenProject> projectsToResolve =
272 LifecycleDependencyResolver.getProjects( session.getCurrentProject(), session,
273 mojoDescriptor.isAggregator() );
274 for ( MavenProject projectToResolve : projectsToResolve )
275 {
276 projectToResolve.setArtifactFilter( artifactFilter );
277 }
278 }
279
280 private ArtifactFilter getArtifactFilter( MojoDescriptor mojoDescriptor )
281 {
282 String scopeToResolve = mojoDescriptor.getDependencyResolutionRequired();
283 String scopeToCollect = mojoDescriptor.getDependencyCollectionRequired();
284
285 List<String> scopes = new ArrayList<>( 2 );
286 if ( StringUtils.isNotEmpty( scopeToCollect ) )
287 {
288 scopes.add( scopeToCollect );
289 }
290 if ( StringUtils.isNotEmpty( scopeToResolve ) )
291 {
292 scopes.add( scopeToResolve );
293 }
294
295 if ( scopes.isEmpty() )
296 {
297 return null;
298 }
299 else
300 {
301 return new CumulativeScopeArtifactFilter( scopes );
302 }
303 }
304
305 public List<MavenProject> executeForkedExecutions( MojoExecution mojoExecution, MavenSession session,
306 ProjectIndex projectIndex )
307 throws LifecycleExecutionException
308 {
309 List<MavenProject> forkedProjects = Collections.emptyList();
310
311 Map<String, List<MojoExecution>> forkedExecutions = mojoExecution.getForkedExecutions();
312
313 if ( !forkedExecutions.isEmpty() )
314 {
315 eventCatapult.fire( ExecutionEvent.Type.ForkStarted, session, mojoExecution );
316
317 MavenProject project = session.getCurrentProject();
318
319 forkedProjects = new ArrayList<>( forkedExecutions.size() );
320
321 try
322 {
323 for ( Map.Entry<String, List<MojoExecution>> fork : forkedExecutions.entrySet() )
324 {
325 String projectId = fork.getKey();
326
327 int index = projectIndex.getIndices().get( projectId );
328
329 MavenProject forkedProject = projectIndex.getProjects().get( projectId );
330
331 forkedProjects.add( forkedProject );
332
333 MavenProject executedProject = forkedProject.clone();
334
335 forkedProject.setExecutionProject( executedProject );
336
337 List<MojoExecution> mojoExecutions = fork.getValue();
338
339 if ( mojoExecutions.isEmpty() )
340 {
341 continue;
342 }
343
344 try
345 {
346 session.setCurrentProject( executedProject );
347 session.getProjects().set( index, executedProject );
348 projectIndex.getProjects().put( projectId, executedProject );
349
350 eventCatapult.fire( ExecutionEvent.Type.ForkedProjectStarted, session, mojoExecution );
351
352 execute( session, mojoExecutions, projectIndex );
353
354 eventCatapult.fire( ExecutionEvent.Type.ForkedProjectSucceeded, session, mojoExecution );
355 }
356 catch ( LifecycleExecutionException e )
357 {
358 eventCatapult.fire( ExecutionEvent.Type.ForkedProjectFailed, session, mojoExecution, e );
359
360 throw e;
361 }
362 finally
363 {
364 projectIndex.getProjects().put( projectId, forkedProject );
365 session.getProjects().set( index, forkedProject );
366 session.setCurrentProject( project );
367 }
368 }
369
370 eventCatapult.fire( ExecutionEvent.Type.ForkSucceeded, session, mojoExecution );
371 }
372 catch ( LifecycleExecutionException e )
373 {
374 eventCatapult.fire( ExecutionEvent.Type.ForkFailed, session, mojoExecution, e );
375
376 throw e;
377 }
378 }
379
380 return forkedProjects;
381 }
382 }