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.text.SimpleDateFormat;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.Date;
31 import java.util.HashMap;
32 import java.util.HashSet;
33 import java.util.LinkedHashMap;
34 import java.util.LinkedHashSet;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Properties;
38
39 import org.apache.maven.artifact.ArtifactUtils;
40 import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
41 import org.apache.maven.eventspy.internal.EventSpyDispatcher;
42 import org.apache.maven.execution.DefaultMavenExecutionResult;
43 import org.apache.maven.execution.ExecutionEvent;
44 import org.apache.maven.execution.MavenExecutionRequest;
45 import org.apache.maven.execution.MavenExecutionRequestPopulationException;
46 import org.apache.maven.execution.MavenExecutionRequestPopulator;
47 import org.apache.maven.execution.MavenExecutionResult;
48 import org.apache.maven.execution.MavenSession;
49 import org.apache.maven.execution.ProjectDependencyGraph;
50 import org.apache.maven.lifecycle.internal.ExecutionEventCatapult;
51 import org.apache.maven.lifecycle.internal.LifecycleStarter;
52 import org.apache.maven.model.Plugin;
53 import org.apache.maven.model.building.ModelProblem;
54 import org.apache.maven.model.building.ModelProblemUtils;
55 import org.apache.maven.model.building.ModelSource;
56 import org.apache.maven.model.building.UrlModelSource;
57 import org.apache.maven.plugin.LegacySupport;
58 import org.apache.maven.project.MavenProject;
59 import org.apache.maven.project.ProjectBuilder;
60 import org.apache.maven.project.ProjectBuildingException;
61 import org.apache.maven.project.ProjectBuildingRequest;
62 import org.apache.maven.project.ProjectBuildingResult;
63 import org.apache.maven.repository.LocalRepositoryNotAccessibleException;
64 import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
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 simpleLocalRepositoryManagerFactory;
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 private MavenExecutionResult doExecute( MavenExecutionRequest request )
208 {
209 if ( request.getStartTime() != null )
210 {
211 request.getSystemProperties().put( "${build.timestamp}",
212 new SimpleDateFormat( "yyyyMMdd-hhmm" ).format( request.getStartTime() ) );
213 }
214
215 request.setStartTime( new Date() );
216
217 MavenExecutionResult result = new DefaultMavenExecutionResult();
218
219 try
220 {
221 validateLocalRepository( request );
222 }
223 catch ( LocalRepositoryNotAccessibleException e )
224 {
225 return addExceptionToResult( result, e );
226 }
227
228 DefaultRepositorySystemSession repoSession = (DefaultRepositorySystemSession) newRepositorySession( request );
229
230 MavenSession session = new MavenSession( container, repoSession, request, result );
231 legacySupport.setSession( session );
232
233 try
234 {
235 for ( AbstractMavenLifecycleParticipant listener : getLifecycleParticipants( Collections.<MavenProject> emptyList() ) )
236 {
237 listener.afterSessionStart( session );
238 }
239 }
240 catch ( MavenExecutionException e )
241 {
242 return addExceptionToResult( result, e );
243 }
244
245 eventCatapult.fire( ExecutionEvent.Type.ProjectDiscoveryStarted, session, null );
246
247 List<MavenProject> projects;
248 try
249 {
250 projects = getProjectsForMavenReactor( session );
251
252
253
254 session.setAllProjects( projects );
255 }
256 catch ( ProjectBuildingException e )
257 {
258 return addExceptionToResult( result, e );
259 }
260
261 validateProjects( projects );
262
263
264
265
266
267
268 ProjectDependencyGraph projectDependencyGraph = createProjectDependencyGraph( projects, request, result, true );
269
270 session.setProjects( projectDependencyGraph.getSortedProjects() );
271
272 if ( result.hasExceptions() )
273 {
274 return result;
275 }
276
277 try
278 {
279 session.setProjectMap( getProjectMap( session.getProjects() ) );
280 }
281 catch ( DuplicateProjectException e )
282 {
283 return addExceptionToResult( result, e );
284 }
285
286 WorkspaceReader reactorWorkspace;
287 sessionScope.enter();
288 sessionScope.seed( MavenSession.class, session );
289 try
290 {
291 reactorWorkspace = container.lookup( WorkspaceReader.class );
292 }
293 catch ( ComponentLookupException e )
294 {
295 return addExceptionToResult( result, e );
296 }
297
298
299
300
301
302
303
304
305 repoSession.setWorkspaceReader( ChainedWorkspaceReader.newInstance( reactorWorkspace,
306 repoSession.getWorkspaceReader() ) );
307
308 repoSession.setReadOnly();
309
310 ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
311 try
312 {
313 for ( AbstractMavenLifecycleParticipant listener : getLifecycleParticipants( projects ) )
314 {
315 Thread.currentThread().setContextClassLoader( listener.getClass().getClassLoader() );
316
317 listener.afterProjectsRead( session );
318 }
319 }
320 catch ( MavenExecutionException e )
321 {
322 return addExceptionToResult( result, e );
323 }
324 finally
325 {
326 Thread.currentThread().setContextClassLoader( originalClassLoader );
327 }
328
329
330
331
332
333
334
335
336
337 projectDependencyGraph = createProjectDependencyGraph( session.getProjects(), request, result, false );
338
339 if ( result.hasExceptions() )
340 {
341 try
342 {
343 afterSessionEnd( projects, session );
344 }
345 catch ( MavenExecutionException e )
346 {
347 return addExceptionToResult( result, e );
348 }
349
350 return result;
351 }
352
353 session.setProjects( projectDependencyGraph.getSortedProjects() );
354
355 session.setProjectDependencyGraph( projectDependencyGraph );
356
357 result.setTopologicallySortedProjects( session.getProjects() );
358
359 result.setProject( session.getTopLevelProject() );
360
361 lifecycleStarter.execute( session );
362
363 validateActivatedProfiles( session.getProjects(), request.getActiveProfiles() );
364
365 if ( session.getResult().hasExceptions() )
366 {
367 return addExceptionToResult( result, session.getResult().getExceptions().get( 0 ) );
368 }
369
370 try
371 {
372 afterSessionEnd( projects, session );
373 }
374 catch ( MavenExecutionException e )
375 {
376 return addExceptionToResult( result, e );
377 }
378
379 sessionScope.exit();
380
381 return result;
382 }
383
384 private void afterSessionEnd( Collection<MavenProject> projects, MavenSession session )
385 throws MavenExecutionException
386 {
387 ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
388 try
389 {
390 for ( AbstractMavenLifecycleParticipant listener : getLifecycleParticipants( projects ) )
391 {
392 Thread.currentThread().setContextClassLoader( listener.getClass().getClassLoader() );
393
394 listener.afterSessionEnd( session );
395 }
396 }
397 finally
398 {
399 Thread.currentThread().setContextClassLoader( originalClassLoader );
400 }
401 }
402
403 public RepositorySystemSession newRepositorySession( MavenExecutionRequest request )
404 {
405 DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
406
407 session.setCache( request.getRepositoryCache() );
408
409 Map<Object, Object> configProps = new LinkedHashMap<Object, Object>();
410 configProps.put( ConfigurationProperties.USER_AGENT, getUserAgent() );
411 configProps.put( ConfigurationProperties.INTERACTIVE, request.isInteractiveMode() );
412 configProps.putAll( request.getSystemProperties() );
413 configProps.putAll( request.getUserProperties() );
414
415 session.setOffline( request.isOffline() );
416 session.setChecksumPolicy( request.getGlobalChecksumPolicy() );
417 if ( request.isNoSnapshotUpdates() )
418 {
419 session.setUpdatePolicy( RepositoryPolicy.UPDATE_POLICY_NEVER );
420 }
421 else if ( request.isUpdateSnapshots() )
422 {
423 session.setUpdatePolicy( RepositoryPolicy.UPDATE_POLICY_ALWAYS );
424 }
425 else
426 {
427 session.setUpdatePolicy( null );
428 }
429
430 int errorPolicy = 0;
431 errorPolicy |= request.isCacheNotFound() ? ResolutionErrorPolicy.CACHE_NOT_FOUND : 0;
432 errorPolicy |= request.isCacheTransferError() ? ResolutionErrorPolicy.CACHE_TRANSFER_ERROR : 0;
433 session.setResolutionErrorPolicy( new SimpleResolutionErrorPolicy( errorPolicy, errorPolicy
434 | ResolutionErrorPolicy.CACHE_NOT_FOUND ) );
435
436 session.setArtifactTypeRegistry( RepositoryUtils.newArtifactTypeRegistry( artifactHandlerManager ) );
437
438 LocalRepository localRepo = new LocalRepository( request.getLocalRepository().getBasedir() );
439
440 if ( request.isUseLegacyLocalRepository() )
441 {
442 logger.warn( "Disabling enhanced local repository: using legacy is strongly discouraged to ensure build reproducibility." );
443 try
444 {
445 session.setLocalRepositoryManager( simpleLocalRepositoryManagerFactory.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 location = ModelProblemUtils.formatLocation( problem, result.getProjectId() );
690 logger.warn( problem.getMessage() + ( StringUtils.isNotEmpty( location ) ? " @ " + location : "" ) );
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 project : projects )
756 {
757 String projectKey = ArtifactUtils.key( project.getGroupId(), project.getArtifactId(), project.getVersion() );
758
759 projectsMap.put( projectKey, project );
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. This plugin was pulled from the local repository!" );
776 }
777 }
778 }
779 }
780 }
781
782 private void validateActivatedProfiles( List<MavenProject> projects, List<String> activeProfileIds )
783 {
784 Collection<String> notActivatedProfileIds = new LinkedHashSet<String>( activeProfileIds );
785
786 for ( MavenProject project : projects )
787 {
788 for ( List<String> profileIds : project.getInjectedProfileIds().values() )
789 {
790 notActivatedProfileIds.removeAll( profileIds );
791 }
792 }
793
794 for ( String notActivatedProfileId : notActivatedProfileIds )
795 {
796 logger.warn( "The requested profile \"" + notActivatedProfileId
797 + "\" could not be activated because it does not exist." );
798 }
799 }
800
801 @Deprecated
802 protected Logger getLogger()
803 {
804 return logger;
805 }
806
807 private ProjectDependencyGraph createProjectDependencyGraph( Collection<MavenProject> projects, MavenExecutionRequest request,
808 MavenExecutionResult result, boolean trimming )
809 {
810 ProjectDependencyGraph projectDependencyGraph = null;
811
812 try
813 {
814 projectDependencyGraph = new DefaultProjectDependencyGraph( projects );
815
816 if ( trimming )
817 {
818 List<MavenProject> activeProjects = projectDependencyGraph.getSortedProjects();
819
820 activeProjects = trimSelectedProjects( activeProjects, projectDependencyGraph, request );
821 activeProjects = trimExcludedProjects( activeProjects, request );
822 activeProjects = trimResumedProjects( activeProjects, request );
823
824 if ( activeProjects.size() != projectDependencyGraph.getSortedProjects().size() )
825 {
826 projectDependencyGraph =
827 new FilteredProjectDependencyGraph( projectDependencyGraph, activeProjects );
828 }
829 }
830 }
831 catch ( CycleDetectedException e )
832 {
833 String message = "The projects in the reactor contain a cyclic reference: " + e.getMessage();
834
835 ProjectCycleException error = new ProjectCycleException( message, e );
836
837 addExceptionToResult( result, error );
838 }
839 catch ( org.apache.maven.project.DuplicateProjectException e )
840 {
841 addExceptionToResult( result, e );
842 }
843 catch ( MavenExecutionException e )
844 {
845 addExceptionToResult( result, e );
846 }
847
848 return projectDependencyGraph;
849 }
850
851 private List<MavenProject> trimSelectedProjects( List<MavenProject> projects, ProjectDependencyGraph graph,
852 MavenExecutionRequest request )
853 throws MavenExecutionException
854 {
855 List<MavenProject> result = projects;
856
857 if ( !request.getSelectedProjects().isEmpty() )
858 {
859 File reactorDirectory = null;
860 if ( request.getBaseDirectory() != null )
861 {
862 reactorDirectory = new File( request.getBaseDirectory() );
863 }
864
865 Collection<MavenProject> selectedProjects = new LinkedHashSet<MavenProject>( projects.size() );
866
867 for ( String selector : request.getSelectedProjects() )
868 {
869 MavenProject selectedProject = null;
870
871 for ( MavenProject project : projects )
872 {
873 if ( isMatchingProject( project, selector, reactorDirectory ) )
874 {
875 selectedProject = project;
876 break;
877 }
878 }
879
880 if ( selectedProject != null )
881 {
882 selectedProjects.add( selectedProject );
883 }
884 else
885 {
886 throw new MavenExecutionException( "Could not find the selected project in the reactor: "
887 + selector, request.getPom() );
888 }
889 }
890
891 boolean makeUpstream = false;
892 boolean makeDownstream = false;
893
894 if ( MavenExecutionRequest.REACTOR_MAKE_UPSTREAM.equals( request.getMakeBehavior() ) )
895 {
896 makeUpstream = true;
897 }
898 else if ( MavenExecutionRequest.REACTOR_MAKE_DOWNSTREAM.equals( request.getMakeBehavior() ) )
899 {
900 makeDownstream = true;
901 }
902 else if ( MavenExecutionRequest.REACTOR_MAKE_BOTH.equals( request.getMakeBehavior() ) )
903 {
904 makeUpstream = true;
905 makeDownstream = true;
906 }
907 else if ( StringUtils.isNotEmpty( request.getMakeBehavior() ) )
908 {
909 throw new MavenExecutionException( "Invalid reactor make behavior: " + request.getMakeBehavior(),
910 request.getPom() );
911 }
912
913 if ( makeUpstream || makeDownstream )
914 {
915 for ( MavenProject selectedProject : new ArrayList<MavenProject>( selectedProjects ) )
916 {
917 if ( makeUpstream )
918 {
919 selectedProjects.addAll( graph.getUpstreamProjects( selectedProject, true ) );
920 }
921 if ( makeDownstream )
922 {
923 selectedProjects.addAll( graph.getDownstreamProjects( selectedProject, true ) );
924 }
925 }
926 }
927
928 result = new ArrayList<MavenProject>( selectedProjects.size() );
929
930 for ( MavenProject project : projects )
931 {
932 if ( selectedProjects.contains( project ) )
933 {
934 result.add( project );
935 }
936 }
937 }
938
939 return result;
940 }
941
942 private List<MavenProject> trimExcludedProjects( List<MavenProject> projects, MavenExecutionRequest request )
943 throws MavenExecutionException
944 {
945 List<MavenProject> result = projects;
946
947 if ( !request.getExcludedProjects().isEmpty() )
948 {
949 File reactorDirectory = null;
950
951 if ( request.getBaseDirectory() != null )
952 {
953 reactorDirectory = new File( request.getBaseDirectory() );
954 }
955
956 Collection<MavenProject> excludedProjects = new LinkedHashSet<MavenProject>( projects.size() );
957
958 for ( String selector : request.getExcludedProjects() )
959 {
960 MavenProject excludedProject = null;
961
962 for ( MavenProject project : projects )
963 {
964 if ( isMatchingProject( project, selector, reactorDirectory ) )
965 {
966 excludedProject = project;
967 break;
968 }
969 }
970
971 if ( excludedProject != null )
972 {
973 excludedProjects.add( excludedProject );
974 }
975 else
976 {
977 throw new MavenExecutionException( "Could not find the selected project in the reactor: "
978 + selector, request.getPom() );
979 }
980 }
981
982 result = new ArrayList<MavenProject>( projects.size() );
983 for ( MavenProject project : projects )
984 {
985 if ( !excludedProjects.contains( project ) )
986 {
987 result.add( project );
988 }
989 }
990 }
991
992 return result;
993 }
994
995 private List<MavenProject> trimResumedProjects( List<MavenProject> projects, MavenExecutionRequest request )
996 throws MavenExecutionException
997 {
998 List<MavenProject> result = projects;
999
1000 if ( StringUtils.isNotEmpty( request.getResumeFrom() ) )
1001 {
1002 File reactorDirectory = null;
1003 if ( request.getBaseDirectory() != null )
1004 {
1005 reactorDirectory = new File( request.getBaseDirectory() );
1006 }
1007
1008 String selector = request.getResumeFrom();
1009
1010 result = new ArrayList<MavenProject>( projects.size() );
1011
1012 boolean resumed = false;
1013
1014 for ( MavenProject project : projects )
1015 {
1016 if ( !resumed && isMatchingProject( project, selector, reactorDirectory ) )
1017 {
1018 resumed = true;
1019 }
1020
1021 if ( resumed )
1022 {
1023 result.add( project );
1024 }
1025 }
1026
1027 if ( !resumed )
1028 {
1029 throw new MavenExecutionException( "Could not find project to resume reactor build from: " + selector
1030 + " vs " + projects, request.getPom() );
1031 }
1032 }
1033
1034 return result;
1035 }
1036
1037 private boolean isMatchingProject( MavenProject project, String selector, File reactorDirectory )
1038 {
1039
1040 if ( selector.indexOf( ':' ) >= 0 )
1041 {
1042 String id = ':' + project.getArtifactId();
1043
1044 if ( id.equals( selector ) )
1045 {
1046 return true;
1047 }
1048
1049 id = project.getGroupId() + id;
1050
1051 if ( id.equals( selector ) )
1052 {
1053 return true;
1054 }
1055 }
1056
1057
1058 else if ( reactorDirectory != null )
1059 {
1060 File selectedProject = new File( new File( reactorDirectory, selector ).toURI().normalize() );
1061
1062 if ( selectedProject.isFile() )
1063 {
1064 return selectedProject.equals( project.getFile() );
1065 }
1066 else if ( selectedProject.isDirectory() )
1067 {
1068 return selectedProject.equals( project.getBasedir() );
1069 }
1070 }
1071
1072 return false;
1073 }
1074
1075 }