さらにブリッジプログラムをマシにする

 昨日のエントリのブリッジプログラムは、異常系の処理があまりにもやっつけだったので少し改良したいと思います。具体的には、COBOL モジュールが見つからなかった場合に例外をスローするようにします。

 まず、スローする例外は以下のようにします。

package bridge;

public class CobolModuleException extends Exception {
    public CobolModuleException(String message) {
        super(message);
    }
}

 これ踏まえて、COBOL モジュールを呼び出す Java 側のプログラムは以下のようになります。

package bridge;

public class CobolBridge {
    static {
        // ライブラリのロード
        System.loadLibrary("j2cob");
    }

    /**
     * COBOL モジュールの初期化を行います。
     */
    public native void init();

    /**
     * COBOL モジュールを呼び出します。
     * 
     * @param moduleName
     *            COBOL モジュール名
     * @param parameter
     *            COBOL モジュールへのパラメータ
     * @throws CobolModuleException
     *            COBOL モジュールの呼び出しに失敗した場合
     */
    public native void callCobol(String moduleName, byte[] parameter)
           throws CobolModuleException;

	
    public static void main(String[] args) {
         CobolBridge cobolBridge = new CobolBridge();

         byte[] name = "Hoge      ".getBytes();

         cobolBridge.init();
         try {
             cobolBridge.callCobol("hello", name);
         } catch (CobolModuleException e) {
             e.printStackTrace();
         }
    }
}

 throws 宣言が追加されても C のヘッダファイルに変更はありませんので、javah を実行する必要はありません。

 C プログラムは以下のようになります。前回は単に標準エラー出力にエラーメッセージを出していましたが、今回は例外をスローするようになっています。Java 側でリファクタリングすることを考えると、本当は例外クラス名はプリプロセッサ定数にして Makefile あたりで定義した方がいいかもしれません。

#include <libcob.h>
#include "bridge_CobolBridge.h"

/* 動的 COBOL モジュールのプロトタイプ宣言 */
static int (*cobMod)(char *);

JNIEXPORT void JNICALL Java_bridge_CobolBridge_init
  (JNIEnv *env, jobject obj)
{
    /* COBOL プログラムの初期化 */
    cob_init(0, NULL);
}

JNIEXPORT void JNICALL Java_bridge_CobolBridge_callCobol
  (JNIEnv *env, jobject obj, jstring modName, jbyteArray param)
{
    /* モジュール名の取得 */
    const jbyte *mn = (*env)->GetStringUTFChars(env, modName, NULL);

    /* モジュールの取得 */
    cobMod = cob_resolve((char *)mn);

    /* モジュール名資源のリリース */
    (*env)->ReleaseStringUTFChars(env, modName, mn);

    if (cobMod == NULL) {
        /* 例外をスロー */
        jclass e = (*env)->FindClass(env, "bridge/CobolModuleException");
        (*env)->ThrowNew(env, e, cob_resolve_error());
        return;
    }
    /* 引数の配列の参照を取得 */
    jbyte *p = (*env)->GetByteArrayElements(env, param, NULL);
    /* COBOL プログラムの実行 */
    cobMod((char*)p);
    /* 資源のリリース */
    (*env)->ReleaseByteArrayElements(env, param, p, 0);
}