JDK 5, JSR223, Rhino, E4X (1)

前面的一篇博客中,我写了怎么在JDK5的环境下使用Rhino的E4X功能,下面要说的是如何在JDK5中使用JSR223的Scripting框架。JSR223即javax.script包是JDK6.0才引入的,并且集成了Rhino作为JavaScript的引擎。不过JDK6集成的Rhino是经过删减功能的,包括主要的E4X没有加入。需要解决的问题有几个:

首先把JSR223的JDK6的实现剥离出来,这个容易,找到JDK6安装目录下面的rt.jar,保留javax.script和com.sun.script两个包,删除其余的文件夹,把此jar命名为jsr223.jar。此外在META-INF下面添加services文件夹,里面添加文件内容为com.sun.script.javascript.RhinoScriptEngineFactory的javax.script.ScriptEngineFactory文件。这完成了最基本的功能,不过这还不够。因为默认的com.sun.script.javascript.RhinoScriptEngine的实现中,把E4X禁用掉了。做法是我前面说的一样,反编译之后可以看到:

java 代码
  1. ContextFactory.initGlobal(new ContextFactory() {   
  2.   
  3. protected Context makeContext()   
  4. {   
  5. Context context = super.makeContext();   
  6. context.setClassShutter(RhinoClassShutter.getInstance());   
  7. context.setWrapFactory(RhinoWrapFactory.getInstance());   
  8. return context;   
  9. }   
  10.   
  11. public boolean hasFeature(Context context, int i)   
  12. {   
  13. if(i == 6)   
  14. return false//此处是关键   
  15. else  
  16. return super.hasFeature(context, i);   
  17. }   
  18.   
  19. }   
  20. );   

从代码中可以看到,6就是E4X的feature,默认的处理是直接返回false,要把它改成返回true。由于没有源代码,所以解决办法就只有一个,直接生成Java字节码。这个很多工具可以做到,我用的是ASM,首先查看原始的RhinoScriptEngine$1.class的字节码,然后修改一处地方就可以了。用此class文件替换到原来的,就完成了第一步。

第二步是因为JDK6对Rhino做了很多修改,很多类都去掉或者进行了修改,类所在的包也变化了。因此有两种方案,一种是修改com.sun.script下面的class文件,让它加载我们提供的org.mozilla.javascript下面的类,不过这会修改多个class文件,不理想。所以我的方案是把已有的Rhino的源代码结构修改成现有的sun实现的结构,删除掉sun原来的Rhino的类,这样com.sun.script下面的类就会加载完整功能的Rhino了。要完成这样的功能,需要对Rhino的代码进行修改,把org.mozilla映射到sun.org.mozilla,org.mozilla.javasscript下面的映射到sun.org.mozilla.javascript.internal。我写了一个Python脚本来完成这个工作。编译这些文件就可以得到新的jar,放到classpath下面就可以了。

至此,就可以在JDK 6中利用JSR223来使用Rhino的E4X了。测试一下就可以了:

java 代码
  1. ScriptEngineManager sem = new ScriptEngineManager();   
  2. ScriptEngine engine = sem.getEngineByName(”js”);   
  3. if (engine != null) {   
  4.   String str = “var i = Math.cos(Math.PI);print(i);var order = <order><person>alex</person></order>;print(order.person);”;   
  5.   try {   
  6.      Object result = engine.eval(str);   
  7.      System.out.println(result);   
  8.   } catch (ScriptException e) {   
  9.     e.printStackTrace();   
  10.   }   
  11. }   

下载地址:suncrack.jar

你可能感兴趣的:(JavaScript,jdk,框架,python,sun)