月曜日, 7月 19, 2010

rhinoでe4xを使う

Windowsのantでスクリプト実行をしていたのだけど、何故かant経由だとe4xがうまく使えなかった。javaコマンドで直接起動する分には問題ない。

D:\work\blog-gae>java -cp war\WEB-INF\lib\js.jar org.mozilla.javascript.tools.shell.Main work\e4x.js

以下そのときのantのターゲット。

<target name="rhino-run">
<property name="classes" value="war/WEB-INF/lib/js.jar:war/WEB-INF/lib/mailapi.jar:war/WEB-INF/lib/smtp.jar"/>
<echo message="Running ${script}"/>
<java classname="org.mozilla.javascript.tools.shell.Main"
classpath="${classes}"
failonerror="true">
<arg value="${script}" />
</java>
</target>

そのときのe4xテストスクリプトは以下。
// var a = require("test0.js");

var i = '<a><b><c>aaaa</c></b><b><c>bbbb</c></b></a>';

var xml = new XML(i);

//print(xml.a.b.c[1].toString());
//print(xml.a.b.c[1]);

// 何故か先頭要素を省いたものが正解
print(xml.b.c[1]);

エラーは以下のとおり。

D:\work\blog-gae>ant rhino-run -Dscript="work\e4x.js"
Buildfile: build.xml

rhino-run:
[echo] Running work\e4x.js
[java] js: uncaught JavaScript runtime exception: ReferenceError: "XML" is not defined.
[java]

BUILD FAILED
D:\work\blog-gae\build.xml:141: Java returned: 3

Total time: 1 second
D:\work\blog-gae>

これは(やはり)classpathの問題のようで、以下のスクリプト(コチラを参考)でclasspathを出してみると、
var strConf = "java.class.path";
var cwd = environment[strConf];
cwd = cwd.replace(/;/g, "\n");
print(strConf + " = " + cwd);

antのものばかりで、肝心のjs.jarが出ない。

D:\work\blog-gae>ant rhino-run -Dscript="work\env0.js"
Buildfile: build.xml

rhino-run:
  [echo] Running work\env0.js
  [java] java.class.path = D:\work\apache-ant-1.7.1\bin\..\lib\ant-launcher.j
ar
  [java] d:\Documents and Settings\00962724\.ant\lib\ivy-2.0.0-rc2.jar
  [java] D:\work\apache-ant-1.7.1\lib\ant-antlr.jar
  [java] D:\work\apache-ant-1.7.1\lib\ant-apache-bcel.jar
  [java] D:\work\apache-ant-1.7.1\lib\ant-apache-bsf.jar
snip
  [java] D:\work\apache-ant-1.7.1\lib\xercesImpl.jar
  [java] D:\work\apache-ant-1.7.1\lib\xml-apis.jar
  [java] C:\Program Files\Java\jdk1.6.0_18\lib\tools.jar

BUILD SUCCESSFUL
Total time: 1 second
D:\work\blog-gae>

そこで、上記ターゲットにantを実行しているjvmとは別のvmで実行するようforkを入れると、

<target name="rhino-run">
 <property name="classes" value="war/WEB-INF/lib/js.jar:war/WEB-INF/lib/mailapi.jar:war/WEB-INF/lib/smtp.jar">
 <echo message="Running ${script}">
 <java fork="yes" classname="org.mozilla.javascript.tools.shell.Main" classpath="${classes}" failonerror="true">
     <arg value="${script}">
 </arg>
</java>
</echo></property></target>

うまくjs.jarが動くようになり、

D:\work\blog-gae>ant rhino-run -Dscript="work\env0.js"
Buildfile: build.xml

rhino-run:
  [echo] Running work\env0.js
  [java] java.class.path = D:\work\blog-gae\war\WEB-INF\lib\js.jar
  [java] D:\work\blog-gae\war\WEB-INF\lib\mailapi.jar
  [java] D:\work\blog-gae\war\WEB-INF\lib\smtp.jar

BUILD SUCCESSFUL
Total time: 3 seconds
D:\work\blog-gae>

e4xが正常に動作した。

D:\work\blog-gae>ant rhino-run -Dscript="work\e4x.js"
Buildfile: build.xml

rhino-run:
  [echo] Running work\e4x.js
  [java] bbbb

BUILD SUCCESSFUL
Total time: 1 second
D:\work\blog-gae>

検索すると意外にrhinoのバージョン問題か、などいろいろでるけど、1.7R1で正常に使えています