タイトルJava Watch on the X》3 - 今度こそ「JavaからAppleScript」を実行する(1)カテゴリーAppleScript, Java Watch on the X
作成日2001/11/28 17:10:15作成者新居雅行
【MDOnline読者様限定コンテンツ】
前回のJava Watch on the Xでは、さっそく“最後の手段”としてのAppleScriptを実行する方法を、さっそうと紹介しようとしたが、なぜかJDirectでOSA関連のAPIをたたく方法ではきちんどスクリプトが動作しなかった。そのリベンジということで、きちんと動くAppleScriptの実行クラスを作成したので、それを紹介しよう。ポイントは、Mac OS Xに用意されているosascriptというコマンドを使うことだ。このコマンドを呼び出すクラスを作成した。もちろん、Mac OS Xでないと利用できないクラスになる点は注意してもらいたい。Mac OS 8/9でも使えないし、WindowsやLinuxでもだめだ。もっとも、後者のOSはAppleScript自体が動かない…。

プログラムのポイントは、単に外部のプロセスを呼び出し、そこで標準入出力や診断入出力をどうするのかといった点だけである。まずは、サンプルプログラムをダウンロードしておいてもらいたい。Mac OS X 10.1のDeveloper Toolsで利用可能なプロジェクトファイルが含まれている。

◇サンプルプログラム:MDOnline_03_DoAppleScript
 http://mdonline.jp/figs/01/0041/MDOnline_03_DoAppleScript.sit

ソースファイルは3つだが、AboutBox.javaとMDOnline_03_DoAppleScript.javaは、プロジェクトを新たに作成するとき、「Swing Application」をテンプレートとして選択して表示されるものだ。なお、AppleScriptの実行テストを行うために、MDOnline_03_DoAppleScript.javaにはプログラムを追加しているが、このクラスのコンストラクタの後半にそれらがある。どこに追加したのか分かるようにはしておいてあるので、ソースを御覧いただきたい。プログラムとしては、paintメソッドでdrawStringで文字をでっかく書くのをやめて、BorderLayoutにしてウインドウいっぱいにJTextAreaを配置し、そこで文字列を表示できるようにしている。
そして、実際にAppleScriptを実行するクラスはAppleScriptRunner.javaに定義してある。そのクラスのドキュメントだけ、オンラインで参照できるようにしておいた。(前記のサンプルプログラムのディレクトリにも入っている)

◇AppleScriptRunnerクラス
 http://mdonline.jp/figs/01/0041/AppleScriptRunner.html

こうしたクラスを作成するとき、どこまで汎用的に作るかということはなかなか難しいところであるが、ある程度の分かりやすさと汎用性を兼ね備えて作ったつもりである。そのため、staticなクラスとした。メインとなるのは、doScriptメソッドである。staticなメソッドであるため、

AppleScriptRunner.doScript(".....");

で呼び出すことで、引数に文字列で指定したAppleScriptのプログラムを実行する。スクリプト編集プログラム(Script Editor)を使って実行したときには、実行後に「結果」ウインドウで、resultの値が得られるが、このdoScriptでは、その結果は戻り値のテキストとして得られる。テキストなので、戻り値自体が参照の場合などでは後処理も必要かもしれないが、スクリプトによる情報の取得結果などは基本的には得られるところだ。
スクリプトの実行でエラーがあったら、getErrorMessageメソッドでそのエラーを文字列として取得できる。逆に、エラーがあったかどうかは、getErrorMessageの戻り値で判断するしかない。エラーがなければnullとなる。このgetErrorMessageメソッドもstaticなので、

AppleScriptRunner.getErrorMessage()

と利用すればいい。なお、スクリプトでのエラーがあった場合も例外を発生させるという方が考え様によっては便利なときもあるだろう。そのときは、ソースを修正して使っていただければかまわない。
デバッグ用に用意したのが、setPrintScriptメソッドでこれもstaticだ。この引数にtrueを与えて呼び出すと、doScriptのメソッド内で、スクリプトの実行を行う前に実行するスクリプトを標準出力に書き出す。思った通りのスクリプトプログラムとなっているかを確認できるという具合だ。
実際にさまざまなスクリプトを作るようになったときに面倒なのが、ファイルの指定方法がJavaとAppleScriptで大きく違うところだ。これを吸収するために、getMacOSPathというクラスメソッドを用意した。たとえば、

AppleScriptRunner.getMacOSPath(new File("/Users/msyk/test.txt"))

の戻り値は、以下のような文字列となる。

(file "Users:msyk:test.txt" of startup disk)

いちおう、起動ボリュームでも、起動ボリュームでない場合でも対応できるようにした。また、Fileオブジェクトがフォルダのものなら、folder ... となるようにしている。チルダをホームディレクトリに変更したりもする。また、さまざまな文字列の変換も組み込んである。また、31バイトを超える長さのファイル名でもいちおう基本的には動くことを確認している(FinderはOKのようだがアプリケーションが対応しているいかどうかの問題がある)。
これにより、JavaのFileクラスから、AppleScriptでのファイル参照形式が得られるが、もちろん、基本的にはFinderのスクリプト向けである。なお、あらゆるキャラクタに適用されるのかと言われれば、若干自信はない面もあるので、もし、ある種の文字列がファイル名に入っている場合にうまくいかないなどの不具合があれば、ぜひともおしえていただきたい。
あと、いくつかのstaticメソッドを用意したが、いずれも、doScriptを使った応用である。getCommentやsetCommentは、Fileクラスで指定したファイルのコメントを取り出したり、あるいはコメントを設定できるものだ。doScriptByFinderは、Finderに実行させるスクリプトプログラムの断片を与えて、doScriptを実行するものだ。要は、tell application "Finder"とend tellの間の部分だけを指定することで、プログラムの実行をできるようにしたものである。ズボラさん向きかもしれない(笑)。

doScriptメソッドを使ったプログラム例を紹介しておこう。MDOnline_03_DoAppleScript.javaにあるように、たとえば次のようにすることで、AppleScriptのプログラムを実行することができる。(\は実際にはバックスペースである)

String script = "tell application \"Finder\"\r activate\rend tell";
try {
System.out.println(AppleScriptRunner.doScript(script));
}
catch(Exception e) { System.out.println(e.getMessage()); }
System.out.println("Script Error-->"+AppleScriptRunner.getErrorMessage());

簡単なスクリプトだが、変数scriptには、以下のようなAppleScriptプログラムを代入している。

tell application "Finder"
activate
end tell

実行されると、Finderがアクティブになるというだけである。このスクリプトは結果はなにもないので、標準出力には何も出力されないし、スクリプトのエラーはnullとなる。まじめには、getErrorMessageメソッドの戻り値を見てnullなら出力しないということを組み込む必要はあるだろうが、ここはテストランということでお許しいただきたいと思う。なお、ここでは改行は\rとしているが、\nにしても稼働する。何でもいいようだ。また、日本語を含むスクリプトも、単にJavaの文字列として用意すればいい。特に変換をしなくてもいいようである。
ここで、スクリプトとして、

script = "tell application \"Finder\"\r zzzzzzz\rend tell";

のように無理に間違ったものを指定すると、標準出力には次のように表示される。

========== Execute the following script:
tell application "Finder"
zzzzzzz
end tell
==========

Script Error-->execution error: The variable zzzzzzz is not defined. (-2753)

つまり、getErrorMessageメソッドで、スクリプトのエラーメッセージを取り出しているということになるわけだ。

AppleScriptRunnerクラスの使い方はおおまかには以上の通りだ。ファイルのコメントの設定などとなると、class MacFile extends java.io.Fileなどとして、MacFileクラスをきちんと定義して使えとおっしゃるかもしれないが、今回は簡単に完結するサンプルであるとしてお許しいただきたい。引き続いて、AppleScriptRunnerクラスの中身を解説しよう。

(この項、続く)
関連リンク