I'm facing similar issue. I want to extract specific files from plugin's dependencies in order not to pollute main artifact's dependencies.
The solution using "old" Maven API is obvious and straightforward. Except the deprecation.
I decided to investigate new ways to do it using new API.
My main inspiration was Maven Dependency Plug-In especially GetMojo, UnpackDependenciesMojo and UnpackUtil.
In short, what has to be done:
- Create
org.apache.maven.shared.transfer.dependencies.DependableCoordinate
which points to desired GAV. Nothing special here; use org.apache.maven.shared.transfer.dependencies.DefaultDependableCoordinate
POJO.
- Resolve the artifact. This is probably the most complex task. We need to set-up repositories, which can be obtained from Project's remote repositories and injecting proxies and authorization stuff. With this done we can use
org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolver
to do the job.
- Extracting resolved artifact.
org.codehaus.plexus.archiver.UnArchiver
is our friend. To get an instance, we can use org.codehaus.plexus.archiver.manager.ArchiverManager#getUnArchiver()
. There are two options: by type or by file extension.
I developed/tested the following code with Maven 3.8.6 and Maven 3.9.1.
Common injection
@Parameter(defaultValue = "${project.build.directory}/download", required = true)
private File outputDirectory;
@Parameter
private List<String> includes = new ArrayList<>();
@Inject
private ArchiverManager archiverManager;
@Inject
private RepositorySystem repositorySystem;
@Inject
private DependencyResolver dependencyResolver;
@Parameter(defaultValue = "${plugin}", readonly = true, required = true)
private PluginDescriptor pluginDescriptor;
@Parameter(defaultValue = "${project}", readonly = true, required = true)
private MavenProject project;
@Parameter(defaultValue = "${session}", required = true, readonly = true)
private MavenSession session;
Creation of repositories for DependencyResolver
private static List<ArtifactRepository> createRepositories(
final MavenProject project,
final MavenSession session,
final RepositorySystem repositorySystem) {
final List<ArtifactRepository> repositories = new ArrayList<>();
final var policy = new ArtifactRepositoryPolicy(
true,
ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS,
ArtifactRepositoryPolicy.CHECKSUM_POLICY_FAIL);
project.getRemoteArtifactRepositories().forEach(
remoteRepository -> repositories.add(
new MavenArtifactRepository(
remoteRepository.getId(),
remoteRepository.getUrl(),
remoteRepository.getLayout(),
policy,
policy)));
final var settings = session.getSettings();
repositorySystem.injectMirror(repositories, settings.getMirrors());
repositorySystem.injectProxy(repositories, settings.getProxies());
repositorySystem.injectAuthentication(repositories, settings.getServers());
return repositories;
}
Resolving DependableCoordinate
private static Iterable<ArtifactResult> resolveArtifact(
final DependableCoordinate artifact,
final List<ArtifactRepository> repositories,
final MavenSession session,
final DependencyResolver dependencyResolver)
throws DependencyResolverException {
final ProjectBuildingRequest buildingRequest
= new DefaultProjectBuildingRequest(session.getProjectBuildingRequest());
buildingRequest.setRemoteRepositories(repositories);
return dependencyResolver.resolveDependencies(buildingRequest, artifact, null);
}
The extraction itself
private static void extract(
final Artifact artifact,
final File directory,
final FileSelector[] selectors,
final ArchiverManager archiverManager)
throws IOException, MojoFailureException {
try {
if (!directory.exists()) {
if (!directory.mkdirs()) {
throw new IOException(String.format("Failed to create directory [%s].", directory));
}
}
UnArchiver unArchiver;
try {
unArchiver = archiverManager.getUnArchiver(artifact.getType());
} catch (final NoSuchArchiverException ex) {
unArchiver = archiverManager.getUnArchiver(artifact.getFile());
}
unArchiver.setFileSelectors(selectors);
unArchiver.setSourceFile(artifact.getFile());
unArchiver.setDestDirectory(directory);
unArchiver.extract();
} catch (final NoSuchArchiverException ex) {
throw new MojoFailureException(
String.format("Could not determine archive type for artifact [%s].", artifact),
ex);
}
}
And finally the control loop
private static final Logger LOGGER = LoggerFactory.getLogger(DependencyDownloadMojo.class);
private static final List<String> DEFAULT_INCLUDES = Collections.singletonList("*.txt");
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
LOGGER.debug("About to download resources from dependencies.");
final var repositories = createRepositories(project, session, repositorySystem);
final var dependencies = getPluginDependencies(pluginDescriptor.getPlugin());
final var selectors = createSelectors(includes);
LOGGER.info("Using resource selectors: [{}].", (Object) selectors);
for (final var dependency : dependencies) {
try {
LOGGER.info("About to download resources from dependency [{}].", dependency);
LOGGER.debug("About to resolve Artifact [{}].", dependency);
final var artifactResults = resolveArtifact(dependency, repositories, session, dependencyResolver);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Dependency resolves to [{}].", artifactResults);
for (final var artifactResult : artifactResults) {
LOGGER.debug("Dependency resolves to [{}]; location: [{}].",
artifactResult.getArtifact(),
artifactResult.getArtifact().getFile());
}
}
for (final var artifactResult : artifactResults) {
final var artifact = artifactResult.getArtifact();
LOGGER.info("About to extract resources from artifact [{}].", artifact);
try {
extract(artifact, outputDirectory, selectors, archiverManager);
} catch (final IOException ex) {
final var message = String.format(
"Failed to extract resources from artifact [%s].", artifact);
LOGGER.error(message, ex);
throw new MojoExecutionException(message, ex);
}
}
} catch (final DependencyResolverException ex) {
final var message = String.format("Failed to resolve dependency [%s].", dependency);
LOGGER.error(message, ex);
throw new MojoFailureException(message, ex);
}
}
}
private FileSelector[] createSelectors(final List<String> includes) {
final List<FileSelector> result = new ArrayList<>();
final List<String> includesOrDefaults = new ArrayList<>();
if (includes.isEmpty()) {
LOGGER.debug("Using default includes [{}].", DEFAULT_INCLUDES);
includesOrDefaults.addAll(DEFAULT_INCLUDES);
} else {
LOGGER.debug("Using provided includes [{}].", includes);
includesOrDefaults.addAll(includes);
}
for (final var include : includesOrDefaults) {
final var selector = new IncludeExcludeFileSelector();
selector.setIncludes(new String[] { include });
result.add(selector);
}
return result.toArray(new FileSelector[0]);
}
The most important—POM
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>global.sandbox.test.dependency.download.maven.plugin</groupId>
<artifactId>dependency-download-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>maven-plugin</packaging>
<parent>
<groupId>global.sandbox.test.dependency.download</groupId>
<artifactId>dependency-download</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<properties>
<maven.version>3.8.2</maven.version>
<maven-plugin-plugin.version>3.8.2</maven-plugin-plugin.version>
<sisu-maven-plugin.version>0.9.0.M2</sisu-maven-plugin.version>
<plexus-archiver.version>4.7.1</plexus-archiver.version>
<maven-artifact-transfer.version>0.13.1</maven-artifact-transfer.version>
</properties>
<prerequisites>
<maven>3.8.2</maven>
</prerequisites>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>${maven.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>${maven.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-model</artifactId>
<version>${maven.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>${maven.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>${maven.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-archiver</artifactId>
<version>${plexus-archiver.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-artifact-transfer</artifactId>
<version>${maven-artifact-transfer.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgs>-Xlint:all</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>${maven-plugin-plugin.version}</version>
<configuration>
<skipErrorNoDescriptorsFound>false</skipErrorNoDescriptorsFound>
<extractors>
<extractor>java-annotations</extractor>
</extractors>
</configuration>
</plugin>
<plugin>
<groupId>org.eclipse.sisu</groupId>
<artifactId>sisu-maven-plugin</artifactId>
<version>${sisu-maven-plugin.version}</version>
<executions>
<execution>
<id>index-project</id>
<goals>
<goal>main-index</goal>
<goal>test-index</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Parent POM
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>global.sandbox.test.dependency.download</groupId>
<artifactId>dependency-download</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>dependency</module>
<module>dependency-download-maven-plugin</module>
<module>usage</module>
</modules>
<properties>
<maven.compiler.release>17</maven.compiler.release>
<maven.compiler.target>${maven.compiler.release}</maven.compiler.target>
<maven.compiler.source>${maven.compiler.release}</maven.compiler.source>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
<maven-resources-plugin.version>3.3.1</maven-resources-plugin.version>
<maven-enforcer-plugin.version>3.3.0</maven-enforcer-plugin.version>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>${maven-resources-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>${maven-enforcer-plugin.version}</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>enforce-maven</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireMavenVersion>
<version>3.8.0</version>
</requireMavenVersion>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>