1 package org.apache.maven;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 import java.io.File;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.text.SimpleDateFormat;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.Date;
27 import java.util.HashSet;
28 import java.util.LinkedHashMap;
29 import java.util.LinkedHashSet;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Properties;
33
34 import org.apache.maven.artifact.ArtifactUtils;
35 import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
36 import org.apache.maven.eventspy.internal.EventSpyDispatcher;
37 import org.apache.maven.execution.DefaultMavenExecutionResult;
38 import org.apache.maven.execution.ExecutionEvent;
39 import org.apache.maven.execution.MavenExecutionRequest;
40 import org.apache.maven.execution.MavenExecutionRequestPopulationException;
41 import org.apache.maven.execution.MavenExecutionRequestPopulator;
42 import org.apache.maven.execution.MavenExecutionResult;
43 import org.apache.maven.execution.MavenSession;
44 import org.apache.maven.execution.ProjectDependencyGraph;
45 import org.apache.maven.lifecycle.internal.ExecutionEventCatapult;
46 import org.apache.maven.lifecycle.internal.LifecycleStarter;
47 import org.apache.maven.model.building.ModelProblem;
48 import org.apache.maven.model.building.ModelProblemUtils;
49 import org.apache.maven.model.building.ModelSource;
50 import org.apache.maven.model.building.UrlModelSource;
51 import org.apache.maven.plugin.LegacySupport;
52 import org.apache.maven.project.DuplicateProjectException;
53 import org.apache.maven.project.MavenProject;
54 import org.apache.maven.project.ProjectBuilder;
55 import org.apache.maven.project.ProjectBuildingException;
56 import org.apache.maven.project.ProjectBuildingRequest;
57 import org.apache.maven.project.ProjectBuildingResult;
58 import org.apache.maven.project.ProjectSorter;
59 import org.apache.maven.repository.DelegatingLocalArtifactRepository;
60 import org.apache.maven.repository.LocalRepositoryNotAccessibleException;
61 import org.apache.maven.settings.Mirror;
62 import org.apache.maven.settings.Proxy;
63 import org.apache.maven.settings.Server;
64 import org.apache.maven.settings.building.SettingsProblem;
65 import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest;
66 import org.apache.maven.settings.crypto.SettingsDecrypter;
67 import org.apache.maven.settings.crypto.SettingsDecryptionResult;
68 import org.codehaus.plexus.PlexusContainer;
69 import org.codehaus.plexus.component.annotations.Component;
70 import org.codehaus.plexus.component.annotations.Requirement;
71 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
72 import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
73 import org.codehaus.plexus.logging.Logger;
74 import org.codehaus.plexus.util.IOUtil;
75 import org.codehaus.plexus.util.StringUtils;
76 import org.codehaus.plexus.util.dag.CycleDetectedException;
77 import org.codehaus.plexus.util.xml.Xpp3Dom;
78 import org.sonatype.aether.ConfigurationProperties;
79 import org.sonatype.aether.RepositorySystem;
80 import org.sonatype.aether.RepositorySystemSession;
81 import org.sonatype.aether.collection.DependencyGraphTransformer;
82 import org.sonatype.aether.collection.DependencyManager;
83 import org.sonatype.aether.collection.DependencySelector;
84 import org.sonatype.aether.collection.DependencyTraverser;
85 import org.sonatype.aether.repository.Authentication;
86 import org.sonatype.aether.repository.LocalRepository;
87 import org.sonatype.aether.repository.RepositoryPolicy;
88 import org.sonatype.aether.repository.WorkspaceReader;
89 import org.sonatype.aether.util.DefaultRepositorySystemSession;
90 import org.sonatype.aether.util.graph.manager.ClassicDependencyManager;
91 import org.sonatype.aether.util.graph.selector.AndDependencySelector;
92 import org.sonatype.aether.util.graph.selector.ExclusionDependencySelector;
93 import org.sonatype.aether.util.graph.selector.OptionalDependencySelector;
94 import org.sonatype.aether.util.graph.selector.ScopeDependencySelector;
95 import org.sonatype.aether.util.graph.transformer.ChainedDependencyGraphTransformer;
96 import org.sonatype.aether.util.graph.transformer.NearestVersionConflictResolver;
97 import org.sonatype.aether.util.graph.transformer.ConflictMarker;
98 import org.sonatype.aether.util.graph.transformer.JavaDependencyContextRefiner;
99 import org.sonatype.aether.util.graph.transformer.JavaEffectiveScopeCalculator;
100 import org.sonatype.aether.util.graph.traverser.FatArtifactTraverser;
101 import org.sonatype.aether.util.repository.ChainedWorkspaceReader;
102 import org.sonatype.aether.util.repository.DefaultAuthenticationSelector;
103 import org.sonatype.aether.util.repository.DefaultMirrorSelector;
104 import org.sonatype.aether.util.repository.DefaultProxySelector;
105
106
107
108
109 @Component(role = Maven.class)
110 public class DefaultMaven
111 implements Maven
112 {
113
114 @Requirement
115 private Logger logger;
116
117 @Requirement
118 protected ProjectBuilder projectBuilder;
119
120 @Requirement
121 private LifecycleStarter lifecycleStarter;
122
123 @Requirement
124 protected PlexusContainer container;
125
126 @Requirement
127 MavenExecutionRequestPopulator populator;
128
129 @Requirement
130 private ExecutionEventCatapult eventCatapult;
131
132 @Requirement
133 private ArtifactHandlerManager artifactHandlerManager;
134
135 @Requirement( optional = true, hint = "ide" )
136 private WorkspaceReader workspaceRepository;
137
138 @Requirement
139 private RepositorySystem repoSystem;
140
141 @Requirement
142 private SettingsDecrypter settingsDecrypter;
143
144 @Requirement
145 private LegacySupport legacySupport;
146
147 @Requirement
148 private EventSpyDispatcher eventSpyDispatcher;
149
150 public MavenExecutionResult execute( MavenExecutionRequest request )
151 {
152 MavenExecutionResult result;
153
154 try
155 {
156 result = doExecute( populator.populateDefaults( request ) );
157 }
158 catch ( OutOfMemoryError e )
159 {
160 result = processResult( new DefaultMavenExecutionResult(), e );
161 }
162 catch ( MavenExecutionRequestPopulationException e )
163 {
164 result = processResult( new DefaultMavenExecutionResult(), e );
165 }
166 catch ( RuntimeException e )
167 {
168 result =
169 processResult( new DefaultMavenExecutionResult(),
170 new InternalErrorException( "Internal error: " + e, e ) );
171 }
172 finally
173 {
174 legacySupport.setSession( null );
175 }
176
177 return result;
178 }
179
180 @SuppressWarnings({"ThrowableInstanceNeverThrown", "ThrowableResultOfMethodCallIgnored"})
181 private MavenExecutionResult doExecute( MavenExecutionRequest request )
182 {
183
184 if ( request.getStartTime() != null )
185 {
186 request.getSystemProperties().put( "${build.timestamp}", new SimpleDateFormat( "yyyyMMdd-hhmm" ).format( request.getStartTime() ) );
187 }
188
189 request.setStartTime( new Date() );
190
191 MavenExecutionResult result = new DefaultMavenExecutionResult();
192
193 try
194 {
195 validateLocalRepository( request );
196 }
197 catch ( LocalRepositoryNotAccessibleException e )
198 {
199 return processResult( result, e );
200 }
201
202 DelegatingLocalArtifactRepository delegatingLocalArtifactRepository =
203 new DelegatingLocalArtifactRepository( request.getLocalRepository() );
204
205 request.setLocalRepository( delegatingLocalArtifactRepository );
206
207 DefaultRepositorySystemSession repoSession = (DefaultRepositorySystemSession) newRepositorySession( request );
208
209 MavenSession session = new MavenSession( container, repoSession, request, result );
210 legacySupport.setSession( session );
211
212 try
213 {
214 for ( AbstractMavenLifecycleParticipant listener : getLifecycleParticipants( Collections.<MavenProject> emptyList() ) )
215 {
216 listener.afterSessionStart( session );
217 }
218 }
219 catch ( MavenExecutionException e )
220 {
221 return processResult( result, e );
222 }
223
224 eventCatapult.fire( ExecutionEvent.Type.ProjectDiscoveryStarted, session, null );
225
226 request.getProjectBuildingRequest().setRepositorySession( session.getRepositorySession() );
227
228
229
230 List<MavenProject> projects;
231 try
232 {
233 projects = getProjectsForMavenReactor( request );
234 }
235 catch ( ProjectBuildingException e )
236 {
237 return processResult( result, e );
238 }
239
240 session.setProjects( projects );
241
242 result.setTopologicallySortedProjects( session.getProjects() );
243
244 result.setProject( session.getTopLevelProject() );
245
246 try
247 {
248 Map<String, MavenProject> projectMap;
249 projectMap = getProjectMap( session.getProjects() );
250
251
252
253
254
255
256 ReactorReader reactorRepository = new ReactorReader( projectMap );
257
258 repoSession.setWorkspaceReader( ChainedWorkspaceReader.newInstance( reactorRepository,
259 repoSession.getWorkspaceReader() ) );
260 }
261 catch ( org.apache.maven.DuplicateProjectException e )
262 {
263 return processResult( result, e );
264 }
265
266 ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
267 try
268 {
269 for ( AbstractMavenLifecycleParticipant listener : getLifecycleParticipants( projects ) )
270 {
271 Thread.currentThread().setContextClassLoader( listener.getClass().getClassLoader() );
272
273 listener.afterProjectsRead( session );
274 }
275 }
276 catch ( MavenExecutionException e )
277 {
278 return processResult( result, e );
279 }
280 finally
281 {
282 Thread.currentThread().setContextClassLoader( originalClassLoader );
283 }
284
285 try
286 {
287 ProjectSorter projectSorter = new ProjectSorter( session.getProjects() );
288
289 ProjectDependencyGraph projectDependencyGraph = createDependencyGraph( projectSorter, request );
290
291 session.setProjects( projectDependencyGraph.getSortedProjects() );
292
293 session.setProjectDependencyGraph( projectDependencyGraph );
294 }
295 catch ( CycleDetectedException e )
296 {
297 String message = "The projects in the reactor contain a cyclic reference: " + e.getMessage();
298
299 ProjectCycleException error = new ProjectCycleException( message, e );
300
301 return processResult( result, error );
302 }
303 catch ( DuplicateProjectException e )
304 {
305 return processResult( result, e );
306 }
307 catch ( MavenExecutionException e )
308 {
309 return processResult( result, e );
310 }
311
312 result.setTopologicallySortedProjects( session.getProjects() );
313
314 if ( result.hasExceptions() )
315 {
316 return result;
317 }
318
319 lifecycleStarter.execute( session );
320
321 validateActivatedProfiles( session.getProjects(), request.getActiveProfiles() );
322
323 if ( session.getResult().hasExceptions() )
324 {
325 return processResult( result, session.getResult().getExceptions().get( 0 ) );
326 }
327
328 return result;
329 }
330
331 public RepositorySystemSession newRepositorySession( MavenExecutionRequest request )
332 {
333 DefaultRepositorySystemSession session = new DefaultRepositorySystemSession();
334
335 session.setCache( request.getRepositoryCache() );
336
337 session.setIgnoreInvalidArtifactDescriptor( true ).setIgnoreMissingArtifactDescriptor( true );
338
339 Map<Object, Object> configProps = new LinkedHashMap<Object, Object>();
340 configProps.put( ConfigurationProperties.USER_AGENT, getUserAgent() );
341 configProps.put( ConfigurationProperties.INTERACTIVE, Boolean.valueOf( request.isInteractiveMode() ) );
342 configProps.putAll( request.getSystemProperties() );
343 configProps.putAll( request.getUserProperties() );
344
345 session.setOffline( request.isOffline() );
346 session.setChecksumPolicy( request.getGlobalChecksumPolicy() );
347 session.setUpdatePolicy( request.isUpdateSnapshots() ? RepositoryPolicy.UPDATE_POLICY_ALWAYS : null );
348
349 session.setNotFoundCachingEnabled( request.isCacheNotFound() );
350 session.setTransferErrorCachingEnabled( request.isCacheTransferError() );
351
352 session.setArtifactTypeRegistry( RepositoryUtils.newArtifactTypeRegistry( artifactHandlerManager ) );
353
354 LocalRepository localRepo = new LocalRepository( request.getLocalRepository().getBasedir() );
355 session.setLocalRepositoryManager( repoSystem.newLocalRepositoryManager( localRepo ) );
356
357 if ( request.getWorkspaceReader() != null )
358 {
359 session.setWorkspaceReader( request.getWorkspaceReader() );
360 }
361 else
362 {
363 session.setWorkspaceReader( workspaceRepository );
364 }
365
366 DefaultSettingsDecryptionRequest decrypt = new DefaultSettingsDecryptionRequest();
367 decrypt.setProxies( request.getProxies() );
368 decrypt.setServers( request.getServers() );
369 SettingsDecryptionResult decrypted = settingsDecrypter.decrypt( decrypt );
370
371 if ( logger.isDebugEnabled() )
372 {
373 for ( SettingsProblem problem : decrypted.getProblems() )
374 {
375 logger.debug( problem.getMessage(), problem.getException() );
376 }
377 }
378
379 DefaultMirrorSelector mirrorSelector = new DefaultMirrorSelector();
380 for ( Mirror mirror : request.getMirrors() )
381 {
382 mirrorSelector.add( mirror.getId(), mirror.getUrl(), mirror.getLayout(), false, mirror.getMirrorOf(),
383 mirror.getMirrorOfLayouts() );
384 }
385 session.setMirrorSelector( mirrorSelector );
386
387 DefaultProxySelector proxySelector = new DefaultProxySelector();
388 for ( Proxy proxy : decrypted.getProxies() )
389 {
390 Authentication proxyAuth = new Authentication( proxy.getUsername(), proxy.getPassword() );
391 proxySelector.add( new org.sonatype.aether.repository.Proxy( proxy.getProtocol(), proxy.getHost(), proxy.getPort(),
392 proxyAuth ), proxy.getNonProxyHosts() );
393 }
394 session.setProxySelector( proxySelector );
395
396 DefaultAuthenticationSelector authSelector = new DefaultAuthenticationSelector();
397 for ( Server server : decrypted.getServers() )
398 {
399 Authentication auth =
400 new Authentication( server.getUsername(), server.getPassword(), server.getPrivateKey(),
401 server.getPassphrase() );
402 authSelector.add( server.getId(), auth );
403
404 if ( server.getConfiguration() != null )
405 {
406 Xpp3Dom dom = (Xpp3Dom) server.getConfiguration();
407 for ( int i = dom.getChildCount() - 1; i >= 0; i-- )
408 {
409 Xpp3Dom child = dom.getChild( i );
410 if ( "wagonProvider".equals( child.getName() ) )
411 {
412 dom.removeChild( i );
413 }
414 }
415
416 XmlPlexusConfiguration config = new XmlPlexusConfiguration( dom );
417 configProps.put( "aether.connector.wagon.config." + server.getId(), config );
418 }
419
420 configProps.put( "aether.connector.perms.fileMode." + server.getId(), server.getFilePermissions() );
421 configProps.put( "aether.connector.perms.dirMode." + server.getId(), server.getDirectoryPermissions() );
422 }
423 session.setAuthenticationSelector( authSelector );
424
425 DependencyTraverser depTraverser = new FatArtifactTraverser();
426 session.setDependencyTraverser( depTraverser );
427
428 DependencyManager depManager = new ClassicDependencyManager();
429 session.setDependencyManager( depManager );
430
431 DependencySelector depFilter =
432 new AndDependencySelector( new ScopeDependencySelector( "test", "provided" ), new OptionalDependencySelector(),
433 new ExclusionDependencySelector() );
434 session.setDependencySelector( depFilter );
435
436 DependencyGraphTransformer transformer =
437 new ChainedDependencyGraphTransformer( new ConflictMarker(), new JavaEffectiveScopeCalculator(),
438 new NearestVersionConflictResolver(),
439 new JavaDependencyContextRefiner() );
440 session.setDependencyGraphTransformer( transformer );
441
442 session.setTransferListener( request.getTransferListener() );
443
444 session.setRepositoryListener( eventSpyDispatcher.chainListener( new LoggingRepositoryListener( logger ) ) );
445
446 session.setUserProps( request.getUserProperties() );
447 session.setSystemProps( request.getSystemProperties() );
448 session.setConfigProps( configProps );
449
450 return session;
451 }
452
453 private String getUserAgent()
454 {
455 StringBuilder buffer = new StringBuilder( 128 );
456
457 buffer.append( "Apache-Maven/" ).append( getMavenVersion() );
458 buffer.append( " (" );
459 buffer.append( "Java " ).append( System.getProperty( "java.version" ) );
460 buffer.append( "; " );
461 buffer.append( System.getProperty( "os.name" ) ).append( " " ).append( System.getProperty( "os.version" ) );
462 buffer.append( ")" );
463
464 return buffer.toString();
465 }
466
467 private String getMavenVersion()
468 {
469 Properties props = new Properties();
470
471 InputStream is = getClass().getResourceAsStream( "/META-INF/maven/org.apache.maven/maven-core/pom.properties" );
472 if ( is != null )
473 {
474 try
475 {
476 props.load( is );
477 }
478 catch ( IOException e )
479 {
480 logger.debug( "Failed to read Maven version", e );
481 }
482 IOUtil.close( is );
483 }
484
485 return props.getProperty( "version", "unknown-version" );
486 }
487
488 @SuppressWarnings({"ResultOfMethodCallIgnored"})
489 private void validateLocalRepository( MavenExecutionRequest request )
490 throws LocalRepositoryNotAccessibleException
491 {
492 File localRepoDir = request.getLocalRepositoryPath();
493
494 logger.debug( "Using local repository at " + localRepoDir );
495
496 localRepoDir.mkdirs();
497
498 if ( !localRepoDir.isDirectory() )
499 {
500 throw new LocalRepositoryNotAccessibleException( "Could not create local repository at " + localRepoDir );
501 }
502 }
503
504 private Collection<AbstractMavenLifecycleParticipant> getLifecycleParticipants( Collection<MavenProject> projects )
505 {
506 Collection<AbstractMavenLifecycleParticipant> lifecycleListeners =
507 new LinkedHashSet<AbstractMavenLifecycleParticipant>();
508
509 ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
510 try
511 {
512 try
513 {
514 lifecycleListeners.addAll( container.lookupList( AbstractMavenLifecycleParticipant.class ) );
515 }
516 catch ( ComponentLookupException e )
517 {
518
519 logger.warn( "Failed to lookup lifecycle participants: " + e.getMessage() );
520 }
521
522 Collection<ClassLoader> scannedRealms = new HashSet<ClassLoader>();
523
524 for ( MavenProject project : projects )
525 {
526 ClassLoader projectRealm = project.getClassRealm();
527
528 if ( projectRealm != null && scannedRealms.add( projectRealm ) )
529 {
530 Thread.currentThread().setContextClassLoader( projectRealm );
531
532 try
533 {
534 lifecycleListeners.addAll( container.lookupList( AbstractMavenLifecycleParticipant.class ) );
535 }
536 catch ( ComponentLookupException e )
537 {
538
539 logger.warn( "Failed to lookup lifecycle participants: " + e.getMessage() );
540 }
541 }
542 }
543 }
544 finally
545 {
546 Thread.currentThread().setContextClassLoader( originalClassLoader );
547 }
548
549 return lifecycleListeners;
550 }
551
552 private MavenExecutionResult processResult( MavenExecutionResult result, Throwable e )
553 {
554 if ( !result.getExceptions().contains( e ) )
555 {
556 result.addException( e );
557 }
558
559 return result;
560 }
561
562 private List<MavenProject> getProjectsForMavenReactor( MavenExecutionRequest request )
563 throws ProjectBuildingException
564 {
565 List<MavenProject> projects = new ArrayList<MavenProject>();
566
567
568
569 if ( request.getPom() == null )
570 {
571 ModelSource modelSource = new UrlModelSource( DefaultMaven.class.getResource( "project/standalone.xml" ) );
572 MavenProject project =
573 projectBuilder.build( modelSource, request.getProjectBuildingRequest() ).getProject();
574 project.setExecutionRoot( true );
575 projects.add( project );
576 request.setProjectPresent( false );
577 return projects;
578 }
579
580 List<File> files = Arrays.asList( request.getPom().getAbsoluteFile() );
581 collectProjects( projects, files, request );
582 return projects;
583 }
584
585 private Map<String, MavenProject> getProjectMap( List<MavenProject> projects )
586 throws org.apache.maven.DuplicateProjectException
587 {
588 Map<String, MavenProject> index = new LinkedHashMap<String, MavenProject>();
589 Map<String, List<File>> collisions = new LinkedHashMap<String, List<File>>();
590
591 for ( MavenProject project : projects )
592 {
593 String projectId = ArtifactUtils.key( project.getGroupId(), project.getArtifactId(), project.getVersion() );
594
595 MavenProject collision = index.get( projectId );
596
597 if ( collision == null )
598 {
599 index.put( projectId, project );
600 }
601 else
602 {
603 List<File> pomFiles = collisions.get( projectId );
604
605 if ( pomFiles == null )
606 {
607 pomFiles = new ArrayList<File>( Arrays.asList( collision.getFile(), project.getFile() ) );
608 collisions.put( projectId, pomFiles );
609 }
610 else
611 {
612 pomFiles.add( project.getFile() );
613 }
614 }
615 }
616
617 if ( !collisions.isEmpty() )
618 {
619 throw new org.apache.maven.DuplicateProjectException( "Two or more projects in the reactor"
620 + " have the same identifier, please make sure that <groupId>:<artifactId>:<version>"
621 + " is unique for each project: " + collisions, collisions );
622 }
623
624 return index;
625 }
626
627 private void collectProjects( List<MavenProject> projects, List<File> files, MavenExecutionRequest request )
628 throws ProjectBuildingException
629 {
630 ProjectBuildingRequest projectBuildingRequest = request.getProjectBuildingRequest();
631
632 List<ProjectBuildingResult> results = projectBuilder.build( files, request.isRecursive(), projectBuildingRequest );
633
634 boolean problems = false;
635
636 for ( ProjectBuildingResult result : results )
637 {
638 projects.add( result.getProject() );
639
640 if ( !result.getProblems().isEmpty() && logger.isWarnEnabled() )
641 {
642 logger.warn( "" );
643 logger.warn( "Some problems were encountered while building the effective model for "
644 + result.getProject().getId() );
645
646 for ( ModelProblem problem : result.getProblems() )
647 {
648 String location = ModelProblemUtils.formatLocation( problem, result.getProjectId() );
649 logger.warn( problem.getMessage() + ( StringUtils.isNotEmpty( location ) ? " @ " + location : "" ) );
650 }
651
652 problems = true;
653 }
654 }
655
656 if ( problems )
657 {
658 logger.warn( "" );
659 logger.warn( "It is highly recommended to fix these problems"
660 + " because they threaten the stability of your build." );
661 logger.warn( "" );
662 logger.warn( "For this reason, future Maven versions might no"
663 + " longer support building such malformed projects." );
664 logger.warn( "" );
665 }
666 }
667
668 private void validateActivatedProfiles( List<MavenProject> projects, List<String> activeProfileIds )
669 {
670 Collection<String> notActivatedProfileIds = new LinkedHashSet<String>( activeProfileIds );
671
672 for ( MavenProject project : projects )
673 {
674 for ( List<String> profileIds : project.getInjectedProfileIds().values() )
675 {
676 notActivatedProfileIds.removeAll( profileIds );
677 }
678 }
679
680 for ( String notActivatedProfileId : notActivatedProfileIds )
681 {
682 logger.warn( "The requested profile \"" + notActivatedProfileId
683 + "\" could not be activated because it does not exist." );
684 }
685 }
686
687 protected Logger getLogger()
688 {
689 return logger;
690 }
691
692 private ProjectDependencyGraph createDependencyGraph( ProjectSorter sorter, MavenExecutionRequest request )
693 throws MavenExecutionException
694 {
695 ProjectDependencyGraph graph = new DefaultProjectDependencyGraph( sorter );
696
697 List<MavenProject> activeProjects = sorter.getSortedProjects();
698
699 activeProjects = trimSelectedProjects( activeProjects, graph, request );
700 activeProjects = trimResumedProjects( activeProjects, request );
701
702 if ( activeProjects.size() != sorter.getSortedProjects().size() )
703 {
704 graph = new FilteredProjectDependencyGraph( graph, activeProjects );
705 }
706
707 return graph;
708 }
709
710 private List<MavenProject> trimSelectedProjects( List<MavenProject> projects, ProjectDependencyGraph graph,
711 MavenExecutionRequest request )
712 throws MavenExecutionException
713 {
714 List<MavenProject> result = projects;
715
716 if ( !request.getSelectedProjects().isEmpty() )
717 {
718 File reactorDirectory = null;
719 if ( request.getBaseDirectory() != null )
720 {
721 reactorDirectory = new File( request.getBaseDirectory() );
722 }
723
724 Collection<MavenProject> selectedProjects = new LinkedHashSet<MavenProject>( projects.size() );
725
726 for ( String selector : request.getSelectedProjects() )
727 {
728 MavenProject selectedProject = null;
729
730 for ( MavenProject project : projects )
731 {
732 if ( isMatchingProject( project, selector, reactorDirectory ) )
733 {
734 selectedProject = project;
735 break;
736 }
737 }
738
739 if ( selectedProject != null )
740 {
741 selectedProjects.add( selectedProject );
742 }
743 else
744 {
745 throw new MavenExecutionException( "Could not find the selected project in the reactor: "
746 + selector, request.getPom() );
747 }
748 }
749
750 boolean makeUpstream = false;
751 boolean makeDownstream = false;
752
753 if ( MavenExecutionRequest.REACTOR_MAKE_UPSTREAM.equals( request.getMakeBehavior() ) )
754 {
755 makeUpstream = true;
756 }
757 else if ( MavenExecutionRequest.REACTOR_MAKE_DOWNSTREAM.equals( request.getMakeBehavior() ) )
758 {
759 makeDownstream = true;
760 }
761 else if ( MavenExecutionRequest.REACTOR_MAKE_BOTH.equals( request.getMakeBehavior() ) )
762 {
763 makeUpstream = true;
764 makeDownstream = true;
765 }
766 else if ( StringUtils.isNotEmpty( request.getMakeBehavior() ) )
767 {
768 throw new MavenExecutionException( "Invalid reactor make behavior: " + request.getMakeBehavior(),
769 request.getPom() );
770 }
771
772 if ( makeUpstream || makeDownstream )
773 {
774 for ( MavenProject selectedProject : new ArrayList<MavenProject>( selectedProjects ) )
775 {
776 if ( makeUpstream )
777 {
778 selectedProjects.addAll( graph.getUpstreamProjects( selectedProject, true ) );
779 }
780 if ( makeDownstream )
781 {
782 selectedProjects.addAll( graph.getDownstreamProjects( selectedProject, true ) );
783 }
784 }
785 }
786
787 result = new ArrayList<MavenProject>( selectedProjects.size() );
788
789 for ( MavenProject project : projects )
790 {
791 if ( selectedProjects.contains( project ) )
792 {
793 result.add( project );
794 }
795 }
796 }
797
798 return result;
799 }
800
801 private List<MavenProject> trimResumedProjects( List<MavenProject> projects, MavenExecutionRequest request )
802 throws MavenExecutionException
803 {
804 List<MavenProject> result = projects;
805
806 if ( StringUtils.isNotEmpty( request.getResumeFrom() ) )
807 {
808 File reactorDirectory = null;
809 if ( request.getBaseDirectory() != null )
810 {
811 reactorDirectory = new File( request.getBaseDirectory() );
812 }
813
814 String selector = request.getResumeFrom();
815
816 result = new ArrayList<MavenProject>( projects.size() );
817
818 boolean resumed = false;
819
820 for ( MavenProject project : projects )
821 {
822 if ( !resumed && isMatchingProject( project, selector, reactorDirectory ) )
823 {
824 resumed = true;
825 }
826
827 if ( resumed )
828 {
829 result.add( project );
830 }
831 }
832
833 if ( !resumed )
834 {
835 throw new MavenExecutionException( "Could not find project to resume reactor build from: " + selector
836 + " vs " + projects, request.getPom() );
837 }
838 }
839
840 return result;
841 }
842
843 private boolean isMatchingProject( MavenProject project, String selector, File reactorDirectory )
844 {
845
846 if ( selector.indexOf( ':' ) >= 0 )
847 {
848 String id = ':' + project.getArtifactId();
849
850 if ( id.equals( selector ) )
851 {
852 return true;
853 }
854
855 id = project.getGroupId() + id;
856
857 if ( id.equals( selector ) )
858 {
859 return true;
860 }
861 }
862
863
864 else if ( reactorDirectory != null )
865 {
866 File selectedProject = new File( new File( reactorDirectory, selector ).toURI().normalize() );
867
868 if ( selectedProject.isFile() )
869 {
870 return selectedProject.equals( project.getFile() );
871 }
872 else if ( selectedProject.isDirectory() )
873 {
874 return selectedProject.equals( project.getBasedir() );
875 }
876 }
877
878 return false;
879 }
880
881 }