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