現在、当サイト「mozilla.org 日本語版」の和訳文書は更新されておらず、mozilla.org の原文 よりも内容が古くなっている可能性があります。ご不便をお掛けしますが、最新の情報は原文をご確認ください。



現在位置: Rhino プロジェクト・ページ > Rhino 組み込み

チュートリアル: Rhino 組み込み

Rhino の組み込みは、簡単に、よい結果をもたらすことができます。 組み込み開発者側のさらなる努力によって、オブジェクトはスクリプトに公開され、 もっと便利にカスタマイズできます。

このチュートリアルでは、簡単な組み込みから、さらにカスタマイズされた複雑な組み込みまで、順を追って案内します。 十分 それに沿った、コンパイル可能なサンプルを提供します。

これらのサンプルは、配布物の rhino/examples ディレクトリ、 あるいは、cvs の mozilla/js/rhino/examples にもあります。 このドキュメントは、lxr を使用することで リンクしています。

このドキュメントでは、で JavaScript コードを、で Java コードを、 そして でシェルのログを示します。

本ドキュメントでは …

RunScript … 簡単な組み込み

Rhino でできる、もっとも簡単な組み込みは、RunScript サンプル のようなものです。 コマンドラインからスクリプトを読み込み、それを実行し、そして結果をプリントする、それだけです。

ここに、シェルコマンドラインからの、RunScript 使用例があります …

$ java RunScript "Math.cos(Math.PI)"
-1
$ java RunScript 'function f(x){return x+1} f(7)'
8

クラスパス (classpath) に、Rhino のクラスと RunScript サンプルのクラスファイルの 両方の指定が必要なことに注意してください。 さぁ、これから一行ずつ、main の中身を調べてみましょう。

コンテキストに入る (Entering a Context)

このコードは、Context を作成し、入ります。(enter します)

Context cx = Context.enter();

Context は、スクリプトの実行環境に関する情報を保持します。

標準オブジェクトの初期化

このコードは、標準のオブジェクトを初期化します (Object, Function, etc.)。

Scriptable scope = cx.initStandardObjects();

スクリプトを実行できるようにする前に、これを行っておく必要があります。 null パラメーターは、後の呼び出しに使用するスコープオブジェクト (scope) を、 作成して返すように、initStandardObjects に伝えます。

引数の取り集め

このコードは、標準の Java であり、Rhino 特有ではありません。 単にすべての引数を集めて、それらを一緒に連結するにすぎません。

String s = "";
for (int i=0; i < args.length; i++) {
    s += args[i];
}

スクリプトを評価 (Evaluating)

このコードは、コンテキスト cx を使用し ストリングを評価 (evaluate) します。

Object result = cx.evaluateString(scope, s, "<cmd>", 1, null);

スクリプトの評価では、scope 内で変数を検索して、エラーについては、 ファイル名 <cmd> で行番号 1 としてレポートされるでしょう。

結果をプリント

このコードは、スクリプトの評価の結果 (変数 result の内容) をプリントします。

System.out.println(cx.toString(result));

result は、ストリング、JavaScript オブジェクト、または他の値かもしれません。 toString メソッドは、どんな JavaScript の値もストリングに変換します。

コンテキストを出る (Exit the Context)

このコードは、コンテキストを出ます。(exit します)

} finally {
    Context.exit();
}

この、コンテキストと現スレッドとの関連付けの解除は、欠くことのできない後処理です。 enter 呼び出しのそれぞれに対して、exit 呼び出しがあるべきです。 例外 (exception) が投げられても、それが間違いなく呼び出されるように、Context.enter() 開始の後の、try ブロックに対応する finally ブロックに、それを記述します。

Java API のありさま

Java API の使用

組み込みに必要とされる追加コードはありません。 LiveConnect と呼ばれる JavaScript の機能で、JavaScript プログラムと Java オブジェクトが対話します (相互作用します) …

$ java RunScript 'java.lang.System.out.println(3)'
3.0
undefined

インターフェースの実装

Rhino を使用することで、JavaScript オブジェクトは、任意の Java インターフェースを実装することができます。 Java のコードを記述する必要はありません —— それは、Rhino の LiveConnect 実装の一部だからです。 例えば、java.lang.Runnable の実装の方法を、Rhino shell セッションで 見ることができます …

js> obj = { run: function() { print('hi'); } }
[object Object]
js> obj.run()
hi
js> r = new java.lang.Runnable(obj);
[object Object]
js> t = new java.lang.Thread(r)
Thread[Thread-0,5,main]
js> t.start()
hi

Java オブジェクトを追加

次の例は、RunScript2 です。 これは、RunScript とほとんど同じですが、2 行のコードの追加があります …

Object wrappedOut = Context.javaToJS(System.out, scope);
ScriptableObject.putProperty(scope, "out", wrappedOut);

これらの行は、System.out の JavaScript 側への反映である、 グローバル変数 out を追加します …

$ java RunScript2 'out.println(42)'
42.0
undefined

Java から JavaScript オブジェクトを使用する

スクリプトを評価した後に、変数や関数のためにスコープを検索し、値を取り出したり、JavaScript 関数を呼び出したりすることが可能です。 これは、RunScript3 サンプルで説明されます。 このサンプルは、変数 x の値と、関数 f の呼び出しの結果を、プリントする機能が追加されます。 xf の両方が、スクリプトの評価によって定義されると 期待できます。例えば、

$ java RunScript3 'x = 7'
x = 7
f is undefined or not a function.
$ java RunScript3 'function f(a) { return a; }'
x is not defined.
f('my args') = my arg

JavaScript 変数の使用

x の値をプリントするために、以下のコードを加えます。

Object x = scope.get("x", scope);
if (x == Scriptable.NOT_FOUND) {
    System.out.println("x is not defined.");
} else {
    System.out.println("x = " + Context.toString(x));
}

JavaScript 関数の呼び出し

関数 f を得て、それを呼び出し、そして結果をプリントするために、 このコードを加えます …

Object fObj = scope.get("f", scope);
if (!(fObj instanceof Function)) {
    System.out.println("f is undefined or not a function.");
} else {
    Object functionArgs[] = { "my arg" };
    Function f = (Function)fObj;
    Object result = f.call(cx, scope, scope, functionArgs);
    String report = "f('my args') = " + Context.toString(result);
    System.out.println(report);
}

JavaScript ホスト・オブジェクト

ホスト・オブジェクトの定義

カスタム・ホスト・オブジェクトは、動的プロパティーのような、特殊な JavaScript 機能を実装することができます。

Counter サンプル

Counter サンプルは、 簡単なホスト・オブジェクトです。下記の方法によって、その手順を経験できます。

シェルで組み込み関数 defineClass を使用して、新しいホスト・オブジェクトのクラスを試してみるのは簡単です。 後で、RunScript にそれを追加する方法を、見ることができます。 (java -jar オプションは、クラスパスを他に置き換えてしまうので、 それを使用して Counter クラスにアクセスすることはできないことに、注意してください)

$ java -cp 'js.jar;examples' org.mozilla.javascript.tools.shell.Main
js> defineClass("Counter")
js> c = new Counter(7)
[object Counter]
js> c.count
7
js> c.count
8
js> c.count
9
js> c.resetCount()
js> c.count
0

Counter のコンストラクター

引数のないコンストラクターは、Rhino ランタイムによって、インスタンスの作成に使用されます。 counter サンプルでは、初期化する必要がないので、実装は空になっています。

public Counter () { }

メソッド jsConstructor は、JavaScript コンストラクターを定義します。 それは、上記の JavaScript コード new Counter(7) の式で呼び出されます。

public void jsConstructor(int a) { count
= a; }

クラス名

クラス名は、getClassName メソッドによって定義されます。 これは、コンストラクター名を決定するのに使用されます。

public String getClassName() { return "Counter";
}

動的プロパティー

動的 (dynamic) プロパティーは、jsGet_jsSet_ で始まるメソッドで定義します。 メソッド jsGet_count は、count プロパティーを定義します。

public int jsGet_count() { return count++;
}

JavaScript コードの c.count 式 (あるいは表現)は、このメソッドを呼び出すことで、 上記の結果になります。

JavaScript の「メソッド」を定義

メソッドは、jsFunction_ 接頭語を使用して定義することができます。 ここに、JavaScript の resetCount を定義します。

public void jsFunction_resetCount() { count
= 0; }

上記の c.resetCount() は、このメソッドを呼び出します。

RunScript に Counter を追加

今度は、RunScript4 サンプルを見てください。これは、2 か所を除き RunScript と同じです。 メソッド ScriptableObject.defineClass に、Java のクラスを使用して、トップレベル・スコープで Counter "class" を定義します …

ScriptableObject.defineClass(scope, Counter.class);

すると、スクリプトから Counter オブジェクトを参照できるようになります …

$ java RunScript4 'c = new Counter(3); c.count;
c.count;'

それから、Java のコードにより、Counter オブジェクトの新しいインスタンスを作り、 7 の値を使って構築し、それを、トップレベル変数 myCounter に割り当てます

Object[] arg = { new Integer(7) };
Scriptable myCounter = cx.newObject(scope, "Counter", arg);
scope.put("myCounter", scope, myCounter);

すると、スクリプトから myCounter オブジェクトを参照できるようになります …

$ java RunScript3 'RunScript4 'myCounter.count; myCounter.count'
8