1 package org.apache.maven; 2 3 18 19 20 import org.apache.maven.artifact.manager.WagonManager; 21 import org.apache.maven.artifact.repository.ArtifactRepository; 22 import org.apache.maven.artifact.resolver.ArtifactResolutionException; 23 import org.apache.maven.artifact.versioning.DefaultArtifactVersion; 24 import org.apache.maven.execution.BuildFailure; 25 import org.apache.maven.execution.MavenExecutionRequest; 26 import org.apache.maven.execution.MavenSession; 27 import org.apache.maven.execution.ReactorManager; 28 import org.apache.maven.execution.RuntimeInformation; 29 import org.apache.maven.lifecycle.LifecycleExecutionException; 30 import org.apache.maven.lifecycle.LifecycleExecutor; 31 import org.apache.maven.model.Profile; 32 import org.apache.maven.monitor.event.EventDispatcher; 33 import org.apache.maven.monitor.event.MavenEvents; 34 import org.apache.maven.profiles.ProfileManager; 35 import org.apache.maven.profiles.activation.ProfileActivationException; 36 import org.apache.maven.project.DuplicateProjectException; 37 import org.apache.maven.project.MavenProject; 38 import org.apache.maven.project.MavenProjectBuilder; 39 import org.apache.maven.project.ProjectBuildingException; 40 import org.apache.maven.reactor.MavenExecutionException; 41 import org.apache.maven.settings.Mirror; 42 import org.apache.maven.settings.Proxy; 43 import org.apache.maven.settings.Server; 44 import org.apache.maven.settings.Settings; 45 import org.apache.maven.settings.SettingsUtils; 46 import org.apache.maven.usability.SystemWarnings; 47 import org.apache.maven.usability.diagnostics.ErrorDiagnostics; 48 import org.codehaus.plexus.PlexusConstants; 49 import org.codehaus.plexus.PlexusContainer; 50 import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException; 51 import org.codehaus.plexus.component.repository.exception.ComponentLookupException; 52 import org.codehaus.plexus.context.Context; 53 import org.codehaus.plexus.context.ContextException; 54 import org.codehaus.plexus.logging.AbstractLogEnabled; 55 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable; 56 import org.codehaus.plexus.util.FileUtils; 57 import org.codehaus.plexus.util.dag.CycleDetectedException; 58 import org.codehaus.plexus.util.xml.Xpp3Dom; 59 60 import java.io.File ; 61 import java.io.IOException ; 62 import java.text.DateFormat ; 63 import java.text.SimpleDateFormat ; 64 import java.util.ArrayList ; 65 import java.util.Collections ; 66 import java.util.Date ; 67 import java.util.Iterator ; 68 import java.util.List ; 69 import java.util.TimeZone ; 70 71 75 public class DefaultMaven 76 extends AbstractLogEnabled 77 implements Maven, Contextualizable 78 { 79 83 protected MavenProjectBuilder projectBuilder; 84 85 protected LifecycleExecutor lifecycleExecutor; 86 87 protected PlexusContainer container; 88 89 protected ErrorDiagnostics errorDiagnostics; 90 91 protected RuntimeInformation runtimeInformation; 92 93 private static final long MB = 1024 * 1024; 94 95 private static final int MS_PER_SEC = 1000; 96 97 private static final int SEC_PER_MIN = 60; 98 99 103 public void execute( MavenExecutionRequest request ) 104 throws MavenExecutionException 105 { 106 EventDispatcher dispatcher = request.getEventDispatcher(); 107 108 String event = MavenEvents.REACTOR_EXECUTION; 109 110 dispatcher.dispatchStart( event, request.getBaseDirectory() ); 111 112 ReactorManager rm; 113 try 114 { 115 rm = doExecute( request, dispatcher ); 116 } 117 catch ( LifecycleExecutionException e ) 118 { 119 dispatcher.dispatchError( event, request.getBaseDirectory(), e ); 120 121 logError( e, request.isShowErrors() ); 122 123 stats( request.getStartTime() ); 124 125 line(); 126 127 throw new MavenExecutionException( e.getMessage(), e ); 128 } 129 catch ( BuildFailureException e ) 130 { 131 dispatcher.dispatchError( event, request.getBaseDirectory(), e ); 132 133 logFailure( e, request.isShowErrors() ); 134 135 stats( request.getStartTime() ); 136 137 line(); 138 139 throw new MavenExecutionException( e.getMessage(), e ); 140 } 141 catch ( Throwable t ) 142 { 143 dispatcher.dispatchError( event, request.getBaseDirectory(), t ); 144 145 logFatal( t ); 146 147 stats( request.getStartTime() ); 148 149 line(); 150 151 throw new MavenExecutionException( "Error executing project within the reactor", t ); 152 } 153 154 156 logReactorSummary( rm ); 158 159 if ( rm.hasBuildFailures() ) 160 { 161 logErrors( rm, request.isShowErrors() ); 162 163 if ( !ReactorManager.FAIL_NEVER.equals( rm.getFailureBehavior() ) ) 164 { 165 dispatcher.dispatchError( event, request.getBaseDirectory(), null ); 166 167 getLogger().info( "BUILD ERRORS" ); 168 169 line(); 170 171 stats( request.getStartTime() ); 172 173 line(); 174 175 throw new MavenExecutionException( "Some builds failed" ); 176 } 177 else 178 { 179 getLogger().info( " + Ignoring failures" ); 180 } 181 } 182 183 logSuccess( rm ); 184 185 stats( request.getStartTime() ); 186 187 line(); 188 189 dispatcher.dispatchEnd( event, request.getBaseDirectory() ); 190 } 191 192 private void logErrors( ReactorManager rm, boolean showErrors ) 193 { 194 for ( Iterator it = rm.getSortedProjects().iterator(); it.hasNext(); ) 195 { 196 MavenProject project = (MavenProject) it.next(); 197 198 if ( rm.hasBuildFailure( project ) ) 199 { 200 BuildFailure buildFailure = rm.getBuildFailure( project ); 201 202 getLogger().info( 203 "Error for project: " + project.getName() + " (during " + buildFailure.getTask() + ")" ); 204 205 line(); 206 207 logDiagnostics( buildFailure.getCause() ); 208 209 logTrace( buildFailure.getCause(), showErrors ); 210 } 211 } 212 213 if ( !showErrors ) 214 { 215 getLogger().info( "For more information, run Maven with the -e switch" ); 216 217 line(); 218 } 219 220 } 221 222 private ReactorManager doExecute( MavenExecutionRequest request, EventDispatcher dispatcher ) 223 throws MavenExecutionException, BuildFailureException, LifecycleExecutionException 224 { 225 if ( request.getSettings().isOffline() ) 226 { 227 getLogger().info( SystemWarnings.getOfflineWarning() ); 228 229 WagonManager wagonManager = null; 230 231 try 232 { 233 wagonManager = (WagonManager) container.lookup( WagonManager.ROLE ); 234 235 wagonManager.setOnline( false ); 236 } 237 catch ( ComponentLookupException e ) 238 { 239 throw new MavenExecutionException( "Cannot retrieve WagonManager in order to set offline mode.", e ); 240 } 241 finally 242 { 243 try 244 { 245 container.release( wagonManager ); 246 } 247 catch ( ComponentLifecycleException e ) 248 { 249 getLogger().warn( "Cannot release WagonManager.", e ); 250 } 251 } 252 } 253 254 try 255 { 256 resolveParameters( request.getSettings() ); 257 } 258 catch ( ComponentLookupException e ) 259 { 260 throw new MavenExecutionException( "Unable to configure Maven for execution", e ); 261 } 262 catch ( ComponentLifecycleException e ) 263 { 264 throw new MavenExecutionException( "Unable to configure Maven for execution", e ); 265 } 266 catch ( SettingsConfigurationException e ) 267 { 268 throw new MavenExecutionException( "Unable to configure Maven for execution", e ); 269 } 270 271 ProfileManager globalProfileManager = request.getGlobalProfileManager(); 272 273 globalProfileManager.loadSettingsProfiles( request.getSettings() ); 274 275 getLogger().info( "Scanning for projects..." ); 276 277 boolean foundProjects = true; 278 List projects = getProjects( request, globalProfileManager ); 279 if ( projects.isEmpty() ) 280 { 281 projects.add( getSuperProject( request ) ); 282 foundProjects = false; 283 } 284 285 ReactorManager rm; 286 try 287 { 288 rm = new ReactorManager( projects ); 289 290 String requestFailureBehavior = request.getFailureBehavior(); 291 292 if ( requestFailureBehavior != null ) 293 { 294 rm.setFailureBehavior( requestFailureBehavior ); 295 } 296 } 297 catch ( CycleDetectedException e ) 298 { 299 throw new BuildFailureException( 300 "The projects in the reactor contain a cyclic reference: " + e.getMessage(), e ); 301 } 302 catch ( DuplicateProjectException e ) 303 { 304 throw new BuildFailureException( e.getMessage(), e ); 305 } 306 307 if ( rm.hasMultipleProjects() ) 308 { 309 getLogger().info( "Reactor build order: " ); 310 311 for ( Iterator i = rm.getSortedProjects().iterator(); i.hasNext(); ) 312 { 313 MavenProject project = (MavenProject) i.next(); 314 getLogger().info( " " + project.getName() ); 315 } 316 } 317 318 MavenSession session = createSession( request, rm ); 319 320 session.setUsingPOMsFromFilesystem( foundProjects ); 321 322 lifecycleExecutor.execute( session, rm, dispatcher ); 323 324 return rm; 325 } 326 327 private MavenProject getSuperProject( MavenExecutionRequest request ) 328 throws MavenExecutionException 329 { 330 MavenProject superProject; 331 try 332 { 333 superProject = projectBuilder.buildStandaloneSuperProject( request.getLocalRepository() ); 334 335 } 336 catch ( ProjectBuildingException e ) 337 { 338 throw new MavenExecutionException( e.getMessage(), e ); 339 } 340 return superProject; 341 } 342 343 private List getProjects( MavenExecutionRequest request, ProfileManager globalProfileManager ) 344 throws MavenExecutionException, BuildFailureException 345 { 346 List projects; 347 try 348 { 349 List files = getProjectFiles( request ); 350 351 projects = collectProjects( files, request.getLocalRepository(), request.isRecursive(), 352 request.getSettings(), globalProfileManager, !request.isReactorActive() ); 353 354 } 355 catch ( IOException e ) 356 { 357 throw new MavenExecutionException( "Error processing projects for the reactor: " + e.getMessage(), e ); 358 } 359 catch ( ArtifactResolutionException e ) 360 { 361 throw new MavenExecutionException( e.getMessage(), e ); 362 } 363 catch ( ProjectBuildingException e ) 364 { 365 throw new MavenExecutionException( e.getMessage(), e ); 366 } 367 catch ( ProfileActivationException e ) 368 { 369 throw new MavenExecutionException( e.getMessage(), e ); 370 } 371 return projects; 372 } 373 374 private void logReactorSummaryLine( String name, String status ) 375 { 376 logReactorSummaryLine( name, status, -1 ); 377 } 378 379 private void logReactorSummaryLine( String name, String status, long time ) 380 { 381 StringBuffer messageBuffer = new StringBuffer (); 382 383 messageBuffer.append( name ); 384 385 int dotCount = 54; 386 387 dotCount -= name.length(); 388 389 messageBuffer.append( " " ); 390 391 for ( int i = 0; i < dotCount; i++ ) 392 { 393 messageBuffer.append( '.' ); 394 } 395 396 messageBuffer.append( " " ); 397 398 messageBuffer.append( status ); 399 400 if ( time >= 0 ) 401 { 402 messageBuffer.append( " [" ); 403 404 messageBuffer.append( getFormattedTime( time ) ); 405 406 messageBuffer.append( "]" ); 407 } 408 409 getLogger().info( messageBuffer.toString() ); 410 } 411 412 private static String getFormattedTime( long time ) 413 { 414 String pattern = "s.SSS's'"; 415 if ( time / 60000L > 0 ) 416 { 417 pattern = "m:s" + pattern; 418 if ( time / 3600000L > 0 ) 419 { 420 pattern = "H:m" + pattern; 421 } 422 } 423 DateFormat fmt = new SimpleDateFormat ( pattern ); 424 fmt.setTimeZone( TimeZone.getTimeZone( "UTC" ) ); 425 return fmt.format( new Date ( time ) ); 426 } 427 428 private List collectProjects( List files, ArtifactRepository localRepository, boolean recursive, Settings settings, 429 ProfileManager globalProfileManager, boolean isRoot ) 430 throws ArtifactResolutionException, ProjectBuildingException, ProfileActivationException, 431 MavenExecutionException, BuildFailureException 432 { 433 List projects = new ArrayList ( files.size() ); 434 435 for ( Iterator iterator = files.iterator(); iterator.hasNext(); ) 436 { 437 File file = (File ) iterator.next(); 438 439 boolean usingReleasePom = false; 440 441 if ( RELEASE_POMv4.equals( file.getName() ) ) 442 { 443 getLogger().info( "NOTE: Using release-pom: " + file + " in reactor build." ); 444 usingReleasePom = true; 445 } 446 447 MavenProject project = getProject( file, localRepository, settings, globalProfileManager ); 448 449 if ( isRoot ) 450 { 451 project.setExecutionRoot( true ); 452 } 453 454 if ( project.getPrerequisites() != null && project.getPrerequisites().getMaven() != null ) 455 { 456 DefaultArtifactVersion version = new DefaultArtifactVersion( project.getPrerequisites().getMaven() ); 457 if ( runtimeInformation.getApplicationVersion().compareTo( version ) < 0 ) 458 { 459 throw new BuildFailureException( "Unable to build project '" + project.getFile() + 460 "; it requires Maven version " + version.toString() ); 461 } 462 } 463 464 if ( project.getModules() != null && !project.getModules().isEmpty() && recursive ) 465 { 466 project.setPackaging( "pom" ); 468 469 File basedir = file.getParentFile(); 470 471 List moduleFiles = new ArrayList ( project.getModules().size() ); 473 for ( Iterator i = project.getModules().iterator(); i.hasNext(); ) 474 { 475 String name = (String ) i.next(); 476 477 File moduleFile; 478 479 if ( usingReleasePom ) 480 { 481 moduleFile = new File ( basedir, name + "/" + Maven.RELEASE_POMv4 ); 482 } 483 else 484 { 485 moduleFile = new File ( basedir, name + "/" + Maven.POMv4 ); 486 } 487 488 moduleFiles.add( moduleFile ); 489 } 490 491 List collectedProjects = 492 collectProjects( moduleFiles, localRepository, recursive, settings, globalProfileManager, false ); 493 projects.addAll( collectedProjects ); 494 project.setCollectedProjects( collectedProjects ); 495 } 496 projects.add( project ); 497 } 498 499 return projects; 500 } 501 502 public MavenProject getProject( File pom, ArtifactRepository localRepository, Settings settings, 503 ProfileManager globalProfileManager ) 504 throws ProjectBuildingException, ArtifactResolutionException, ProfileActivationException 505 { 506 if ( pom.exists() ) 507 { 508 if ( pom.length() == 0 ) 509 { 510 throw new ProjectBuildingException( "unknown", "The file " + pom.getAbsolutePath() + 511 " you specified has zero length." ); 512 } 513 } 514 515 return projectBuilder.build( pom, localRepository, globalProfileManager ); 516 } 517 518 522 527 protected MavenSession createSession( MavenExecutionRequest request, ReactorManager rpm ) 528 { 529 return new MavenSession( container, request.getSettings(), request.getLocalRepository(), 530 request.getEventDispatcher(), rpm, request.getGoals(), request.getBaseDirectory(), 531 request.getExecutionProperties(), request.getStartTime() ); 532 } 533 534 540 private void resolveParameters( Settings settings ) 541 throws ComponentLookupException, ComponentLifecycleException, SettingsConfigurationException 542 { 543 WagonManager wagonManager = (WagonManager) container.lookup( WagonManager.ROLE ); 544 545 try 546 { 547 Proxy proxy = settings.getActiveProxy(); 548 549 if ( proxy != null ) 550 { 551 if ( proxy.getHost() == null ) 552 { 553 throw new SettingsConfigurationException( "Proxy in settings.xml has no host" ); 554 } 555 556 wagonManager.addProxy( proxy.getProtocol(), proxy.getHost(), proxy.getPort(), proxy.getUsername(), 557 proxy.getPassword(), proxy.getNonProxyHosts() ); 558 } 559 560 for ( Iterator i = settings.getServers().iterator(); i.hasNext(); ) 561 { 562 Server server = (Server) i.next(); 563 564 wagonManager.addAuthenticationInfo( server.getId(), server.getUsername(), server.getPassword(), 565 server.getPrivateKey(), server.getPassphrase() ); 566 567 wagonManager.addPermissionInfo( server.getId(), server.getFilePermissions(), 568 server.getDirectoryPermissions() ); 569 570 if ( server.getConfiguration() != null ) 571 { 572 wagonManager.addConfiguration( server.getId(), (Xpp3Dom) server.getConfiguration() ); 573 } 574 } 575 576 for ( Iterator i = settings.getMirrors().iterator(); i.hasNext(); ) 577 { 578 Mirror mirror = (Mirror) i.next(); 579 580 wagonManager.addMirror( mirror.getId(), mirror.getMirrorOf(), mirror.getUrl() ); 581 } 582 } 583 finally 584 { 585 container.release( wagonManager ); 586 } 587 } 588 589 593 public void contextualize( Context context ) 594 throws ContextException 595 { 596 container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY ); 597 } 598 599 603 protected void logFatal( Throwable error ) 604 { 605 line(); 606 607 getLogger().error( "FATAL ERROR" ); 608 609 line(); 610 611 logDiagnostics( error ); 612 613 logTrace( error, true ); 614 } 615 616 protected void logError( Exception e, boolean showErrors ) 617 { 618 line(); 619 620 getLogger().error( "BUILD ERROR" ); 621 622 line(); 623 624 logDiagnostics( e ); 625 626 logTrace( e, showErrors ); 627 628 if ( !showErrors ) 629 { 630 getLogger().info( "For more information, run Maven with the -e switch" ); 631 632 line(); 633 } 634 } 635 636 protected void logFailure( BuildFailureException e, boolean showErrors ) 637 { 638 line(); 639 640 getLogger().error( "BUILD FAILURE" ); 641 642 line(); 643 644 logDiagnostics( e ); 645 646 logTrace( e, showErrors ); 647 648 if ( !showErrors ) 649 { 650 getLogger().info( "For more information, run Maven with the -e switch" ); 651 652 line(); 653 } 654 } 655 656 private void logTrace( Throwable t, boolean showErrors ) 657 { 658 if ( getLogger().isDebugEnabled() ) 659 { 660 getLogger().debug( "Trace", t ); 661 662 line(); 663 } 664 else if ( showErrors ) 665 { 666 getLogger().info( "Trace", t ); 667 668 line(); 669 } 670 } 671 672 private void logDiagnostics( Throwable t ) 673 { 674 String message = null; 675 if ( errorDiagnostics != null ) 676 { 677 message = errorDiagnostics.diagnose( t ); 678 } 679 680 if ( message == null ) 681 { 682 message = t.getMessage(); 683 } 684 685 getLogger().info( message ); 686 687 line(); 688 } 689 690 protected void logSuccess( ReactorManager rm ) 691 { 692 line(); 693 694 getLogger().info( "BUILD SUCCESSFUL" ); 695 696 line(); 697 } 698 699 private void logReactorSummary( ReactorManager rm ) 700 { 701 if ( rm.hasMultipleProjects() && rm.executedMultipleProjects() ) 702 { 703 getLogger().info( "" ); 704 getLogger().info( "" ); 705 706 713 line(); 714 getLogger().info( "Reactor Summary:" ); 715 line(); 716 717 for ( Iterator it = rm.getSortedProjects().iterator(); it.hasNext(); ) 718 { 719 MavenProject project = (MavenProject) it.next(); 720 721 if ( rm.hasBuildFailure( project ) ) 722 { 723 logReactorSummaryLine( project.getName(), "FAILED", rm.getBuildFailure( project ).getTime() ); 724 } 725 else if ( rm.isBlackListed( project ) ) 726 { 727 logReactorSummaryLine( project.getName(), "SKIPPED (dependency build failed or was skipped)" ); 728 } 729 else if ( rm.hasBuildSuccess( project ) ) 730 { 731 logReactorSummaryLine( project.getName(), "SUCCESS", rm.getBuildSuccess( project ).getTime() ); 732 } 733 else 734 { 735 logReactorSummaryLine( project.getName(), "NOT BUILT" ); 736 } 737 } 738 line(); 739 } 740 } 741 742 protected void stats( Date start ) 743 { 744 Date finish = new Date (); 745 746 long time = finish.getTime() - start.getTime(); 747 748 getLogger().info( "Total time: " + formatTime( time ) ); 749 750 getLogger().info( "Finished at: " + finish ); 751 752 System.gc(); 754 755 Runtime r = Runtime.getRuntime(); 756 757 getLogger().info( 758 "Final Memory: " + ( r.totalMemory() - r.freeMemory() ) / MB + "M/" + r.totalMemory() / MB + "M" ); 759 } 760 761 protected void line() 762 { 763 getLogger().info( "------------------------------------------------------------------------" ); 764 } 765 766 protected static String formatTime( long ms ) 767 { 768 long secs = ms / MS_PER_SEC; 769 770 long min = secs / SEC_PER_MIN; 771 772 secs = secs % SEC_PER_MIN; 773 774 String msg = ""; 775 776 if ( min > 1 ) 777 { 778 msg = min + " minutes "; 779 } 780 else if ( min == 1 ) 781 { 782 msg = "1 minute "; 783 } 784 785 if ( secs > 1 ) 786 { 787 msg += secs + " seconds"; 788 } 789 else if ( secs == 1 ) 790 { 791 msg += "1 second"; 792 } 793 else if ( min == 0 ) 794 { 795 msg += "< 1 second"; 796 } 797 return msg; 798 } 799 800 private List getProjectFiles( MavenExecutionRequest request ) 801 throws IOException 802 { 803 List files = Collections.EMPTY_LIST; 804 805 File userDir = new File ( System.getProperty( "user.dir" ) ); 806 if ( request.isReactorActive() ) 807 { 808 812 String includes = System.getProperty( "maven.reactor.includes", "**/" + POMv4 + ",**/" + RELEASE_POMv4 ); 813 String excludes = System.getProperty( "maven.reactor.excludes", POMv4 + "," + RELEASE_POMv4 ); 814 815 files = FileUtils.getFiles( userDir, includes, excludes ); 816 817 filterOneProjectFilePerDirectory( files ); 818 819 Collections.sort( files ); 821 } 822 else if ( request.getPomFile() != null ) 823 { 824 File projectFile = new File ( request.getPomFile() ).getAbsoluteFile(); 825 826 if ( projectFile.exists() ) 827 { 828 files = Collections.singletonList( projectFile ); 829 } 830 } 831 else 832 { 833 File projectFile = new File ( userDir, RELEASE_POMv4 ); 834 835 if ( !projectFile.exists() ) 836 { 837 projectFile = new File ( userDir, POMv4 ); 838 } 839 840 if ( projectFile.exists() ) 841 { 842 files = Collections.singletonList( projectFile ); 843 } 844 } 845 846 return files; 847 } 848 849 private void filterOneProjectFilePerDirectory( List files ) 850 { 851 List releaseDirs = new ArrayList (); 852 853 for ( Iterator it = files.iterator(); it.hasNext(); ) 854 { 855 File projectFile = (File ) it.next(); 856 857 if ( RELEASE_POMv4.equals( projectFile.getName() ) ) 858 { 859 releaseDirs.add( projectFile.getParentFile() ); 860 } 861 } 862 863 for ( Iterator it = files.iterator(); it.hasNext(); ) 864 { 865 File projectFile = (File ) it.next(); 866 867 if ( !RELEASE_POMv4.equals( projectFile.getName() ) && releaseDirs.contains( projectFile.getParentFile() ) ) 869 { 870 it.remove(); 871 } 872 } 873 } 874 } 875 | Popular Tags |