James君!〜Mailetの開発

開発の流れ

さて、本題の Mailet の開発である。まあ、Mailet 自体を書くのはさほど難しいことではない。が、開発プロセス自体に意外な落し穴があったりするので、少し注意が必要だ。

まず、開発の流れを最初に説明しよう。

  1. James は Mailete に特定の処理をさせるべくメールの中身から「それに相当するか?」を判定するための判定器(Matcher)を持っている。だから必要に応じて、Matcher を書くか、作りつけの Matcher で大丈夫か確認する。まあ、大概の Matcher はあらかじめ用意されているので、書かないで済むことも多かろう。
  2. で、「メールに受け取ったらさせたい処理」を Mailet として書く。
  3. 書いた Matcher と Mailet が動くように、config.xml を設定する。いわゆる「パイプライン」風になっているので、少しややこしいが、後で説明する。
  4. 書いた Matcher, Mailet のクラスを jar ファイルに固める。そして、SAR-INF/lib/ ディレクトリに固めた jar ファイルを置く。
  5. そして SAR-INF/config.xml やいじらなかった他のファイルとともに、james.sar に固める。
  6. で、james.sar を実際に動かすディレクトリにコピーする。必然的に既存の james.sar を上書きすることになるな。

まあ、こんなん読む方のほとんどはプロだろう。だから、いきなり実際に James をインストールしたディレクトリで開発作業をする、なんてことはしないと思う。どこかに作業ディレクトリを作って、そこに james.sar をコピーするのが最初だろうね。この作業ディレクトリの中身はこういう風にしようか。

work -+- james.sar
      +- build -+- SAR-INF -+- config.xml
      |         |           +- environment.xml
      |         |           +- assembly.xml           
      |         |           +- lib  -+- james.jar など解凍したライブラリ
      |         |                    +- 自分で開発するライブラリ
      |         +- conf    -+- james-fetchmail.xml など
      +- build.xml
      +- src     自分で開発する分のソース
      +- classes 自分で開発する分のクラス

さて、ここでの問題は、「たとえば config.xml を修正するんだけど、その修正したものと、以前修正した実行ディレクトリの config.xml との関係は???」ということである。つまり、修正した新しい config.xml は固められて james.sar に入っていることになる。しかし、前のページの例などでは、直接実行ディレクトリの config.xml を修正したよね...あれあれ??

この回答はこうだ。phoenix は apps/ 以下にある SAR ファイルを、実行時に、work/james-ランダム数/ に解凍して使う。このとき、apps/ 以下に対応するファイルがあれば、work/james-ランダム数/ 以下には解凍して抜き出さない。ということは、次のような注意事項があるわけだな。

もし config.xml などを変更する必要があるなら、james.sar にそれを加えて jar するのと同時に、実行ディレクトリである james-2.2.0/apps/james/SAR-INF/ からそれを削除するか、あるいは変更後の内容で james.sar に加えて james-2.2.0/apps/james/SAR-INF/config.xml を上書きする必要がある。

まあ、勘のいい開発者なら??となって手が止まるところだろうけど、これに気がつかないと「変更したはずなのに変更が反映されない...」で悩み倒すことになる。気をつけてくれたまえ。

で以降の解説で書いた筆者の Matcher&Mailet のソースをここで配布する。テキトーに持っていってくれたまえ。こんなん PDS でいいぞ。

としてみると、これを使った開発環境セットアップはこんな感じになる。

localhost:~$ mkdir work   # 作業ディレクトリ
localhost:~$ cd work
localhost:~/work$ wget http://www.nurs.or.jp/~sug/soft/james/mailets.tgz
localhost:~/work$ tar xvfz mailets.tgz
localhost:~/work$ export JAMES_HOME=/usr/local/james-2.2.0  # 環境変数を設定
localhost:~/work$ cp $JAMES_HOME/apps/james.sar .
localhost:~/work$ cd build
localhost:~/work/build$ jar xvf ../james.sar
localhost:~/work/build$ cd ..
localhost:~/work$ ant package          # ./james.sar を再構築するなら...
localhost:~/work$ ant install          # $JAMES_HOME に james.sar などをインストール
localhost:~/work$ cd $JAMES_HOME
localhost:/usr/local/james-2.2.0$ bin/run.sh        # James の起動

こんなの単なる筆者の都合だが、JAMES_HOME という環境変数に、あなたが James をインストールしたパスを設定しておいてくれ。この環境変数に依存して build.xml が書かれている。

build.xml

build.xml の内容はこんなことろか。解説上面倒なので、環境変数 JAMES_HOME を利用する James のインストールディレクトリに設定しておいてくれたまえ。

<project name="james" default="compile" basedir=".">
   <property name="debug.flag" value="yes" />
   <property environment="env" />

   <property name="lib.dir"
      value="./build/SAR-INF/lib" />
   <!-- export JAMES_HOME=/usr/local/james/james-2.2.0
       とか環境変数を設定しておいてくれたかな? -->
   <property name="james.dir"
      value="${env.JAMES_HOME}" />
   <property name="james.appdir"
      value="${james.dir}/apps" />
   <property name="james.libdir"
      value="${james.dir}/lib" />

   <property name="build"
      value="./build" />
   <property name="classes"
      value="./classes" />
   <property name="src"
      value="./src" />
   

  <path id="lib.classpath">
      <pathelement path="${classes}" />
      <fileset dir="${lib.dir}">
         <include name="*.jar" />
      </fileset>      
      <fileset dir="${james.libdir}">
         <include name="*.jar" />
      </fileset>      
  </path>

  <!-- 環境変数 JAMES_HOME を設定しないとバチが当たる -->
  <target name="init" unless="env.JAMES_HOME" >
     <echo>**********************************</echo>
     <echo>* Please set Env-var: JAMES_HOME *</echo>
     <echo>**********************************</echo>
     <fail message="see above" />
  </target>

  <target name="compile" depends="init">
     <copy todir="${classes}">
        <fileset dir="${src}" includes="**/*.xml" />
	<fileset dir="${src}" includes="**/*.properties" />
     </copy>
     <javac srcdir="${src}" destdir="${classes}" 
       debug="${debug.flag}" classpathref="lib.classpath"/>
  </target>

  <!-- mymailet.jar と james.sar の両方を作る -->
  <target name="package" depends="compile" >
      <jar jarfile="${lib.dir}/mymailet.jar" basedir="${classes}" 
          includes="**/*" />
      <jar jarfile="james.sar" basedir="${build}" includes="**/*" />
  </target>

  <!-- 先ほど書いたように、config.xml などはコピーする -->
  <target name="install" depends="package">
      <copy file="james.sar" todir="${james.appdir}" />
     <copy todir="${james.appdir}/james">
        <fileset dir="${build}" includes="**/*.xml" />
     </copy>
  </target>

  <target name="clean">
     <delete>
         <fileset dir="${classes}" includes="**/*.class" />
     </delete>
  </target>
</project>



copyright by K.Sugiura, 1996-2006