【问题标题】:How to get the dependency tree in a Maven 3 plugin?如何在 Maven 3 插件中获取依赖树?
【发布时间】:2012-04-21 21:08:01
【问题描述】:

在 Maven 2 mojo 中,您可以使用类似的方法来获取依赖关系树:

DependencyNode rootNode;
try {
  rootNode = treeBuilder.buildDependencyTree(project, localRepository,
      artifactFactory, artifactMetadataSource, null, artifactCollector);
} catch (DependencyTreeBuilderException e) {
  throw new MojoExecutionException("Failed to create dependency tree.", e);
}
final CollectingDependencyNodeVisitor visitor = new CollectingDependencyNodeVisitor();
rootNode.accept(visitor);
final List<DependencyNode> nodes = visitor.getNodes();

Maven 3 的等价物是什么?与此同时,许多相关类已被弃用(ArtifactCollectorArtifactMetadataSource 等)。

【问题讨论】:

    标签: java maven maven-3 aether


    【解决方案1】:

    我没有在网上找到任何可行的解决方案,所以我查看了 Maven 源代码并自己制定了一个解决方案。以下大部分代码是从 maven 源代码中复制的,我已经使用 Maven 3.5.4 对其进行了测试,并且运行良好。

    import org.apache.maven.artifact.Artifact;
    import org.apache.maven.artifact.ArtifactUtils;
    import org.apache.maven.execution.MavenSession;
    import org.apache.maven.plugin.AbstractMojo;
    import org.apache.maven.plugin.MojoExecutionException;
    import org.apache.maven.plugins.annotations.Mojo;
    import org.apache.maven.plugins.annotations.Parameter;
    import org.apache.maven.plugins.annotations.ResolutionScope;
    import org.apache.maven.project.DefaultDependencyResolutionRequest;
    import org.apache.maven.project.DependencyResolutionResult;
    import org.apache.maven.project.MavenProject;
    import org.apache.maven.project.ProjectDependenciesResolver;
    import org.eclipse.aether.graph.DependencyFilter;
    import org.eclipse.aether.graph.DependencyNode;
    import org.eclipse.aether.util.filter.AndDependencyFilter;
    import org.eclipse.aether.util.filter.ScopeDependencyFilter;
    
    import javax.inject.Inject;
    import java.util.*;
    
    @Mojo( name = "test-mojo", requiresDependencyResolution = ResolutionScope.RUNTIME)
    public class TestMojo extends AbstractMojo {
    
        @Parameter(defaultValue = "${project}", readonly = true, required = true)
        private MavenProject project;
        @Parameter(defaultValue = "${session}", readonly = true, required = true)
        private MavenSession session;
        @Inject
        private ProjectDependenciesResolver dependenciesResolver;
    
        public void execute() throws MojoExecutionException {
            try {
                Collection<String> scopesToResolve = new HashSet<>();
                scopesToResolve.add("compile");
                scopesToResolve.add("provided");
                scopesToResolve.add("runtime");
                scopesToResolve.add("system");
                scopesToResolve.add("test");
                Collection<String> scopesToCollect = new HashSet<>();
                scopesToCollect.add("compile");
                scopesToCollect.add("provided");
                scopesToCollect.add("runtime");
                scopesToCollect.add("system");
                scopesToCollect.add("test");
                Collection<Artifact> projectArtifacts = new HashSet<>();
                projectArtifacts.add(project.getArtifact());
                DependencyFilter collectionFilter = new ScopeDependencyFilter( null, negate( scopesToCollect ) );
                DependencyFilter resolutionFilter = new ScopeDependencyFilter( null, negate( scopesToResolve ) );
                resolutionFilter = AndDependencyFilter.newInstance( collectionFilter, resolutionFilter );
                resolutionFilter = AndDependencyFilter.newInstance( resolutionFilter, new ReactorDependencyFilter( projectArtifacts ) );
                DefaultDependencyResolutionRequest request =
                        new DefaultDependencyResolutionRequest( project, session.getRepositorySession() );
                request.setResolutionFilter( resolutionFilter );
                DependencyResolutionResult result = dependenciesResolver.resolve( request );
    
                // Here is your dependency gragh, you can do whatever you want with it.
                List<DependencyNode> children = result.getDependencyGraph().getChildren();
                List<DependencyNode> grandChildren = children.get(0).getChildren();
            } catch (Exception e) {
                e.printStackTrace();
                throw new MojoExecutionException(e.getMessage());
            }
        }
    
        private Collection<String> negate( Collection<String> scopes )
        {
            Collection<String> result = new HashSet<>();
            Collections.addAll( result, "system", "compile", "provided", "runtime", "test" );
    
            for ( String scope : scopes )
            {
                if ( "compile".equals( scope ) )
                {
                    result.remove( "compile" );
                    result.remove( "system" );
                    result.remove( "provided" );
                }
                else if ( "runtime".equals( scope ) )
                {
                    result.remove( "compile" );
                    result.remove( "runtime" );
                }
                else if ( "compile+runtime".equals( scope ) )
                {
                    result.remove( "compile" );
                    result.remove( "system" );
                    result.remove( "provided" );
                    result.remove( "runtime" );
                }
                else if ( "runtime+system".equals( scope ) )
                {
                    result.remove( "compile" );
                    result.remove( "system" );
                    result.remove( "runtime" );
                }
                else if ( "test".equals( scope ) )
                {
                    result.clear();
                }
            }
    
            return result;
        }
        private static class ReactorDependencyFilter
                implements DependencyFilter
        {
    
            private Set<String> keys = new HashSet<>();
    
            ReactorDependencyFilter( Collection<Artifact> artifacts )
            {
                for ( Artifact artifact : artifacts )
                {
                    String key = ArtifactUtils.key( artifact );
                    keys.add( key );
                }
            }
    
            public boolean accept(DependencyNode node, List<DependencyNode> parents )
            {
                org.eclipse.aether.graph.Dependency dependency = node.getDependency();
                if ( dependency != null )
                {
                    org.eclipse.aether.artifact.Artifact a = dependency.getArtifact();
                    String key = ArtifactUtils.key( a.getGroupId(), a.getArtifactId(), a.getVersion() );
                    return !keys.contains( key );
                }
                return false;
            }
    
        }
    }
    
    

    另外,请注意您需要添加一些依赖项才能使其正常工作。这是我的。

    <dependencies>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-plugin-api</artifactId>
            <version>3.6.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.maven.plugin-tools</groupId>
            <artifactId>maven-plugin-annotations</artifactId>
            <version>3.6.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-project</artifactId>
            <version>2.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.maven.shared</groupId>
            <artifactId>maven-common-artifact-filters</artifactId>
            <version>3.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-core</artifactId>
            <version>3.5.4</version>
        </dependency>
    </dependencies>
    

    【讨论】:

      【解决方案2】:

      您需要使用Aether(这是 Maven 3 正在使用的)。我建议使用一个简单的包装器,称为jcabi-aether(我是它的开发者)。

      【讨论】:

      • 抱歉,user944849 指向 Aether 的速度更快。不过,为你投了赞成票。
      • jcabi-aether 最后一个版本来自2014,有没有更好的方法?
      【解决方案3】:

      Maven 3 使用Aether 进行依赖解析。文档底部附近是另一个在 Maven 插件中使用 Aether 的链接。

      【讨论】:

      • 尽管我真的很喜欢 yegor256 的 lib jcabi-aether
      猜你喜欢
      • 1970-01-01
      • 2014-05-29
      • 2013-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-23
      • 1970-01-01
      • 2014-04-16
      相关资源
      最近更新 更多