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