Cómo acceder a la jerarquía de dependencias de Maven dentro de un complemento

En mi complemento necesito procesar la jerarquía de dependencias y obtener información (groupId, artifactId, versión, etc.) sobre cada dependencia y si fue excluida. ¿Cuál es la mejor manera de hacer esto?

El complemento de dependencia tiene el objective del árbol que hace la mayor parte de este trabajo. Procesa un MavenProject utilizando DependencyTreeBuilder , esto devuelve un DependencyNode con información jerárquica sobre las dependencias resueltas (y sus dependencias transitivas).

Puede copiar gran parte del código directamente desde TreeMojo. Utiliza CollectingDependencyNodeVisitor para recorrer el árbol y generar una List de todos los nodos.

Puede acceder al Artifact para el nodo llamando a getArtifact() y luego obtener la información del artefacto según sea necesario. Para obtener el motivo de exclusión, DependencyNode tiene un método getState() que devuelve un int que indica si se ha incluido la dependencia o, en caso getState() , el motivo para omitirla (hay constantes en la clase DependencyNode para verificar el valor de retorno)

 //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 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(); } } 

Puede usar MavenProject # getDependencyArtifacts () o MavenProject # getDependencies () (el último también devuelve dependencias transitivas).

 /** * 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(); ... } } 

No estoy del todo seguro, pero creo que ambos métodos devuelven una colección de implementaciones de Artifact que exponen getters para groupId, artifactId, version, etc.

Aquí hay un ejemplo actualizado de Maven3 sobre cómo obtener todas las dependencias (incluida la transitiva) y también tener acceso a los archivos en sí (si, por ejemplo, necesita agregar las rutas a una ruta de clases).

 // 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. } } } 

Cambiar los parámetros en el Mojo es una pieza muy importante que me faltaba. Sin él, líneas como las siguientes:

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

Solo devolverá el directorio de clases, no la ruta que espera.

Cambiar el requiresDependencyCollection y requiresDependencyResolution a diferentes valores le permitirá cambiar el scope de lo que desea capturar. La documentación del maven puede proporcionar más detalles.

Intente utilizar la clase de utilidad Aether de jcabi-aether para obtener una lista de todas las dependencias de cualquier artefacto:

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

Maven 3 usa el éter, hay una muestra aquí: https://docs.sonatype.org/display/AETHER/Home

¿Por qué no recuperar todas las dependencias (tanto las directas como transitorias) y verificar la exclusión?

 @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) ) { ... } } } 

Para Maven 3 puedes usar DependencyGraphBuilder. Hace más o menos lo mismo que DependencyTreeBuilder.

Aquí está el ejemplo

  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 children = visitor.getNodes(); getLog().info("CHILDREN ARE :"); for(DependencyNode node : children) { Artifact atf = node.getArtifact(); } }catch(Exception e) { e.printStackTrace(); } 
Intereting Posts