タイトル | JavaアプリケーションからAppleScriptのプログラムを実行する | カテゴリー | Java, AppleScript |
作成日 | 2000/9/21 2:48:38 | 作成者 | 新居雅行 |
Javaでのプログラミングで苦しむのは、Javaにない機能をどうするかということだ。もちろん、JNI(Java Native Interface)という仕組みでC/C++などで作ったライブラリを呼び出すことができるので、ライブラリを作って…と言えばそれまでだが、それはそれで大変な作業である。せっかくのJavaの心地よさも苦痛と変わってくるかもしれない。しかしながら、苦痛は少ない方がいい。また、できないこともやっぱりできた方がいい。そこで、Mac OSで稼動させるアプリケーションに限定されるが、Mac OS的な解決方法を紹介しよう。一言で言えば、JavaのアプリケーションからAppleScriptのプログラムを動かすのである。そのプログラムは、Javaのプログラムの中で文字列で作成したものを実行できるようにする。だから、固定したスクリプトではなく、プログラムで動的に組み立てたスクリプトが使えるのである。もともと、これは、筆者がJavaのプログラムで、ファイルのラベルやコメントを設定するということをしたいために作ったクラスである。JConfigなどのネイティブライブラリを含むものもあるのだが、コメントの書き込みができないなど、必要とした機能は揃っていなかった。しかしながら、やりたいことは、AppleScriptでおおむねできることは実証済みであったので、汎用的なスクリプト作成プログラムを組んでみたのである。 AppleScriptのプログラムを単に実行するのは、ポイントは簡単なのである。ToolboxにOSADoScriptという関数があって、これを呼び出せば済む。本来はコンパイルと実行を別々に行え、何度も実行するのであれば1度のコンパイルで実行をくり返すことを行えば効率的かも知れない。こちらの手法については、JShell-2000のソースを御覧になればいいだろう。今回紹介するのは、OSADoScriptを用いて、1つのToolbox関数呼び出しでスクリプトを実行するやり方である。1つ呼び出すだけだから簡単かと言えばそうでもない。まず、こうしたToolboxの呼び出しを行うために、MRJに用意されたJDirect2という仕組みを使うようにする。JDirect2を使って最終的にOSADoScriptを呼び出すようなお膳立てがまずある。次に、OSADoScriptに設定する引数や、戻り値についての処理をしなければならない。ここは、実際にはCの構造体に相当する部分の処理をJavaで書くことになり、これがまたややこしい。Cの構造体は、int型配列でつまりは自分で構築しないといけないのである。さすがに複雑であったが、実はJShell-2000のソースコードを参考にさせてもらったため、その意味ではなんとかこなせた。 なお、蛇足とは思うがPure Javaに反することは事実だ。JDirect2というMac OS荷しか存在しない機能を使うからだ。しかしながら、WindowsではAppleScript自体存在しないから、たとえJNIを使ってもクロスプラットフォーム対応にはならない。だから、Mac OSネイティブなJava機能を使って何か問題があるとは思えない。なお、MRJ環境下でも、アプレットの場合はスクリプトの実行はできない。JDirect2はアプレットからは利用できないのである。 ◇JShell-2000 http://www.vmeng.com/beard/JShell/ 作成したプログラムは、別掲の記事に掲載した。AppleScriptUtilsというクラスがそれだ。汎用的に使うことを考えてスタティックで利用をすることにした。もちろん、この内容を持ったAppleScriptUtils.javaというファイルを作って保存しておけばよい。たとえば、CodeWarriorでJavaのアプリケーションをひな形から作り、そのプロジェクトにAppleScriptUtils.javaファイルを追加すればいい。参考のために、このAppleScriptUtilsを利用した例のプログラムApplication1.javaも掲載した。 AppleScriptUtilsの使い方は極めて簡単だ。Application1.javaを見ていただきたいが、AppleScriptUtils.doScriptメソッドの引数に、AppleScriptのスクリプトプログラムをString型で指定するだけである。doScriptの戻り値は実行が成功した場合には、最後にgetした値が戻される。また、失敗したらエラーメッセージが戻される。このままだとエラーかどうかを見分けられないのであるが、そうした必要がある場合には、doScript側に手を入れてもらいたい。なお、doScript側では実行するスクリプトプログラムをコンソールに出力しているのであるが、実用面ではこれもコメントするなどしてもらいたい。 ではここで、AppleScriptUtilsクラスの説明をしよう。MRJ関連のクラスについては利用パッケージを明確にするために、importはしていない。さて、Toolboxを利用するためには、システムに存在するライブラリを呼び出すというのがPowerPC環境での基本的な手法だ。多くの関数のエントリはInterfaceLibにある。CodeWarriorでのCやC++のプログラム作成ではそのあたりは有名だろうけど、こうしたファイルが機能拡張フォルダにあるわけではないので、結局は知っていないと分からない事実だ。このInterfaceLibをロードするために、IFLibraryというインタフェースの定義を行う。これはJDirect2での決まり文句と思った方がいいだろう。さらに、OSADoScriptなど、AppleScript関連の関数のエントリは、AppleScriptLibというライブラリにある。これは機能拡張フォルダにファイルとしても存在するが、CodeWarriorのCのプログラムでこの関数を使う場合には、やはりAppleScriptLibをプロジェクトに登録しておかないといけない。このライブラリをロードするために、やはりお決まりのインタフェース定義をASLibraryという名前で行う。そして、実際にToolbox関数呼び出しを行うプログラムが含まれるクラスAppleScriptUtilsを定義する。ここでは、IFLibrary、ASLibraryのインタフェースをインプリメントする。こうすれば、JDirect2の機能を使ってAppleScriptUtilsの中で、それぞれのライブラリにある関数を利用できるのである。 AppleScriptUtilsの最初には、native宣言がある。ここでは実際に使うToolbox関数のスケルトン定義を行うわけだ。実は、OSADoScriptを使うために他にもいろいろなToolbox関数が結局必要になる。これらの関数の引数はもちろん、本来はC言語で定義されている。たとえば、CでのlongはJavaでのint、ハンドルはintの配列にするなど、読み替えて定義が必要になる。詳細は、MRJのJDirect2のドキュメントを見てもらいたい。ここでnative宣言を行えば、Javaのプログラム内でこれらの関数をメソッドとして利用できるようになるというわけだ。 OSADoScriptの使い方は、Inside Macintosh: Interapplication CommunicationのChapter 10に記載がある。久々に黒背表紙の分厚い紙の固まりのIMを引っ張り出した。ポイントは、OpenDefaultComponentによってスクリプトコンポーネントを取り出すこと、そして実行するスクリプトプログラムのテキストをディスクリプタとして記述しておき、OSADoScriptに臨むというところだろう。このあたりは、テキストとして与えるプログラムの場合はお決まりの手法だと思ってもらえるといいだろう。引数には16進数を指定したが、Cでプログラムする場合は定義定数が使える。だが、Javaだとそれは使えない。もちろん、真面目に変数定義をしてもいいのだが、ここでは読みやすさを考えて定数を直接定義した。16真数の意味(たとえば、0x54455854は実は‘TEXT’である)ということは、プログラムのコメントに記載しておいた。なおディスクリプタ化するときには、テキストへのポインタを渡す必要がある。ポインタはbyte型の配列としてJavaでは扱われるので、スクリプトのテキストをgetBytesでバイト列に変換しておく。こうして、AECreateDescでディスクリプタ化する。ここで、ディスクリプタに相当する変数であるsourceData、resultDataについては、実態はJavaのint型の配列であるが、その配列領域があたかもCの構造体のように見えないといけない。ディスクリプタは、Cのlongが2つ並んだものであるから、Javaではintが2つ並んだものとなる。これの初期化を最初にやっておくというか、「int[] sourceData = {0,0};」によって、intが2つ分のメモリ領域を確保するのである。単に「int[] sourceData;」だけなら、ポインタが用意されるだけで、構造体のデータを置く場所は確保されない。こうした初期化によって構造体のメモリ確保を行っておかないと、Toolbox関数を呼び出したときに完全にフリーズしてしまうことになる。Toolboxで使う構造体を利用する時のポイントとなるだろう。 (続く) | |
関連リンク |