本腰入れてJRuby(その3) Apache BSFさんと仲良くなろう
BSFのドキュメントがほとんどなくて困ってうろうろしたので、分かった事を書いていく。
BSFを使ったスクリプトの呼び出しはこんな感じ。
BSFManager manager = new BSFManager(); String hello = "Javaの世界からこんにちは!"; manager.registerBean("hello", hello); // (1) InputStreamReader reader = new InputStreamReader(this.getClass().getResource("test.rb").openStream()); manager.exec("ruby", "(java)", -1, -1, IOUtils.getStringFromReader(reader));
test.rbは、この処理を実装しているクラスと同じパッケージに置いている事を前提にしています。(ってあたりまえかw)
test.rbの中身はこんな感じ。
hello = $bsf.lookupBean("hello") puts hello
$bsfというのは、BSFManagerをラップしたBSFFunctionsというクラスの暗黙オブジェクト。BSFManager#registerBeanで登録したBeanをlookupBeanで取得することができます。
BSFManagerにはもう一つ、BSFManager#declareBean(String beanName,Object bean,Class beanClass)というインターフェースがあり、こちらを使うと宣言したbeanはさっきの$bsfからlookupBeanしなくてもそのまま使えます。どういうことかと言うと、
String hello = "Javaの世界からこんにちは!"; // manager.registerBean("hello", hello); // (1) manager.declareBean("hello", hello,String.class); // (1)をこう置き換える
puts $hello
と言うように呼べます。が、BSFManagerのソースを見てみると、すべてのScriptEngineに対してdeclareBeanで宣言したBeanが登録されていました。局所的に使うBeanを登録するにはちょっとスコープが広すぎるわけです。(Rubyの世界だと'$'がついている変数はグローバルスコープなんすね。Rhinoだと"bsf"のまんまで呼び出せた。他の言語だとどうなんだろう。)
BSFの対応言語はJRuby以外にもJavaScript(Rhino)やJython、Groovyとかがあり、実行時にどの言語かを指定することができます。(Scalaがなくてビックリした)
String source; // JRuby manager.exec("ruby", "(java)", -1, -1,source); // Rhino manager.exec("javascript", "(java)", -1, -1,source); // Jython manager.exec("jython", "(java)", -1, -1,source); // Groovy manager.exec("groovy", "(java)", -1, -1,source);
BSFManagerと同じパッケージにあるLanguage.propertiesでScriptEngineとマッピングしているようです。またファイルの拡張子からどの言語か判断して実行するインターフェースもあります。
String langType = BSFManager.getLangFromFilename(filename);
Java6でサポートされたJSR233のインターフェースの方が実行速度的に優位ですが、Java5でも動く環境にするのならBSFを使わないといけません。JRubyのインターフェースを直で叩く事も考えられますが、JRubyの開発者は推奨していません。(そりゃそうだ。)