private void ensurePluginContainerIsComplete()

in maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginManager.java [738:912]


    private void ensurePluginContainerIsComplete( PluginDescriptor pluginDescriptor,
                                                  PlexusContainer pluginContainer,
                                                  MavenProject project,
                                                  MavenSession session )
        throws ArtifactNotFoundException, PluginManagerException, ArtifactResolutionException
    {
        // if the plugin's already been used once, don't re-do this step...
        // otherwise, we have to finish resolving the plugin's classpath and start the container.
        if ( ( pluginDescriptor.getArtifacts() != null ) && ( pluginDescriptor.getArtifacts().size() == 1 ) )
        {
            Artifact pluginArtifact = (Artifact) pluginDescriptor.getArtifacts().get( 0 );

            ArtifactRepository localRepository = session.getLocalRepository();

            ArtifactMetadataSource metadataSource = session.getProjectBuilderConfiguration().getMetadataSource();
            if ( metadataSource == null )
            {
                 metadataSource = artifactMetadataSource;
            }
            
            ResolutionGroup resolutionGroup;
            try
            {
                resolutionGroup = metadataSource.retrieve( pluginArtifact, localRepository,
                                                                   project.getPluginArtifactRepositories() );
            }
            catch ( ArtifactMetadataRetrievalException e )
            {
                throw new ArtifactResolutionException( "Unable to download metadata from repository for plugin '"
                    + pluginArtifact.getId() + "': " + e.getMessage(), pluginArtifact, e );
            }

            Set rgArtifacts = resolutionGroup.getArtifacts();

            rgArtifacts = checkPlexusUtils( rgArtifacts, artifactFactory );

            // [jdcasey; 20-March-2008]:
            // This is meant to eliminate the introduction of duplicated artifacts.
            // Since much of the reasoning for reversing the order of introduction of
            // plugin dependencies rests on the notion that we need to be able to
            // introduce upgraded versions of plugin dependencies on a case-by-case
            // basis, we need to remove the original version prior to artifact
            // resolution. This is consistent with recent thinking on duplicated
            // dependency specifications within a POM, where that case should
            // throw a model validation exception.
            //
            // Here, we just want to remove any chance that the ArtifactCollector
            // could make a bad choice, and use the old version in spite of our
            // explicit preference otherwise.

            // First, we're going to accumulate plugin dependencies in an ordered map,
            // keyed by dependencyConflictId (the ordered map is meant to preserve relative
            // ordering of the dependencies that do make the cut).
            Map dependencyMap = new LinkedHashMap();

            // Next, we need to accumulate all dependencies in a List, to make it
            // simpler to iterate through them all and add them to the map.
            List all = new ArrayList();

            // plugin-level dependencies from the consuming POM override dependencies
            // from the plugin's own POM.
            all.addAll( pluginDescriptor.getIntroducedDependencyArtifacts() );

            // add in the deps from the plugin POM now.
            all.addAll( rgArtifacts );

            for ( Iterator it = all.iterator(); it.hasNext(); )
            {
                Artifact artifact = (Artifact) it.next();
                String conflictId = artifact.getDependencyConflictId();

                // if the map already contains this dependencyConflictId, it constitutes an
                // overridden dependency. Don't use the old one (we know it's old from the
                // order in which dependencies were added to this list).
                if ( !dependencyMap.containsKey( conflictId ) )
                {
                    dependencyMap.put( conflictId, artifact );
                }
            }

            // Create an ordered set of dependencies from the ordered map we used above, to feed into the resolver.
            Set dependencies = new LinkedHashSet( dependencyMap.values() );

            if ( getLogger().isDebugEnabled() )
            {
                // list all dependencies to be used by this plugin (first-level deps, not transitive ones).
                getLogger().debug( "Plugin dependencies for:\n\n" + pluginDescriptor.getId()
                                   + "\n\nare:\n\n"
                                   + StringUtils.join( dependencies.iterator(), "\n" ) + "\n\n" );
            }

            List repositories = new ArrayList();
            repositories.addAll( resolutionGroup.getResolutionRepositories() );
            repositories.addAll( project.getRemoteArtifactRepositories() );

            /* get plugin managed versions */
            Map pluginManagedDependencies = new HashMap();
            try
            {
                MavenProject pluginProject =
                    mavenProjectBuilder.buildFromRepository( pluginArtifact, project.getRemoteArtifactRepositories(),
                                                             localRepository );
                if ( pluginProject != null )
                {
                    pluginManagedDependencies = pluginProject.getManagedVersionMap();
                }
            }
            catch ( ProjectBuildingException e )
            {
                // this can't happen, it would have blowed up at artifactMetadataSource.retrieve()
            }

            ArtifactResolutionResult result = artifactResolver.resolveTransitively( dependencies, pluginArtifact,
                                                                                    pluginManagedDependencies,
                                                                                    localRepository, repositories,
                                                                                    metadataSource,
                                                                                    artifactFilter );

            Set resolved = result.getArtifacts();

            for ( Iterator it = resolved.iterator(); it.hasNext(); )
            {
                Artifact artifact = (Artifact) it.next();

                if ( !artifact.equals( pluginArtifact ) )
                {
                    artifact = project.replaceWithActiveArtifact( artifact );

                    try
                    {
                        pluginContainer.addJarResource( artifact.getFile() );
                    }
                    catch ( PlexusContainerException e )
                    {
                        throw new PluginManagerException( "Error adding plugin dependency '"
                            + artifact.getDependencyConflictId() + "' into plugin manager: " + e.getMessage(), e );
                    }
                }
            }

            pluginDescriptor.setClassRealm( pluginContainer.getContainerRealm() );

            List unresolved = new ArrayList( dependencies );

            unresolved.removeAll( resolved );

            if ( getLogger().isDebugEnabled() )
            {
                // list all artifacts that were filtered out during the resolution process.
                // these are already present in the core container.
                getLogger().debug( " The following artifacts were filtered out for plugin: "
                                   + pluginDescriptor.getId()
                                   + " because they're already in the core of Maven:\n\n"
                                   + StringUtils.join( unresolved.iterator(), "\n" )
                                   + "\n\nThese will use the artifact files already in the core ClassRealm instead, to allow them to be included in PluginDescriptor.getArtifacts().\n\n" );
            }

            // Grab a file for all filtered artifacts, even if it means resolving them. This
            // is necessary in order to present a full complement of a plugin's transitive
            // dependencies to anyone who calls PluginDescriptor.getArtifacts().
            resolveCoreArtifacts( unresolved, localRepository, resolutionGroup.getResolutionRepositories() );

            // Re-join resolved and filtered-but-now-resolved artifacts.
            // NOTE: The process of filtering then re-adding some artifacts will
            // result in different ordering within the PluginDescriptor.getArtifacts()
            // List than should have happened if none had been filtered. All filtered
            // artifacts will be listed last...
            List allResolved = new ArrayList( resolved.size() + unresolved.size() );

            allResolved.addAll( resolved );
            allResolved.addAll( unresolved );

            pluginDescriptor.setArtifacts( allResolved );
        }
    }