1 package org.apache.maven.plugin.version; 2 3 18 19 import org.apache.maven.artifact.Artifact; 20 import org.apache.maven.artifact.ArtifactUtils; 21 import org.apache.maven.artifact.factory.ArtifactFactory; 22 import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException; 23 import org.apache.maven.artifact.metadata.ArtifactMetadataSource; 24 import org.apache.maven.artifact.metadata.ResolutionGroup; 25 import org.apache.maven.artifact.repository.ArtifactRepository; 26 import org.apache.maven.artifact.versioning.ArtifactVersion; 27 import org.apache.maven.artifact.versioning.DefaultArtifactVersion; 28 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; 29 import org.apache.maven.artifact.versioning.VersionRange; 30 import org.apache.maven.execution.RuntimeInformation; 31 import org.apache.maven.model.Plugin; 32 import org.apache.maven.model.ReportPlugin; 33 import org.apache.maven.plugin.InvalidPluginException; 34 import org.apache.maven.plugin.registry.MavenPluginRegistryBuilder; 35 import org.apache.maven.plugin.registry.PluginRegistry; 36 import org.apache.maven.plugin.registry.PluginRegistryUtils; 37 import org.apache.maven.plugin.registry.TrackableBase; 38 import org.apache.maven.plugin.registry.io.xpp3.PluginRegistryXpp3Writer; 39 import org.apache.maven.project.MavenProject; 40 import org.apache.maven.project.MavenProjectBuilder; 41 import org.apache.maven.project.ProjectBuildingException; 42 import org.apache.maven.settings.RuntimeInfo; 43 import org.apache.maven.settings.Settings; 44 import org.codehaus.plexus.components.interactivity.InputHandler; 45 import org.codehaus.plexus.logging.AbstractLogEnabled; 46 import org.codehaus.plexus.util.IOUtil; 47 import org.codehaus.plexus.util.StringUtils; 48 import org.codehaus.plexus.util.xml.pull.XmlPullParserException; 49 50 import java.io.File ; 51 import java.io.FileWriter ; 52 import java.io.IOException ; 53 import java.text.ParseException ; 54 import java.text.SimpleDateFormat ; 55 import java.util.Date ; 56 import java.util.HashMap ; 57 import java.util.Iterator ; 58 import java.util.List ; 59 import java.util.Map ; 60 61 public class DefaultPluginVersionManager 62 extends AbstractLogEnabled 63 implements PluginVersionManager 64 { 65 private MavenPluginRegistryBuilder mavenPluginRegistryBuilder; 66 67 private ArtifactFactory artifactFactory; 68 69 private InputHandler inputHandler; 70 71 private ArtifactMetadataSource artifactMetadataSource; 72 73 private PluginRegistry pluginRegistry; 75 76 private MavenProjectBuilder mavenProjectBuilder; 77 78 private RuntimeInformation runtimeInformation; 79 80 private Map resolvedMetaVersions = new HashMap (); 82 83 public String resolvePluginVersion( String groupId, String artifactId, MavenProject project, Settings settings, 84 ArtifactRepository localRepository ) 85 throws PluginVersionResolutionException, InvalidPluginException, PluginVersionNotFoundException 86 { 87 return resolvePluginVersion( groupId, artifactId, project, settings, localRepository, false ); 88 } 89 90 public String resolveReportPluginVersion( String groupId, String artifactId, MavenProject project, 91 Settings settings, ArtifactRepository localRepository ) 92 throws PluginVersionResolutionException, InvalidPluginException, PluginVersionNotFoundException 93 { 94 return resolvePluginVersion( groupId, artifactId, project, settings, localRepository, true ); 95 } 96 97 private String resolvePluginVersion( String groupId, String artifactId, MavenProject project, Settings settings, 98 ArtifactRepository localRepository, boolean resolveAsReportPlugin ) 99 throws PluginVersionResolutionException, InvalidPluginException, PluginVersionNotFoundException 100 { 101 String version = getVersionFromPluginConfig( groupId, artifactId, project, resolveAsReportPlugin ); 103 104 107 if ( version == null ) 109 { 110 if ( project.getProjectReferences() != null ) 111 { 112 String refId = ArtifactUtils.versionlessKey( groupId, artifactId ); 113 MavenProject ref = (MavenProject) project.getProjectReferences().get( refId ); 114 if ( ref != null ) 115 { 116 version = ref.getVersion(); 117 } 118 } 119 } 120 121 String updatedVersion = null; 123 124 boolean promptToPersist = false; 126 127 RuntimeInfo settingsRTInfo = settings.getRuntimeInfo(); 128 129 Boolean pluginUpdateOverride = settingsRTInfo.getPluginUpdateOverride(); 131 132 if ( StringUtils.isEmpty( version ) && settings.isUsePluginRegistry() ) 135 { 136 version = resolveExistingFromPluginRegistry( groupId, artifactId ); 138 139 if ( StringUtils.isNotEmpty( version ) ) 140 { 141 if ( Boolean.TRUE.equals( pluginUpdateOverride ) || 148 ( !Boolean.FALSE.equals( pluginUpdateOverride ) && shouldCheckForUpdates( groupId, artifactId ) ) ) 149 { 150 updatedVersion = 151 resolveMetaVersion( groupId, artifactId, project, localRepository, Artifact.LATEST_VERSION ); 152 153 if ( StringUtils.isNotEmpty( updatedVersion ) && !updatedVersion.equals( version ) ) 154 { 155 boolean isRejected = checkForRejectedStatus( groupId, artifactId, updatedVersion ); 157 158 promptToPersist = !isRejected; 160 161 if ( isRejected ) 163 { 164 updatedVersion = null; 165 } 166 else 167 { 168 getLogger().info( 169 "Plugin \'" + constructPluginKey( groupId, artifactId ) + "\' has updates." ); 170 } 171 } 172 } 173 } 174 } 175 176 boolean forcePersist = false; 177 178 if ( StringUtils.isEmpty( version ) ) 181 { 182 version = resolveMetaVersion( groupId, artifactId, project, localRepository, Artifact.LATEST_VERSION ); 184 185 if ( version != null ) 186 { 187 updatedVersion = version; 189 190 forcePersist = true; 192 promptToPersist = false; 193 } 194 } 195 196 if ( StringUtils.isEmpty( version ) ) 199 { 200 version = resolveMetaVersion( groupId, artifactId, project, localRepository, Artifact.RELEASE_VERSION ); 202 203 if ( version != null ) 204 { 205 updatedVersion = version; 207 208 forcePersist = true; 210 promptToPersist = false; 211 } 212 } 213 214 if ( StringUtils.isEmpty( version ) && project.getGroupId().equals( groupId ) && 217 project.getArtifactId().equals( artifactId ) ) 218 { 219 version = project.getVersion(); 220 } 221 222 if ( StringUtils.isEmpty( version ) ) 224 { 225 throw new PluginVersionNotFoundException( groupId, artifactId ); 226 } 227 228 if ( settings.isUsePluginRegistry() ) 230 { 231 boolean inInteractiveMode = settings.isInteractiveMode(); 236 237 String s = getPluginRegistry( groupId, artifactId ).getAutoUpdate(); 240 boolean autoUpdate = true; 241 if ( s != null ) 242 { 243 autoUpdate = Boolean.valueOf( s ).booleanValue(); 244 } 245 246 boolean persistUpdate = forcePersist || ( promptToPersist && 260 !Boolean.FALSE.equals( pluginUpdateOverride ) && ( inInteractiveMode || autoUpdate ) ); 261 262 Boolean applyToAll = settings.getRuntimeInfo().getApplyToAllPluginUpdates(); 264 265 promptToPersist = 275 promptToPersist && pluginUpdateOverride == null && applyToAll == null && inInteractiveMode; 276 277 if ( promptToPersist ) 278 { 279 persistUpdate = promptToPersistPluginUpdate( version, updatedVersion, groupId, artifactId, settings ); 280 } 281 282 if ( !Boolean.FALSE.equals( applyToAll ) && persistUpdate ) 288 { 289 updatePluginVersionInRegistry( groupId, artifactId, updatedVersion ); 290 291 version = updatedVersion; 293 } 294 else if ( promptToPersist ) 297 { 298 addNewVersionToRejectedListInExisting( groupId, artifactId, updatedVersion ); 299 } 300 } 301 302 return version; 303 } 304 305 private boolean shouldCheckForUpdates( String groupId, String artifactId ) 306 throws PluginVersionResolutionException 307 { 308 PluginRegistry pluginRegistry = getPluginRegistry( groupId, artifactId ); 309 310 org.apache.maven.plugin.registry.Plugin plugin = getPlugin( groupId, artifactId, pluginRegistry ); 311 312 if ( plugin == null ) 313 { 314 return true; 315 } 316 else 317 { 318 String lastChecked = plugin.getLastChecked(); 319 320 if ( StringUtils.isEmpty( lastChecked ) ) 321 { 322 return true; 323 } 324 else 325 { 326 SimpleDateFormat format = 327 new SimpleDateFormat ( org.apache.maven.plugin.registry.Plugin.LAST_CHECKED_DATE_FORMAT ); 328 329 try 330 { 331 Date lastCheckedDate = format.parse( lastChecked ); 332 333 return IntervalUtils.isExpired( pluginRegistry.getUpdateInterval(), lastCheckedDate ); 334 } 335 catch ( ParseException e ) 336 { 337 getLogger().warn( "Last-checked date for plugin {" + constructPluginKey( groupId, artifactId ) + 338 "} is invalid. Checking for updates." ); 339 340 return true; 341 } 342 } 343 } 344 } 345 346 private boolean checkForRejectedStatus( String groupId, String artifactId, String version ) 347 throws PluginVersionResolutionException 348 { 349 PluginRegistry pluginRegistry = getPluginRegistry( groupId, artifactId ); 350 351 org.apache.maven.plugin.registry.Plugin plugin = getPlugin( groupId, artifactId, pluginRegistry ); 352 353 return plugin.getRejectedVersions().contains( version ); 354 } 355 356 private boolean promptToPersistPluginUpdate( String version, String updatedVersion, String groupId, 357 String artifactId, Settings settings ) 358 throws PluginVersionResolutionException 359 { 360 try 361 { 362 StringBuffer message = new StringBuffer (); 363 364 if ( version != null && version.equals( updatedVersion ) ) 366 { 367 message.append( "Unregistered plugin detected.\n\n" ); 368 } 369 else 370 { 371 message.append( "New plugin version detected.\n\n" ); 372 } 373 374 message.append( "Group ID: " ).append( groupId ).append( "\n" ); 375 message.append( "Artifact ID: " ).append( artifactId ).append( "\n" ); 376 message.append( "\n" ); 377 378 if ( version != null && !version.equals( updatedVersion ) ) 380 { 381 message.append( "Registered Version: " ).append( version ).append( "\n" ); 382 } 383 384 message.append( "Detected plugin version: " ).append( updatedVersion ).append( "\n" ); 385 message.append( "\n" ); 386 message.append( "Would you like to use this new version from now on? ( [Y]es, [n]o, [a]ll, n[o]ne ) " ); 387 388 getLogger().info( message.toString() ); 391 392 String persistAnswer = inputHandler.readLine(); 393 394 boolean shouldPersist = true; 395 396 if ( !StringUtils.isEmpty( persistAnswer ) ) 397 { 398 persistAnswer = persistAnswer.toLowerCase(); 399 400 if ( persistAnswer.startsWith( "y" ) ) 401 { 402 shouldPersist = true; 403 } 404 else if ( persistAnswer.startsWith( "a" ) ) 405 { 406 shouldPersist = true; 407 408 settings.getRuntimeInfo().setApplyToAllPluginUpdates( Boolean.TRUE ); 409 } 410 else if ( persistAnswer.indexOf( "o" ) > -1 ) 411 { 412 settings.getRuntimeInfo().setApplyToAllPluginUpdates( Boolean.FALSE ); 413 } 414 else if ( persistAnswer.startsWith( "n" ) ) 415 { 416 shouldPersist = false; 417 } 418 else 419 { 420 shouldPersist = true; 422 } 423 } 424 425 if ( shouldPersist ) 426 { 427 getLogger().info( "Updating plugin version to " + updatedVersion ); 428 } 429 else 430 { 431 getLogger().info( "NOT updating plugin version to " + updatedVersion ); 432 } 433 434 return shouldPersist; 435 436 } 437 catch ( IOException e ) 438 { 439 throw new PluginVersionResolutionException( groupId, artifactId, "Can't read user input.", e ); 440 } 441 } 442 443 private void addNewVersionToRejectedListInExisting( String groupId, String artifactId, String rejectedVersion ) 444 throws PluginVersionResolutionException 445 { 446 PluginRegistry pluginRegistry = getPluginRegistry( groupId, artifactId ); 447 448 org.apache.maven.plugin.registry.Plugin plugin = getPlugin( groupId, artifactId, pluginRegistry ); 449 450 String pluginKey = constructPluginKey( groupId, artifactId ); 451 452 if ( plugin != null && !TrackableBase.GLOBAL_LEVEL.equals( plugin.getSourceLevel() ) ) 453 { 454 plugin.addRejectedVersion( rejectedVersion ); 455 456 writeUserRegistry( groupId, artifactId, pluginRegistry ); 457 458 getLogger().warn( "Plugin version: " + rejectedVersion + " added to your rejectedVersions list.\n" + 459 "You will not be prompted for this version again.\n\nPlugin: " + pluginKey ); 460 } 461 else 462 { 463 getLogger().warn( 464 "Cannot add rejectedVersion entry for: " + rejectedVersion + ".\n\nPlugin: " + pluginKey ); 465 } 466 } 467 468 private String resolveExistingFromPluginRegistry( String groupId, String artifactId ) 469 throws PluginVersionResolutionException 470 { 471 PluginRegistry pluginRegistry = getPluginRegistry( groupId, artifactId ); 472 473 org.apache.maven.plugin.registry.Plugin plugin = getPlugin( groupId, artifactId, pluginRegistry ); 474 475 String version = null; 476 477 if ( plugin != null ) 478 { 479 version = plugin.getUseVersion(); 480 } 481 482 return version; 483 } 484 485 private org.apache.maven.plugin.registry.Plugin getPlugin( String groupId, String artifactId, 486 PluginRegistry pluginRegistry ) 487 { 488 Map pluginsByKey; 489 490 if ( pluginRegistry != null ) 491 { 492 pluginsByKey = pluginRegistry.getPluginsByKey(); 493 } 494 else 495 { 496 pluginsByKey = new HashMap (); 497 } 498 499 String pluginKey = constructPluginKey( groupId, artifactId ); 500 501 return (org.apache.maven.plugin.registry.Plugin) pluginsByKey.get( pluginKey ); 502 } 503 504 private String constructPluginKey( String groupId, String artifactId ) 505 { 506 return groupId + ":" + artifactId; 507 } 508 509 private String getVersionFromPluginConfig( String groupId, String artifactId, MavenProject project, 510 boolean resolveAsReportPlugin ) 511 { 512 String version = null; 513 514 if ( resolveAsReportPlugin ) 515 { 516 if ( project.getReportPlugins() != null ) 517 { 518 for ( Iterator it = project.getReportPlugins().iterator(); it.hasNext() && version == null; ) 519 { 520 ReportPlugin plugin = (ReportPlugin) it.next(); 521 522 if ( groupId.equals( plugin.getGroupId() ) && artifactId.equals( plugin.getArtifactId() ) ) 523 { 524 version = plugin.getVersion(); 525 } 526 } 527 } 528 } 529 else 530 { 531 if ( project.getBuildPlugins() != null ) 532 { 533 for ( Iterator it = project.getBuildPlugins().iterator(); it.hasNext() && version == null; ) 534 { 535 Plugin plugin = (Plugin) it.next(); 536 537 if ( groupId.equals( plugin.getGroupId() ) && artifactId.equals( plugin.getArtifactId() ) ) 538 { 539 version = plugin.getVersion(); 540 } 541 } 542 } 543 } 544 545 return version; 546 } 547 548 private void updatePluginVersionInRegistry( String groupId, String artifactId, String version ) 549 throws PluginVersionResolutionException 550 { 551 PluginRegistry pluginRegistry = getPluginRegistry( groupId, artifactId ); 552 553 org.apache.maven.plugin.registry.Plugin plugin = getPlugin( groupId, artifactId, pluginRegistry ); 554 555 if ( plugin != null ) 557 { 558 if ( PluginRegistry.GLOBAL_LEVEL.equals( plugin.getSourceLevel() ) ) 559 { 560 getLogger().warn( "Cannot update registered version for plugin {" + groupId + ":" + artifactId + 562 "}; it is specified in the global registry." ); 563 } 564 else 565 { 566 plugin.setUseVersion( version ); 567 568 SimpleDateFormat format = 569 new SimpleDateFormat ( org.apache.maven.plugin.registry.Plugin.LAST_CHECKED_DATE_FORMAT ); 570 571 plugin.setLastChecked( format.format( new Date () ) ); 572 } 573 } 574 else 575 { 576 plugin = new org.apache.maven.plugin.registry.Plugin(); 577 578 plugin.setGroupId( groupId ); 579 plugin.setArtifactId( artifactId ); 580 plugin.setUseVersion( version ); 581 582 pluginRegistry.addPlugin( plugin ); 583 584 pluginRegistry.flushPluginsByKey(); 585 } 586 587 writeUserRegistry( groupId, artifactId, pluginRegistry ); 588 } 589 590 private void writeUserRegistry( String groupId, String artifactId, PluginRegistry pluginRegistry ) 591 { 592 File pluginRegistryFile = pluginRegistry.getRuntimeInfo().getFile(); 593 594 PluginRegistry extractedUserRegistry = PluginRegistryUtils.extractUserPluginRegistry( pluginRegistry ); 595 596 if ( extractedUserRegistry != null ) 598 { 599 FileWriter fWriter = null; 600 601 try 602 { 603 pluginRegistryFile.getParentFile().mkdirs(); 604 fWriter = new FileWriter ( pluginRegistryFile ); 605 606 PluginRegistryXpp3Writer writer = new PluginRegistryXpp3Writer(); 607 608 writer.write( fWriter, extractedUserRegistry ); 609 } 610 catch ( IOException e ) 611 { 612 getLogger().warn( 613 "Cannot rewrite user-level plugin-registry.xml with new plugin version of plugin: \'" + groupId + 614 ":" + artifactId + "\'.", e ); 615 } 616 finally 617 { 618 IOUtil.close( fWriter ); 619 } 620 } 621 } 622 623 private PluginRegistry getPluginRegistry( String groupId, String artifactId ) 624 throws PluginVersionResolutionException 625 { 626 if ( pluginRegistry == null ) 627 { 628 try 629 { 630 pluginRegistry = mavenPluginRegistryBuilder.buildPluginRegistry(); 631 } 632 catch ( IOException e ) 633 { 634 throw new PluginVersionResolutionException( groupId, artifactId, 635 "Error reading plugin registry: " + e.getMessage(), e ); 636 } 637 catch ( XmlPullParserException e ) 638 { 639 throw new PluginVersionResolutionException( groupId, artifactId, 640 "Error parsing plugin registry: " + e.getMessage(), e ); 641 } 642 643 if ( pluginRegistry == null ) 644 { 645 pluginRegistry = mavenPluginRegistryBuilder.createUserPluginRegistry(); 646 } 647 } 648 649 return pluginRegistry; 650 } 651 652 private String resolveMetaVersion( String groupId, String artifactId, MavenProject project, 653 ArtifactRepository localRepository, String metaVersionId ) 654 throws PluginVersionResolutionException, InvalidPluginException 655 { 656 Artifact artifact = artifactFactory.createProjectArtifact( groupId, artifactId, metaVersionId ); 657 658 String key = artifact.getDependencyConflictId(); 659 if ( resolvedMetaVersions.containsKey( key ) ) 660 { 661 return (String ) resolvedMetaVersions.get( key ); 662 } 663 664 String version = null; 665 666 try 668 { 669 ResolutionGroup resolutionGroup = 670 artifactMetadataSource.retrieve( artifact, localRepository, project.getPluginArtifactRepositories() ); 671 672 artifact = resolutionGroup.getPomArtifact(); 675 } 676 catch ( ArtifactMetadataRetrievalException e ) 677 { 678 throw new PluginVersionResolutionException( groupId, artifactId, e.getMessage(), e ); 679 } 680 681 String artifactVersion = artifact.getVersion(); 682 683 if ( artifact.getFile() != null ) 685 { 686 boolean pluginValid = false; 687 688 while ( !pluginValid && artifactVersion != null ) 689 { 690 pluginValid = true; 691 MavenProject pluginProject; 692 try 693 { 694 artifact = artifactFactory.createProjectArtifact( groupId, artifactId, artifactVersion ); 695 pluginProject = mavenProjectBuilder.buildFromRepository( artifact, 696 project.getPluginArtifactRepositories(), 697 localRepository, false ); 698 } 699 catch ( ProjectBuildingException e ) 700 { 701 throw new InvalidPluginException( "Unable to build project information for plugin '" + 702 ArtifactUtils.versionlessKey( groupId, artifactId ) + "': " + e.getMessage(), e ); 703 } 704 705 if ( pluginProject.getPrerequisites() != null && pluginProject.getPrerequisites().getMaven() != null ) 707 { 708 DefaultArtifactVersion requiredVersion = 709 new DefaultArtifactVersion( pluginProject.getPrerequisites().getMaven() ); 710 711 if ( runtimeInformation.getApplicationVersion().compareTo( requiredVersion ) < 0 ) 712 { 713 getLogger().info( "Ignoring available plugin update: " + artifactVersion + 714 " as it requires Maven version " + requiredVersion ); 715 716 VersionRange vr; 717 try 718 { 719 vr = VersionRange.createFromVersionSpec( "(," + artifactVersion + ")" ); 720 } 721 catch ( InvalidVersionSpecificationException e ) 722 { 723 throw new PluginVersionResolutionException( groupId, artifactId, 724 "Error getting available plugin versions: " + 725 e.getMessage(), e ); 726 } 727 728 getLogger().debug( "Trying " + vr ); 729 try 730 { 731 List versions = artifactMetadataSource.retrieveAvailableVersions( artifact, localRepository, 732 project.getPluginArtifactRepositories() ); 733 ArtifactVersion v = vr.matchVersion( versions ); 734 artifactVersion = v != null ? v.toString() : null; 735 } 736 catch ( ArtifactMetadataRetrievalException e ) 737 { 738 throw new PluginVersionResolutionException( groupId, artifactId, 739 "Error getting available plugin versions: " + 740 e.getMessage(), e ); 741 } 742 743 if ( artifactVersion != null ) 744 { 745 getLogger().debug( "Found " + artifactVersion ); 746 pluginValid = false; 747 } 748 } 749 } 750 } 751 } 752 753 if ( !metaVersionId.equals( artifactVersion ) ) 754 { 755 version = artifactVersion; 756 resolvedMetaVersions.put( key, version ); 757 } 758 759 return version; 760 } 761 762 } 763 | Popular Tags |