S2Mai のテンプレートパスを少し指定できるように

S2Mai は手軽にメール送信メソッドを作れる、という印象。だけれども、テンプレートのパスがパッケージ込みクラス+メソッド名で固定になっているので、「運用者がテンプレートを書き換えたい」場合にはちょっとわかりづらい。
そこで、クラスパス上という制限だけはそのままに、ファイル名をメソッド単位で指定できるようにしてみた。具体的にはメソッドにアノテーションを付け、そこでファイル名(拡張子除く)を指定する形。
前提として MaiMetaDataFactory の実装および MaiMetaData の実装を作成し、s2mai.dicon および s2mai-core.dicon を別名で定義してそっちを使うようにする。ここは詳細略。MaiMetaDataFactory の方も MaiMetaData の実装インスタンスを変えるだけなので略。
作成したアノテーション

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MailTemplatePath {
    /**
     * テンプレートファイルパスの部分文字列。
     * <p>
     * クラスパスのルートから、この文字列 + "." + 拡張子を探す。
     * 先頭は "/" 無し、拡張子を除いたファイル名を指定する。
     * {@see ClassLoader#getResource(java.lang.String)}
     * </p>
     * @return テンプレートファイルパスの部分文字列。
     */
    String value();
}

MaiMetaData の実装。org.seasar.mai.meta.impl.MaiMetaDataImpl を extends して、getTemplatePath を override。あと ext が private なので別に保持するように変更。

org.seasar.mai.meta.impl.MaiMetaDataImpl の拡張
    public synchronized String getTemplatePath(Method method) {
        String path = templatePathCache.get(method);
        if (path != null) {
            return path;
        }
        MailTemplatePath annotation = method.getAnnotation(MailTemplatePath.class);
        if (annotation == null) {
            Class<?> maiClass = method.getDeclaringClass();
            path = maiClass.getName().replaceAll("\\.", "/") + "_" + method.getName() + "." + ext;
        } else {
            path = annotation.value() + "." + ext;
        }

        templatePathCache.put(method, path);

        return path;
    }

あとは XxxMai のメソッドに @MailTemplatePath("foo/bar") と書けば、クラスパスルートから foo/bar.ftl というファイルを探してテンプレートとして使用される。