web-dev-qa-db-ja.com

プラグイン内でMavenの依存関係階層にアクセスする方法

私のプラグインでは、依存関係の階層を処理し、各依存関係に関する情報(groupId、artifactId、versionなど)とそれが除外されているかどうかを取得する必要があります。これを行うための最良の方法は何ですか?

36
talk to frank

依存関係プラグインには、この作業のほとんどを実行する ツリーゴール があります。 MavenProjectを使用してDependencyTreeBuilderを処理します。これにより、解決された依存関係(およびそれらの推移的な依存関係)に関する階層情報を含むDependencyNodeが返されます。

TreeMojoから直接コードの多くをコピーできます。 CollectingDependencyNodeVisitorを使用してツリーをトラバースし、すべてのノードのListを生成します。

getArtifact()を呼び出すことでノードのArtifactにアクセスし、必要に応じてアーティファクト情報を取得できます。除外理由を取得するために、DependencyNodeにはgetState()メソッドがあり、依存関係が含まれているかどうか、または含まれていない場合はそれを省略した理由を示すintを返します(定数があります)戻り値をチェックするDependencyNodeクラス)

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

MavenProject#getDependencyArtifacts() または MavenProject#getDependencies() を使用できます(後者は推移的な依存関係も返します)。

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

       ...
    }

}

完全にはわかりませんが、どちらのメソッドも、groupId、artifactId、versionなどのゲッターを公開する Artifact 実装のコレクションを返すと思います。

20
Pascal Thivent

これは、すべての依存関係(推移的を含む)を取得し、ファイル自体にアクセスする方法(たとえば、クラスパスにパスを追加する必要がある場合)に関する最新のMaven3の例です。

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

Mojoのパラメーターを変更することは、私が見逃していた非常に重要な部分です。それがないと、次のような行になります。

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

期待するパスではなく、classesディレクトリのみを返します。

RequireDependencyCollectionとrequiresDependencyResolutionを異なる値に変更すると、取得する対象のスコープを変更できます。 Mavenドキュメント で詳細を確認できます。

14
wrestang

Aether ユーティリティクラス jcabi-aether を使用して、アーティファクトのすべての依存関係のリストを取得してみてください。

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
);
5
yegor256

すべての依存関係(直接依存関係と推移的依存関係の両方)を取り戻し、除外を確認しないのはなぜですか?

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

Maven 3はエーテルを使用します。ここにサンプルがあります: https://docs.sonatype.org/display/AETHER/Home

2
Yann Le Moigne

Maven 3の場合、DependencyGraphBuilderを使用できます。 DependencyTreeBuilderとほとんど同じことをします。

これが例です

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