Javaを使ったSDKのサンプル

SDKとは

OpenOffice.org SDKはJavaやC++、Basic、OLE、XMLなどを利用してOpenOffice.orgの機能拡張などのために使用されるツール群と900ページにも及ぶマニュアル、そしてSDKを試すためのサンプルで構成されています。 このドキュメントでは900ページも及ぶマニュアルの最初の方にある基本的なサンプルを動作させるための手引きをします。このドキュメントが示すのはJavaを利用したサンプルで、また、IDEと呼ばれる開発環境のうちの一つNetBeansを利用します。このドキュメントではNetBeansの設定も解説しています。

また、このサンプルでは特にSDKに同梱されているツールを使うわけではありませんが、Developer's guideなどの有用な情報がHTMLとPDFの2つのフォーマットで提供されていたり、今後UNOコンポーネントなどのもっと難しいことをOpenOffice.orgを利用して開発することになるとSDKのツールを利用することになります。よって、このドキュメントではSDKのインストール方法も解説します。

Developer's guideでいうところの:
このドキュメントはSDKに含まれているDeveloper's guideの"2.3 Getting Started"と"2.5 Working with Object"に相当する内容が含まれています。

また、このドキュメントの読者はWindows XPを利用していてJava(JDK)とmake、コンパイラの設定をすでに済ませているものとします。Java言語もある程度知っているものとします。NetBeansは各種Windows(NT、2000、XP)、Linuxに対応していますので、Linuxを利用していない場合は各所適宜読み替えるようにしてください。

NetBeansでなくても:
NetBeans以外のIDEを利用している方、エディタでちくちくコードを書いてjava、javacをそのたびにコマンドで打っている時代遅れな勇者はNetBeansを利用しなくてもこのサンプルを動作させることはできます。IDEを利用している方は、プログラムをコンパイル/実行するときにclasspathを設定できるようにするだけです。また、任意にJavaのソースコードからJavaコードのコード補完機能をできるようにするとなお良いでしょう。また、時代遅れな勇者はがんばってjava、javacを利用するときにいちいちclasspathを指定しなければいけなかったり、コードの補完機能を使えなかったりしますが、君たちならばそれらの問題を自分で解決する能力をもっているでしょう。よくわからなければ、NetBeansを使いましょう。

SDKのダウンロード

まずはSDKをダウンロードしましょう。OpenOffice.org SDKのページから最新バージョンをダウンロードしてください。ページの下の方にSDKがダウンロードできるミラーサーバーが示してあります。SDKをダウンロードし、解凍してください。

SDKのインストール

SDKの解凍が完了したら、次はSDKの設定をしなければいけません。解凍をしたディレクトリにある、"configureWindowsNT"というバッチファイルをダブルクリックするなどして実行してください。以下の項目について聞かれますので、適切なパスを指定してください。

パスに空白がある場合

OpenOffice.orgのインストールパスはきっと、C:\Program Files\にあることでしょう。このようにパスに空白がある場合には"(クオーテーションマーク)でそのパスを囲ってください。

これでSDKのインストールは完了です。とりあえず、SDKをインストールしたディレクトリにあるindex.htmlを見てみましょう。900ページにも及ぶDeveloper's guideとIDL, UNO, C++のリファレンスがあることが確認できます。また、SDKに含まれているSDKを利用した例(Examples)に関する解説があります。上述のとおりSDKをインストールすると、Examplesに書かれたほとんどの例を実行することができます。ぜひとも各種Examplesを実行して遊んでみるのもよいでしょう。
また、この先はDeveloper's guideの第2章のほんのさわりの部分にある、コード例を実行するように手引きをしますが、できるならばオリジナルのDeveloper's guideを読みながらUNOなどに関する知識を、時間をかけて習得してください。900ページもあるドキュメントを読破したときには、きっとあなたは優秀な開発者として認められるでしょう。

NetBeansのダウンロードとインストール

次はNetBeansのダウンロードです。別のIDEを使う人はこの項目を読み飛ばしてください。どのIDEを使っていても必要な設定はOpenOffice.orgをインストールしたディレクトリにあるprogram/classes以下の各種jarアーカイブをクラスパスとして設定することだけです。NetBeansを利用する方は、このあとでクラスパスにそのjarファイルを追加する方法を解説します。

まず、NetBeansからNetBeansの日本語版をダウンロードしてください。このページの右上に小さく"Download"と書いてありますので、そこをまずクリック。クリックした先のページでIDEのダウンロードとありますので。NetBeansをダウンロードしてください。
ダウンロードのページにはOpenOffice.orgが紹介されています。あ、そういえば、OpenOffice.orgは当然インストールしてありますよね?

NetBeansのアーカイブをダウンロードし、解凍したら、解凍したディレクトリにあるbinディレクトリ、さらにそのなかにあるrunideをダブルクリックしてください。これでNetBeansが起動します。いくつか質問をされるので、適切に答えてNetBeansのインストールを完了させてください。

NetBeansの設定

NetBeansの設定をしましょう。NetBeansにはプロジェクト管理機能とコード補完機能がありますので、これらOpenOffice.org SDKでも使えるように設定します。

プロジェクトの設定

NetBeansを起動したらば、まずメニューから「プロジェクト」-「プロジェクトマネージャ」を選択し、表示されたプロジェクトマネージャダイアログで「新規」ボタンをクリックしてください。新規プロジェクト名を尋ねられますので、適当に"OpenOffice"とでもしてOKボタンを押してください。

ソースコード補完機能の設定

ソースコード補完機能を利用するには、まず、エクスプローラに唯一りストされている「ファイルシステム」を右クリックし、「マウント」-「アーカイブ(JAR, Zip)」を選択してください。アーカイブを選択するダイアログがでてきますので、ここでOpenOffice.orgをインストールしたディレクトリにある、program\classesディレクトリにある全jarファイルを選択して「完了」をクリックしてください。これでエクスプローラーにいくつかのjarファイルが表示されるようになりました。
また、このマウントという作業によってJavaコンパイル/実行をする際に自動てきにこれらのjarファイルをクラスパスとして設定してくれます。

次にこれらのjarファイルのソースコードからソースコード補完に必要な情報を取得します。エクスプローラーに表示されたすべてのjarファイルを選択し、「ツール」-「構文解析データベースの更新」をメニューから選択してください。各ファイルごとに構文解析データベースを更新するためのダイアログが表示されます、それぞれ「構文解析データベースファイルの接頭辞」に適当なオリジナルな値を設定して了解ボタンを押してください。すべてのjarファイルについて設定が終われば、コード補完機能に関する設定は終了です。

OpenOffice.orgと通信をする

IDEの設定が完了したら、あとは実際にソースコードを書いてみて実行するだけです。

OpenOffice.orgを通信できるように起動する

その前にOpenOffice.orgをTCP/IPで通信できるように設定しましょう。ただし、これには2通りの方法があります。ここでは両方解説しますが、方法1では直接設定ファイルを書き換えてOpenOffice.orgを普通に起動する方法を説明し、方法2では設定ファイルをいじらずにOpenOffice.orgを起動する際に特別な引数を与える方法を説明しています。
前者の方は、一度設定をしてしまえば、いちいちOpenOffice.orgを起動する際に引数を設定しなくても済むことになりますが、設定ファイルをいじるのが不安な方には後者の方法をとることをお薦めします。

方法1

まず、OpenOffice.orgをインストールしたディレクトリから/share/config/registry/instance/org/openoffice/Setup.xmlというファイルを編集します。

<ooSetupConnectiknoURL cfg:type="string"/>

という記述がありますので、これを

<ooSetupConnectionURL cfg:type="string">socket,port=8100;urp;</ooSetupConnectionURL>

というように書き換えてください。これであとは普通にOpenOffice.orgを起動するだけです。

方法2

OpenOffice.orgを起動する際に引数を与えます。まず、Windowsの「スタート」メニューから「ファイル名を指定して実行」を選択してください。ここで、名前にOpenOffice.orgの実行ファイル"soffice.exe"をまず指定します。そして、そのあとに空白を入れてから"-accept=socket,port=8100;urp;"と入力してください。だいたい以下のようになります。

C:\Program Files\OpenOffice.org1.0.1\program\soffice "-accept=socket,port=8100;urp;"

入力が終えたら、「OK」を押してください。これでOpenOffice.orgが起動します。

Javaの設定:
OpenOffice.orgが起動したら、「ツール」-「オプション」-「OpenOffice.org」-「セキュリティ」-「Java」-「使用する」にチェックが入っていることを確認してください。チェックが入っていない場合はチェックして、「OK」ボタンを押してください。

最初の通信

OpenOffice.orgは立ち上がりましたか?とりあえず、まずはOpenOffice.orgは起動させたまま放っておいて、実際にOpenOffice.orgと通信をするためのJavaのコードを書いてみましょう。

NetBeansを使っている方は、まずファイルシステムにこれから書くソースコードを保存するディレクトリをマウントします。エクスプローラで「ファイルシステム」を右クリックし、「マウント」-「ローカルディレクトリ」を選択してください。ここでこれから書くソースコードを保存するディレクトリを選択して「完了」を押してください。

エクスプローラには、指定したディレクトリの名前がついた新しい項目が追加されたはずです。次にこの項目を右クリックし、「新規」-「Classes」-「Main」を選択してください。新規オブジェクト名には"FirstConnection"を指定し、あとの設定は不要ですのでそのまま「完了」ボタンをクリックしてください。これでmainメソッドが記述されたテンプレートが、新規ソースコードとして作成されました。ちょっとだけコードを書く手間が省けましたね。

そしたら、さきほど自動生成したFirstConnection.javaにコードを書きます。が、最初から長ったらしいコードです。ソースコードの補完機能をうまく利用して、根気強く以下のようなソースコードを書いてください。(コピペはダメ ;) )


import com.sun.star.bridge.XUnoUrlResolver;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.beans.XPropertySet;

public class FirstConnection extends java.lang.Object {

    private XComponentContext xRemoteContext = null;
    private XMultiComponentFactory xRemoteServiceManager = null;
    
    public static void main(String[] args) {
        FirstConnection firstConnection1 = new FirstConnection();
        try {
            firstConnection1.useConnection();
        }
        catch (java.lang.Exception e){
            e.printStackTrace();
        }
        finally {
            System.exit(0);
;   "uno:socket,host=localhost,port=8100;urp;StarOffice.ServiceManager"); 
             }
    }
    
    protected void useConnection() throws java.lang.Exception {
        try {
            xRemoteServiceManager = this.getRemoteServiceManager(
                    "uno:socket,host=localhost,port=8100;urp;StarOffice.ServiceManager"); 
            String available = (null != xRemoteServiceManager ? "available" : "not available");
            System.out.println( "remote ServiceManager is " + available );
            //サービスマネージャーとなにかするにはここにコードを書く
        }
        catch( com.sun.star.connection.NoConnectException e )
        {
                System.err.println( "No process listening on the resource" );
                e.printStackTrace();
                throw e;
        }
        catch( com.sun.star.lang.DisposedException e ) { //works from Patch 1
            xRemoteContext = null;
            throw e;
        }          
    }
    
    protected XMultiComponentFactory getRemoteServiceManager(String unoUrl) throws java.lang.Exception { 
        if (xRemoteContext == null) {
            //ステップ1: ローカルにコンポーネントコンテキストを作成し、ローカルのサービスマネージャを取得
            //サービスマネージャにXUnoUrlResolverインターフェースを利用してUnoUrlResolverオブジェクトを作らせる
            XComponentContext xLocalContext =
                com.sun.star.comp.helper.Bootstrap.createInitialComponentContext(null);
            XMultiComponentFactory xLocalServiceManager = xLocalContext.getServiceManager();
            Object urlResolver  = xLocalServiceManager.createInstanceWithContext( 
                "com.sun.star.bridge.UnoUrlResolver", xLocalContext );
            //urlResolverオブジェクトからXUnoUrlResolverインターフェースを取得
            XUnoUrlResolver xUnoUrlResolver = (XUnoUrlResolver) UnoRuntime.queryInterface( 
                XUnoUrlResolver.class, urlResolver );
            //ステップ2: リモートサービスマネージャを呼び出すためにxUrlResolverインターフェースを使用し、
            //DefaultContextプロパティを検索、そしてリモートサービスマネージャを取得
            Object initialObject = xUnoUrlResolver.resolve( unoUrl );
            XPropertySet xPropertySet = (XPropertySet)UnoRuntime.queryInterface(
                XPropertySet.class, initialObject);
            Object context = xPropertySet.getPropertyValue("DefaultContext");  
          
            xRemoteContext = (XComponentContext)UnoRuntime.queryInterface(
                XComponentContext.class, context);
        }
        return xRemoteContext.getServiceManager();
    }
}

ソースコードが書けたら、メニューより「構築」-「コンパイル」でコンパイルをし、コンパイルが問題なく完了したら「構築」-「実行」として実行してみてください。ここで、OpenOffice.orgとうまく通信ができていると"remote ServiceManager is available"と表示されるはずです。これはOpenOffice.orgと正常に通信ができたという証拠です。試しにOpenOffice.orgを終了させて、再びこのプログラムを実行すると"No process listening on the resource"と表示されることが確認できます。

表計算ソフトを遠隔操作

前述のサンプルだけでは、本当にOpenOffice.orgと通信ができたのかどうか疑わしく思うでしょう。そこで、この章ではDeverloper's guide 2.5.2 "Example: Working with a Spreadsheet Document"で示されているサンプルを動かして、OpenOffice.orgを遠隔操作しているという実感を味わうことにしましょう。

Developer's guideではFirstLoadComponentという新しいクラスを作成して例を示していますが、ここでは面倒なので、前章のコードを引き続きいじるようにしましょう。

それではまず、ファイルの冒頭import文の固まりに、さらに以下のimport文を追加してください。

import com.sun.star.beans.PropertyValue;
import com.sun.star.lang.XComponent;
import com.sun.star.sheet.XSpreadsheetDocument;
import com.sun.star.sheet.XSpreadsheets;
import com.sun.star.sheet.XSpreadsheet;
import com.sun.star.sheet.XSpreadsheetView;
import com.sun.star.table.XCell;
import com.sun.star.frame.XModel;
import com.sun.star.frame.XController;
import com.sun.star.frame.XComponentLoader;

次にuseConnectionメソッドを以下のように書き換えてください。

protected void useConnection() throws java.lang.Exception {
    try {
        xRemoteServiceManager = this.getRemoteServiceManager(
                "uno:socket,host=localhost,port=8100;urp;StarOffice.ServiceManager"); 
        //新しいドキュメントを作成するためにはDesktopのXComponentLoaderインターフェースが必要なのでDesktopを取得します
        Object desktop = xRemoteServiceManager.createInstanceWithContext(
            "com.sun.star.frame.Desktop", xRemoteContext);

        //DesktopからXComponentLoaderインターフェースを取得
        XComponentLoader xComponentLoader = (XComponentLoader)UnoRuntime.queryInterface(
            XComponentLoader.class, desktop);
        //loadComponentFromURLメソッドを呼び出すのに必要なPropertyValue構造体の配列を作成
        PropertyValue[] loadProps = new PropertyValue[0];

        //新しいCalcファイルを作成
        XComponent xSpreadsheetComponent = xComponentLoader.loadComponentFromURL(
            "private:factory/scalc", "_blank", 0, loadProps);
        //getSheet()を使いたいので、XSpreadsheetDocumentインターフェースを取得
        XSpreadsheetDocument xSpreadsheetDocument = (XSpreadsheetDocument)UnoRuntime.queryInterface(
            XSpreadsheetDocument.class, xSpreadsheetComponent);
        //getSheetsメソッドでシートのコンテナを取得
        XSpreadsheets xSpreadsheets = xSpreadsheetDocument.getSheets();
        //新しいシートを0という位置に挿入し、シート名でそのシートオブジェクトを取得、さらにそのオブジェクトからXSpreadインターフェースを取得
        xSpreadsheets.insertNewByName("MySheet", (short)0);
        Object sheet = xSpreadsheets.getByName("MySheet");
        XSpreadsheet xSpreadsheet = (XSpreadsheet)UnoRuntime.queryInterface(
            XSpreadsheet.class, sheet);
        //XSpreadsheetインターフェースを使用して、0,0に位置するA1セルを取得、同セルに21を入力
        XCell xCell = xSpreadsheet.getCellByPosition(0, 0);
        xCell.setValue(21);
        //0,1にあるA2にも値を入力
        xCell = xSpreadsheet.getCellByPosition(0, 1);
        xCell.setValue(21);
        //2つのセルの総計
        xCell = xSpreadsheet.getCellByPosition(0, 2);
        xCell.setFormula("=sum(A1:A2)");
        //セルのプロパティCellStyleにアクセスするためにXPropertySetインターフェースを取得
        XPropertySet xCellProps = (XPropertySet)UnoRuntime.queryInterface(
            XPropertySet.class, xCell);
        //数式に"Result"セルスタイルを割り当て
        xCellProps.setPropertyValue("CellStyle", "Result");
        //新しく作成したシートをアクティブなシートにしたいので、モデルからコントローラーを取得する必要があります
        //まず、シートコンポーネントからXModelインターフェースを取得
        XModel xSpreadsheetModel = (XModel)UnoRuntime.queryInterface(
           XModel.class, xSpreadsheetComponent);

        //そしてモデルから現在アクティブなコントローラーを取得
        XController xSpreadsheetController = xSpreadsheetModel.getCurrentController();
        //setActiveSheetメソッドを呼び出したいのでXSpreadViewインターフェースをそのコントローラーから取得
        XSpreadsheetView xSpreadsheetView = (XSpreadsheetView)UnoRuntime.queryInterface(
           XSpreadsheetView.class, xSpreadsheetController);
        //setActiveSheetメソッドで新しく作成したシートをアクティブシートにします
        xSpreadsheetView.setActiveSheet(xSpreadsheet);     
    }
    catch( com.sun.star.lang.DisposedException e ) { //works from Patch 1
        xRemoteContext = null;
        throw e;
    }          
}

そして、再びコンパイルして実行すると、OpenOffice.orgが勝手に表計算ソフトを立ち上げ、勝手にシートを開いて、勝手にA1とA2に"21"を入力、勝手にA3にA1とA2を足す数式が入力され、勝手にResultスタイルが適用されて斜体に下線が引かれます。

以上がSDKと一緒に配布されたDeveloper's guideの最初の2つのサンプルコードでした。よりOpenOffice.orgについて知りたい人、UNOについて勉強したい人、OpenOffice.orgに追加機能をつけてみたい人、StarBasicでは満足しない人は、このあとDeveloper's guideを呼んでみることをお薦めします。また、SDKやDeveloper's guide、UNOや各種APIに関する議論はdev@api.openoffice.orgメーリングリスト(英語)で行われています。このメーリングリストに参加するにはdev-subscribe@api.openoffice.orgに空のメールを送るだけです。ぜひ、みなさんもメーリングリストに参加し、OpenOffice.orgにあんな機能やこんな機能をつけてみましょう ;)


制作者:中本崇志
デザイン:小浦寛裕
$Id: sdksample.html,v 1.2 2003/12/30 01:02:14 maho Exp $