Find dependencies of a Maven Dependency object - maven

I'm writing a Maven 3 plugin that needs to know the transitive dependencies of a given org.apache.maven.model.Dependency. How can I do that?

In Maven 3, you access all dependencies in a tree-based form by relying on the maven-dependency-tree shared component:
A tree-based API for resolution of Maven project dependencies.
This component introduces the DependencyGraphBuilder that can build the dependency tree for a given Maven project. You can also filter artifacts with a ArtifactFilter, that has a couple of built-in implementations to filter by groupId, artifactId (IncludesArtifactFilter and ExcludesArtifactFilter), scope (ScopeArtifactFilter), etc. If the fiter is null, all dependencies are kept.
In your case, since you target a specific artifact, you could add a IncludesArtifactFilter with the pattern groupId:artifactId of your artifact. A sample code would be:
#Mojo(name = "foo")
public class MyMojo extends AbstractMojo {
#Parameter(defaultValue = "${project}", readonly = true, required = true)
private MavenProject project;
#Parameter(defaultValue = "${session}", readonly = true, required = true)
private MavenSession session;
#Component(hint = "default")
private DependencyGraphBuilder dependencyGraphBuilder;
public void execute() throws MojoExecutionException, MojoFailureException {
ArtifactFilter artifactFilter = new IncludesArtifactFilter(Arrays.asList("groupId:artifactId"));
ProjectBuildingRequest buildingRequest = new DefaultProjectBuildingRequest(session.getProjectBuildingRequest());
buildingRequest.setProject(project);
try {
DependencyNode rootNode = dependencyGraphBuilder.buildDependencyGraph(buildingRequest, artifactFilter);
CollectingDependencyNodeVisitor visitor = new CollectingDependencyNodeVisitor();
rootNode.accept(visitor);
for (DependencyNode node : visitor.getNodes()) {
System.out.println(node.toNodeString());
}
} catch (DependencyGraphBuilderException e) {
throw new MojoExecutionException("Couldn't build dependency graph", e);
}
}
}
This gives access to the root node of the dependency tree, which is the current project. From that node, you can access all chidren by calling the getChildren() method. So if you want to list all dependencies, you can traverse that graph recursively. This component does provide a facility for doing that with the CollectingDependencyNodeVisitor. It will collect all dependencies into a List to easily loop through it.
For the Maven plugin, the following dependency is therefore necessary:
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-dependency-tree</artifactId>
<version>3.0</version>
</dependency>

So the following code should give you an impression how to do it.
#Mojo( name = "test", requiresDependencyResolution = ResolutionScope.COMPILE, defaultPhase = LifecyclePhase.PACKAGE ...)
public class TestMojo
extends AbstractMojo
{
#Parameter( defaultValue = "${project}", readonly = true )
private MavenProject project;
public void execute()
throws MojoExecutionException, MojoFailureException
{
List<Dependency> dependencies = project.getDependencies();
for ( Dependency dependency : dependencies )
{
getLog().info( "Dependency: " + getId(dependency) );
}
Set<Artifact> artifacts = project.getArtifacts();
for ( Artifact artifact : artifacts )
{
getLog().info( "Artifact: " + artifact.getId() );
}
}
private String getId(Dependency dep) {
StringBuilder sb = new StringBuilder();
sb.append( dep.getGroupId() );
sb.append( ':' );
sb.append( dep.getArtifactId() );
sb.append( ':' );
sb.append( dep.getVersion() );
return sb.toString();
}
}
The above code will give you the resolved artifacts as well as dependencies. You need to make a difference between the dependencies (in this case the project dependencies without transitive and the artifacts which are the solved artifacts incl. transitive.).
Most important is requiresDependencyResolution = ResolutionScope.COMPILE otherwise you will get null for getArtifacts().
The suggestion by Tunaki will work for any kind of artifact which is not part of your project...The question is what you really need?

Related

How to get the location of a Maven dependency in a custom plugin?

In a custom Maven plugin, during of execution I need to know the location of all dependencies of the Maven project, something like
/home/kider/.m2/repository/org/jdom/jdom/1.1/jdom-1.1.jar
I tried to get the dependencies one by one from MavenProject but I have access only to the GAV informations, but not to the file itself.
#Mojo(name = "testplugin", defaultPhase = LifecyclePhase.TEST)
public class MyMojo extends AbstractMojo {
#Parameter( defaultValue = "${localRepository}", readonly = true, required = true )
private ArtifactRepository localRepo;
#Parameter(defaultValue = "${project}")
public MavenProject project;
...
for (Dependency dep : this.project.getDependencyManagement().getDependencies()) {
this.localRepo.getBasedir()
+ File.separator
+ dep.getGroupId().replace(".", File.separator)
+ File.separator
+ dep.getArtifactId().replace(".", File.separator)
+ File.separator
+ dep.getVersion()
}
Is there any other solution to this?

Getting the versioning through maven API

I'm trying to get the versions of a maven artifact by using:
#Mojo(name = "myGoal", defaultPhase = LifecyclePhase.VERIFY)
public class MyMojo extends AbstractMojo{
#Parameter(defaultValue = "${project}", readonly = true)
private MavenProject project;
public void execute() throws MojoExecutionException, MojoFailureException {
Artifact myartifact = project.getArtifact();
ArtifactRepositoryMetadata artifactRepoMetadata = new ArtifactRepositoryMetadata(myartifact);
Versioning versioning = artifactRepoMetadata.getMetadata().getVersioning();
List<Version> versions = versioning.getVersions();
But for some reason "versioning" is null. What do I need to do to get it to work and return the versioning so that I can get a list of versions for my artifact?

Gradle - publish all project's dependencies to another artifactory

As a software house, we are being asked, to deliver the software with all of its dependencies. The dependencies should be published to another artifactory. In another words - we would like to take all of the project's dependencies from our artifactory and publish them into another artifactory in a way that would enable the client to build the software.
Is there a way to do that in Gradle?
Adapted from this gist
public class MavenArtifactCopyTask extends DefaultTask {
#Input
List<Configuration> configurations;
#OutputDirectory
File repoDir
#TaskAction
void build() {
for (Configuration configuration : configurations) {
copyJars(configuration)
copyPoms(configuration)
}
}
private void copyJars(Configuration configuration) {
configuration.resolvedConfiguration.resolvedArtifacts.each { artifact ->
def moduleVersionId = artifact.moduleVersion.id
File moduleDir = new File(repoDir, "${moduleVersionId.group.replace('.','/')}/${moduleVersionId.name}/${moduleVersionId.version}")
GFileUtils.mkdirs(moduleDir)
GFileUtils.copyFile(artifact.file, new File(moduleDir, artifact.file.name))
}
}
private void copyPoms(Configuration configuration) {
def componentIds = configuration.incoming.resolutionResult.allDependencies.collect { it.selected.id }
def result = project.dependencies.createArtifactResolutionQuery()
.forComponents(componentIds)
.withArtifacts(MavenModule, MavenPomArtifact)
.execute()
for(component in result.resolvedComponents) {
def componentId = component.id
if(componentId instanceof ModuleComponentIdentifier) {
File moduleDir = new File(repoDir, "${componentId.group.replace('.','/')}/${componentId.module}/${componentId.version}")
GFileUtils.mkdirs(moduleDir)
File pomFile = component.getArtifacts(MavenPomArtifact)[0].file
GFileUtils.copyFile(pomFile, new File(moduleDir, pomFile.name))
}
}
}
}
Usage
task copyMavenArtifacts(type: MavenArtifactCopyTask) {
configurations = [project.configurations.all, project.buildScript.configurations.classpath]
repoDir = file("$buildDir/mavenArtifacts")
}
Once all the jars & poms are in a local folder in a maven directory structure you can
Upload them all to another repository
Use the folder as a maven repository
You can use repository replication https://www.jfrog.com/confluence/display/RTF/Repository+Replication

For a Maven 3 plugin what is the latest way to resolve a artifact

What is the latest way of resolving an Artifact within a Maven 3.2.5 plugin. ArtifactResolver and ArtifactFactory(depreciated) are in the compat library which implies that there is a newer/better way of resolution, but I can not find any examples, docs or searches that do not use the above.
Thanks
Michael
There's a blog from sonatype on exactly this:
http://blog.sonatype.com/2011/01/how-to-use-aether-in-maven-plugins
This is the code from the blog entry (full details are obviously described there):
public MyMojo extends AbstractMojo {
/**
* The entry point to Aether, i.e. the component doing all the work.
*/
#Component
private RepositorySystem repoSystem;
/**
* The current repository/network configuration of Maven.
*/
#Parameter(defaultValue = "${repositorySystemSession}", readonly = true)
private RepositorySystemSession repoSession;
/**
* The project's remote repositories to use for the resolution of plugins and their dependencies.
*/
#Parameter(defaultValue = "${project.remotePluginRepositories}", readonly = true)
private List<RemoteRepository> remoteRepos;
public void execute() throws MojoExecutionException, MojoFailureException {
ArtifactRequest request = new ArtifactRequest();
request.setArtifact(new DefaultArtifact( "org.apache.maven:maven-model:3.0" ) );
request.setRepositories( remoteRepos );
ArtifactResult result = repoSystem.resolveArtifact( repoSession, request );
}
}
You can then use result.getArtifact() to get the artifact and result.getArtifact().getFile() to get the file of the artifact if you need it.

how to pass maven module classes to a maven plugin

I've developed a maven plugin, which can scan classes within a module, to find some specific classes and do something about them.
The problem is that, when I'm using this plugin in a maven module, It's not able to find classes within that module.
I've checked the plugin classpath and it only contains plugin classes and it's dependencies.
Is there any way to automatically include module classes into plugin classpath?
I took this approach and apparently it's working:
1 - a MavenProject parameter is needed within your Mojo class:
#Parameter(defaultValue = "${project}", required = true, readonly = true)
private MavenProject project;
2 - and then you can get the classpath elements from project instance:
try {
Set<URL> urls = new HashSet<>();
List<String> elements = project.getTestClasspathElements();
//getRuntimeClasspathElements()
//getCompileClasspathElements()
//getSystemClasspathElements()
for (String element : elements) {
urls.add(new File(element).toURI().toURL());
}
ClassLoader contextClassLoader = URLClassLoader.newInstance(
urls.toArray(new URL[0]),
Thread.currentThread().getContextClassLoader());
Thread.currentThread().setContextClassLoader(contextClassLoader);
} catch (DependencyResolutionRequiredException e) {
throw new RuntimeException(e);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}

Resources