Coverage Report - org.apache.maven.plugin.version.DefaultPluginVersionManager
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultPluginVersionManager
0 %
0/228
0 %
0/156
5,867
 
 1  
 package org.apache.maven.plugin.version;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *  http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import org.apache.maven.artifact.Artifact;
 23  
 import org.apache.maven.artifact.ArtifactUtils;
 24  
 import org.apache.maven.artifact.factory.ArtifactFactory;
 25  
 import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
 26  
 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
 27  
 import org.apache.maven.artifact.metadata.ResolutionGroup;
 28  
 import org.apache.maven.artifact.repository.ArtifactRepository;
 29  
 import org.apache.maven.artifact.versioning.ArtifactVersion;
 30  
 import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
 31  
 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
 32  
 import org.apache.maven.artifact.versioning.VersionRange;
 33  
 import org.apache.maven.execution.RuntimeInformation;
 34  
 import org.apache.maven.model.Plugin;
 35  
 import org.apache.maven.model.ReportPlugin;
 36  
 import org.apache.maven.plugin.InvalidPluginException;
 37  
 import org.apache.maven.plugin.registry.MavenPluginRegistryBuilder;
 38  
 import org.apache.maven.plugin.registry.PluginRegistry;
 39  
 import org.apache.maven.plugin.registry.PluginRegistryUtils;
 40  
 import org.apache.maven.plugin.registry.TrackableBase;
 41  
 import org.apache.maven.plugin.registry.io.xpp3.PluginRegistryXpp3Writer;
 42  
 import org.apache.maven.project.MavenProject;
 43  
 import org.apache.maven.project.MavenProjectBuilder;
 44  
 import org.apache.maven.project.ProjectBuildingException;
 45  
 import org.apache.maven.settings.RuntimeInfo;
 46  
 import org.apache.maven.settings.Settings;
 47  
 import org.codehaus.plexus.components.interactivity.InputHandler;
 48  
 import org.codehaus.plexus.logging.AbstractLogEnabled;
 49  
 import org.codehaus.plexus.util.IOUtil;
 50  
 import org.codehaus.plexus.util.StringUtils;
 51  
 import org.codehaus.plexus.util.WriterFactory;
 52  
 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
 53  
 
 54  
 import java.io.File;
 55  
 import java.io.IOException;
 56  
 import java.io.Writer;
 57  
 import java.text.ParseException;
 58  
 import java.text.SimpleDateFormat;
 59  
 import java.util.Date;
 60  
 import java.util.HashMap;
 61  
 import java.util.Iterator;
 62  
 import java.util.List;
 63  
 import java.util.Map;
 64  
 
 65  0
 public class DefaultPluginVersionManager
 66  
     extends AbstractLogEnabled
 67  
     implements PluginVersionManager
 68  
 {
 69  
     private MavenPluginRegistryBuilder mavenPluginRegistryBuilder;
 70  
 
 71  
     private ArtifactFactory artifactFactory;
 72  
 
 73  
     private InputHandler inputHandler;
 74  
 
 75  
     private ArtifactMetadataSource artifactMetadataSource;
 76  
 
 77  
     // TODO: [jc] Revisit to remove this piece of state. PLUGIN REGISTRY MAY BE UPDATED ON DISK OUT-OF-PROCESS!
 78  
     private PluginRegistry pluginRegistry;
 79  
 
 80  
     private MavenProjectBuilder mavenProjectBuilder;
 81  
 
 82  
     private RuntimeInformation runtimeInformation;
 83  
 
 84  
     // TODO: Revisit to remove this piece of state. PLUGIN REGISTRY MAY BE UPDATED ON DISK OUT-OF-PROCESS!
 85  0
     private Map resolvedMetaVersions = new HashMap();
 86  
 
 87  
     public String resolvePluginVersion( String groupId, String artifactId, MavenProject project, Settings settings,
 88  
                                         ArtifactRepository localRepository )
 89  
         throws PluginVersionResolutionException, InvalidPluginException, PluginVersionNotFoundException
 90  
     {
 91  0
         return resolvePluginVersion( groupId, artifactId, project, settings, localRepository, false );
 92  
     }
 93  
 
 94  
     public String resolveReportPluginVersion( String groupId, String artifactId, MavenProject project,
 95  
                                               Settings settings, ArtifactRepository localRepository )
 96  
         throws PluginVersionResolutionException, InvalidPluginException, PluginVersionNotFoundException
 97  
     {
 98  0
         return resolvePluginVersion( groupId, artifactId, project, settings, localRepository, true );
 99  
     }
 100  
 
 101  
     private String resolvePluginVersion( String groupId, String artifactId, MavenProject project, Settings settings,
 102  
                                          ArtifactRepository localRepository, boolean resolveAsReportPlugin )
 103  
         throws PluginVersionResolutionException, InvalidPluginException, PluginVersionNotFoundException
 104  
     {
 105  
         // first pass...if the plugin is specified in the pom, try to retrieve the version from there.
 106  0
         String version = getVersionFromPluginConfig( groupId, artifactId, project, resolveAsReportPlugin );
 107  
 
 108  
         // NOTE: We CANNOT check the current project version here, so delay it until later.
 109  
         // It will prevent plugins from building themselves, if they are part of the lifecycle mapping.
 110  
 
 111  
         // if there was no explicit version, try for one in the reactor
 112  0
         if ( version == null )
 113  
         {
 114  0
             if ( project.getProjectReferences() != null )
 115  
             {
 116  0
                 String refId = ArtifactUtils.versionlessKey( groupId, artifactId );
 117  0
                 MavenProject ref = (MavenProject) project.getProjectReferences().get( refId );
 118  0
                 if ( ref != null )
 119  
                 {
 120  0
                     version = ref.getVersion();
 121  
                 }
 122  
             }
 123  
         }
 124  
 
 125  
         // we're NEVER going to persist POM-derived plugin versions.
 126  0
         String updatedVersion = null;
 127  
 
 128  
         // we're not going to prompt the user to accept a plugin update until we find one.
 129  0
         boolean promptToPersist = false;
 130  
 
 131  0
         RuntimeInfo settingsRTInfo = settings.getRuntimeInfo();
 132  
 
 133  
         // determine the behavior WRT prompting the user and installing plugin updates.
 134  0
         Boolean pluginUpdateOverride = settingsRTInfo.getPluginUpdateOverride();
 135  
 
 136  
         // second pass...if we're using the plugin registry, and the plugin is listed in the plugin-registry.xml, use
 137  
         // the version from <useVersion/>.
 138  0
         if ( StringUtils.isEmpty( version ) && settings.isUsePluginRegistry() )
 139  
         {
 140  
             // resolve existing useVersion.
 141  0
             version = resolveExistingFromPluginRegistry( groupId, artifactId );
 142  
 
 143  0
             if ( StringUtils.isNotEmpty( version ) )
 144  
             {
 145  
                 // 2. check for updates. Determine whether this is the right time to attempt to update the version.
 146  
                 // Only check for plugin updates if:
 147  
                 //
 148  
                 //  a. the CLI switch to force plugin updates is set, OR BOTH OF THE FOLLOWING:
 149  
                 //  b. the CLI switch to suppress plugin updates is NOT set, AND
 150  
                 //  c. the update interval for the plugin has triggered an update check.
 151  0
                 if ( Boolean.TRUE.equals( pluginUpdateOverride ) ||
 152  
                     ( !Boolean.FALSE.equals( pluginUpdateOverride ) && shouldCheckForUpdates( groupId, artifactId ) ) )
 153  
                 {
 154  0
                     updatedVersion =
 155  
                         resolveMetaVersion( groupId, artifactId, project, localRepository, Artifact.LATEST_VERSION );
 156  
 
 157  0
                     if ( StringUtils.isNotEmpty( updatedVersion ) && !updatedVersion.equals( version ) )
 158  
                     {
 159  
                         // see if this version we've resolved is on our previously rejected list.
 160  0
                         boolean isRejected = checkForRejectedStatus( groupId, artifactId, updatedVersion );
 161  
 
 162  
                         // we should only prompt to use this version if the user has not previously rejected it.
 163  0
                         promptToPersist = !isRejected;
 164  
 
 165  
                         // if we've rejected this version previously, forget about updating.
 166  0
                         if ( isRejected )
 167  
                         {
 168  0
                             updatedVersion = null;
 169  
                         }
 170  
                         else
 171  
                         {
 172  0
                             getLogger().info(
 173  
                                 "Plugin \'" + constructPluginKey( groupId, artifactId ) + "\' has updates." );
 174  
                         }
 175  
                     }
 176  
                 }
 177  
             }
 178  
         }
 179  
 
 180  0
         boolean forcePersist = false;
 181  
 
 182  
         // third pass...we're always checking for latest install/deploy, so retrieve the version for LATEST metadata and
 183  
         // also set that resolved version as the <useVersion/> in settings.xml.
 184  0
         if ( StringUtils.isEmpty( version ) )
 185  
         {
 186  
             // 1. resolve the version to be used
 187  0
             version = resolveMetaVersion( groupId, artifactId, project, localRepository, Artifact.LATEST_VERSION );
 188  
 
 189  0
             if ( version != null )
 190  
             {
 191  
                 // 2. Set the updatedVersion so the user will be prompted whether to make this version permanent.
 192  0
                 updatedVersion = version;
 193  
 
 194  
                 // 3. Persist this version without prompting.
 195  0
                 forcePersist = true;
 196  0
                 promptToPersist = false;
 197  
             }
 198  
         }
 199  
 
 200  
         // final pass...retrieve the version for RELEASE and also set that resolved version as the <useVersion/>
 201  
         // in settings.xml.
 202  0
         if ( StringUtils.isEmpty( version ) )
 203  
         {
 204  
             // 1. resolve the version to be used
 205  0
             version = resolveMetaVersion( groupId, artifactId, project, localRepository, Artifact.RELEASE_VERSION );
 206  
 
 207  0
             if ( version != null )
 208  
             {
 209  
                 // 2. Set the updatedVersion so the user will be prompted whether to make this version permanent.
 210  0
                 updatedVersion = version;
 211  
 
 212  
                 // 3. Persist this version without prompting.
 213  0
                 forcePersist = true;
 214  0
                 promptToPersist = false;
 215  
             }
 216  
         }
 217  
 
 218  
         // if we're still empty here, and the current project matches the plugin in question, use the current project's
 219  
         // version, I guess...
 220  0
         if ( StringUtils.isEmpty( version ) && project.getGroupId().equals( groupId ) &&
 221  
             project.getArtifactId().equals( artifactId ) )
 222  
         {
 223  0
             version = project.getVersion();
 224  
         }
 225  
 
 226  
         // if we still haven't found a version, then fail early before we get into the update goop.
 227  0
         if ( StringUtils.isEmpty( version ) )
 228  
         {
 229  0
             throw new PluginVersionNotFoundException( groupId, artifactId );
 230  
         }
 231  
 
 232  
         // if the plugin registry is inactive, then the rest of this goop is useless...
 233  0
         if ( settings.isUsePluginRegistry() )
 234  
         {
 235  
             // determine whether this build is running in interactive mode
 236  
             // If it's not, then we'll defer to the autoUpdate setting from the registry
 237  
             // for a decision on updating the plugin in the registry...rather than prompting
 238  
             // the user.
 239  0
             boolean inInteractiveMode = settings.isInteractiveMode();
 240  
 
 241  
             // determines what should be done if we're in non-interactive mode.
 242  
             // if true, then just update the registry with the new versions.
 243  0
             String s = getPluginRegistry( groupId, artifactId ).getAutoUpdate();
 244  0
             boolean autoUpdate = true;
 245  0
             if ( s != null )
 246  
             {
 247  0
                 autoUpdate = Boolean.valueOf( s ).booleanValue();
 248  
             }
 249  
 
 250  
             // We should persist by default if:
 251  
             //
 252  
             // 0. RELEASE or LATEST was used to resolve the plugin version (it's not in the registry)
 253  
             //
 254  
             // -OR-
 255  
             //
 256  
             // 1. we detected a change in the plugin version from what was in the registry, or
 257  
             //      a. the plugin is not registered
 258  
             // 2. the pluginUpdateOverride flag has NOT been set to Boolean.FALSE (suppression mode)
 259  
             // 3. we're in interactive mode, or
 260  
             //      a. the registry is declared to be in autoUpdate mode
 261  
             //
 262  
             // NOTE: This is only the default value; it may be changed as the result of prompting the user.
 263  0
             boolean persistUpdate = forcePersist || ( promptToPersist &&
 264  
                 !Boolean.FALSE.equals( pluginUpdateOverride ) && ( inInteractiveMode || autoUpdate ) );
 265  
 
 266  
             // retrieve the apply-to-all flag, if it's been set previously.
 267  0
             Boolean applyToAll = settings.getRuntimeInfo().getApplyToAllPluginUpdates();
 268  
 
 269  
             // Incorporate interactive-mode CLI overrides, and previous decisions on apply-to-all, if appropriate.
 270  
             //
 271  
             // don't prompt if RELEASE or LATEST was used to resolve the plugin version
 272  
             // don't prompt if not in interactive mode.
 273  
             // don't prompt if the CLI pluginUpdateOverride is set (either suppression or force mode will stop prompting)
 274  
             // don't prompt if the user has selected ALL/NONE previously in this session
 275  
             //
 276  
             // NOTE: We're incorporating here, to make the usages of this check more consistent and 
 277  
             // resistant to change.
 278  0
             promptToPersist =
 279  
                 promptToPersist && pluginUpdateOverride == null && applyToAll == null && inInteractiveMode;
 280  
 
 281  0
             if ( promptToPersist )
 282  
             {
 283  0
                 persistUpdate = promptToPersistPluginUpdate( version, updatedVersion, groupId, artifactId, settings );
 284  
             }
 285  
 
 286  
             // if it is determined that we should use this version, persist it as useVersion.
 287  
             // cases where this version will be persisted:
 288  
             // 1. the user is prompted and answers yes or all
 289  
             // 2. the user has previously answered all in this session
 290  
             // 3. the build is running in non-interactive mode, and the registry setting is for auto-update
 291  0
             if ( !Boolean.FALSE.equals( applyToAll ) && persistUpdate )
 292  
             {
 293  0
                 updatePluginVersionInRegistry( groupId, artifactId, updatedVersion );
 294  
 
 295  
                 // we're using the updated version of the plugin in this session as well.
 296  0
                 version = updatedVersion;
 297  
             }
 298  
             // otherwise, if we prompted the user to update, we should treat this as a rejectedVersion, and
 299  
             // persist it iff the plugin pre-exists and is in the user-level registry.
 300  0
             else if ( promptToPersist )
 301  
             {
 302  0
                 addNewVersionToRejectedListInExisting( groupId, artifactId, updatedVersion );
 303  
             }
 304  
         }
 305  
 
 306  0
         return version;
 307  
     }
 308  
 
 309  
     private boolean shouldCheckForUpdates( String groupId, String artifactId )
 310  
         throws PluginVersionResolutionException
 311  
     {
 312  0
         PluginRegistry pluginRegistry = getPluginRegistry( groupId, artifactId );
 313  
 
 314  0
         org.apache.maven.plugin.registry.Plugin plugin = getPlugin( groupId, artifactId, pluginRegistry );
 315  
 
 316  0
         if ( plugin == null )
 317  
         {
 318  0
             return true;
 319  
         }
 320  
         else
 321  
         {
 322  0
             String lastChecked = plugin.getLastChecked();
 323  
 
 324  0
             if ( StringUtils.isEmpty( lastChecked ) )
 325  
             {
 326  0
                 return true;
 327  
             }
 328  
             else
 329  
             {
 330  0
                 SimpleDateFormat format =
 331  
                     new SimpleDateFormat( org.apache.maven.plugin.registry.Plugin.LAST_CHECKED_DATE_FORMAT );
 332  
 
 333  
                 try
 334  
                 {
 335  0
                     Date lastCheckedDate = format.parse( lastChecked );
 336  
 
 337  0
                     return IntervalUtils.isExpired( pluginRegistry.getUpdateInterval(), lastCheckedDate );
 338  
                 }
 339  0
                 catch ( ParseException e )
 340  
                 {
 341  0
                     getLogger().warn( "Last-checked date for plugin {" + constructPluginKey( groupId, artifactId ) +
 342  
                         "} is invalid. Checking for updates." );
 343  
 
 344  0
                     return true;
 345  
                 }
 346  
             }
 347  
         }
 348  
     }
 349  
 
 350  
     private boolean checkForRejectedStatus( String groupId, String artifactId, String version )
 351  
         throws PluginVersionResolutionException
 352  
     {
 353  0
         PluginRegistry pluginRegistry = getPluginRegistry( groupId, artifactId );
 354  
 
 355  0
         org.apache.maven.plugin.registry.Plugin plugin = getPlugin( groupId, artifactId, pluginRegistry );
 356  
 
 357  0
         return plugin.getRejectedVersions().contains( version );
 358  
     }
 359  
 
 360  
     private boolean promptToPersistPluginUpdate( String version, String updatedVersion, String groupId,
 361  
                                                  String artifactId, Settings settings )
 362  
         throws PluginVersionResolutionException
 363  
     {
 364  
         try
 365  
         {
 366  0
             StringBuffer message = new StringBuffer();
 367  
 
 368  
             // this means that the plugin is not registered.
 369  0
             if ( version != null && version.equals( updatedVersion ) )
 370  
             {
 371  0
                 message.append( "Unregistered plugin detected.\n\n" );
 372  
             }
 373  
             else
 374  
             {
 375  0
                 message.append( "New plugin version detected.\n\n" );
 376  
             }
 377  
 
 378  0
             message.append( "Group ID: " ).append( groupId ).append( "\n" );
 379  0
             message.append( "Artifact ID: " ).append( artifactId ).append( "\n" );
 380  0
             message.append( "\n" );
 381  
 
 382  
             // this means that we've detected a new, non-rejected plugin version.
 383  0
             if ( version != null && !version.equals( updatedVersion ) )
 384  
             {
 385  0
                 message.append( "Registered Version: " ).append( version ).append( "\n" );
 386  
             }
 387  
 
 388  0
             message.append( "Detected plugin version: " ).append( updatedVersion ).append( "\n" );
 389  0
             message.append( "\n" );
 390  0
             message.append( "Would you like to use this new version from now on? ( [Y]es, [n]o, [a]ll, n[o]ne ) " );
 391  
 
 392  
             // TODO: check the GUI-friendliness of this approach to collecting input.
 393  
             // If we can't port this prompt into a GUI, IDE-integration will not work well.
 394  0
             getLogger().info( message.toString() );
 395  
 
 396  0
             String persistAnswer = inputHandler.readLine();
 397  
 
 398  0
             boolean shouldPersist = true;
 399  
 
 400  0
             if ( !StringUtils.isEmpty( persistAnswer ) )
 401  
             {
 402  0
                 persistAnswer = persistAnswer.toLowerCase();
 403  
 
 404  0
                 if ( persistAnswer.startsWith( "y" ) )
 405  
                 {
 406  0
                     shouldPersist = true;
 407  
                 }
 408  0
                 else if ( persistAnswer.startsWith( "a" ) )
 409  
                 {
 410  0
                     shouldPersist = true;
 411  
 
 412  0
                     settings.getRuntimeInfo().setApplyToAllPluginUpdates( Boolean.TRUE );
 413  
                 }
 414  0
                 else if ( persistAnswer.indexOf( "o" ) > -1 )
 415  
                 {
 416  0
                     settings.getRuntimeInfo().setApplyToAllPluginUpdates( Boolean.FALSE );
 417  
                 }
 418  0
                 else if ( persistAnswer.startsWith( "n" ) )
 419  
                 {
 420  0
                     shouldPersist = false;
 421  
                 }
 422  
                 else
 423  
                 {
 424  
                     // default to yes.
 425  0
                     shouldPersist = true;
 426  
                 }
 427  
             }
 428  
 
 429  0
             if ( shouldPersist )
 430  
             {
 431  0
                 getLogger().info( "Updating plugin version to " + updatedVersion );
 432  
             }
 433  
             else
 434  
             {
 435  0
                 getLogger().info( "NOT updating plugin version to " + updatedVersion );
 436  
             }
 437  
 
 438  0
             return shouldPersist;
 439  
 
 440  
         }
 441  0
         catch ( IOException e )
 442  
         {
 443  0
             throw new PluginVersionResolutionException( groupId, artifactId, "Can't read user input.", e );
 444  
         }
 445  
     }
 446  
 
 447  
     private void addNewVersionToRejectedListInExisting( String groupId, String artifactId, String rejectedVersion )
 448  
         throws PluginVersionResolutionException
 449  
     {
 450  0
         PluginRegistry pluginRegistry = getPluginRegistry( groupId, artifactId );
 451  
 
 452  0
         org.apache.maven.plugin.registry.Plugin plugin = getPlugin( groupId, artifactId, pluginRegistry );
 453  
 
 454  0
         String pluginKey = constructPluginKey( groupId, artifactId );
 455  
 
 456  0
         if ( plugin != null && !TrackableBase.GLOBAL_LEVEL.equals( plugin.getSourceLevel() ) )
 457  
         {
 458  0
             plugin.addRejectedVersion( rejectedVersion );
 459  
 
 460  0
             writeUserRegistry( groupId, artifactId, pluginRegistry );
 461  
 
 462  0
             getLogger().warn( "Plugin version: " + rejectedVersion + " added to your rejectedVersions list.\n" +
 463  
                 "You will not be prompted for this version again.\n\nPlugin: " + pluginKey );
 464  
         }
 465  
         else
 466  
         {
 467  0
             getLogger().warn(
 468  
                 "Cannot add rejectedVersion entry for: " + rejectedVersion + ".\n\nPlugin: " + pluginKey );
 469  
         }
 470  0
     }
 471  
 
 472  
     private String resolveExistingFromPluginRegistry( String groupId, String artifactId )
 473  
         throws PluginVersionResolutionException
 474  
     {
 475  0
         PluginRegistry pluginRegistry = getPluginRegistry( groupId, artifactId );
 476  
 
 477  0
         org.apache.maven.plugin.registry.Plugin plugin = getPlugin( groupId, artifactId, pluginRegistry );
 478  
 
 479  0
         String version = null;
 480  
 
 481  0
         if ( plugin != null )
 482  
         {
 483  0
             version = plugin.getUseVersion();
 484  
         }
 485  
 
 486  0
         return version;
 487  
     }
 488  
 
 489  
     private org.apache.maven.plugin.registry.Plugin getPlugin( String groupId, String artifactId,
 490  
                                                                PluginRegistry pluginRegistry )
 491  
     {
 492  
         Map pluginsByKey;
 493  
 
 494  0
         if ( pluginRegistry != null )
 495  
         {
 496  0
             pluginsByKey = pluginRegistry.getPluginsByKey();
 497  
         }
 498  
         else
 499  
         {
 500  0
             pluginsByKey = new HashMap();
 501  
         }
 502  
 
 503  0
         String pluginKey = constructPluginKey( groupId, artifactId );
 504  
 
 505  0
         return (org.apache.maven.plugin.registry.Plugin) pluginsByKey.get( pluginKey );
 506  
     }
 507  
 
 508  
     private String constructPluginKey( String groupId, String artifactId )
 509  
     {
 510  0
         return groupId + ":" + artifactId;
 511  
     }
 512  
 
 513  
     private String getVersionFromPluginConfig( String groupId, String artifactId, MavenProject project,
 514  
                                                boolean resolveAsReportPlugin )
 515  
     {
 516  0
         String version = null;
 517  
 
 518  0
         if ( resolveAsReportPlugin )
 519  
         {
 520  0
             if ( project.getReportPlugins() != null )
 521  
             {
 522  0
                 for ( Iterator it = project.getReportPlugins().iterator(); it.hasNext() && version == null; )
 523  
                 {
 524  0
                     ReportPlugin plugin = (ReportPlugin) it.next();
 525  
 
 526  0
                     if ( groupId.equals( plugin.getGroupId() ) && artifactId.equals( plugin.getArtifactId() ) )
 527  
                     {
 528  0
                         version = plugin.getVersion();
 529  
                     }
 530  0
                 }
 531  
             }
 532  
         }
 533  
         else
 534  
         {
 535  0
             if ( project.getBuildPlugins() != null )
 536  
             {
 537  0
                 for ( Iterator it = project.getBuildPlugins().iterator(); it.hasNext() && version == null; )
 538  
                 {
 539  0
                     Plugin plugin = (Plugin) it.next();
 540  
 
 541  0
                     if ( groupId.equals( plugin.getGroupId() ) && artifactId.equals( plugin.getArtifactId() ) )
 542  
                     {
 543  0
                         version = plugin.getVersion();
 544  
                     }
 545  0
                 }
 546  
             }
 547  
         }
 548  
 
 549  0
         return version;
 550  
     }
 551  
 
 552  
     private void updatePluginVersionInRegistry( String groupId, String artifactId, String version )
 553  
         throws PluginVersionResolutionException
 554  
     {
 555  0
         PluginRegistry pluginRegistry = getPluginRegistry( groupId, artifactId );
 556  
 
 557  0
         org.apache.maven.plugin.registry.Plugin plugin = getPlugin( groupId, artifactId, pluginRegistry );
 558  
 
 559  
         // if we can find the plugin, but we've gotten here, the useVersion must be missing; fill it in.
 560  0
         if ( plugin != null )
 561  
         {
 562  0
             if ( PluginRegistry.GLOBAL_LEVEL.equals( plugin.getSourceLevel() ) )
 563  
             {
 564  
                 // do nothing. We don't rewrite the globals, under any circumstances.
 565  0
                 getLogger().warn( "Cannot update registered version for plugin {" + groupId + ":" + artifactId +
 566  
                     "}; it is specified in the global registry." );
 567  
             }
 568  
             else
 569  
             {
 570  0
                 plugin.setUseVersion( version );
 571  
 
 572  0
                 SimpleDateFormat format =
 573  
                     new SimpleDateFormat( org.apache.maven.plugin.registry.Plugin.LAST_CHECKED_DATE_FORMAT );
 574  
 
 575  0
                 plugin.setLastChecked( format.format( new Date() ) );
 576  0
             }
 577  
         }
 578  
         else
 579  
         {
 580  0
             plugin = new org.apache.maven.plugin.registry.Plugin();
 581  
 
 582  0
             plugin.setGroupId( groupId );
 583  0
             plugin.setArtifactId( artifactId );
 584  0
             plugin.setUseVersion( version );
 585  
 
 586  0
             pluginRegistry.addPlugin( plugin );
 587  
 
 588  0
             pluginRegistry.flushPluginsByKey();
 589  
         }
 590  
 
 591  0
         writeUserRegistry( groupId, artifactId, pluginRegistry );
 592  0
     }
 593  
 
 594  
     private void writeUserRegistry( String groupId, String artifactId, PluginRegistry pluginRegistry )
 595  
     {
 596  0
         File pluginRegistryFile = pluginRegistry.getRuntimeInfo().getFile();
 597  
 
 598  0
         PluginRegistry extractedUserRegistry = PluginRegistryUtils.extractUserPluginRegistry( pluginRegistry );
 599  
 
 600  
         // only rewrite the user-level registry if one existed before, or if we've created user-level data here.
 601  0
         if ( extractedUserRegistry != null )
 602  
         {
 603  0
             Writer fWriter = null;
 604  
 
 605  
             try
 606  
             {
 607  0
                 pluginRegistryFile.getParentFile().mkdirs();
 608  0
                 fWriter = WriterFactory.newXmlWriter( pluginRegistryFile );
 609  
 
 610  0
                 PluginRegistryXpp3Writer writer = new PluginRegistryXpp3Writer();
 611  
 
 612  0
                 writer.write( fWriter, extractedUserRegistry );
 613  
             }
 614  0
             catch ( IOException e )
 615  
             {
 616  0
                 getLogger().warn(
 617  
                     "Cannot rewrite user-level plugin-registry.xml with new plugin version of plugin: \'" + groupId +
 618  
                         ":" + artifactId + "\'.", e );
 619  
             }
 620  
             finally
 621  
             {
 622  0
                 IOUtil.close( fWriter );
 623  0
             }
 624  
         }
 625  0
     }
 626  
 
 627  
     private PluginRegistry getPluginRegistry( String groupId, String artifactId )
 628  
         throws PluginVersionResolutionException
 629  
     {
 630  0
         if ( pluginRegistry == null )
 631  
         {
 632  
             try
 633  
             {
 634  0
                 pluginRegistry = mavenPluginRegistryBuilder.buildPluginRegistry();
 635  
             }
 636  0
             catch ( IOException e )
 637  
             {
 638  0
                 throw new PluginVersionResolutionException( groupId, artifactId,
 639  
                                                             "Error reading plugin registry: " + e.getMessage(), e );
 640  
             }
 641  0
             catch ( XmlPullParserException e )
 642  
             {
 643  0
                 throw new PluginVersionResolutionException( groupId, artifactId,
 644  
                                                             "Error parsing plugin registry: " + e.getMessage(), e );
 645  0
             }
 646  
 
 647  0
             if ( pluginRegistry == null )
 648  
             {
 649  0
                 pluginRegistry = mavenPluginRegistryBuilder.createUserPluginRegistry();
 650  
             }
 651  
         }
 652  
 
 653  0
         return pluginRegistry;
 654  
     }
 655  
 
 656  
     private String resolveMetaVersion( String groupId, String artifactId, MavenProject project,
 657  
                                        ArtifactRepository localRepository, String metaVersionId )
 658  
         throws PluginVersionResolutionException, InvalidPluginException
 659  
     {
 660  0
         Artifact artifact = artifactFactory.createProjectArtifact( groupId, artifactId, metaVersionId );
 661  
 
 662  0
         String key = artifact.getDependencyConflictId();
 663  0
         if ( resolvedMetaVersions.containsKey( key ) )
 664  
         {
 665  0
             return (String) resolvedMetaVersions.get( key );
 666  
         }
 667  
 
 668  0
         String version = null;
 669  
 
 670  
         // This takes the spec version and resolves a real version
 671  
         try
 672  
         {
 673  0
             ResolutionGroup resolutionGroup =
 674  
                 artifactMetadataSource.retrieve( artifact, localRepository, project.getPluginArtifactRepositories() );
 675  
 
 676  
             // switching this out with the actual resolved artifact instance, since the MMSource re-creates the pom
 677  
             // artifact.
 678  0
             artifact = resolutionGroup.getPomArtifact();
 679  
         }
 680  0
         catch ( ArtifactMetadataRetrievalException e )
 681  
         {
 682  0
             throw new PluginVersionResolutionException( groupId, artifactId, e.getMessage(), e );
 683  0
         }
 684  
 
 685  0
         String artifactVersion = artifact.getVersion();
 686  
 
 687  
         // make sure this artifact was actually resolved to a file in the repo...
 688  0
         if ( artifact.getFile() != null )
 689  
         {
 690  0
             boolean pluginValid = false;
 691  
 
 692  0
             while ( !pluginValid && artifactVersion != null )
 693  
             {
 694  0
                 pluginValid = true;
 695  
                 MavenProject pluginProject;
 696  
                 try
 697  
                 {
 698  0
                     artifact = artifactFactory.createProjectArtifact( groupId, artifactId, artifactVersion );
 699  0
                     pluginProject = mavenProjectBuilder.buildFromRepository( artifact,
 700  
                                                                              project.getPluginArtifactRepositories(),
 701  
                                                                              localRepository, false );
 702  
                 }
 703  0
                 catch ( ProjectBuildingException e )
 704  
                 {
 705  0
                     throw new InvalidPluginException( "Unable to build project information for plugin '" +
 706  
                         ArtifactUtils.versionlessKey( groupId, artifactId ) + "': " + e.getMessage(), e );
 707  0
                 }
 708  
 
 709  
                 // if we don't have the required Maven version, then ignore an update
 710  0
                 if ( pluginProject.getPrerequisites() != null && pluginProject.getPrerequisites().getMaven() != null )
 711  
                 {
 712  0
                     DefaultArtifactVersion requiredVersion =
 713  
                         new DefaultArtifactVersion( pluginProject.getPrerequisites().getMaven() );
 714  
 
 715  0
                     if ( runtimeInformation.getApplicationVersion().compareTo( requiredVersion ) < 0 )
 716  
                     {
 717  0
                         getLogger().info( "Ignoring available plugin update: " + artifactVersion +
 718  
                             " as it requires Maven version " + requiredVersion );
 719  
 
 720  
                         VersionRange vr;
 721  
                         try
 722  
                         {
 723  0
                             vr = VersionRange.createFromVersionSpec( "(," + artifactVersion + ")" );
 724  
                         }
 725  0
                         catch ( InvalidVersionSpecificationException e )
 726  
                         {
 727  0
                             throw new PluginVersionResolutionException( groupId, artifactId,
 728  
                                                                         "Error getting available plugin versions: " +
 729  
                                                                             e.getMessage(), e );
 730  0
                         }
 731  
 
 732  0
                         getLogger().debug( "Trying " + vr );
 733  
                         try
 734  
                         {
 735  0
                             List versions = artifactMetadataSource.retrieveAvailableVersions( artifact, localRepository,
 736  
                                                                                               project.getPluginArtifactRepositories() );
 737  0
                             ArtifactVersion v = vr.matchVersion( versions );
 738  0
                             artifactVersion = v != null ? v.toString() : null;
 739  
                         }
 740  0
                         catch ( ArtifactMetadataRetrievalException e )
 741  
                         {
 742  0
                             throw new PluginVersionResolutionException( groupId, artifactId,
 743  
                                                                         "Error getting available plugin versions: " +
 744  
                                                                             e.getMessage(), e );
 745  0
                         }
 746  
 
 747  0
                         if ( artifactVersion != null )
 748  
                         {
 749  0
                             getLogger().debug( "Found " + artifactVersion );
 750  0
                             pluginValid = false;
 751  
                         }
 752  
                     }
 753  
                 }
 754  0
             }
 755  
         }
 756  
 
 757  0
         if ( !metaVersionId.equals( artifactVersion ) )
 758  
         {
 759  0
             version = artifactVersion;
 760  0
             resolvedMetaVersions.put( key, version );
 761  
         }
 762  
 
 763  0
         return version;
 764  
     }
 765  
 
 766  
 }