JARファイルから特定のクラスを除外するAntカスタムタグ

あるプロジェクトで、ビルド時にとあるOSSのJARファイルからクラスを除外するということをやっていたが*1、余りにも面倒なやり方で行っていたのでさくっとAntのカスタムタグを作成して自動化してみた。

これまでのやり方

  • build.propertiesに除外するクラスパターンを書く
exclude.classes=org/example/Foo.class,\
                          org/example/Bar.class
  • build.xmlで上記除外リストを利用してunjarタスクで除外しつつ解凍し、再びJARファイルにパッケージングする。
	<target name="default" depends="depends" description="description">
		<unjar src="target/base.jar" dest="work">
			<patternset>
				<exclude name="${exclude.classes}" />
			</patternset>
		</unjar>
		<jar destfile="target/result.jar" basedir="work" />
	</target>

このやり方だと、差し替えたいクラスが増える度にbuild.propertiesをメンテナンスする必要がある。面倒だし、記入漏れやミスが発生することが過去何回もあった。

Antカスタムタグでの方法

そもそも除外したいクラスは別途JARファイルとしてあるので、わざわざbuild.propertiesに書かなくてもJARファイルから除外リストを自動すれば良い。というわけでAntタスククラスを作成。

使い方

  • taskdefを定義し、classpath属性にビルドしたant-tasks-ext-1.0.jarを指定する。Ant本体のJAR(ant-1.7.0.jar)も合わせて指定する。resource属性にはantlib.xmlを指定する。
  • 実際に使うところでは、excludejarタグを記述する。
    • destfile: 編集後の出力するJARファイルを指定する。
    • basefile: 編集したいJARファイルを指定する。
    • excludefile: 除外したいクラスを持つJARファイルを指定する。
    • autoclean: workディレクトリを自動削除する場合はtrueを指定する。無指定の場合はデフォルトfalse。
    • work: 作業用ディレクトリを指定する。無指定の場合は、OSのtmpディレクトリ(java.io.tmpdir)が自動的に使われる。

記述例は以下。

<?xml version="1.0" encoding="UTF-8"?>
<project name="project" default="default">

    <taskdef classpath="lib/ant-tasks-ext-1.0.jar;lib/ant-1.7.0.jar" resource="antlib.xml" />

    <target name="default">
        <excludejar destfile="target/result.jar"
            basefile="target/base.jar"
            excludefile="target/exclude.jar"
            autoclean="true"
            work="./work" />
    </target>

</project>

これでようやく除外リストのメンテナンスから解放される!!

*1:そもそも何故除外していたかいうと、一部のクラスだけ改修して別のJARファイルに格納して利用していたのだが、同名クラスが存在すると環境によってはロード順が異なり意図しない動作になるらしいとのこと。そこでAntで一度除外したいクラスを除いて解凍し、再パッケージするという運用になっていた。