Hudsonを利用してファイルI/Fを実現したい(4)

今回は、前回のエントリ(id:sikakura:20110225)の図で言うところのファイルのダウンロード
について実装検証したいと思います。

Apache Commons HttpClientで指定されたURLにアクセスし、レスポンスを保存すればファイルのダウンロードになります。
HttpResponseからEntiryを取得し、そのオブジェクトからgetContent()メソッドを呼び出すとストリーム型で返ってきます。
ストリームが取得できたら、適当なバッファ単位(例えば1024Byteごととか)でストリームを読み込み、ファイルに出力したら良さそうです。
注意点としては、HTTPでのダウンロードなので該当するページ(この場合ファイル)が無い場合でもストリームは正常に取得できます。
正常に終了したと思って、保存されたファイルの中身を見てみると、中身はブラウザで存在しないページにアクセスしたような内容のものになっています。
対応方法としては、レスポンスのステータスコードを見るようにしました。ステータスコードが200以外の場合はエラーとしています。
この部分は、もっと慎重にするなら送信側と受信側でMD5値を比較し、一致すれば正常終了するなどしたほうが良いかもしれません。
java.security.MessageDigestを使用すれば比較的簡単にMD5値が取得できるようですし。今回のサンプルでは行ってません。

urlには、"http://192.168.0.1/hudson/job/SourceJob/ws/data.csv"のような文字列を想定しています。
filenameには、"data.csv"等を想定しています。
今のコーディングでは、送信側が指定するファイル名と受信側が保存するファイル名を同じにしています。
引数にfilenameを追加しているのは、単にurlからファイル名だけ切り出すのが面倒だっただけです。。。

    boolean download(String url, String filename) {
        initialize(url);
        InputStream is = null;
        FileOutputStream fos = null;
        try {
            for (int i = 0; i < 2; i++) {
                HttpResponse response = httpclient.execute(targetHost, httppost, localcontext);
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    if (response.getStatusLine().getStatusCode() != 200)
                        throw new IOException("指定のファイル("+ filename + ")が見つかりません");
                    else
                        is = response.getEntity().getContent();
                }
            }
            byte[] buffer = new byte[1024];
            int length = 0;
            fos = new FileOutputStream(new File(filename));
            while ((length = is.read(buffer)) >= 0) {
                fos.write(buffer, 0, length);
            }
            fos.close();
            is.close();
        } catch (ClientProtocolException e) {
        } catch (IOException ioe) {
            System.err.println(ioe.getMessage());
            return false;
        } finally {
            httpclient.getConnectionManager().shutdown();
        }
        return true;
    }

コーディングしていて気づいたのですが、この仕様だとHudsonから起動するプログラムは、引数として
ファイル送信元のworkspace名とファイル名(上の例だと、"http://192.168.0.1/hudson/job/SourceJob/ws/data.csv"のSourceJobdata.csvの2つ)
現在の想定だと、送信元からJavaプログラム実行し、Hudsonジョブを起動。そのHudsonジョブに設定されているJavaプログラムがリモートで実行される
ことになるので、送信元から実行するJavaプログラムに引数で指定した値がなんとかHudsonに渡せて、その値をHudsonジョブで使用できれば良さそうです。
Hudsonにはパラメータビルドというものがあるので、これを利用することにしました。

送信元からJavaプログラムを実行し、Hudsonジョブを起動する時のURLに渡したい値をURLパラメータ形式で指定します。
変更前:http://192.168.0.1/hudson/job/IFJOB/build
変更後:http://192.168.0.1/hudson/job/IFJOB/buildWithParameters?HU_JOB=IFJOB&HU_FILE=data.csv
するとHudsonのWindowsジョブ実行のコマンドを設定するところで、%HU_JOB%や%HU_FILE%といった指定をすることで、渡されてきた値が使用できます。


ここまでで、一通りの連携とPGパーツごとの動作確認が取れました。
最後はまとめをしたいと思います。
今日はここまで。