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