让Rhino的E4X在JDK5下运行

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对象。需要去掉一些不用的名称使得编译通过。

发表您的评论

您必须 登录 才能发表评论.