001package org.apache.maven; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.io.File; 023import java.io.IOException; 024import java.io.InputStream; 025import java.text.SimpleDateFormat; 026import java.util.ArrayList; 027import java.util.Arrays; 028import java.util.Collection; 029import java.util.Collections; 030import java.util.Date; 031import java.util.HashSet; 032import java.util.LinkedHashMap; 033import java.util.LinkedHashSet; 034import java.util.List; 035import java.util.Map; 036import java.util.Properties; 037 038import org.apache.maven.artifact.ArtifactUtils; 039import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; 040import org.apache.maven.eventspy.internal.EventSpyDispatcher; 041import org.apache.maven.execution.DefaultMavenExecutionResult; 042import org.apache.maven.execution.ExecutionEvent; 043import org.apache.maven.execution.MavenExecutionRequest; 044import org.apache.maven.execution.MavenExecutionRequestPopulationException; 045import org.apache.maven.execution.MavenExecutionRequestPopulator; 046import org.apache.maven.execution.MavenExecutionResult; 047import org.apache.maven.execution.MavenSession; 048import org.apache.maven.execution.ProjectDependencyGraph; 049import org.apache.maven.lifecycle.internal.ExecutionEventCatapult; 050import org.apache.maven.lifecycle.internal.LifecycleStarter; 051import org.apache.maven.model.building.ModelProblem; 052import org.apache.maven.model.building.ModelProblemUtils; 053import org.apache.maven.model.building.ModelSource; 054import org.apache.maven.model.building.UrlModelSource; 055import org.apache.maven.plugin.LegacySupport; 056import org.apache.maven.project.MavenProject; 057import org.apache.maven.project.ProjectBuilder; 058import org.apache.maven.project.ProjectBuildingException; 059import org.apache.maven.project.ProjectBuildingRequest; 060import org.apache.maven.project.ProjectBuildingResult; 061import org.apache.maven.project.ProjectSorter; 062import org.apache.maven.repository.DelegatingLocalArtifactRepository; 063import org.apache.maven.repository.LocalRepositoryNotAccessibleException; 064import org.apache.maven.repository.internal.MavenRepositorySystemUtils; 065import org.apache.maven.settings.Mirror; 066import org.apache.maven.settings.Proxy; 067import org.apache.maven.settings.Server; 068import org.apache.maven.settings.building.SettingsProblem; 069import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest; 070import org.apache.maven.settings.crypto.SettingsDecrypter; 071import org.apache.maven.settings.crypto.SettingsDecryptionResult; 072import org.codehaus.plexus.PlexusContainer; 073import org.codehaus.plexus.component.annotations.Component; 074import org.codehaus.plexus.component.annotations.Requirement; 075import org.codehaus.plexus.component.repository.exception.ComponentLookupException; 076import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration; 077import org.codehaus.plexus.logging.Logger; 078import org.codehaus.plexus.util.IOUtil; 079import org.codehaus.plexus.util.StringUtils; 080import org.codehaus.plexus.util.dag.CycleDetectedException; 081import org.codehaus.plexus.util.xml.Xpp3Dom; 082import org.eclipse.aether.ConfigurationProperties; 083import org.eclipse.aether.DefaultRepositorySystemSession; 084import org.eclipse.aether.RepositorySystem; 085import org.eclipse.aether.RepositorySystemSession; 086import org.eclipse.aether.repository.LocalRepository; 087import org.eclipse.aether.repository.NoLocalRepositoryManagerException; 088import org.eclipse.aether.repository.RepositoryPolicy; 089import org.eclipse.aether.repository.WorkspaceReader; 090import org.eclipse.aether.resolution.ResolutionErrorPolicy; 091import org.eclipse.aether.spi.localrepo.LocalRepositoryManagerFactory; 092import org.eclipse.aether.util.repository.AuthenticationBuilder; 093import org.eclipse.aether.util.repository.ChainedWorkspaceReader; 094import org.eclipse.aether.util.repository.DefaultAuthenticationSelector; 095import org.eclipse.aether.util.repository.DefaultMirrorSelector; 096import org.eclipse.aether.util.repository.DefaultProxySelector; 097import org.eclipse.aether.util.repository.SimpleResolutionErrorPolicy; 098 099/** 100 * @author Jason van Zyl 101 */ 102@Component( role = Maven.class ) 103public 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 public MavenExecutionResult execute( MavenExecutionRequest request ) 147 { 148 MavenExecutionResult result; 149 150 try 151 { 152 result = doExecute( populator.populateDefaults( request ) ); 153 } 154 catch ( OutOfMemoryError e ) 155 { 156 result = addExceptionToResult( new DefaultMavenExecutionResult(), e ); 157 } 158 catch ( MavenExecutionRequestPopulationException e ) 159 { 160 result = addExceptionToResult( new DefaultMavenExecutionResult(), e ); 161 } 162 catch ( RuntimeException e ) 163 { 164 result = 165 addExceptionToResult( new DefaultMavenExecutionResult(), 166 new InternalErrorException( "Internal error: " + e, e ) ); 167 } 168 finally 169 { 170 legacySupport.setSession( null ); 171 } 172 173 return result; 174 } 175 176 private MavenExecutionResult doExecute( MavenExecutionRequest request ) 177 { 178 //TODO: Need a general way to inject standard properties 179 if ( request.getStartTime() != null ) 180 { 181 request.getSystemProperties().put( "${build.timestamp}", 182 new SimpleDateFormat( "yyyyMMdd-hhmm" ).format( request.getStartTime() ) ); 183 } 184 185 request.setStartTime( new Date() ); 186 187 MavenExecutionResult result = new DefaultMavenExecutionResult(); 188 189 try 190 { 191 validateLocalRepository( request ); 192 } 193 catch ( LocalRepositoryNotAccessibleException e ) 194 { 195 return addExceptionToResult( result, e ); 196 } 197 198 DelegatingLocalArtifactRepository delegatingLocalArtifactRepository = 199 new DelegatingLocalArtifactRepository( request.getLocalRepository() ); 200 201 request.setLocalRepository( delegatingLocalArtifactRepository ); 202 203 DefaultRepositorySystemSession repoSession = (DefaultRepositorySystemSession) newRepositorySession( request ); 204 205 MavenSession session = new MavenSession( container, repoSession, request, result ); 206 legacySupport.setSession( session ); 207 208 try 209 { 210 for ( AbstractMavenLifecycleParticipant listener : getLifecycleParticipants( Collections.<MavenProject> emptyList() ) ) 211 { 212 listener.afterSessionStart( session ); 213 } 214 } 215 catch ( MavenExecutionException e ) 216 { 217 return addExceptionToResult( result, e ); 218 } 219 220 eventCatapult.fire( ExecutionEvent.Type.ProjectDiscoveryStarted, session, null ); 221 222 request.getProjectBuildingRequest().setRepositorySession( session.getRepositorySession() ); 223 224 //TODO: optimize for the single project or no project 225 226 List<MavenProject> projects; 227 try 228 { 229 projects = getProjectsForMavenReactor( request ); 230 } 231 catch ( ProjectBuildingException e ) 232 { 233 return addExceptionToResult( result, e ); 234 } 235 236 session.setProjects( projects ); 237 238 result.setTopologicallySortedProjects( session.getProjects() ); 239 240 result.setProject( session.getTopLevelProject() ); 241 242 try 243 { 244 Map<String, MavenProject> projectMap; 245 projectMap = getProjectMap( session.getProjects() ); 246 247 // Desired order of precedence for local artifact repositories 248 // 249 // Reactor 250 // Workspace 251 // User Local Repository 252 ReactorReader reactorRepository = new ReactorReader( projectMap ); 253 254 repoSession.setWorkspaceReader( ChainedWorkspaceReader.newInstance( reactorRepository, 255 repoSession.getWorkspaceReader() ) ); 256 } 257 catch ( DuplicateProjectException e ) 258 { 259 return addExceptionToResult( result, e ); 260 } 261 262 repoSession.setReadOnly(); 263 264 ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); 265 try 266 { 267 for ( AbstractMavenLifecycleParticipant listener : getLifecycleParticipants( projects ) ) 268 { 269 Thread.currentThread().setContextClassLoader( listener.getClass().getClassLoader() ); 270 271 listener.afterProjectsRead( session ); 272 } 273 } 274 catch ( MavenExecutionException e ) 275 { 276 return addExceptionToResult( result, e ); 277 } 278 finally 279 { 280 Thread.currentThread().setContextClassLoader( originalClassLoader ); 281 } 282 283 try 284 { 285 ProjectSorter projectSorter = new ProjectSorter( session.getProjects() ); 286 287 ProjectDependencyGraph projectDependencyGraph = createDependencyGraph( projectSorter, request ); 288 289 session.setProjects( projectDependencyGraph.getSortedProjects() ); 290 291 session.setProjectDependencyGraph( projectDependencyGraph ); 292 } 293 catch ( CycleDetectedException e ) 294 { 295 String message = "The projects in the reactor contain a cyclic reference: " + e.getMessage(); 296 297 ProjectCycleException error = new ProjectCycleException( message, e ); 298 299 return addExceptionToResult( result, error ); 300 } 301 catch ( org.apache.maven.project.DuplicateProjectException e ) 302 { 303 return addExceptionToResult( result, e ); 304 } 305 catch ( MavenExecutionException e ) 306 { 307 return addExceptionToResult( result, e ); 308 } 309 310 result.setTopologicallySortedProjects( session.getProjects() ); 311 312 if ( result.hasExceptions() ) 313 { 314 return result; 315 } 316 317 lifecycleStarter.execute( session ); 318 319 validateActivatedProfiles( session.getProjects(), request.getActiveProfiles() ); 320 321 if ( session.getResult().hasExceptions() ) 322 { 323 return addExceptionToResult( result, session.getResult().getExceptions().get( 0 ) ); 324 } 325 326 return result; 327 } 328 329 public RepositorySystemSession newRepositorySession( MavenExecutionRequest request ) 330 { 331 DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession(); 332 333 session.setCache( request.getRepositoryCache() ); 334 335 Map<Object, Object> configProps = new LinkedHashMap<Object, Object>(); 336 configProps.put( ConfigurationProperties.USER_AGENT, getUserAgent() ); 337 configProps.put( ConfigurationProperties.INTERACTIVE, request.isInteractiveMode() ); 338 configProps.putAll( request.getSystemProperties() ); 339 configProps.putAll( request.getUserProperties() ); 340 341 session.setOffline( request.isOffline() ); 342 session.setChecksumPolicy( request.getGlobalChecksumPolicy() ); 343 if ( request.isNoSnapshotUpdates() ) 344 { 345 session.setUpdatePolicy( RepositoryPolicy.UPDATE_POLICY_NEVER ); 346 } 347 else if ( request.isUpdateSnapshots() ) 348 { 349 session.setUpdatePolicy( RepositoryPolicy.UPDATE_POLICY_ALWAYS ); 350 } 351 else 352 { 353 session.setUpdatePolicy( null ); 354 } 355 356 int errorPolicy = 0; 357 errorPolicy |= request.isCacheNotFound() ? ResolutionErrorPolicy.CACHE_NOT_FOUND : 0; 358 errorPolicy |= request.isCacheTransferError() ? ResolutionErrorPolicy.CACHE_TRANSFER_ERROR : 0; 359 session.setResolutionErrorPolicy( new SimpleResolutionErrorPolicy( errorPolicy, errorPolicy 360 | ResolutionErrorPolicy.CACHE_NOT_FOUND ) ); 361 362 session.setArtifactTypeRegistry( RepositoryUtils.newArtifactTypeRegistry( artifactHandlerManager ) ); 363 364 LocalRepository localRepo = new LocalRepository( request.getLocalRepository().getBasedir() ); 365 366 if ( request.isUseLegacyLocalRepository() ) 367 { 368 logger.warn( "Disabling enhanced local repository: using legacy is strongly discouraged to ensure build reproducibility." ); 369 try 370 { 371 session.setLocalRepositoryManager( simpleLocalRepositoryManagerFactory.newInstance( session, localRepo ) ); 372 } 373 catch ( NoLocalRepositoryManagerException e ) 374 { 375 376 logger.warn( "Failed to configure legacy local repository: back to default" ); 377 session.setLocalRepositoryManager( repoSystem.newLocalRepositoryManager( session, localRepo ) ); 378 } 379 } 380 else 381 { 382 session.setLocalRepositoryManager( repoSystem.newLocalRepositoryManager( session, localRepo ) ); 383 } 384 385 if ( request.getWorkspaceReader() != null ) 386 { 387 session.setWorkspaceReader( request.getWorkspaceReader() ); 388 } 389 else 390 { 391 session.setWorkspaceReader( workspaceRepository ); 392 } 393 394 DefaultSettingsDecryptionRequest decrypt = new DefaultSettingsDecryptionRequest(); 395 decrypt.setProxies( request.getProxies() ); 396 decrypt.setServers( request.getServers() ); 397 SettingsDecryptionResult decrypted = settingsDecrypter.decrypt( decrypt ); 398 399 if ( logger.isDebugEnabled() ) 400 { 401 for ( SettingsProblem problem : decrypted.getProblems() ) 402 { 403 logger.debug( problem.getMessage(), problem.getException() ); 404 } 405 } 406 407 DefaultMirrorSelector mirrorSelector = new DefaultMirrorSelector(); 408 for ( Mirror mirror : request.getMirrors() ) 409 { 410 mirrorSelector.add( mirror.getId(), mirror.getUrl(), mirror.getLayout(), false, mirror.getMirrorOf(), 411 mirror.getMirrorOfLayouts() ); 412 } 413 session.setMirrorSelector( mirrorSelector ); 414 415 DefaultProxySelector proxySelector = new DefaultProxySelector(); 416 for ( Proxy proxy : decrypted.getProxies() ) 417 { 418 AuthenticationBuilder authBuilder = new AuthenticationBuilder(); 419 authBuilder.addUsername( proxy.getUsername() ).addPassword( proxy.getPassword() ); 420 proxySelector.add( new org.eclipse.aether.repository.Proxy( proxy.getProtocol(), proxy.getHost(), 421 proxy.getPort(), authBuilder.build() ), 422 proxy.getNonProxyHosts() ); 423 } 424 session.setProxySelector( proxySelector ); 425 426 DefaultAuthenticationSelector authSelector = new DefaultAuthenticationSelector(); 427 for ( Server server : decrypted.getServers() ) 428 { 429 AuthenticationBuilder authBuilder = new AuthenticationBuilder(); 430 authBuilder.addUsername( server.getUsername() ).addPassword( server.getPassword() ); 431 authBuilder.addPrivateKey( server.getPrivateKey(), server.getPassphrase() ); 432 authSelector.add( server.getId(), authBuilder.build() ); 433 434 if ( server.getConfiguration() != null ) 435 { 436 Xpp3Dom dom = (Xpp3Dom) server.getConfiguration(); 437 for ( int i = dom.getChildCount() - 1; i >= 0; i-- ) 438 { 439 Xpp3Dom child = dom.getChild( i ); 440 if ( "wagonProvider".equals( child.getName() ) ) 441 { 442 dom.removeChild( i ); 443 } 444 } 445 446 XmlPlexusConfiguration config = new XmlPlexusConfiguration( dom ); 447 configProps.put( "aether.connector.wagon.config." + server.getId(), config ); 448 } 449 450 configProps.put( "aether.connector.perms.fileMode." + server.getId(), server.getFilePermissions() ); 451 configProps.put( "aether.connector.perms.dirMode." + server.getId(), server.getDirectoryPermissions() ); 452 } 453 session.setAuthenticationSelector( authSelector ); 454 455 session.setTransferListener( request.getTransferListener() ); 456 457 session.setRepositoryListener( eventSpyDispatcher.chainListener( new LoggingRepositoryListener( logger ) ) ); 458 459 session.setUserProperties( request.getUserProperties() ); 460 session.setSystemProperties( request.getSystemProperties() ); 461 session.setConfigProperties( configProps ); 462 463 return session; 464 } 465 466 private String getUserAgent() 467 { 468 return "Apache-Maven/" + getMavenVersion() 469 + " (Java " + System.getProperty( "java.version" ) + "; " 470 + System.getProperty( "os.name" ) + " " + System.getProperty( "os.version" ) + ")"; 471 } 472 473 private String getMavenVersion() 474 { 475 Properties props = new Properties(); 476 477 InputStream is = getClass().getResourceAsStream( "/META-INF/maven/org.apache.maven/maven-core/pom.properties" ); 478 if ( is != null ) 479 { 480 try 481 { 482 props.load( is ); 483 } 484 catch ( IOException e ) 485 { 486 logger.debug( "Failed to read Maven version", e ); 487 } 488 IOUtil.close( is ); 489 } 490 491 return props.getProperty( "version", "unknown-version" ); 492 } 493 494 private void validateLocalRepository( MavenExecutionRequest request ) 495 throws LocalRepositoryNotAccessibleException 496 { 497 File localRepoDir = request.getLocalRepositoryPath(); 498 499 logger.debug( "Using local repository at " + localRepoDir ); 500 501 localRepoDir.mkdirs(); 502 503 if ( !localRepoDir.isDirectory() ) 504 { 505 throw new LocalRepositoryNotAccessibleException( "Could not create local repository at " + localRepoDir ); 506 } 507 } 508 509 private Collection<AbstractMavenLifecycleParticipant> getLifecycleParticipants( Collection<MavenProject> projects ) 510 { 511 Collection<AbstractMavenLifecycleParticipant> lifecycleListeners = 512 new LinkedHashSet<AbstractMavenLifecycleParticipant>(); 513 514 ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); 515 try 516 { 517 try 518 { 519 lifecycleListeners.addAll( container.lookupList( AbstractMavenLifecycleParticipant.class ) ); 520 } 521 catch ( ComponentLookupException e ) 522 { 523 // this is just silly, lookupList should return an empty list! 524 logger.warn( "Failed to lookup lifecycle participants: " + e.getMessage() ); 525 } 526 527 Collection<ClassLoader> scannedRealms = new HashSet<ClassLoader>(); 528 529 for ( MavenProject project : projects ) 530 { 531 ClassLoader projectRealm = project.getClassRealm(); 532 533 if ( projectRealm != null && scannedRealms.add( projectRealm ) ) 534 { 535 Thread.currentThread().setContextClassLoader( projectRealm ); 536 537 try 538 { 539 lifecycleListeners.addAll( container.lookupList( AbstractMavenLifecycleParticipant.class ) ); 540 } 541 catch ( ComponentLookupException e ) 542 { 543 // this is just silly, lookupList should return an empty list! 544 logger.warn( "Failed to lookup lifecycle participants: " + e.getMessage() ); 545 } 546 } 547 } 548 } 549 finally 550 { 551 Thread.currentThread().setContextClassLoader( originalClassLoader ); 552 } 553 554 return lifecycleListeners; 555 } 556 557 private MavenExecutionResult addExceptionToResult( MavenExecutionResult result, Throwable e ) 558 { 559 if ( !result.getExceptions().contains( e ) ) 560 { 561 result.addException( e ); 562 } 563 564 return result; 565 } 566 567 private List<MavenProject> getProjectsForMavenReactor( MavenExecutionRequest request ) 568 throws ProjectBuildingException 569 { 570 List<MavenProject> projects = new ArrayList<MavenProject>(); 571 572 // We have no POM file. 573 // 574 if ( request.getPom() == null ) 575 { 576 ModelSource modelSource = new UrlModelSource( DefaultMaven.class.getResource( "project/standalone.xml" ) ); 577 MavenProject project = 578 projectBuilder.build( modelSource, request.getProjectBuildingRequest() ).getProject(); 579 project.setExecutionRoot( true ); 580 projects.add( project ); 581 request.setProjectPresent( false ); 582 return projects; 583 } 584 585 List<File> files = Arrays.asList( request.getPom().getAbsoluteFile() ); 586 collectProjects( projects, files, request ); 587 return projects; 588 } 589 590 private Map<String, MavenProject> getProjectMap( List<MavenProject> projects ) 591 throws DuplicateProjectException 592 { 593 Map<String, MavenProject> index = new LinkedHashMap<String, MavenProject>(); 594 Map<String, List<File>> collisions = new LinkedHashMap<String, List<File>>(); 595 596 for ( MavenProject project : projects ) 597 { 598 String projectId = ArtifactUtils.key( project.getGroupId(), project.getArtifactId(), project.getVersion() ); 599 600 MavenProject collision = index.get( projectId ); 601 602 if ( collision == null ) 603 { 604 index.put( projectId, project ); 605 } 606 else 607 { 608 List<File> pomFiles = collisions.get( projectId ); 609 610 if ( pomFiles == null ) 611 { 612 pomFiles = new ArrayList<File>( Arrays.asList( collision.getFile(), project.getFile() ) ); 613 collisions.put( projectId, pomFiles ); 614 } 615 else 616 { 617 pomFiles.add( project.getFile() ); 618 } 619 } 620 } 621 622 if ( !collisions.isEmpty() ) 623 { 624 throw new DuplicateProjectException( "Two or more projects in the reactor" 625 + " have the same identifier, please make sure that <groupId>:<artifactId>:<version>" 626 + " is unique for each project: " + collisions, collisions ); 627 } 628 629 return index; 630 } 631 632 private void collectProjects( List<MavenProject> projects, List<File> files, MavenExecutionRequest request ) 633 throws ProjectBuildingException 634 { 635 ProjectBuildingRequest projectBuildingRequest = request.getProjectBuildingRequest(); 636 637 List<ProjectBuildingResult> results = projectBuilder.build( files, request.isRecursive(), projectBuildingRequest ); 638 639 boolean problems = false; 640 641 for ( ProjectBuildingResult result : results ) 642 { 643 projects.add( result.getProject() ); 644 645 if ( !result.getProblems().isEmpty() && logger.isWarnEnabled() ) 646 { 647 logger.warn( "" ); 648 logger.warn( "Some problems were encountered while building the effective model for " 649 + result.getProject().getId() ); 650 651 for ( ModelProblem problem : result.getProblems() ) 652 { 653 String location = ModelProblemUtils.formatLocation( problem, result.getProjectId() ); 654 logger.warn( problem.getMessage() + ( StringUtils.isNotEmpty( location ) ? " @ " + location : "" ) ); 655 } 656 657 problems = true; 658 } 659 } 660 661 if ( problems ) 662 { 663 logger.warn( "" ); 664 logger.warn( "It is highly recommended to fix these problems" 665 + " because they threaten the stability of your build." ); 666 logger.warn( "" ); 667 logger.warn( "For this reason, future Maven versions might no" 668 + " longer support building such malformed projects." ); 669 logger.warn( "" ); 670 } 671 } 672 673 private void validateActivatedProfiles( List<MavenProject> projects, List<String> activeProfileIds ) 674 { 675 Collection<String> notActivatedProfileIds = new LinkedHashSet<String>( activeProfileIds ); 676 677 for ( MavenProject project : projects ) 678 { 679 for ( List<String> profileIds : project.getInjectedProfileIds().values() ) 680 { 681 notActivatedProfileIds.removeAll( profileIds ); 682 } 683 } 684 685 for ( String notActivatedProfileId : notActivatedProfileIds ) 686 { 687 logger.warn( "The requested profile \"" + notActivatedProfileId 688 + "\" could not be activated because it does not exist." ); 689 } 690 } 691 692 protected Logger getLogger() 693 { 694 return logger; 695 } 696 697 private ProjectDependencyGraph createDependencyGraph( ProjectSorter sorter, MavenExecutionRequest request ) 698 throws MavenExecutionException 699 { 700 ProjectDependencyGraph graph = new DefaultProjectDependencyGraph( sorter ); 701 702 List<MavenProject> activeProjects = sorter.getSortedProjects(); 703 704 activeProjects = trimSelectedProjects( activeProjects, graph, request ); 705 activeProjects = trimResumedProjects( activeProjects, request ); 706 707 if ( activeProjects.size() != sorter.getSortedProjects().size() ) 708 { 709 graph = new FilteredProjectDependencyGraph( graph, activeProjects ); 710 } 711 712 return graph; 713 } 714 715 private List<MavenProject> trimSelectedProjects( List<MavenProject> projects, ProjectDependencyGraph graph, 716 MavenExecutionRequest request ) 717 throws MavenExecutionException 718 { 719 List<MavenProject> result = projects; 720 721 if ( !request.getSelectedProjects().isEmpty() ) 722 { 723 File reactorDirectory = null; 724 if ( request.getBaseDirectory() != null ) 725 { 726 reactorDirectory = new File( request.getBaseDirectory() ); 727 } 728 729 Collection<MavenProject> selectedProjects = new LinkedHashSet<MavenProject>( projects.size() ); 730 731 for ( String selector : request.getSelectedProjects() ) 732 { 733 MavenProject selectedProject = null; 734 735 for ( MavenProject project : projects ) 736 { 737 if ( isMatchingProject( project, selector, reactorDirectory ) ) 738 { 739 selectedProject = project; 740 break; 741 } 742 } 743 744 if ( selectedProject != null ) 745 { 746 selectedProjects.add( selectedProject ); 747 } 748 else 749 { 750 throw new MavenExecutionException( "Could not find the selected project in the reactor: " 751 + selector, request.getPom() ); 752 } 753 } 754 755 boolean makeUpstream = false; 756 boolean makeDownstream = false; 757 758 if ( MavenExecutionRequest.REACTOR_MAKE_UPSTREAM.equals( request.getMakeBehavior() ) ) 759 { 760 makeUpstream = true; 761 } 762 else if ( MavenExecutionRequest.REACTOR_MAKE_DOWNSTREAM.equals( request.getMakeBehavior() ) ) 763 { 764 makeDownstream = true; 765 } 766 else if ( MavenExecutionRequest.REACTOR_MAKE_BOTH.equals( request.getMakeBehavior() ) ) 767 { 768 makeUpstream = true; 769 makeDownstream = true; 770 } 771 else if ( StringUtils.isNotEmpty( request.getMakeBehavior() ) ) 772 { 773 throw new MavenExecutionException( "Invalid reactor make behavior: " + request.getMakeBehavior(), 774 request.getPom() ); 775 } 776 777 if ( makeUpstream || makeDownstream ) 778 { 779 for ( MavenProject selectedProject : new ArrayList<MavenProject>( selectedProjects ) ) 780 { 781 if ( makeUpstream ) 782 { 783 selectedProjects.addAll( graph.getUpstreamProjects( selectedProject, true ) ); 784 } 785 if ( makeDownstream ) 786 { 787 selectedProjects.addAll( graph.getDownstreamProjects( selectedProject, true ) ); 788 } 789 } 790 } 791 792 result = new ArrayList<MavenProject>( selectedProjects.size() ); 793 794 for ( MavenProject project : projects ) 795 { 796 if ( selectedProjects.contains( project ) ) 797 { 798 result.add( project ); 799 } 800 } 801 } 802 803 return result; 804 } 805 806 private List<MavenProject> trimResumedProjects( List<MavenProject> projects, MavenExecutionRequest request ) 807 throws MavenExecutionException 808 { 809 List<MavenProject> result = projects; 810 811 if ( StringUtils.isNotEmpty( request.getResumeFrom() ) ) 812 { 813 File reactorDirectory = null; 814 if ( request.getBaseDirectory() != null ) 815 { 816 reactorDirectory = new File( request.getBaseDirectory() ); 817 } 818 819 String selector = request.getResumeFrom(); 820 821 result = new ArrayList<MavenProject>( projects.size() ); 822 823 boolean resumed = false; 824 825 for ( MavenProject project : projects ) 826 { 827 if ( !resumed && isMatchingProject( project, selector, reactorDirectory ) ) 828 { 829 resumed = true; 830 } 831 832 if ( resumed ) 833 { 834 result.add( project ); 835 } 836 } 837 838 if ( !resumed ) 839 { 840 throw new MavenExecutionException( "Could not find project to resume reactor build from: " + selector 841 + " vs " + projects, request.getPom() ); 842 } 843 } 844 845 return result; 846 } 847 848 private boolean isMatchingProject( MavenProject project, String selector, File reactorDirectory ) 849 { 850 // [groupId]:artifactId 851 if ( selector.indexOf( ':' ) >= 0 ) 852 { 853 String id = ':' + project.getArtifactId(); 854 855 if ( id.equals( selector ) ) 856 { 857 return true; 858 } 859 860 id = project.getGroupId() + id; 861 862 if ( id.equals( selector ) ) 863 { 864 return true; 865 } 866 } 867 868 // relative path, e.g. "sub", "../sub" or "." 869 else if ( reactorDirectory != null ) 870 { 871 File selectedProject = new File( new File( reactorDirectory, selector ).toURI().normalize() ); 872 873 if ( selectedProject.isFile() ) 874 { 875 return selectedProject.equals( project.getFile() ); 876 } 877 else if ( selectedProject.isDirectory() ) 878 { 879 return selectedProject.equals( project.getBasedir() ); 880 } 881 } 882 883 return false; 884 } 885 886}