[ACCEPTED]-How to get access to Maven's dependency hierarchy within a plugin-aether

Accepted answer
Score: 29

The dependency plugin has the tree goal that does 15 most of this work. It processes a MavenProject using 14 the DependencyTreeBuilder, this returns a DependencyNode with hierarchical 13 information about the resolved dependencies 12 (and their transitive dependencies).

You 11 can copy much of the code directly from 10 the TreeMojo. It uses the CollectingDependencyNodeVisitor to traverse the 9 tree and produce a List of all the nodes.

You 8 can access the Artifact for the node by calling 7 getArtifact(), then get the artifact information as needed. To 6 get the exclusion reason, DependencyNode has a getState() method 5 that returns an int indicating if the dependency 4 has been included, or if not what the reason 3 for omitting it was (there are constants 2 in the DependencyNode class to check the 1 return value against)

//All components need this annotation, omitted for brevity

/**
 * @component
 * @required
 * @readonly
 */
private ArtifactFactory artifactFactory;
private ArtifactMetadataSource artifactMetadataSource;
private ArtifactCollector artifactCollector;
private DependencyTreeBuilder treeBuilder;
private ArtifactRepository localRepository;
private MavenProject project;

public void execute() throws MojoExecutionException, MojoFailureException {
    try {
        ArtifactFilter artifactFilter = new ScopeArtifactFilter(null);

        DependencyNode rootNode = treeBuilder.buildDependencyTree(project,
                localRepository, artifactFactory, artifactMetadataSource,
                artifactFilter, artifactCollector);

        CollectingDependencyNodeVisitor visitor = 
            new CollectingDependencyNodeVisitor();

        rootNode.accept(visitor);

        List<DependencyNode> nodes = visitor.getNodes();
        for (DependencyNode dependencyNode : nodes) {
            int state = dependencyNode.getState();
            Artifact artifact = dependencyNode.getArtifact();
            if(state == DependencyNode.INCLUDED) {                    
                //...
            } 
        }
    } catch (DependencyTreeBuilderException e) {
        // TODO handle exception
        e.printStackTrace();
    }
}
Score: 22

You could use MavenProject#getDependencyArtifacts() or MavenProject#getDependencies() (the later one returns 4 also transitive dependencies).

/**
 * Test Mojo
 *
 * @goal test
 * @requiresDependencyResolution compile
 */
public class TestMojo extends AbstractMojo {

    /**
     * The Maven Project.
     *
     * @parameter expression="${project}"
     * @required
     * @readonly
     */
    private MavenProject project = null;

    /**
     * Execute Mojo.
     *
     * @throws MojoExecutionException If an error occurs.
     * @throws MojoFailureException If an error occurs.
     */
    public void execute() throws MojoExecutionException,
MojoFailureException {

        ...

        Set dependencies = project.getDependencies();

       ...
    }

}

I'm not totally 3 sure but I think both methods return a collection 2 of Artifact implementations that expose getters 1 for groupId, artifactId, version, etc.

Score: 18

Here is an up to date, Maven3 example on 12 how to get all dependencies (including transitive) as 11 well as have access to the files themselves 10 (if you for instance need to add the paths 9 to a classpath).

// Default phase is not necessarily important.
// Both requiresDependencyCollection and requiresDependencyResolution are extremely important however!
@Mojo(name = "simple", defaultPhase = LifecyclePhase.PROCESS_RESOURCES, requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME)
public class SimpleMojo extends AbstractMojo {
  @Parameter(defaultValue = "${project}", readonly = true)
  private MavenProject mavenProject;

  @Override
  public void execute() throws MojoExecutionException, MojoFailureException {
    for (final Artifact artifact : mavenProject.getArtifacts()) {
      // Do whatever you need here.
      // If having the actual file (artifact.getFile()) is not important, you do not need requiresDependencyResolution.
    }
  }
}

Changing the parameters 8 in the Mojo is a very important piece that 7 I was missing. Without it, lines like the 6 following:

@Parameter(defaultValue = "${project.compileClasspathElements}", readonly = true, required = true)
private List<String> compilePath;

Will only return the classes directory, not 5 the path you expect.

Changing the requiresDependencyCollection 4 and requiresDependencyResolution to different 3 values will allow you to change the scope 2 of what you want to grab. The maven documentation can provide 1 more detail.

Score: 6

Try to use Aether utility class from jcabi-aether to get a 1 list of all dependencies of any artifact:

File repo = this.session.getLocalRepository().getBasedir();
Collection<Artifact> deps = new Aether(this.getProject(), repo).resolve(
  new DefaultArtifact("junit", "junit-dep", "", "jar", "4.10"),
  JavaScopes.RUNTIME
);
Score: 4

Why not just get back all the dependencies 2 (both direct and transitive ones) and check 1 for exclusion?

@Parameter(property = "project", required = true, readonly = true)
private MavenProject project;

public void execute() throws MojoExecutionException
{
  for (Artifact a : project.getArtifacts()) {
    if( a.getScope().equals(Artifact.SCOPE_TEST) ) { ... }
    if( a.getScope().equals(Artifact.SCOPE_PROVIDED) ) { ... }
    if( a.getScope().equals(Artifact.SCOPE_RUNTIME) ) { ... }
  }
}
Score: 2

Maven 3 use aether, there is sample here 1 : https://docs.sonatype.org/display/AETHER/Home

Score: 1

For Maven 3 you can use DependencyGraphBuilder. It 2 does pretty much the same thing as DependencyTreeBuilder.

Here 1 is the example

    import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
    import org.apache.maven.artifact.resolver.filter.IncludesArtifactFilter;
    import org.apache.maven.execution.MavenSession;
    import org.apache.maven.model.Dependency;
    import org.apache.maven.plugins.annotations.ResolutionScope;
    import org.apache.maven.plugins.annotations.LifecyclePhase;
    import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder;

    import org.apache.maven.shared.dependency.graph.DependencyNode;
    import org.apache.maven.shared.dependency.graph.traversal.CollectingDependencyNodeVisitor;

    public class AnanlyzeTransitiveDependencyMojo extends AbstractMojo{

        @Parameter(defaultValue = "${project}", readonly = true, required = true)
        private MavenProject project;

        @Parameter(defaultValue = "${session}", readonly = true, required = true)
        private MavenSession session;

        @Component(hint="maven3")
        private DependencyGraphBuilder dependencyGraphBuilder;

        @Override
        public void execute() throws MojoExecutionException, MojoFailureException {
    // If you want to filter out certain dependencies.
             ArtifactFilter artifactFilter = new IncludesArtifactFilter("groupId:artifactId:version");
             ProjectBuildingRequest buildingRequest = new DefaultProjectBuildingRequest(session.getProjectBuildingRequest());
             buildingRequest.setProject(project);
            try{
               DependencyNode depenGraphRootNode = dependencyGraphBuilder.buildDependencyGraph(buildingRequest, artifactFilter);
               CollectingDependencyNodeVisitor visitor = new  CollectingDependencyNodeVisitor();
               depenGraphRootNode.accept(visitor);
               List<DependencyNode> children = visitor.getNodes();

               getLog().info("CHILDREN ARE :");
               for(DependencyNode node : children) {
                   Artifact atf = node.getArtifact();
            }
}catch(Exception e) {
    e.printStackTrace();
}

More Related questions