Hello -
I’m looking to programatically obtain an effective model from a POM file.
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’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>
I’m unable to figure out how to obtain a ModelResolver without resorting to
reflecting on org.apache.maven.repository.internal.DefaultModelResolver.