最終回 プラグインを配布してみんなに使ってもらおう


萩原 巧
リトルソフト株式会社
2006/12/13


HSQLDBを起動するために必須プラグインを使う

 HSQLDB起動、停止ダイアログの表示ができた田中君。続いては、選択したHSQLDBの起動処理を行う。

長尾君 「やっと、ここまで来たね。これからは先ほどのHSQLDB起動ダイアログで選択したHSQLDBの起動処理を実装しよう」

 HSQLDBにはいくつかの動作モードがありますが、このプラグインでは一般的な「HSQLDBサーバモード(Hsqldb Server)」()で起動を行います。

コラム 起動モードとは
HSQLDBは利用形態によって、各種動作モードを選択することができます。

サーバモード
  • HSQLDBサーバ(Hsqldb Server):最も一般的なモード。ほかのDBと同じようにサーバを起動し動作します
  • Hsqldbウェブサーバ(HsqldbWebServer):HTTPプロトコルで接続が可能なサーバとして動作します。
スタンドアロンモード
  • プロセス(In-Process):クライアントアプリケーションと同じVMで動作します。
  • メモリデータベース(Memory-Only Databases):プロセスモードでデータを含むデータベースをメモリ上で動作します。
詳しくは、HSQLDBドキュメントをご覧ください。

 動作のイメージとしては、Eclipseから新たにJavaシステムプロセス(VM)を起動して、その上で指定したHSQLDBが起動します。

動作イメージ

長尾君 「クラスを作成する前に、プラグイン設定ファイル[plugin.xml]の[依存関係]タブを開いて、必須プラグインに[org.eclipse.debug.core][org.eclipse.jdt.launching][org.eclipse.ui.console][org.eclipse.core.resources]の4つを追加しよう」
編集部注必須プラグインの概念や追加方法については連載2回目の[Eclipseの機能を拡張しよう]をご覧ください。
plugin.xmlを開き、必須プラグインを4つ追加

長尾君 「これから作成するHSQLDBの起動、停止やHSQLDBの動作状況をコンソールに表示するために、これらのプラグインは必要なんだ。続いて、HSQLDBが起動や停止を制御するクラスを作成しよう」

項目名称 内容
パッケージ hsqldb.util]と設定してください
名前(クラス名) HSQLDBInvoker]と設定してください
スーパークラス なし

長尾君 「このクラスでは、HSQLDBの起動、停止コマンドをEclipse上から実行し、その状態をコンソールで確認することができるんだ。起動、停止のコマンドイメージは次のとおりだよ」

起動コマンド

java -classpath [ライブラリのパス]\hsqldb.jar org.hsqldb.Server -database [データベースパス+データベース名] -port[ポート番号] -silent(※) false

 (※)silentモードがfalseの場合、起動時のステータスや実行したSQL等をコンソールに表示することができます。
停止コマンド

java -classpath [ライブラリのパス]\hsqldb.jar org.hsqldb.util.ShutdownServer -database [データベースパス+データベース名] -port[ポート番号] ?shutdownarg IMMEDIATELY


田中君 「上記コマンドをEclipseから実行していると考えればいいんだね」

HSQLDB起動、停止メソッドの作成

  作成した[HSQLDBInvoker]クラスに、起動、停止メソッドを以下のように実装します。難解な内容がありますが、ご了承ください。

HSQLDB起動、停止メソッド
    private static String fsep = java.io.File.separator;

    public void launchHSQLDB(boolean isStart, String name
                           , String path, String port)
    throws Exception{                                  //(1)

        // クラスパスの取得と設定
        String jarPath = new File(Platform.resolve(        
            HSQLDBPlugin.getDefault().getBundle()
            .getEntry(fsep)).getPath())
                                   .getAbsolutePath(); //(2)
        jarPath += fsep + "lib" + fsep + "hsqldb.jar";

        // アプリケーション引数(オプション)の設定
        String[] classpath = {jarPath};                //(3)
        ArrayList argList
           = setupProgramArguments(name, path, port);  //(4)
        VMRunnerConfiguration vmConfig = null;
        
        //実行クラス、クラスパスおよび
        //引数(オプション)のセット
        if (isStart){
            vmConfig = new VMRunnerConfiguration(
                "org.hsqldb.Server", classpath);       //(6)
            argList.add("-silent");                    //(7)
            argList.add("false");
        } else {
            vmConfig = new VMRunnerConfiguration(
                        "org.hsqldb.util.ShutdownServer"
                                          ,classpath); //(8)
            argList.add("-shutdownarg");               //(9)
            argList.add("IMMEDIATELY");
        }

        // argListをvmConfigに設定
        vmConfig.setProgramArguments(
            (String[])argList.toArray(
               new String[argList.size()]));          //(10)

        ILaunchConfigurationType launchType = DebugPlugin
            .getDefault().getLaunchManager()
            .getLaunchConfigurationType(
        "org.eclipse.jdt.launching.localJavaApplication");
                                                      //(11)

        org.eclipse.debug.core.Launch launch
            = new Launch(launchType.newInstance(null
            , "HSQLDB launch"),ILaunchManager.RUN_MODE
                                             , null); //(12)

        IVMRunner vmRunner = JavaRuntime.getDefaultVMInstall()
            .getVMRunner(ILaunchManager.RUN_MODE);    //(13)
        vmRunner.run(vmConfig, launch, null);         //(14)
    }

    private ArrayList setupProgramArguments(String name
                                       , String path
                                       , String port){//(5)
        ArrayList list = new ArrayList();
        list.add("-database");
        list.add(path + fsep + name);
        list.add("-port");
        list.add(port);
        return list;
    }

 (1):起動、停止メソッド[launchHSQLDB]の引数には、起動するHSQLDB [name]、HSQLDBパス[path]、ポートおよび[port]、起動、停止[isStart]を判断する変数を設定します。

 (2)、(3):hsqldb.jarのパスを設定します。(2)の記述により、起動中のプラグインのパスを取得することができます。

 (4)、(5):[setupProgramArguments] メソッドにて、[launchHSQLDB]の引数として渡されたHSQLDB名称、HSQLDBパス、ポートをArrayList に設定を行います。

 (6):JavaVMが起動するために必要な設定を管理する[VMRunnerConfiguration]クラスに対し、(3)で設定したhsqldb.jarのパスとHSQLDB起動クラス[org.hsqldb.Server]を設定します。

 (7):起動オプションとして、-silent、false を追加します。

 (8):停止する場合は、[VMRunnerConfiguration]クラスに対し、(3)で設定したhsqldb.jarのパスとHSQLDB停止クラス[org.hsqldb.util.ShutdownServer]を設定します。

 (9):停止オプションとして、-shutdownarg IMMEDIATELYを追加します。

 (10):argListに設定した各種アプリケーション引数(オプション)を[VMRunnerConfiguration]クラスに設定します。

 (11)、(12):vmから起動を行うタイプ[launchType]の取得を行い、起動用オブジェクト[launch]を生成します。

 (13):Eclipseで使用しているデフォルトのJavaVM(JavaRuntime.getDefaultVMInstall())を取得し、起動用オブジェクト[vmRunner]を生成します。

 (14):(13)で生成した[vmRunner]の[run]メソッドにて、HSQLDBの起動、停止を行います。

田中君 「……。このソースは、ちょっと難しいなぁ」
長尾君 「確かにこれはいままでで一番分かりにくいソースだね。以前にもいったけど、Eclipseが持っているAPIをうまく活用して、実現させたい機能を実装することが大事だよ。そのためには、APIドキュメントや各種資料をよく読んで少しでも理解を深めていってほしいな。起動クラスを作成したら、HSQLDBに起動や停止処理を実装するよ。[HSQLStartAction]、[HSQLStopAction]の[run]メソッドに以下の処理を追加しよう」

[HSQLStartAction]クラスのrunメソッド
    public void run(IAction action) {
        try{
            final HSQLActionDialog dlg
                = new HSQLActionDialog(null
                           ,"HSQLDB 起動ダイアログ"); // (1)
            if (dlg.open() == Dialog.OK){
                String name = dlg .getDBName();    // 追加部分
                String path = dlg .getDBPath();
                String port = dlg .getDBPort();
                HSQLDBInvoker inv = new HSQLDBInvoker();
                // [HSQLStopAction]クラスの場合、
                // 第1引数はfalseになります。
                inv.launchHSQLDB(true,name,path,port);

            }
        } catch(Exception e){
            MessageDialog.openInformation( null,"HSQLDBPlugin"
            , "HSQLDB 起動処理中にエラーが発生しました。\n"
                                            + e.getMessage());
        }
    }

長尾君 追加部分では、先ほど作成した[HSQLDBInvoker]クラスのインスタンス化を行い、[launchHSQLDB]メソッドを実行しているんだ、引数にはHSQLDB起動ダイアログで選択したデータベースの名称、パス、ポートを設定しているよ。ここまでできたら、動作の確認をしよう」

 田中君は動作の確認を行った。

起動しても、コンソールにステータスが表示されない

田中君 「あれ? コンソールに何も表示されないね。これじゃ、ちゃんと動いているか分からないや」
長尾君 「正しくコーディングがされていれば、HSQLDBは起動しているはずだけど、コンソールに出力する部分の実装は、あえてまだ行っていないから、この結果でも正しいよ。HSQLDBが起動したか気になるなら、HSQLDatabaseManagerから起動を確認してみてもいいね」

 田中君はHSQLDatabaseManagerから、HSQLDBが正しく起動できることを確認した。

長尾君 「HSQLDBが起動できたね。では、最後の実装を行おう。コンソールにHSQLDBの状態を出力できるように[HSQLDBInvoker]クラスのソースを追加しよう」

[HSQLDBInvoker]クラスに追加 (赤字部分
    private static String fsep = java.io.File.separator;

    // メッセージコンソールのフィールド
    private MessageConsole console = null;
    // メッセージコンソールのデータストリーム
    private MessageConsoleStream stream = null;

    /* StreamListenerを定義し、
        テキストをメッセージコンソールに表示する */
    IStreamListener streamListener = new IStreamListener() {
         //ストリームにテキストが追加されたら
         //実行されるメソッド
         public void streamAppended(String text
                                 , IStreamMonitor monitor) {
              MessageConsoleStream streamOut = stream;
              if (streamOut != null) {
                   // テキストをコンソールに表示
                   streamOut.print(text);
              }
         }
    };


    public void launchHSQLDB(boolean isStart, String name
                           , String path, String port)
    throws Exception{
        String jarPath
            = new File(Platform.resolve(HSQLDBPlugin
            .getDefault().getBundle().getEntry(fsep))
            .getPath()).getAbsolutePath();
        jarPath += fsep + "lib" + fsep + "hsqldb.jar";
        String[] classpath = {jarPath};
        ArrayList argList = setupProgramArguments(name
                                                , path, port);

        VMRunnerConfiguration vmConfig = null;
        if (isStart){
            vmConfig = new VMRunnerConfiguration(
                              "org.hsqldb.Server", classpath);
            argList.add("-silent");
            argList.add("false");

            // コンソールのキャプション
            console = new MessageConsole(
                "HSQLDB [" + name + "] " + path + " -" + port
                                                      , null);
            stream = console.newMessageStream();

            // コンソールの文字色を設定
            stream.setColor(new Color(HSQLDBPlugin
                .getDefault().getWorkbench().getDisplay()
                                                , 0, 0, 128));

            // コンソールマネージャを取得
            IConsoleManager manager = ConsolePlugin
                           .getDefault().getConsoleManager();

            // コンソールマネージャにコンソールを追加する
            manager.addConsoles(new IConsole[] {console});

            // 追加したコンソールを表示する
            manager.showConsoleView(console);
 
       } else {
            vmConfig = new VMRunnerConfiguration(
                "org.hsqldb.util.ShutdownServer", classpath);
            argList.add("-shutdownarg");
            argList.add("IMMEDIATELY");
        }
        vmConfig.setProgramArguments((String[])argList
                        .toArray(new String[argList.size()]));

        ILaunchConfigurationType launchType
            = DebugPlugin.getDefault().getLaunchManager()
           .getLaunchConfigurationType(
           "org.eclipse.jdt.launching.localJavaApplication");

        org.eclipse.debug.core.Launch launch
           = new Launch(launchType.newInstance(null
           , "HSQLDB launch"), ILaunchManager.RUN_MODE, null);

        IVMRunner vmRunner = JavaRuntime.getDefaultVMInstall()
           .getVMRunner(ILaunchManager.RUN_MODE);
        vmRunner.run(vmConfig, launch, null);

        // 起動したプロセス(HSQLDB)のOutputStreamMonitor、
        //ErrorStreamMonitorにstreamListenerを設定する
        launch.getProcesses()[0].getStreamsProxy()
            .getOutputStreamMonitor()
            .addListener(streamListener);
        launch.getProcesses()[0].getStreamsProxy()
            .getErrorStreamMonitor()
            .addListener(streamListener);
    }
編集部注:紙幅の都合上、詳しい説明は割愛しますが、上記実装により、HSQLDBの動作状況や実行したSQL文などがEclipseのコンソールに表示されます。

 田中君は動作の確認を行い、HSQLDBの起動、HSQLDBのコンソールが正しく表示されることを確認した。

HSQLDBのステータスがコンソールに表示される

長尾君 「本当にお疲れさま。これですべての実装が終わったよ」
田中君 「そうだね、振り返ってみると多くのクラスを実装したね。大変だったけど、楽しかったよ」
長尾君 「そういってくれると、教えたかいがあったかな……。ここからは田中君が完成させたHSQLDBプラグインを配布できるようにしよう」

2/3

Index
第6回 プラグインを配布してみんなに使ってもらおう
Page1
HSQLDB起動、停止ダイアログの作成
HSQLDB起動、停止ダイアログの表示
HSQLDatabaseManager起動処理の作成
Page2
HSQLDBを起動するために必須プラグインを使う
HSQLDB起動、停止メソッドの作成
Page3
作ったプラグインをみんなに配布しよう!
おわりに ― プラグインを自作する意義とは? ―



Java Solution全記事一覧



Java Agile フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Java Agile 記事ランキング

本日 月間