Rhino(http://www.mozilla.org/rhino/)已经被集成在JDK6中的JSR223 Scripting框架中。但是在JDK5中使用Rhino的E4X功能是不行的,因为默认情况下该功能是被关闭的,如果想要在JDK5中使用Rhino的E4X功能,就需要一些额外的代码。
查看Rhino的ContextFactory的源代码可以看到,与E4X相关的Context.FEATURE_E4X是在JDK6的时候才返回true的。所以首先需要实现自己的ContextFactory,做如下修改就可以了:
public class E4XContextFactory extends ContextFactory {
protected boolean hasFeature(Context cx, int featureIndex) {
switch (featureIndex) {
case Context.FEATURE_E4X:
return true;
}
return super.hasFeature(cx, featureIndex);
}
}
我们需要在自己的ContextFactory生成的Context中执行JavaScript,这个时候需要使用ContextAction,实现该接口:
下面是一个可以运行某个JavaScript文件的ContextAction实现:
private static class E4XAction implements ContextAction {
private File file;
public E4XAction(File file) {
this.file = file;
}
public Object run(Context context) {
try {
Global global = new Global(context); //参考注意事项2
InputStream ins = new FileInputStream(file);
Reader reader = new InputStreamReader(ins);
Object result = context.evaluateReader(global, reader, file
.getName(), 1, null);
return Context.toString(result);
} catch (Exception e) {
e.printStackTrace();
}
return “!!!ERROR!!!”;
}
}
接下来就是使用此ContextAction了:
File file = new File(”e4xsimple.js”);
E4XContextFactory ecf = new E4XContextFactory();
System.out.println(ecf.call(new E4XAction(file))).toString());
测试文件e4xsimple.js的内容为:
var a = <order><person>alex</person></order>;
print (a.person);
输出是:alex
注意事项
1.把下载到的XMLBeans的lib下面的xbean.jar和jsr173_1.0_api.jar都放到classpath中,否则会报错,说找不到XML这个名字。如果你只放了xbean.jar的话,也会出错。我一开始只放了xbean.jar,出错提示不明显,后来我debug跟踪到 org.mozilla.javascript.xmlimpl.XMLLib在初始化的时候出现了javax.xml.stream的相关类的ClassNotFound的错误,导致XML相关的名称没有被加载。这是因为xbean.jar依赖于jsr173_1.0_api.jar。而网上的教程都说只放xbean.jar就可以,在JDK6中是可以的,因为JDK6的rt.jar中已经添加了JSR173,即javax.xml.stream包,而JDK5中是没有的。
2.如果你想在JavaScript中使用print命令,可以把org.mozilla.javascript.tools.shell.Global拷贝过来加以修改就可以了。我就是这么做的,在执行脚本的时候使用该Global对象。需要去掉一些不用的名称使得编译通过。