简体   繁体   English

在Maven Central上查找工件的所有直接依赖项

[英]Find all direct dependencies of an artifact on Maven Central

For an artifact on Maven central (or any other given Nexus repository), I want to make a list of all direct dependencies. 对于Maven中心(或任何其他给定的Nexus存储库)上的工件,我想列出所有直接依赖项。

At first, I thought about just reading the pom.xml and gather all entries from the dependency section. 起初,我考虑过只读取pom.xml并从依赖项部分收集所有条目。 But I noticed that these entries might have no version (supplied by dependency management) or that entries might come from parent poms. 但我注意到这些条目可能没有版本(由依赖关系管理提供),或者条目可能来自父poms。

My second idea was to build some kind of artificial Maven project and gather the dependencies with mvn dependency:tree . 我的第二个想法是构建某种人工Maven项目并使用mvn dependency:tree收集mvn dependency:tree This might become complicated. 这可能会变得复杂。

What would be the most direct (but also reliable) way? 什么是最直接(但也可靠)的方式?

Outside of a Maven plugin, you can do this programmatically using Aether. 在Maven插件之外,您可以使用Aether以编程方式执行此操作。 There is a method readArtifactDescriptor that does exactly this: 有一个方法readArtifactDescriptor正是这样做的:

Gets information about an artifact like its direct dependencies and potential relocations. 获取有关工件的信息,例如其直接依赖关系和潜在的重定位。

First, add the Aether dependencies to your POM: 首先,将Aether依赖项添加到您的POM:

<dependencies>
    <dependency>
        <groupId>org.eclipse.aether</groupId>
        <artifactId>aether-impl</artifactId>
        <version>${aetherVersion}</version>
    </dependency>
    <dependency>
        <groupId>org.eclipse.aether</groupId>
        <artifactId>aether-connector-basic</artifactId>
        <version>${aetherVersion}</version>
    </dependency>
    <dependency>
        <groupId>org.eclipse.aether</groupId>
        <artifactId>aether-transport-file</artifactId>
        <version>${aetherVersion}</version>
    </dependency>
    <dependency>
        <groupId>org.eclipse.aether</groupId>
        <artifactId>aether-transport-http</artifactId>
        <version>${aetherVersion}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-aether-provider</artifactId>
        <version>${mavenVersion}</version>
    </dependency>
</dependencies>
<properties>
    <aetherVersion>1.1.0</aetherVersion>
    <mavenVersion>3.3.9</mavenVersion>
</properties>

Then you can have: 然后你可以:

public static void main(final String[] args) throws Exception {
    DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator();
    RepositorySystem system = newRepositorySystem(locator);
    RepositorySystemSession session = newSession(system);

    RemoteRepository central = new RemoteRepository.Builder("central", "default", "http://repo1.maven.org/maven2/").build();

    Artifact artifact = new DefaultArtifact("groupId:artifactId:version");
    ArtifactDescriptorRequest request = new ArtifactDescriptorRequest(artifact, Arrays.asList(central), null);
    ArtifactDescriptorResult result = system.readArtifactDescriptor(session, request);

    for (Dependency dependency : result.getDependencies()) {
        System.out.println(dependency);
    }
}

private static RepositorySystem newRepositorySystem(DefaultServiceLocator locator) {
    locator.addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class);
    locator.addService(TransporterFactory.class, FileTransporterFactory.class);
    locator.addService(TransporterFactory.class, HttpTransporterFactory.class);
    return locator.getService(RepositorySystem.class);
}

private static RepositorySystemSession newSession(RepositorySystem system) {
    DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
    LocalRepository localRepo = new LocalRepository("target/local-repo");
    session.setLocalRepositoryManager(system.newLocalRepositoryManager(session, localRepo));
    // set possible proxies and mirrors
    session.setProxySelector(new DefaultProxySelector().add(new Proxy(Proxy.TYPE_HTTP, "host", 3625), Arrays.asList("localhost", "127.0.0.1")));
    session.setMirrorSelector(new DefaultMirrorSelector().add("my-mirror", "http://mirror", "default", false, "external:*", null));
    return session;
}

What this does is creating a Aether repository system and telling it to read the artifact descriptor of a given artifact. 这样做是创建一个Aether存储库系统并告诉它读取给定工件的工件描述符。 The artifact is constructed with the constructor new DefaultArtifact("...") giving it the wanted coordinates. 使用构造函数new DefaultArtifact("...")构造工件,为其提供所需的坐标。

A request object is created with this artifact and the list of repositories to fetch it from. 使用此工件和要从中获取它的存储库列表创建请求对象。 In the above sample, only Maven Central was added, but you could add more RemoteRepository by creating them with the RemoteRepository.Builder class. 在上面的示例中,只添加了Maven Central,但您可以通过使用RemoteRepository.Builder类创建它们来添加更多RemoteRepository After calling readArtifactDescriptor , the result contains the list of direct dependencies, that can be retrieved with getDependencies() . 在调用readArtifactDescriptor ,结果包含可以使用getDependencies()检索的直接依赖项列表。

Proxies and mirrors can be configured with the help of the DefaultProxySelector and DefaultMirrorSelector respectively. 可以分别在DefaultProxySelectorDefaultMirrorSelector的帮助下配置代理和镜像。 DefaultProxySelector.add takes a Proxy as argument, which can be created with its constructor by passing it its type (like "http" ), host, port and optionally an Authentication (take a look at the AuthenticationBuilder class to create authentication objects), and a list of non-proxied host. DefaultProxySelector.addProxy作为参数,可以使用其构造函数创建它的类型(如"http" ),主机,端口和可选的Authentication (查看AuthenticationBuilder类以创建身份验证对象),以及非代理主机列表。 In the same way, DefaultMirrorSelector.add takes its id, URL, type (which is "default" for Maven, but you could have P2 for example), whether it is a repository manager, the actual repository ids mirrored (according to the mirror specification ), and the repository type not mirrored. 以同样的方式, DefaultMirrorSelector.add获取其id,URL,类型(对于Maven来说是"default" ,但您可以使用P2),无论它是存储库管理器,实际存储库ID都是镜像的(根据镜像)规范 ),以及未镜像的存储库类型。

The following workflow seems to be ok: 以下工作流程似乎没问题:

  1. Download the pom from Maven central, put it a separate directory and name it pom.xml . 从Maven central下载pom,将其放在一个单独的目录中,并将其命名为pom.xml

  2. Apply mvn dependency:list -DexcludeTransitive and grab the console output. 应用mvn dependency:list -DexcludeTransitive并获取控制台输出。

  3. Filter the list of dependencies from the console output. 从控制台输出中过滤依赖项列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM