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