You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@maven.apache.org by Sahil Muthoo <sa...@gmail.com> on 2019/04/07 10:48:59 UTC

[maven resolver provider] Trying to programatically build an effective model - can't find a public ModelResolver

Hello -

I’m looking to programatically obtain an effective model from a POM
file from outside a Maven container. Search on the interwebs have
taken me to [Maven Resolver
Provider](https://maven.apache.org/ref/3.6.0/maven-resolver-provider/).
This appears to have [replaced Eclipse
Aether](http://maven.apache.org/aether.html) as a means of
programmatic access to maven model resolution. I initially posted this
to maven-users but got no response. I've also created a [question on
StackOverflow](https://stackoverflow.com/q/55527844/237033) with a
bounty but no dice.

I’ve written some code that works. However I’ve had to resort to
accessing a package private class
(org.apache.maven.repository.internal.DefaultModelResolver) to make it
work. Here’s the code:

public static void main(String[] args) throws Exception {
        DefaultServiceLocator locator = serviceLocator();
        RepositorySystem system = locator.getService(RepositorySystem.class);
        DefaultRepositorySystemSession session =
MavenRepositorySystemUtils.newSession();
        LocalRepository localRepo = new LocalRepository("target/m2");
        session.setLocalRepositoryManager(system.newLocalRepositoryManager(session,
localRepo));

        Constructor<ModelResolver> c = modelResolverCtor();
        RequestTrace requestTrace = new RequestTrace(null);
        ArtifactResolver artifactResolver =
locator.getService(ArtifactResolver.class);
        VersionRangeResolver versionRangeResolver =
locator.getService(VersionRangeResolver.class);
        RemoteRepositoryManager remoteRepositoryManager =
locator.getService(RemoteRepositoryManager.class);
        List<RemoteRepository> repos = List.of(new
RemoteRepository.Builder("central", "default",
"https://repo.maven.apache.org/maven2/").build());
        ModelResolver modelResolver = c.newInstance(session,
requestTrace, "context", artifactResolver, versionRangeResolver,
remoteRepositoryManager, repos);

        DefaultModelBuildingRequest modelBuildingRequest = new
DefaultModelBuildingRequest();
        String springBootPOMPath =

"https://repo.maven.apache.org/maven2/org/springframework/boot/spring-boot/2.1.4.RELEASE/spring-boot-2.1.4.RELEASE.pom";
        File springBootPOM = downloadPOM(springBootPOMPath,
HttpClientBuilder.create().build());
        modelBuildingRequest.setPomFile(springBootPOM);
        modelBuildingRequest.setModelResolver(modelResolver);
        DefaultModelBuilder modelBuilder = new
DefaultModelBuilderFactory().newInstance();
        System.out.println(modelBuilder.build(modelBuildingRequest).getEffectiveModel().getDependencies());
    }

    private static DefaultServiceLocator serviceLocator() {
        DefaultServiceLocator locator =
MavenRepositorySystemUtils.newServiceLocator();
        locator.addService(RepositoryConnectorFactory.class,
BasicRepositoryConnectorFactory.class);
        locator.addService(TransporterFactory.class,
FileTransporterFactory.class);
        locator.addService(TransporterFactory.class,
HttpTransporterFactory.class);
        locator.addService(TransporterFactory.class,
WagonTransporterFactory.class);
        return locator;
    }

    private static Constructor<ModelResolver> modelResolverCtor()
throws ClassNotFoundException, NoSuchMethodException {
        @SuppressWarnings("unchecked") Class<ModelResolver> modelResolverClass =
                (Class<ModelResolver>)
Class.forName("org.apache.maven.repository.internal.DefaultModelResolver");
        Constructor<ModelResolver> c =
modelResolverClass.getDeclaredConstructor(RepositorySystemSession.class,
RequestTrace.class,
                String.class, ArtifactResolver.class,
VersionRangeResolver.class, RemoteRepositoryManager.class,
List.class);
        c.setAccessible(true);
        return c;
    }

    private static File downloadPOM(String pomURL, HttpClient client)
throws Exception {
        HttpGet request = new HttpGet(pomURL);
        HttpResponse response = client.execute(request);
        File outputFile = new File("target/" + Paths.get(new
URI(pomURL).getPath()).getFileName().toString());
        try (InputStream contentStream = response.getEntity().getContent()) {
            Files.copy(contentStream, outputFile.toPath(),
StandardCopyOption.REPLACE_EXISTING);
        }
        return outputFile;
    }

Here are the dependencies I’m using:

<dependency>
    <groupId>org.apache.maven</groupId>
    <artifactId>maven-resolver-provider</artifactId>
    <version>3.6.0</version>
</dependency>
<dependency>
    <groupId>org.apache.maven.resolver</groupId>
    <artifactId>maven-resolver-connector-basic</artifactId>
    <version>1.3.3</version>
</dependency>
<dependency>
    <groupId>org.apache.maven.resolver</groupId>
    <artifactId>maven-resolver-transport-file</artifactId>
    <version>1.3.3</version>
</dependency>
<dependency>
    <groupId>org.apache.maven.resolver</groupId>
    <artifactId>maven-resolver-transport-http</artifactId>
    <version>1.3.3</version>
</dependency>
<dependency>
    <groupId>org.apache.maven.resolver</groupId>
    <artifactId>maven-resolver-transport-wagon</artifactId>
    <version>1.3.3</version>
</dependency>

This works fine but the ModelResolver is package-private and I have to
reflect my way to get to it. My code can break on updates.

It seems I'm not using these libraries as intended. There isn't much
information by way of docs etc.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
For additional commands, e-mail: dev-help@maven.apache.org