How to find a remote repository URL of an artifact for a Maven plugin

129 Views Asked by At

I'm developing a Maven plugin.

The plugin needs to list the dependencies of a project its running in, and determine where (which remote Maven repository) the dependency came from. It's OK if I get just a remote repository, doesn't need to be the original one (i.e., if it came from a mirror, it's OK if I get the mirror URL).

I've run up and down Maven APIs, and can't find anything that will expose this information. It's also obvious that Maven does know it because (a) it did download it from a (remote) repository, and (b) there is a _remote.repositories file alongside the artifact in the local repository that points to the repository the artifact came from.

Besides using the correct API calls, I have other options that I don't like:

  1. Get the pom.xml of the dependency, look at its <distributionManagement>/<repository> tag, and infer the repository. The tag can be missing, and the distribution repository isn't necessarily the same as the repository to get the artifact from.

  2. Read the _remote.repositories from the adjacent location of the locally downloaded artifact, and interpret them. This is a hack, and the file clearly states to not do that, because it's subject to change.

  3. Given all repositories known to the project, poke them all, until I find the one that has the artifact.

If one can point out the Maven APIs I can use to do that, it'd be great.

P.S. The reason for determining the repository URL is to produce a report that stipulates where the dependency actually came from (a specific requirement); the party that receives the report should be able to download the dependency and check whether it matches a declared hash (also present in the report).

1

There are 1 best solutions below

4
Slawomir Jaranowski On

You can use Maven Resolve API.

RepositorySystem#collectDependencies(...)

Before call RepositorySystem#collectDependencies(...) we need to prepare own RepositoryListener as example:


        RepositoryListener myListener = new AbstractRepositoryListener() {
            @Override
            public void artifactResolved(RepositoryEvent event) {
                getLog().info("artifact=" + event.getArtifact() + " repo=" + event.getRepository());
            }
        };

        // copy of repository session
        DefaultRepositorySystemSession mySystemSession =
                new DefaultRepositorySystemSession(session.getRepositorySession());

        // new ChainedRepositoryListener with our own listener
        ChainedRepositoryListener repositoryListener =
                new ChainedRepositoryListener(mySystemSession.getRepositoryListener(), myListener);
        mySystemSession.setRepositoryListener(repositoryListener);


        // ...
        CollectResult collectResult = repositorySystem.collectDependencies(mySystemSession, request);

        // ....

RepositoryEvent#getRepository will contains one repository used to resolve artifact. In some case it can be a local repository if artifact was not resolved by Maven early or was locally installed.

You can examine code of maven-dependency-plugin:list-repositories as example of using Resolve API

https://github.com/apache/maven-dependency-plugin/blob/master/src/main/java/org/apache/maven/plugins/dependency/ListRepositoriesMojo.java