JDK 5, JSR223, Rhino, E4X (2)

之前说了一种在JDK 5中使用JSR223,并提供E4X支持的方案,上面的方案需要对Sun自带的jar进行修改,这可能会有版权之类的问题,所以我采用另外的一种方案,就是提供自己的JSR223的JavaScript实现。可以参考的资料有scripting.dev.java.net上面的其它脚本语言的JSR223实现,还有就是Sun的JavaScript的实现的代码,当然是反编译过的。

不过Sun的实现有点复杂,经过我的删减,最后得到了一个实现,我把它注册成名字为e4x。使用时需要JSR223, JSR173的API jar,Rhino的js.jar,xbean.jar,以及我的这个包。使用下面的代码可以测试:

ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine engine = sem.getEngineByName(”e4x”);
if (engine != null) {
String str = “var order = <order> <person>alex </person></order>;print(order.person);”;
try {
Object result = engine.eval(str);
System.out.println(result);
} catch (ScriptException e) {
e.printStackTrace();
}
}

同样,使用Rhino自带的examples下的e4x目录下的e4x_example.js可以正确解释。

限制

只实现了JavaScript的eval,没有binding和Invokable
下载

该引擎的实现下载地址如下: FullRhinoEngine.jarEclipse工程

没有评论

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禁用掉了。做法是我前面说的一样,反编译之后可以看到:

ContextFactory.initGlobal(new ContextFactory() {

protected Context makeContext()
{
Context context = super.makeContext();
context.setClassShutter(RhinoClassShutter.getInstance());
context.setWrapFactory(RhinoWrapFactory.getInstance());
return context;
}

public boolean hasFeature(Context context, int i)
{
if(i == 6)
return false; //此处是关键
else
return super.hasFeature(context, i);
}

}
);

从代码中可以看到,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了。测试一下就可以了:

ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine engine = sem.getEngineByName(”js”);
if (engine != null) {
String str = “var i = Math.cos(Math.PI);print(i);var order = <order><person>alex</person></order>;print(order.person);”;
try {
Object result = engine.eval(str);
System.out.println(result);
} catch (ScriptException e) {
e.printStackTrace();
}
}

下载地址:suncrack.jar

没有评论

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

(1) 条评论

Ubuntu安装教育网直通车

Ubuntu下面安装教育网直通车是个非常麻烦的事情,我是绕了很多弯路才成功的。在网上搜了很多教程之类的,结合自己的情况才成功。

首先要有合适的源下载软件,这在上一篇里面有写。使用新立得安装php-gtk-pcntl,php-pcntl和pptpconfig这3个软件。接着主要就是参考下面的文章:
http://bdwm.net/bbs/bbscon.php?board=Linux&file=M.1160798054.A&num=1628&attach=0
http://bdwm.net/bbs/bbscon.php?board=Linux&file=M.1161380499.A&num=1688&attach=1
要点:
pptpconfig里面添加新的VPN服务器的时候,要把DNS写上,多个DNS用空格分开就可以了。
不需要PHP的那个脚本,用第二篇文章里面的bash脚本,可以省去安装PHP的工作。
直接运行那个脚本就可以连接了。

没有评论

Ubuntu初探

想装个Linux来做做开发工作,原来在Windows XP下面用Vmware装了个SUSE的虚拟机,就是有点慢,觉得很不爽,所以觉得重新在硬盘上面装一个。这个时候选择了号称目前最流行的Linux发布版本,Ubuntu。下载了最新的6.10,然后刻盘,就开始安装了。

安装过程没什么好说的,图形化界面,直接下一步就可以了。

遇到的第一个问题是显示的问题,刚装上的时候,虽然分辨率是1280*1024,但是FPS很低,拖动窗口都有明显的延迟。知道是显卡驱动没有装好,于是下载Nvidia的驱动:
使用:apt-get install nvidia-glx
安装之后使用sudo nvidia-glx-config enable就可以启用了,接着重启就完成了。不过这个时候的分辨率最大只能是1024*768了,正在尝试修改中。

使用新立得的时候需要添加足够的源来保证可以找到需要的软件,由于我一开始没有装教育网直通车,不能上国外网,而安装之后自带的源cn.archive.ubuntu.com的软件比较少,添加下面的行到/etc/apt/sources.list里面:
deb http://mirror.lupaworld.com/ubuntu/ubuntu-cn edgy main restricted universe multiverse
deb http://ubuntu.cn99.com/ubuntu/ edgy main restricted universe multiverse

这样再使用新立得的时候,就可以找到较多的软件了。

没有评论

GWT初探

GWT的网址:http://code.google.com/webtoolkit/

GWT的源代码地址: http://google-web-toolkit.googlecode.com/svn/

使用GWT提供的命令行工具:projectCreator和applicationCreator来创建项目和应用,可以生成Eclipse的项目。

GWT的编译器支持3种输出模式:默认的是obfuscate,即经过混淆的;另外两种是pretty和detailed。可以通过参数-style pretty来指定。

GWT根据浏览器的类型来使用针对该浏览器的HTML页面。GWT的编译器会编译生成不同版本的HTML页面,这些页面的名字就是该页面的MD5编码。application目录中的以nocache.html结尾的页面中的脚本负责根据用户的浏览器使用不同的HTML页面。 脚本gwt.js负责加载每个模块对应的nocache.html。

没有评论

【翻译】以REST的方式构建Web Services(Building Web Services the REST Way)

原文地址:http://www.xfront.com/REST-Web-Services.html

REST=Representational State Transfer

Web是由资源组成的,资源是任何有意义的项目。“表示”是资源的返回值,“表示”把客户端置于某种“状态”之中。客户端沿着超链接访问另外的资源,新的表示把客户端置于另外一个状态之中。 从而,客户端在每个资源表示时转换状态。

REST是一种体系结构风格,而不是标准。

逻辑URL vs. 物理URL

资源是概念上的实体。表示是资源的具体表现。如下URL:

http://www.parts-depot.com/parts/00345

是逻辑URL而不是物理URL。

REST Web Services的特点

  • 客户端-服务器:拉风格的交互模式:消费方组件把表示拉出来
  • 无状态:每个从客户端到服务器的请求必须包含足够的信息使得服务器理解该请求,不需要服务器上存储的上下文信息
  • 缓存:为了提高网络效率,响应应该可以被标示成可缓存的或是不可缓存的
  • 统一的接口:所有资源通过通用的接口访问(HTTP GET, POST, PUT, DELETE)
  • 命名资源:系统由通过URL命名的资源组成
  • 互连的资源表示:资源的表示通过URL互相联系起来,从而客户端可以从一个状态转换到另一个
  • 层次化的组件:中间件,比如代理服务器,缓存服务器,网关等,可以插入到客户端和资源中间来完成安全和安全等功能

REST Web Services设计原则

  1. 构建REST Web Services的关键是识别出所有需要暴露成服务的概念层实体。
  2. 为每个资源创建URL。
  3. 对资源进行分类,区分出哪些客户端只能获取表示,哪些是可以修改的。前者使用HTTP GET来访问,后者使用HTTP POST, PUT和DELETE来访问。
  4. 所有通过HTTP GET访问的资源必须是没有副作用的。
  5. 没有表示是作为孤岛存在的。在资源表示中放入超链接。
  6. 逐步的暴露数据。不要在单一的文档中暴露所有数据。提供超链接来获取更多的信息。
  7. 使用schema来指定响应的格式。
  8. 说明该服务是使用WSDL文档来调用,而是简单的HTML文档。

没有评论

【原创】网易搜索引擎架构讲座笔记

12月27号,网易搜索引擎“有道”的架构师周枫来我们学校做了一次关于网易搜索引擎架构的讲座,我去听了,记录下来一些我认为有用的信息。

搜索服务质量的四个维度:时效性,完备性,相关性和呈现形式。

采用分布式的架构,查询分发与结果聚合。

基础设施

分布式文件系统自动复制数据,在软件层次解决硬件可用性问题。分布式计算系统自动划分和重试任务。

抓取

抓取的首要问题是调度。抓取礼貌性和带宽利用率,最终的目的是提高整个网页库的质量。

链接分析:分布式的根据链接关系进行静态评分。重复或近似重复页面检测。使用Shingles方法,去除大约40%-50%的页面。

垃圾网页(SPAM)检测和处理,自动分类和手工封禁相结合。

前台

目标:在满足响应速率要求的前提下,尽量提高吞吐率。300ms是响应时间的临界值。将索引库分配到足够多的服务器上,缓存查询结果。索引所占空间大小对于性能影响很大。压缩索引->性能提高。可以将倒排索引压缩20%-30%。

搜索引擎查询的三类:导航类(20%-40%),信息类和交易类。

博客搜索

问题定义:通过关键词查询搜索博客文章,以及博客站点和blogger。主要基于抓取和RSS Feed(包括Atom等)。

强调对博客信息的分析。

如何查找指向某个博客的所有链接:

使用流-排序分布式计算模型(Stream Sort Model),使用多台互相通信的机器

1.按机器平均分配所有边

2.读入所有边,按v2划分发送到相应机器

3.每台机器将所有接收到的边按v2排序

4.排序结果中相邻有相同v2的边是指向v2的所有边

网络释义

把搜索和辞典结合起来。

假设:在网络中,很近距离同时出现的中外文词很有可能互为解释关系。如果同对中外文词在不同网页中出现很多次,则是正确解释关系的可能性就很大。

抽取,归一化(忽略大小写等),统计出现次数,输出超过一定次数的对

没有评论

创意的丢失–China-pub,当当与Amazon的雷同

很早的时候就在Amazon看到了这种风格的页面,后来发现这样的风格也被China-pub和当当给采用了。

下面是Amazon的:

Amazon

China-pub的:

China-pub

当当的:

dangdang

没有评论

使用Dojo的ScriptSrcIO

Dojo支持多种的客户端/浏览器传输方式,ScriptSrcIO是其中一种,指利用HTML的script标签来异步加载数据。随着JSON格式的普及,这是一种非常好的方式。

Yahoo的搜索服务可以使用JSON作为响应格式,简单的利用Dojo的ScriptSrcIO来实现。如下:

function yahooSearch() {
var sUrl = “http://api.search.yahoo.com/WebSearchService/V1/webSearch?appid=YahooDemo&output=json&query=ajax”;
var kwArgs = {
url:  sUrl,
mimetype: “text/javascript”,
transport: “ScriptSrcTransport”,
jsonParamName: “callback”,
load: outputResult
};

dojo.io.bind(kwArgs);
}

函数outputResult用来显示结果。

没有评论

« 下一页