19

pom ファイルの完全に解決されたモデルを取得するにはどうすればよいですか?

これは基本的に、How can i programmaticaly build the effective model of a pom file?の言い換えです。

モジュールのセットに対していくつかの検証ルールを実行する Maven プラグインを構築しています。これらのモジュールの pom ファイルは利用可能ですが、プラグインの実行時にリアクターの一部ではありません。

このメソッドを使用して、pom ファイルを読み取り、対応する Model オブジェクトを取得できます (簡単にするために例外処理を削除しました)。

private Model pomToModel(String pathToPom) throws Exception {
    BufferedReader in = new BufferedReader(new FileReader(pathToPom));
    MavenXpp3Reader reader = new MavenXpp3Reader();
    Model model = reader.read(in);
    return model;
}

そしてそれは機能しますが、Model オブジェクトには pom ファイルと同じ情報しかありません。

「完全に解決された」モデルオブジェクトを取得できるように、そのメソッドをどのように改善できますか? 完全に解決されたということは、つまり、すべての推移的な依存関係と、親 pom からの他のすべてのものです。

乾杯!

4

6 に答える 6

12

やったよ :-)

help:effective-pom と dependency:tree は実際にはまったく役に立ちませんでした。

モジョに注入されるMavenProjectのモデルをmavenがどのように構築するかを調べる必要がありました。help:effective-pom は既に解決済みのモデルを受け取り、dependency:tree は DependencyGraph のみを構築しますが、pom のモデル全体をメモリにロードしません。

以下のコードを使用することで、親からのすべての情報、解決された ${property} 式、および展開された推移的な依存関係を含む Model オブジェクトを取得できました。

方法は次のとおりです。

1) ModelResolver を取得する

インターフェイス org.apache.maven.model.resolution.ModelResolverのインスタンスが必要になります。残念ながら、maven は依存性注入を介して簡単に提供しないため (少なくとも私は見つけることができませんでした)、作成する必要があります。さらに良いことに、そのインターフェースの 2 つの実装のみがパッケージで保護されているため、リフレクション マジックを使用してインスタンス化する必要があります。それを実装する具体的なクラスはDefaultModelResolverProjectModelResolverです。このような DefaultModelResolver を構築できました

/**
 * The Maven Project Object
 * 
 * @parameter expression="${project}"
 * @required2.0
 * @readonly
 */
protected MavenProject project;

/**
 * @component
 */
protected ArtifactResolver artifactResolver;

/**
 * @component
 */
protected RemoteRepositoryManager remoteRepositoryManager;

private Object invoke( Object object, String method )
        throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
    return object.getClass().getMethod( method ).invoke( object );
}

private org.apache.maven.model.resolution.ModelResolver makeModelResolver() throws MojoExecutionException {
    try {
        ProjectBuildingRequest projectBuildingRequest =
        (ProjectBuildingRequest) invoke( project, "getProjectBuildingRequest" );

        Class c = Class.forName("org.apache.maven.repository.internal.DefaultModelResolver");
        Constructor ct = c.getConstructor(new Class[]{RepositorySystemSession.class, 
                RequestTrace.class, String.class,
                ArtifactResolver.class, RemoteRepositoryManager.class,
                List.class});
        ct.setAccessible(true);
        return (org.apache.maven.model.resolution.ModelResolver) ct.newInstance(new Object[]{
                projectBuildingRequest.getRepositorySession(), 
                null, null, artifactResolver, remoteRepositoryManager, 
                project.getRemoteProjectRepositories()});
    } catch (Exception e) {
        throw new MojoExecutionException("Error instantiating DefaultModelResolver", e);
    }
}

2) モデルを構築する

modelResolver がある場合、次のように pom ファイルからモデルを構築できます。

public Model resolveEffectiveModel(File pomfile) {
    try {
        return modelBuilder.build(makeModelBuildRequest(pomfile)).getEffectiveModel();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }   
}

private ModelBuildingRequest makeModelBuildRequest(File artifactFile) {
    DefaultModelBuildingRequest mbr = new DefaultModelBuildingRequest();
    mbr.setPomFile(artifactFile);
    mbr.setModelResolver(modelResolver); // <-- the hard-to-get modelResolver
    return mbr;
}

きれいに見えませんが、私にはうまくいきました.. :P

于 2012-10-04T20:59:30.840 に答える
4

たぶんあなたには遅すぎるかもしれませんが、将来他の人を助けることができれば. だから私はそのようにしました:

@Component
private RepositorySystem repositorySystem;

@Component
private MavenProjectBuilder mavenProjectBuilder;

@Parameter(property = "project.remoteArtifactRepositories")
protected List<ArtifactRepository> remoteRepositories;

@Parameter(property = "localRepository")
protected ArtifactRepository localRepository;

...
Artifact pomArtifact = repositorySystem.createProjectArtifact(groupId, artifactId,version);
MavenProject project = mavenProjectBuilder.buildFromRepository(pomArtifact
                          , remoteRepositories, localRepository);

以上です。それはうまくいくはずです。特別なパッケージ (バンドルなど) がある場合は、ターゲットの pom プロジェクトで、それらのパッケージに関連付けられているプラ​​グインが現在のプロジェクトにインストールされていることを確認してください。

于 2014-10-29T03:26:04.940 に答える
2

あなたが探しているソースコードはhelp:effective-pom、どこかにあります。

---更新の編集---

一目見ただけProject、読み取りpomからMavenを構築する必要があるように思われます。これには、POMの親プロジェクトの解決、他のMavenプラグインアーティファクトのダウンロードと解析、すべての参照の相互接続など、いくつかの手順が含まれる可能性があります。

子供レベルのpomを一人で読むことはそれをしません。

于 2012-07-17T15:03:16.430 に答える
1

「mvn help:effective-pom」が実行されると、maven ヘルプ プラグインは同様のことを行います。

http://svn.apache.org/viewvc/maven/plugins/tags/maven-help-plugin-2.1.1/src/main/java/org/apache/maven/plugins/help/EffectivePomMojo.java?viewを参照してください。 =ソースのマークアップ。

これは推移的な依存関係を示さないと思います。

mvn dependency:tree ゴールはそれを行います: http://svn.apache.org/viewvc/maven/plugins/tags/maven-dependency-plugin-2.4/src/main/java/org/apache/maven/plugin/dependency /TreeMojo.java?view=マークアップ

多分あなたは両方の混合物を作成できますか?

于 2012-07-17T15:07:19.040 に答える