Comment accéder à la hiérarchie de dépendances de Maven dans un plugin
dans mon plugin je dois traiter la hiérarchie de dépendances et obtenir des informations (groupId, artifactId, version etc) sur chaque dépendance et si elle a été exclue. Quelle est la meilleure façon de le faire?
7 réponses
le plugin de dépendances a le arbre but Cela fait la plus grande partie de ce travail. Il traite d'un MavenProject
DependencyTreeBuilder
, il renvoie un DependencyNode
avec des informations hiérarchiques sur les dépendances résolues (et leurs dépendances transitives).
vous pouvez copier une grande partie du code directement à partir du TreeMojo. Il utilise le CollectingDependencyNodeVisitor
pour traverser l'arbre et produire un List
de tous les noeuds.
vous pouvez accéder au Artifact
pour le noeud en appelant getArtifact()
, puis obtenir l'objet d'informations que nécessaire. Pour obtenir la raison de l'exclusion,DependencyNode
a un getState()
méthode qui renvoie un int indiquant si la dépendance a été incluse, ou si ce n'est pas la raison pour laquelle elle a été omise (il y a des constantes dans la classe DependencyNode pour vérifier la valeur de retour)
//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();
}
}
Vous pouvez utiliser MavenProject#getDependencyArtifacts () ou MavenProject#getDependencies () (la dernière renvoie aussi les dépendances transitives).
/**
* 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();
...
}
}
Je ne suis pas totalement sûr mais je pense que les deux méthodes renvoient une collection de Artefact implémentations qui exposent des getters pour groupId, artifactId, version, etc.
voici un exemple mis à jour, Maven3 sur la façon d'obtenir toutes les dépendances (y compris transitive) ainsi que l'accès aux fichiers eux-mêmes (si vous avez besoin par exemple d'ajouter les chemins à un 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.
}
}
}
changer les paramètres du Mojo est une pièce très importante que je manquais. Sans elle, les lignes comme suit:
@Parameter(defaultValue = "${project.compileClasspathElements}", readonly = true, required = true)
private List<String> compilePath;
ne retournera que le répertoire des classes, pas le chemin que vous attendez.
le Changement de la requiresDependencyCollection et requiresdependencerésolution à différentes valeurs vous permettront de changer la portée de ce que vous voulez saisir. Maven documentation peut fournir plus de détails.
Essayez d'utiliser Aether
classe d'utilité de jcabi-aether pour obtenir une liste de toutes les dépendances de tout artefact:
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
);
Maven 3 Utilisez l'éther, il y a un échantillon ici : https://docs.sonatype.org/display/AETHER/Home
pourquoi ne pas simplement récupérer toutes les dépendances (directes et transitoires) et vérifier l'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) ) { ... }
}
}
pour Maven 3 vous pouvez utiliser DependencyGraphBuilder. Il fait à peu près la même chose que DependencyTreeBuilder.
Voici l'exemple
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();
}