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<String>();
85 Set<String> scopesToResolve = new TreeSet<String>();
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 @SuppressWarnings( { "ThrowableInstanceNeverThrown" } )
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.isUsingPOMsFromFilesystem() )
174 {
175 Throwable cause =
176 new MissingProjectException( "Goal requires a project to execute"
177 + " but there is no POM in this directory (" + 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 =
187 new IllegalStateException( "Goal requires online mode for execution"
188 + " but Maven is currently offline." );
189 throw new LifecycleExecutionException( mojoExecution, session.getCurrentProject(), cause );
190 }
191 else
192 {
193 eventCatapult.fire( ExecutionEvent.Type.MojoSkipped, session, mojoExecution );
194
195 return;
196 }
197 }
198
199 List<MavenProject> forkedProjects = executeForkedExecutions( mojoExecution, session, projectIndex );
200
201 ensureDependenciesAreResolved( mojoDescriptor, session, dependencyContext );
202
203 eventCatapult.fire( ExecutionEvent.Type.MojoStarted, session, mojoExecution );
204
205 try
206 {
207 try
208 {
209 pluginManager.executeMojo( session, mojoExecution );
210 }
211 catch ( MojoFailureException e )
212 {
213 throw new LifecycleExecutionException( mojoExecution, session.getCurrentProject(), e );
214 }
215 catch ( MojoExecutionException e )
216 {
217 throw new LifecycleExecutionException( mojoExecution, session.getCurrentProject(), e );
218 }
219 catch ( PluginConfigurationException e )
220 {
221 throw new LifecycleExecutionException( mojoExecution, session.getCurrentProject(), e );
222 }
223 catch ( PluginManagerException e )
224 {
225 throw new LifecycleExecutionException( mojoExecution, session.getCurrentProject(), e );
226 }
227
228 eventCatapult.fire( ExecutionEvent.Type.MojoSucceeded, session, mojoExecution );
229 }
230 catch ( LifecycleExecutionException e )
231 {
232 eventCatapult.fire( ExecutionEvent.Type.MojoFailed, session, mojoExecution, e );
233
234 throw e;
235 }
236 finally
237 {
238 for ( MavenProject forkedProject : forkedProjects )
239 {
240 forkedProject.setExecutionProject( null );
241 }
242 }
243 }
244
245 public void ensureDependenciesAreResolved( MojoDescriptor mojoDescriptor, MavenSession session,
246 DependencyContext dependencyContext )
247 throws LifecycleExecutionException
248
249 {
250 MavenProject project = dependencyContext.getProject();
251 boolean aggregating = mojoDescriptor.isAggregator();
252
253 if ( dependencyContext.isResolutionRequiredForCurrentProject() )
254 {
255 Collection<String> scopesToCollect = dependencyContext.getScopesToCollectForCurrentProject();
256 Collection<String> scopesToResolve = dependencyContext.getScopesToResolveForCurrentProject();
257
258 lifeCycleDependencyResolver.resolveProjectDependencies( project, scopesToCollect, scopesToResolve, session,
259 aggregating, Collections.<Artifact> emptySet() );
260
261 dependencyContext.synchronizeWithProjectState();
262 }
263
264 if ( aggregating )
265 {
266 Collection<String> scopesToCollect = toScopes( mojoDescriptor.getDependencyCollectionRequired() );
267 Collection<String> scopesToResolve = toScopes( mojoDescriptor.getDependencyResolutionRequired() );
268
269 if ( dependencyContext.isResolutionRequiredForAggregatedProjects( scopesToCollect, scopesToResolve ) )
270 {
271 for ( MavenProject aggregatedProject : session.getProjects() )
272 {
273 if ( aggregatedProject != project )
274 {
275 lifeCycleDependencyResolver.resolveProjectDependencies( aggregatedProject, scopesToCollect,
276 scopesToResolve, session, aggregating,
277 Collections.<Artifact> emptySet() );
278 }
279 }
280 }
281 }
282
283 ArtifactFilter artifactFilter = getArtifactFilter( mojoDescriptor );
284 List<MavenProject> projectsToResolve =
285 LifecycleDependencyResolver.getProjects( session.getCurrentProject(), session,
286 mojoDescriptor.isAggregator() );
287 for ( MavenProject projectToResolve : projectsToResolve )
288 {
289 projectToResolve.setArtifactFilter( artifactFilter );
290 }
291 }
292
293 private ArtifactFilter getArtifactFilter( MojoDescriptor mojoDescriptor )
294 {
295 String scopeToResolve = mojoDescriptor.getDependencyResolutionRequired();
296 String scopeToCollect = mojoDescriptor.getDependencyCollectionRequired();
297
298 List<String> scopes = new ArrayList<String>( 2 );
299 if ( StringUtils.isNotEmpty( scopeToCollect ) )
300 {
301 scopes.add( scopeToCollect );
302 }
303 if ( StringUtils.isNotEmpty( scopeToResolve ) )
304 {
305 scopes.add( scopeToResolve );
306 }
307
308 if ( scopes.isEmpty() )
309 {
310 return null;
311 }
312 else
313 {
314 return new CumulativeScopeArtifactFilter( scopes );
315 }
316 }
317
318 public List<MavenProject> executeForkedExecutions( MojoExecution mojoExecution, MavenSession session,
319 ProjectIndex projectIndex )
320 throws LifecycleExecutionException
321 {
322 List<MavenProject> forkedProjects = Collections.emptyList();
323
324 Map<String, List<MojoExecution>> forkedExecutions = mojoExecution.getForkedExecutions();
325
326 if ( !forkedExecutions.isEmpty() )
327 {
328 eventCatapult.fire( ExecutionEvent.Type.ForkStarted, session, mojoExecution );
329
330 MavenProject project = session.getCurrentProject();
331
332 forkedProjects = new ArrayList<MavenProject>( forkedExecutions.size() );
333
334 try
335 {
336 for ( Map.Entry<String, List<MojoExecution>> fork : forkedExecutions.entrySet() )
337 {
338 String projectId = fork.getKey();
339
340 int index = projectIndex.getIndices().get( projectId );
341
342 MavenProject forkedProject = projectIndex.getProjects().get( projectId );
343
344 forkedProjects.add( forkedProject );
345
346 MavenProject executedProject = forkedProject.clone();
347
348 forkedProject.setExecutionProject( executedProject );
349
350 List<MojoExecution> mojoExecutions = fork.getValue();
351
352 if ( mojoExecutions.isEmpty() )
353 {
354 continue;
355 }
356
357 try
358 {
359 session.setCurrentProject( executedProject );
360 session.getProjects().set( index, executedProject );
361 projectIndex.getProjects().put( projectId, executedProject );
362
363 eventCatapult.fire( ExecutionEvent.Type.ForkedProjectStarted, session, mojoExecution );
364
365 execute( session, mojoExecutions, projectIndex );
366
367 eventCatapult.fire( ExecutionEvent.Type.ForkedProjectSucceeded, session, mojoExecution );
368 }
369 catch ( LifecycleExecutionException e )
370 {
371 eventCatapult.fire( ExecutionEvent.Type.ForkedProjectFailed, session, mojoExecution, e );
372
373 throw e;
374 }
375 finally
376 {
377 projectIndex.getProjects().put( projectId, forkedProject );
378 session.getProjects().set( index, forkedProject );
379 session.setCurrentProject( project );
380 }
381 }
382
383 eventCatapult.fire( ExecutionEvent.Type.ForkSucceeded, session, mojoExecution );
384 }
385 catch ( LifecycleExecutionException e )
386 {
387 eventCatapult.fire( ExecutionEvent.Type.ForkFailed, session, mojoExecution, e );
388
389 throw e;
390 }
391 }
392
393 return forkedProjects;
394 }
395 }