倭マン's BLOG

くだらない日々の日記書いてます。 たまにプログラミング関連の記事書いてます。 書いてます。

プラグインを作ろう!(14) -- プロジェクトの構成要素を扱ったプラグインのサンプル

前回、@parameter アノテーションを使用してプロジェクトの構成要素を取得する方法を見ました。 今回は、これを用いて簡単なサンプル・プラグインを作ってみましょう。

サンプルの概要は、「maven-compiler-plugin にエンコーディングが設定されていれば、それに対応する Eclipse の設定ファイルを生成する」というものにします。

サンプル


もう少し具体的にサンプル・プラグインの動作を見てみましょう。

作成するプラグイン(とゴール)の設定は以下の通り:

groupId org.sample
artifactId eclipse
version 0.1
goal generate

対象となる POM ファイルは下記のようなものです:

<project>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <encoding>UTF-8</encoding>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

この POM ファイルがあるプロジェクトのベース・フォルダ上でコマンド

mvn org.sample:eclipse:generate

を実行すると、「.setting」フォルダ(必要なら作成)下に「org.eclipse.core.resources.prefs」という名前で、内容が

#Sat Feb 09 07:48:07 JST 2008
eclipse.preferences.version=1
encoding/<project>=UTF-8

となっている(プロパティ)ファイルが生成されるようにします。

プラグイン・プロジェクトの POM ファイルと Mojo クラスの宣言


サンプル・プラグインを作成するプロジェクトの POM ファイルは以下のような感じ:

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.sample</groupId>
    <artifactId>eclipse</artifactId>
    <version>0.1</version>
    <packaging>maven-plugin</packaging>
    
    <dependencies>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-plugin-api</artifactId>
            <version>2.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-model</artifactId>
            <version>2.0</version>
        </dependency>
   </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.5</source>
          <target>1.5</target>
          <encoding>UTF-8</encoding>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

プロジェクトを構成する要素を扱うので、「maven-model」への依存性を付加しています。

また、Mojo クラスのクラス宣言はこんな感じ:

/**
 * Generate eclipse configuration files for encoding.
 *
 * @goal generate
 */
public class EncodingConfigGeneratorMojo extends AbstractMojo{
    //...
}

クラス名は適当で OK。 Mojo の中身は次節。

Mojo の実装


まず、POM ファイルの設定を読み込みましょう。

可能なら「maven-compiler-plugin」を直接取得したい所ですが、そうはできない*1ので、まず POM ファイルに設定が書かれているプラグイン(/project/build/plugins 要素下の <plugin> 要素)をリストとして取得しましょう:

/** 
 * @parameter  expression="${project.build.plugins}"
 */
private List<Plugin> plugins;

ここで、Plugin クラスは「org.apache.maven.model.Plugin」です。

次に、必要なプラグイン(今の場合「maven-compiler-plugin」)を選び出しましょう。 これには、Plugin#getKey() メソッドを使うと(少々)便利です。 このメソッドで返されるのは「groupId:artifactId」の形をした文字列(String オブジェクト)です。 今の場合「org.apache.maven.plugins:maven-compiler-plugin」となっています。

if(plugin.getKey().equals("org.apache.maven.plugins:maven-compiler-plugin")){
    //....
}

必要なプラグインが見つかったら、Plugin#getConfiguration() メソッドによって POM ファイルの <configuration> 下にある設定を取得しましょう。 ここで返されるオブジェクトは「org.codehaus.plexus.util.xml.Xpp3Dom」型です*2

Xpp3Dom config = (Xpp3Dom)plugin.getConfiguration();

以上のことを実装すると、Mojo クラスは以下のようになります:

public class EncodingConfigGeneratorMojo extends AbstractMojo{

    /** @parameter  expression="${project.build.plugins}" */
    private List<Plugin> plugins;

    private Xpp3Dom compilerConfig;

    public void execute()throws MojoExecutionException{
        this.compilerConfig = getCompilerPluginConfig();
        
        if(this.compilerConfig != null)
            generateEncodingConfig();
    }

    private Xpp3Dom getCompilerPluginConfig(){
        
        for(final Plugin plugin: this.plugins){
            if(plugin.getKey().equals("org.apache.maven.plugins:maven-compiler-plugin")){
                Object obj = plugin.getConfiguration();
                if(obj != null)
                    return (Xpp3Dom)obj;
                else
                    return null;
            }
        }
        return null;
    }

    generateEncodingConfig(){
        //...
    }
}

メソッド generateEncodingConfig() の実装は面倒になったのでやめます。

Xpp3dom を扱う際の注意


Xpp3dom を使う際、文字列リテラルの中であっても日本語が入っていると例外が発生するようです(さすがにコメント内は大丈夫ですが)。 コンパイル・エラーが出ていないのに、なぜかプラグイン・プロジェクトをローカル・リポジトリへインストールすることができませんでした。 以前の記事でも少し書きましたが、「xpp3」と名の付くライブラリは日本語を使う際には注意が必要ダス。

*1:できるかもしれませんが、やり方が分からん。

*2:Xpp3Dom は、名前の通り Dom っぽい API を備えたクラスですが、DOM に比べてかなり簡略化されていて、メソッド名を見るだけで何ができるかすぐに分かると思います。 JavaDocこちら