1 package org.apache.maven;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.Collection;
28 import java.util.Collections;
29 import java.util.Date;
30 import java.util.HashMap;
31 import java.util.HashSet;
32 import java.util.LinkedHashMap;
33 import java.util.LinkedHashSet;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.Properties;
37
38 import org.apache.maven.artifact.ArtifactUtils;
39 import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
40 import org.apache.maven.eventspy.internal.EventSpyDispatcher;
41 import org.apache.maven.execution.DefaultMavenExecutionResult;
42 import org.apache.maven.execution.ExecutionEvent;
43 import org.apache.maven.execution.MavenExecutionRequest;
44 import org.apache.maven.execution.MavenExecutionRequestPopulationException;
45 import org.apache.maven.execution.MavenExecutionRequestPopulator;
46 import org.apache.maven.execution.MavenExecutionResult;
47 import org.apache.maven.execution.MavenSession;
48 import org.apache.maven.execution.ProjectDependencyGraph;
49 import org.apache.maven.lifecycle.internal.ExecutionEventCatapult;
50 import org.apache.maven.lifecycle.internal.LifecycleStarter;
51 import org.apache.maven.model.Plugin;
52 import org.apache.maven.model.building.ModelProblem;
53 import org.apache.maven.model.building.ModelProblemUtils;
54 import org.apache.maven.model.building.ModelSource;
55 import org.apache.maven.model.building.UrlModelSource;
56 import org.apache.maven.plugin.LegacySupport;
57 import org.apache.maven.project.MavenProject;
58 import org.apache.maven.project.ProjectBuilder;
59 import org.apache.maven.project.ProjectBuildingException;
60 import org.apache.maven.project.ProjectBuildingRequest;
61 import org.apache.maven.project.ProjectBuildingResult;
62 import org.apache.maven.repository.LocalRepositoryNotAccessibleException;
63 import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
64 import org.apache.maven.session.scope.internal.SessionScope;
65 import org.apache.maven.settings.Mirror;
66 import org.apache.maven.settings.Proxy;
67 import org.apache.maven.settings.Server;
68 import org.apache.maven.settings.building.SettingsProblem;
69 import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest;
70 import org.apache.maven.settings.crypto.SettingsDecrypter;
71 import org.apache.maven.settings.crypto.SettingsDecryptionResult;
72 import org.codehaus.plexus.PlexusContainer;
73 import org.codehaus.plexus.component.annotations.Component;
74 import org.codehaus.plexus.component.annotations.Requirement;
75 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
76 import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
77 import org.codehaus.plexus.logging.Logger;
78 import org.codehaus.plexus.util.IOUtil;
79 import org.codehaus.plexus.util.StringUtils;
80 import org.codehaus.plexus.util.dag.CycleDetectedException;
81 import org.codehaus.plexus.util.xml.Xpp3Dom;
82 import org.eclipse.aether.ConfigurationProperties;
83 import org.eclipse.aether.DefaultRepositorySystemSession;
84 import org.eclipse.aether.RepositorySystem;
85 import org.eclipse.aether.RepositorySystemSession;
86 import org.eclipse.aether.repository.LocalRepository;
87 import org.eclipse.aether.repository.NoLocalRepositoryManagerException;
88 import org.eclipse.aether.repository.RepositoryPolicy;
89 import org.eclipse.aether.repository.WorkspaceReader;
90 import org.eclipse.aether.resolution.ResolutionErrorPolicy;
91 import org.eclipse.aether.spi.localrepo.LocalRepositoryManagerFactory;
92 import org.eclipse.aether.util.repository.AuthenticationBuilder;
93 import org.eclipse.aether.util.repository.ChainedWorkspaceReader;
94 import org.eclipse.aether.util.repository.DefaultAuthenticationSelector;
95 import org.eclipse.aether.util.repository.DefaultMirrorSelector;
96 import org.eclipse.aether.util.repository.DefaultProxySelector;
97 import org.eclipse.aether.util.repository.SimpleResolutionErrorPolicy;
98
99
100
101
102 @Component( role = Maven.class )
103 public class DefaultMaven
104 implements Maven
105 {
106
107 @Requirement
108 private Logger logger;
109
110 @Requirement
111 protected ProjectBuilder projectBuilder;
112
113 @Requirement
114 private LifecycleStarter lifecycleStarter;
115
116 @Requirement
117 protected PlexusContainer container;
118
119 @Requirement
120 MavenExecutionRequestPopulator populator;
121
122 @Requirement
123 private ExecutionEventCatapult eventCatapult;
124
125 @Requirement
126 private ArtifactHandlerManager artifactHandlerManager;
127
128 @Requirement( optional = true, hint = "ide" )
129 private WorkspaceReader workspaceRepository;
130
131 @Requirement
132 private RepositorySystem repoSystem;
133
134 @Requirement( optional = true, hint = "simple" )
135 private LocalRepositoryManagerFactory simpleLocalRepoMgrFactory;
136
137 @Requirement
138 private SettingsDecrypter settingsDecrypter;
139
140 @Requirement
141 private LegacySupport legacySupport;
142
143 @Requirement
144 private EventSpyDispatcher eventSpyDispatcher;
145
146 @Requirement
147 private SessionScope sessionScope;
148
149 public MavenExecutionResult execute( MavenExecutionRequest request )
150 {
151 MavenExecutionResult result;
152
153 try
154 {
155 result = doExecute( populator.populateDefaults( request ) );
156 }
157 catch ( OutOfMemoryError e )
158 {
159 result = addExceptionToResult( new DefaultMavenExecutionResult(), e );
160 }
161 catch ( MavenExecutionRequestPopulationException e )
162 {
163 result = addExceptionToResult( new DefaultMavenExecutionResult(), e );
164 }
165 catch ( RuntimeException e )
166 {
167 result =
168 addExceptionToResult( new DefaultMavenExecutionResult(), new InternalErrorException( "Internal error: "
169 + e, e ) );
170 }
171 finally
172 {
173 legacySupport.setSession( null );
174 }
175
176 return result;
177 }
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207 @SuppressWarnings( "checkstyle:methodlength" )
208 private MavenExecutionResult doExecute( MavenExecutionRequest request )
209 {
210 request.setStartTime( new Date() );
211
212 MavenExecutionResult result = new DefaultMavenExecutionResult();
213
214 try
215 {
216 validateLocalRepository( request );
217 }
218 catch ( LocalRepositoryNotAccessibleException e )
219 {
220 return addExceptionToResult( result, e );
221 }
222
223 DefaultRepositorySystemSession repoSession = (DefaultRepositorySystemSession) newRepositorySession( request );
224
225 MavenSession session = new MavenSession( container, repoSession, request, result );
226
227
228
229
230
231 sessionScope.enter();
232 sessionScope.seed( MavenSession.class, session );
233
234 legacySupport.setSession( session );
235
236 try
237 {
238 for ( AbstractMavenLifecycleParticipant listener : getLifecycleParticipants( Collections.<MavenProject>emptyList() ) )
239 {
240 listener.afterSessionStart( session );
241 }
242 }
243 catch ( MavenExecutionException e )
244 {
245 return addExceptionToResult( result, e );
246 }
247
248 eventCatapult.fire( ExecutionEvent.Type.ProjectDiscoveryStarted, session, null );
249
250 List<MavenProject> projects;
251 try
252 {
253 projects = getProjectsForMavenReactor( session );
254
255
256
257 session.setAllProjects( projects );
258 }
259 catch ( ProjectBuildingException e )
260 {
261 return addExceptionToResult( result, e );
262 }
263
264 validateProjects( projects );
265
266
267
268
269
270
271 ProjectDependencyGraph projectDependencyGraph = createProjectDependencyGraph( projects, request, result, true );
272
273 if ( result.hasExceptions() )
274 {
275 return result;
276 }
277
278 session.setProjects( projectDependencyGraph.getSortedProjects() );
279
280 try
281 {
282 session.setProjectMap( getProjectMap( session.getProjects() ) );
283 }
284 catch ( DuplicateProjectException e )
285 {
286 return addExceptionToResult( result, e );
287 }
288
289 WorkspaceReader reactorWorkspace;
290 try
291 {
292 reactorWorkspace = container.lookup( WorkspaceReader.class, ReactorReader.HINT );
293 }
294 catch ( ComponentLookupException e )
295 {
296 return addExceptionToResult( result, e );
297 }
298
299
300
301
302
303
304
305
306 repoSession.setWorkspaceReader( ChainedWorkspaceReader.newInstance( reactorWorkspace,
307 repoSession.getWorkspaceReader() ) );
308
309 repoSession.setReadOnly();
310
311 ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
312 try
313 {
314 for ( AbstractMavenLifecycleParticipant listener : getLifecycleParticipants( projects ) )
315 {
316 Thread.currentThread().setContextClassLoader( listener.getClass().getClassLoader() );
317
318 listener.afterProjectsRead( session );
319 }
320 }
321 catch ( MavenExecutionException e )
322 {
323 return addExceptionToResult( result, e );
324 }
325 finally
326 {
327 Thread.currentThread().setContextClassLoader( originalClassLoader );
328 }
329
330
331
332
333
334
335
336
337
338 projectDependencyGraph = createProjectDependencyGraph( session.getProjects(), request, result, false );
339
340 try
341 {
342 if ( result.hasExceptions() )
343 {
344 return result;
345 }
346
347 session.setProjects( projectDependencyGraph.getSortedProjects() );
348
349 session.setProjectDependencyGraph( projectDependencyGraph );
350
351 result.setTopologicallySortedProjects( session.getProjects() );
352
353 result.setProject( session.getTopLevelProject() );
354
355 lifecycleStarter.execute( session );
356
357 validateActivatedProfiles( session.getProjects(), request.getActiveProfiles() );
358
359 if ( session.getResult().hasExceptions() )
360 {
361 return addExceptionToResult( result, session.getResult().getExceptions().get( 0 ) );
362 }
363 }
364 finally
365 {
366 try
367 {
368 afterSessionEnd( projects, session );
369 }
370 catch ( MavenExecutionException e )
371 {
372 return addExceptionToResult( result, e );
373 }
374 finally
375 {
376 sessionScope.exit();
377 }
378 }
379
380 return result;
381 }
382
383 private void afterSessionEnd( Collection<MavenProject> projects, MavenSession session )
384 throws MavenExecutionException
385 {
386 ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
387 try
388 {
389 for ( AbstractMavenLifecycleParticipant listener : getLifecycleParticipants( projects ) )
390 {
391 Thread.currentThread().setContextClassLoader( listener.getClass().getClassLoader() );
392
393 listener.afterSessionEnd( session );
394 }
395 }
396 finally
397 {
398 Thread.currentThread().setContextClassLoader( originalClassLoader );
399 }
400 }
401
402 public RepositorySystemSession newRepositorySession( MavenExecutionRequest request )
403 {
404 DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
405
406 session.setCache( request.getRepositoryCache() );
407
408 Map<Object, Object> configProps = new LinkedHashMap<Object, Object>();
409 configProps.put( ConfigurationProperties.USER_AGENT, getUserAgent() );
410 configProps.put( ConfigurationProperties.INTERACTIVE, request.isInteractiveMode() );
411 configProps.putAll( request.getSystemProperties() );
412 configProps.putAll( request.getUserProperties() );
413
414 session.setOffline( request.isOffline() );
415 session.setChecksumPolicy( request.getGlobalChecksumPolicy() );
416 if ( request.isNoSnapshotUpdates() )
417 {
418 session.setUpdatePolicy( RepositoryPolicy.UPDATE_POLICY_NEVER );
419 }
420 else if ( request.isUpdateSnapshots() )
421 {
422 session.setUpdatePolicy( RepositoryPolicy.UPDATE_POLICY_ALWAYS );
423 }
424 else
425 {
426 session.setUpdatePolicy( null );
427 }
428
429 int errorPolicy = 0;
430 errorPolicy |= request.isCacheNotFound() ? ResolutionErrorPolicy.CACHE_NOT_FOUND : 0;
431 errorPolicy |= request.isCacheTransferError() ? ResolutionErrorPolicy.CACHE_TRANSFER_ERROR : 0;
432 session.setResolutionErrorPolicy( new SimpleResolutionErrorPolicy( errorPolicy, errorPolicy
433 | ResolutionErrorPolicy.CACHE_NOT_FOUND ) );
434
435 session.setArtifactTypeRegistry( RepositoryUtils.newArtifactTypeRegistry( artifactHandlerManager ) );
436
437 LocalRepository localRepo = new LocalRepository( request.getLocalRepository().getBasedir() );
438
439 if ( request.isUseLegacyLocalRepository() )
440 {
441 logger.warn( "Disabling enhanced local repository: using legacy is strongly discouraged to ensure"
442 + " build reproducibility." );
443 try
444 {
445 session.setLocalRepositoryManager( simpleLocalRepoMgrFactory.newInstance( session, localRepo ) );
446 }
447 catch ( NoLocalRepositoryManagerException e )
448 {
449
450 logger.warn( "Failed to configure legacy local repository: back to default" );
451 session.setLocalRepositoryManager( repoSystem.newLocalRepositoryManager( session, localRepo ) );
452 }
453 }
454 else
455 {
456 session.setLocalRepositoryManager( repoSystem.newLocalRepositoryManager( session, localRepo ) );
457 }
458
459 if ( request.getWorkspaceReader() != null )
460 {
461 session.setWorkspaceReader( request.getWorkspaceReader() );
462 }
463 else
464 {
465 session.setWorkspaceReader( workspaceRepository );
466 }
467
468 DefaultSettingsDecryptionRequest decrypt = new DefaultSettingsDecryptionRequest();
469 decrypt.setProxies( request.getProxies() );
470 decrypt.setServers( request.getServers() );
471 SettingsDecryptionResult decrypted = settingsDecrypter.decrypt( decrypt );
472
473 if ( logger.isDebugEnabled() )
474 {
475 for ( SettingsProblem problem : decrypted.getProblems() )
476 {
477 logger.debug( problem.getMessage(), problem.getException() );
478 }
479 }
480
481 DefaultMirrorSelector mirrorSelector = new DefaultMirrorSelector();
482 for ( Mirror mirror : request.getMirrors() )
483 {
484 mirrorSelector.add( mirror.getId(), mirror.getUrl(), mirror.getLayout(), false, mirror.getMirrorOf(),
485 mirror.getMirrorOfLayouts() );
486 }
487 session.setMirrorSelector( mirrorSelector );
488
489 DefaultProxySelector proxySelector = new DefaultProxySelector();
490 for ( Proxy proxy : decrypted.getProxies() )
491 {
492 AuthenticationBuilder authBuilder = new AuthenticationBuilder();
493 authBuilder.addUsername( proxy.getUsername() ).addPassword( proxy.getPassword() );
494 proxySelector.add( new org.eclipse.aether.repository.Proxy( proxy.getProtocol(), proxy.getHost(),
495 proxy.getPort(), authBuilder.build() ),
496 proxy.getNonProxyHosts() );
497 }
498 session.setProxySelector( proxySelector );
499
500 DefaultAuthenticationSelector authSelector = new DefaultAuthenticationSelector();
501 for ( Server server : decrypted.getServers() )
502 {
503 AuthenticationBuilder authBuilder = new AuthenticationBuilder();
504 authBuilder.addUsername( server.getUsername() ).addPassword( server.getPassword() );
505 authBuilder.addPrivateKey( server.getPrivateKey(), server.getPassphrase() );
506 authSelector.add( server.getId(), authBuilder.build() );
507
508 if ( server.getConfiguration() != null )
509 {
510 Xpp3Dom dom = (Xpp3Dom) server.getConfiguration();
511 for ( int i = dom.getChildCount() - 1; i >= 0; i-- )
512 {
513 Xpp3Dom child = dom.getChild( i );
514 if ( "wagonProvider".equals( child.getName() ) )
515 {
516 dom.removeChild( i );
517 }
518 }
519
520 XmlPlexusConfiguration config = new XmlPlexusConfiguration( dom );
521 configProps.put( "aether.connector.wagon.config." + server.getId(), config );
522 }
523
524 configProps.put( "aether.connector.perms.fileMode." + server.getId(), server.getFilePermissions() );
525 configProps.put( "aether.connector.perms.dirMode." + server.getId(), server.getDirectoryPermissions() );
526 }
527 session.setAuthenticationSelector( authSelector );
528
529 session.setTransferListener( request.getTransferListener() );
530
531 session.setRepositoryListener( eventSpyDispatcher.chainListener( new LoggingRepositoryListener( logger ) ) );
532
533 session.setUserProperties( request.getUserProperties() );
534 session.setSystemProperties( request.getSystemProperties() );
535 session.setConfigProperties( configProps );
536
537 return session;
538 }
539
540 private String getUserAgent()
541 {
542 return "Apache-Maven/" + getMavenVersion() + " (Java " + System.getProperty( "java.version" ) + "; "
543 + System.getProperty( "os.name" ) + " " + System.getProperty( "os.version" ) + ")";
544 }
545
546 private String getMavenVersion()
547 {
548 Properties props = new Properties();
549
550 InputStream is = getClass().getResourceAsStream( "/META-INF/maven/org.apache.maven/maven-core/pom.properties" );
551 if ( is != null )
552 {
553 try
554 {
555 props.load( is );
556 }
557 catch ( IOException e )
558 {
559 logger.debug( "Failed to read Maven version", e );
560 }
561 IOUtil.close( is );
562 }
563
564 return props.getProperty( "version", "unknown-version" );
565 }
566
567 private void validateLocalRepository( MavenExecutionRequest request )
568 throws LocalRepositoryNotAccessibleException
569 {
570 File localRepoDir = request.getLocalRepositoryPath();
571
572 logger.debug( "Using local repository at " + localRepoDir );
573
574 localRepoDir.mkdirs();
575
576 if ( !localRepoDir.isDirectory() )
577 {
578 throw new LocalRepositoryNotAccessibleException( "Could not create local repository at " + localRepoDir );
579 }
580 }
581
582 private Collection<AbstractMavenLifecycleParticipant> getLifecycleParticipants( Collection<MavenProject> projects )
583 {
584 Collection<AbstractMavenLifecycleParticipant> lifecycleListeners =
585 new LinkedHashSet<AbstractMavenLifecycleParticipant>();
586
587 ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
588 try
589 {
590 try
591 {
592 lifecycleListeners.addAll( container.lookupList( AbstractMavenLifecycleParticipant.class ) );
593 }
594 catch ( ComponentLookupException e )
595 {
596
597 logger.warn( "Failed to lookup lifecycle participants: " + e.getMessage() );
598 }
599
600 Collection<ClassLoader> scannedRealms = new HashSet<ClassLoader>();
601
602 for ( MavenProject project : projects )
603 {
604 ClassLoader projectRealm = project.getClassRealm();
605
606 if ( projectRealm != null && scannedRealms.add( projectRealm ) )
607 {
608 Thread.currentThread().setContextClassLoader( projectRealm );
609
610 try
611 {
612 lifecycleListeners.addAll( container.lookupList( AbstractMavenLifecycleParticipant.class ) );
613 }
614 catch ( ComponentLookupException e )
615 {
616
617 logger.warn( "Failed to lookup lifecycle participants: " + e.getMessage() );
618 }
619 }
620 }
621 }
622 finally
623 {
624 Thread.currentThread().setContextClassLoader( originalClassLoader );
625 }
626
627 return lifecycleListeners;
628 }
629
630 private MavenExecutionResult addExceptionToResult( MavenExecutionResult result, Throwable e )
631 {
632 if ( !result.getExceptions().contains( e ) )
633 {
634 result.addException( e );
635 }
636
637 return result;
638 }
639
640 private List<MavenProject> getProjectsForMavenReactor( MavenSession session )
641 throws ProjectBuildingException
642 {
643 MavenExecutionRequest request = session.getRequest();
644
645 request.getProjectBuildingRequest().setRepositorySession( session.getRepositorySession() );
646
647 List<MavenProject> projects = new ArrayList<MavenProject>();
648
649
650
651 if ( request.getPom() == null )
652 {
653 ModelSource modelSource = new UrlModelSource( DefaultMaven.class.getResource( "project/standalone.xml" ) );
654 MavenProject project =
655 projectBuilder.build( modelSource, request.getProjectBuildingRequest() ).getProject();
656 project.setExecutionRoot( true );
657 projects.add( project );
658 request.setProjectPresent( false );
659 return projects;
660 }
661
662 List<File> files = Arrays.asList( request.getPom().getAbsoluteFile() );
663 collectProjects( projects, files, request );
664 return projects;
665 }
666
667 private void collectProjects( List<MavenProject> projects, List<File> files, MavenExecutionRequest request )
668 throws ProjectBuildingException
669 {
670 ProjectBuildingRequest projectBuildingRequest = request.getProjectBuildingRequest();
671
672 List<ProjectBuildingResult> results =
673 projectBuilder.build( files, request.isRecursive(), projectBuildingRequest );
674
675 boolean problems = false;
676
677 for ( ProjectBuildingResult result : results )
678 {
679 projects.add( result.getProject() );
680
681 if ( !result.getProblems().isEmpty() && logger.isWarnEnabled() )
682 {
683 logger.warn( "" );
684 logger.warn( "Some problems were encountered while building the effective model for "
685 + result.getProject().getId() );
686
687 for ( ModelProblem problem : result.getProblems() )
688 {
689 String loc = ModelProblemUtils.formatLocation( problem, result.getProjectId() );
690 logger.warn( problem.getMessage() + ( StringUtils.isNotEmpty( loc ) ? " @ " + loc : "" ) );
691 }
692
693 problems = true;
694 }
695 }
696
697 if ( problems )
698 {
699 logger.warn( "" );
700 logger.warn( "It is highly recommended to fix these problems"
701 + " because they threaten the stability of your build." );
702 logger.warn( "" );
703 logger.warn( "For this reason, future Maven versions might no"
704 + " longer support building such malformed projects." );
705 logger.warn( "" );
706 }
707 }
708
709 private Map<String, MavenProject> getProjectMap( Collection<MavenProject> projects )
710 throws DuplicateProjectException
711 {
712 Map<String, MavenProject> index = new LinkedHashMap<String, MavenProject>();
713 Map<String, List<File>> collisions = new LinkedHashMap<String, List<File>>();
714
715 for ( MavenProject project : projects )
716 {
717 String projectId = ArtifactUtils.key( project.getGroupId(), project.getArtifactId(), project.getVersion() );
718
719 MavenProject collision = index.get( projectId );
720
721 if ( collision == null )
722 {
723 index.put( projectId, project );
724 }
725 else
726 {
727 List<File> pomFiles = collisions.get( projectId );
728
729 if ( pomFiles == null )
730 {
731 pomFiles = new ArrayList<File>( Arrays.asList( collision.getFile(), project.getFile() ) );
732 collisions.put( projectId, pomFiles );
733 }
734 else
735 {
736 pomFiles.add( project.getFile() );
737 }
738 }
739 }
740
741 if ( !collisions.isEmpty() )
742 {
743 throw new DuplicateProjectException( "Two or more projects in the reactor"
744 + " have the same identifier, please make sure that <groupId>:<artifactId>:<version>"
745 + " is unique for each project: " + collisions, collisions );
746 }
747
748 return index;
749 }
750
751 private void validateProjects( List<MavenProject> projects )
752 {
753 Map<String, MavenProject> projectsMap = new HashMap<String, MavenProject>();
754
755 for ( MavenProject p : projects )
756 {
757 String projectKey = ArtifactUtils.key( p.getGroupId(), p.getArtifactId(), p.getVersion() );
758
759 projectsMap.put( projectKey, p );
760 }
761
762 for ( MavenProject project : projects )
763 {
764
765 for ( Plugin plugin : project.getBuildPlugins() )
766 {
767 if ( plugin.isExtensions() )
768 {
769 String pluginKey =
770 ArtifactUtils.key( plugin.getGroupId(), plugin.getArtifactId(), plugin.getVersion() );
771
772 if ( projectsMap.containsKey( pluginKey ) )
773 {
774 logger.warn( project.getName() + " uses " + plugin.getKey()
775 + " as extensions, which is not possible within the same reactor build. "
776 + "This plugin was pulled from the local repository!" );
777 }
778 }
779 }
780 }
781 }
782
783 private void validateActivatedProfiles( List<MavenProject> projects, List<String> activeProfileIds )
784 {
785 Collection<String> notActivatedProfileIds = new LinkedHashSet<String>( activeProfileIds );
786
787 for ( MavenProject project : projects )
788 {
789 for ( List<String> profileIds : project.getInjectedProfileIds().values() )
790 {
791 notActivatedProfileIds.removeAll( profileIds );
792 }
793 }
794
795 for ( String notActivatedProfileId : notActivatedProfileIds )
796 {
797 logger.warn( "The requested profile \"" + notActivatedProfileId
798 + "\" could not be activated because it does not exist." );
799 }
800 }
801
802 @Deprecated
803 protected Logger getLogger()
804 {
805 return logger;
806 }
807
808 private ProjectDependencyGraph createProjectDependencyGraph( Collection<MavenProject> projects,
809 MavenExecutionRequest request,
810 MavenExecutionResult result, boolean trimming )
811 {
812 ProjectDependencyGraph projectDependencyGraph = null;
813
814 try
815 {
816 projectDependencyGraph = new DefaultProjectDependencyGraph( projects );
817
818 if ( trimming )
819 {
820 List<MavenProject> activeProjects = projectDependencyGraph.getSortedProjects();
821
822 activeProjects = trimSelectedProjects( activeProjects, projectDependencyGraph, request );
823 activeProjects = trimExcludedProjects( activeProjects, request );
824 activeProjects = trimResumedProjects( activeProjects, request );
825
826 if ( activeProjects.size() != projectDependencyGraph.getSortedProjects().size() )
827 {
828 projectDependencyGraph =
829 new FilteredProjectDependencyGraph( projectDependencyGraph, activeProjects );
830 }
831 }
832 }
833 catch ( CycleDetectedException e )
834 {
835 String message = "The projects in the reactor contain a cyclic reference: " + e.getMessage();
836
837 ProjectCycleException error = new ProjectCycleException( message, e );
838
839 addExceptionToResult( result, error );
840 }
841 catch ( org.apache.maven.project.DuplicateProjectException e )
842 {
843 addExceptionToResult( result, e );
844 }
845 catch ( MavenExecutionException e )
846 {
847 addExceptionToResult( result, e );
848 }
849
850 return projectDependencyGraph;
851 }
852
853 private List<MavenProject> trimSelectedProjects( List<MavenProject> projects, ProjectDependencyGraph graph,
854 MavenExecutionRequest request )
855 throws MavenExecutionException
856 {
857 List<MavenProject> result = projects;
858
859 if ( !request.getSelectedProjects().isEmpty() )
860 {
861 File reactorDirectory = null;
862 if ( request.getBaseDirectory() != null )
863 {
864 reactorDirectory = new File( request.getBaseDirectory() );
865 }
866
867 Collection<MavenProject> selectedProjects = new LinkedHashSet<MavenProject>( projects.size() );
868
869 for ( String selector : request.getSelectedProjects() )
870 {
871 MavenProject selectedProject = null;
872
873 for ( MavenProject project : projects )
874 {
875 if ( isMatchingProject( project, selector, reactorDirectory ) )
876 {
877 selectedProject = project;
878 break;
879 }
880 }
881
882 if ( selectedProject != null )
883 {
884 selectedProjects.add( selectedProject );
885 }
886 else
887 {
888 throw new MavenExecutionException( "Could not find the selected project in the reactor: "
889 + selector, request.getPom() );
890 }
891 }
892
893 boolean makeUpstream = false;
894 boolean makeDownstream = false;
895
896 if ( MavenExecutionRequest.REACTOR_MAKE_UPSTREAM.equals( request.getMakeBehavior() ) )
897 {
898 makeUpstream = true;
899 }
900 else if ( MavenExecutionRequest.REACTOR_MAKE_DOWNSTREAM.equals( request.getMakeBehavior() ) )
901 {
902 makeDownstream = true;
903 }
904 else if ( MavenExecutionRequest.REACTOR_MAKE_BOTH.equals( request.getMakeBehavior() ) )
905 {
906 makeUpstream = true;
907 makeDownstream = true;
908 }
909 else if ( StringUtils.isNotEmpty( request.getMakeBehavior() ) )
910 {
911 throw new MavenExecutionException( "Invalid reactor make behavior: " + request.getMakeBehavior(),
912 request.getPom() );
913 }
914
915 if ( makeUpstream || makeDownstream )
916 {
917 for ( MavenProject selectedProject : new ArrayList<MavenProject>( selectedProjects ) )
918 {
919 if ( makeUpstream )
920 {
921 selectedProjects.addAll( graph.getUpstreamProjects( selectedProject, true ) );
922 }
923 if ( makeDownstream )
924 {
925 selectedProjects.addAll( graph.getDownstreamProjects( selectedProject, true ) );
926 }
927 }
928 }
929
930 result = new ArrayList<MavenProject>( selectedProjects.size() );
931
932 for ( MavenProject project : projects )
933 {
934 if ( selectedProjects.contains( project ) )
935 {
936 result.add( project );
937 }
938 }
939 }
940
941 return result;
942 }
943
944 private List<MavenProject> trimExcludedProjects( List<MavenProject> projects, MavenExecutionRequest request )
945 throws MavenExecutionException
946 {
947 List<MavenProject> result = projects;
948
949 if ( !request.getExcludedProjects().isEmpty() )
950 {
951 File reactorDirectory = null;
952
953 if ( request.getBaseDirectory() != null )
954 {
955 reactorDirectory = new File( request.getBaseDirectory() );
956 }
957
958 Collection<MavenProject> excludedProjects = new LinkedHashSet<MavenProject>( projects.size() );
959
960 for ( String selector : request.getExcludedProjects() )
961 {
962 MavenProject excludedProject = null;
963
964 for ( MavenProject project : projects )
965 {
966 if ( isMatchingProject( project, selector, reactorDirectory ) )
967 {
968 excludedProject = project;
969 break;
970 }
971 }
972
973 if ( excludedProject != null )
974 {
975 excludedProjects.add( excludedProject );
976 }
977 else
978 {
979 throw new MavenExecutionException( "Could not find the selected project in the reactor: "
980 + selector, request.getPom() );
981 }
982 }
983
984 result = new ArrayList<MavenProject>( projects.size() );
985 for ( MavenProject project : projects )
986 {
987 if ( !excludedProjects.contains( project ) )
988 {
989 result.add( project );
990 }
991 }
992 }
993
994 return result;
995 }
996
997 private List<MavenProject> trimResumedProjects( List<MavenProject> projects, MavenExecutionRequest request )
998 throws MavenExecutionException
999 {
1000 List<MavenProject> result = projects;
1001
1002 if ( StringUtils.isNotEmpty( request.getResumeFrom() ) )
1003 {
1004 File reactorDirectory = null;
1005 if ( request.getBaseDirectory() != null )
1006 {
1007 reactorDirectory = new File( request.getBaseDirectory() );
1008 }
1009
1010 String selector = request.getResumeFrom();
1011
1012 result = new ArrayList<MavenProject>( projects.size() );
1013
1014 boolean resumed = false;
1015
1016 for ( MavenProject project : projects )
1017 {
1018 if ( !resumed && isMatchingProject( project, selector, reactorDirectory ) )
1019 {
1020 resumed = true;
1021 }
1022
1023 if ( resumed )
1024 {
1025 result.add( project );
1026 }
1027 }
1028
1029 if ( !resumed )
1030 {
1031 throw new MavenExecutionException( "Could not find project to resume reactor build from: " + selector
1032 + " vs " + projects, request.getPom() );
1033 }
1034 }
1035
1036 return result;
1037 }
1038
1039 private boolean isMatchingProject( MavenProject project, String selector, File reactorDirectory )
1040 {
1041
1042 if ( selector.indexOf( ':' ) >= 0 )
1043 {
1044 String id = ':' + project.getArtifactId();
1045
1046 if ( id.equals( selector ) )
1047 {
1048 return true;
1049 }
1050
1051 id = project.getGroupId() + id;
1052
1053 if ( id.equals( selector ) )
1054 {
1055 return true;
1056 }
1057 }
1058
1059
1060 else if ( reactorDirectory != null )
1061 {
1062 File selectedProject = new File( new File( reactorDirectory, selector ).toURI().normalize() );
1063
1064 if ( selectedProject.isFile() )
1065 {
1066 return selectedProject.equals( project.getFile() );
1067 }
1068 else if ( selectedProject.isDirectory() )
1069 {
1070 return selectedProject.equals( project.getBasedir() );
1071 }
1072 }
1073
1074 return false;
1075 }
1076
1077 }