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