Archive for September, 2005

祝王垠好运

清华梦的粉碎—写给清华大学的退学申请,最初是周五是一个朋友发给我的链接,今早打开Bloglines,这几乎成了很多Blog推荐的文章。
不由得想起了2年前,也差不多是在这个时候,我所经历过的。
其实从上博士的时候就开始抱怨、失望、反叛,这种情绪一直延续到最后退掉。当时最大的梦想是到国外去读书(国外朋友给我们讲述的那里的学习和生活实在令我兴奋),考了GRE、TOEFL,一切准备停当,不过因为女朋友不想去,最后还是放弃了。
那段日子真的是我曾经经历过的最苦闷的一段日子,很多细节实在不愿再去回忆。看到王垠的文章,还是不由得想起。现在还经常会有朋友问我,当初为什么放弃博士,经常会有身边的朋友选择怀着求知的欲望选择继续读博士,也不断有人经过重重艰难再放弃这个学位。而我,现在早已不像当时那么极端,觉得中国的教育制度这不好那不好,现在平和多了,我坚信一切都在像好的方向发展,可最不幸的是,处是变革时代的人。
记着那段经常喝酒,最夸张的一次是拉大米一起陪我出去喝酒,我俩互相发泄着对这种教育制度的不满,直到喝光了身上所有的钱,还厚着脸皮跟酒保多要了一桶,呵呵。最后,我都不知道自己是怎么回的宿舍。
对了,昨天看李敖在清华演讲的全文,最后记下两句:
1) 报告刘老板讲,到目前为止还安全吗?
2) 富兰克林的“哪里有自由、哪里就是我的国家”是错的,李敖把它改为:“这是我的国家、我要使她自由!”。
Popularity: 23%

Popularity: 23%

Googlebombing, Google WiFi

前两天,看到Google Blog中的一篇文章 - "Googlebombing ‘failure’",很有意思:

If you do a Google search on the word [failure] or the phrase [miserable failure], the top result is currently the White House’s official biographical page for President Bush. We’ve received some complaints recently from users who assume that this reflects a political bias on our part. I’d like to explain […]

Popularity: 26%

终于写完,周末就去医院陪奶奶了。先这样吧,最近发生了很多事儿,脑子有点儿乱,也不知道究竟写的怎么样 :(。
最终的文章我放在了这里:
Dissect Eclipse Plugin Framework
希望能对你有些帮助。
Popularity: 27%

Popularity: 27%

Dissect Eclipse Plugin Framework

在讨论Xerdoc DSearch的架构的时候,我们就讨论决定采用Eclipse Plugin Framework,可惜那时Eclipse Plugin Framework和SWT以及其它耦合比较大,因此,决定借鉴Eclipse Plugin Framework的思想,来实现一个自己的轻量级的Plugin Framework。
一晃已经过去快一年了,其实非常早就想把自己研究Eclipse Plugin Framework的心得写下来,米嘉也一再催促,不过一直比较懒,觉着这个题目实在要写的太多,于是一直拖着。后来想想,真的应该早点儿把自己的一些粗糙想法写出来,即是对自己的一个总结,也能对其他人有些帮助。
Eclipse Plugin Framework是一套非常成功的插件框架结构,它的架构师之一就是鼎鼎大名的Erich Gamma,设计模式的作者之一。Eclipse JDT就是架构在这个插件平台上的一个杰出的Java IDE。Eclipse 良好的插件架构也形成了很好的"An architecture of participation",你可以在Eclipse的社区中找到各种各样的插件,这些插件又极大的扩充了Eclipse的功能,提高了易用性。
记着候捷在写《深入浅出MFC》的时候,用很简单甚至粗糙的一些例子来模仿MFC内部的行为(比如消息循环等),效果非常好。我也想用一些Xerdoc DSearch中的代码来模仿一下Eclipse的插件架构。
注:这里所指的Eclipse Plugin Framework的Codebase是2.1.3,因为当时研究的时候,3.0(OSGi Based)还没出来 :P。
1) 插件清单
Eclipse中的插件都用XML文件来进行描述,比如:
<?xml version="1.0" encoding="utf-8"?>
<plugin id="org.eclipse.pde.source" name="%pluginName" version="2.1.3" provider-name="%providerName"> 
    <runtime></runtime>
    <extension point="org.eclipse.pde.core.source">
        <location path="src"> </location>
    </extension> 
</plugin>
这个清单中描述了插件的绝大多数信息,包括插件的id, name(这个是经过i18n的),版本,启动类等。同时,所有的扩展、扩展点也都在这里定义,此插件对外提供的库(包括Native库)以及资源也都要定义在这个文件中。
这个文件的名称是"plugin.xml",Eclipse启动的时候会扫描"plugins"目录下的所有"plugin.xml"文件,进而装载所有的插件。(注:为了提高效率,Eclipse会保存一个中间文件来加速装载,这里并不讨论。)
因此,你需要用XML Parser将这些信息Parse出来,形成插件的基本信息,具体选用Dom、SAX还是Pull Parser都无所谓。
Eclipse采用微内核+插件的模式构架,也就是说,除了一个微小的核儿之外,所有的东西都是插件(All are plugins)。
2) 扩展点概述
Eclipse Plugin Framework最核心的概念应该就要算"Extension Point"(扩展点)了。
打个通俗的比方,"Extension Point"就像我们日常生活中的插销板,而"Extension"就是能够插入到这个插销板上面的插销。
系统的开放性很大程度上也取决于系统究竟给你多少"Extension Point"。
WordPress的Plugin Framework也同样采用这种"Extension Point"的概念构架,它为自己几乎所有的应用都定义了扩展点。比如,有的插件可以在"Header显示扩展点"的地方加入代码来添加CSS样式表,Google Sitemap插件可以在"文章发布扩展点"的地方进行Google Sitemap的提交,Creative Commons插件可以在"Footer显示扩展点"处增加"Creative Common"信息等等。
对于Eclipse来说,因为采用微内核+插件的方式,因此,定义扩展点也就成了你的任务,在扩展功能的同时,你也可以在任何你觉得可能被扩展的地方定义扩展点,来方便其他人扩展系统的功能。
举个例子,Eclipse SWT […]

Popularity: 14%

Dissect Eclipse Plugin Framework (7)

对于一个良好的插件平台来说,仅有一个良好的插件架构是不够的,还需要有非常方便易用的插件开发环境。Eclipse的PDE就是这样的产品,它能够很大程度帮助程序员开发插件,极大降低其它人“participation”的难度 :-)。
相比之下,Netbeans就没有这样的插件开发环境(Netbeans中,插件斗叫做模块 - "Module"),因此,开发插件还是一件很麻烦的事情,这也就造成了其他人“participation”的困难。
基本上就是这样,Eclipse2.1的插件结构真的非常优秀,看到那些代码的时候更佩服最初设计者的想法。Eclipse2.1 Plugin Framework也有一些缺点,比如不能Load/Unload on the fly(动态加载/卸载),需要重启Eclipse等等。
在Eclipse3.0之后,Eclipse决定遵循OSGi的标准来重构其插件机制,拥抱标准,总是一件美好的事情。
最后强烈推荐 "Contributing to Eclipse",由Erich Gamma、Kent Beck执笔,值得一读。
Popularity: 27%

Popularity: 27%

Dissect Eclipse Plugin Framework (6)

在介绍"Extension Point"之前,先来看一个概念:Eclipse中著名的懒加载原则(Lazy Loading Rule)。

懒加载法则:只有在真正需要的时候才加载插件,实现起来最重要的方面就是声明和实现的分离。

插件的外形(比如名字,ID,图标)等等都在插件描述清单"plugin.xml"中声明,而具体功能封装在class文件中。
这种懒加载原则表现在各个方面,比如最基本的插件启动。系统在启动的时候,只加载和启动最必须的一些插件,而其它插件只有在真正用到的时候才被加载和启动,这样可以最大限度的节省系统启动时的资源和时间。而对用户来说,每次启动也确实有很多插件根本不会去用到。
懒加载还表现在扩展点的应用上,待会儿可以看到具体例子。
接下来就看看"Extension Point",像前面曾经介绍的那样,"Extension Point"是Eclipse Plugin Frame中最核心的概念。首先来看一个Xerdoc DS中"Extension Point"和"Extension"的声明:
<extension-point id="Parser">
    <parameter-def id="class" type="string"/>       
    <parameter-def id="icon" type="string"/>
</extension-point>
这是"core"插件中关于"Parser"的扩展点,你可以定义不同的扩展,来增强Xerdoc DS能够索引文件类型的范围。
<extension plugin-id="com.xerdoc.desktop.core" point-id="Parser" id="MP3FileParser">
    <parameter id="class" value="com.xerdoc.desktop.parser.mp3.MP3FileParser"/>
    <parameter id="icon" value="image/mime_icon_Music_mp3.gif"/>
</extension>
这是"mp3 parser"插件中对此扩展点的一个扩展声明,声明了自己扩展的类和图标。图标完全是为了显示,而其中的"class"则是为了加载真正的功能。
"core"插件会在需要的时候加载所有扩展了这个扩展点的插件:
private static void loadSupportedParsers() {
    … …
   
    try {
        descriptor = manager.getPlugin("com.xerdoc.desktop.core")
                .getDescriptor();
 
        //    得到Parser扩展点声明
        IExtensionPoint extPoint = descriptor.getRegistry()
  […]

Popularity: 28%

为奶奶祝福

昨晚12点多从医院回到家,一点儿都没有睡意,就起来继续写Eclipse Plugin那个专题。实在睡不着,上周去看奶奶的时候她还能跟我聊天,可是昨晚,看到她几乎不能清楚的记住我的回答,而连续三次问我:“岩岩,从哪儿来?”,我的眼泪唰的流了下来。看到老爸留眼泪,心里就更难受,他说了两句话都让我心疼,一句是:“去年爷爷送去医院就没再能回来”,一句是“现在我还能叫一声妈”。
今早依旧很早醒来,上午奶奶会去做核磁共振,希望结果会好。
Popularity: 29%

Popularity: 29%

Dissect Eclipse Plugin Framework (5)

I18N(Internationalization,见后注)也是插件平台的一个重要组成部分,国际化软件很重要的一个部分就是I18N的支持。这其实也是"An architecture of participation"的一个方面,只要你留出良好的接口,别人会替你进行各种语言的Translation工作。
Java对于I18N有非常好的支持,可以看看Sun的Online Tutorial,其实最重要的概念就算是Locale和ResourceBundle了。
先来看看Locale:

A Locale object represents a specific geographical, political, or cultural region

常见的比如"zh_CN", "en_US"等等 。它是由Language(语言)和Country(国家/地区)两部分组成的,比如"en"表示英语,"US"表示美国,通常,我们可以通过Locale.getDefault()来得到本地默认的Locale。
当你将Locale设置为其它,理论上,系统的语言、习惯等等也应该被相应的切换。
再来看看ResourceBundle:

Resource bundles contain locale-specific objects. When your program needs a locale-specific resource, a String for example, your program can load it from the resource bundle that is appropriate for the current user’s locale. In this […]

Popularity: 29%

Dissect Eclipse Plugin Framework (4)

准备工作做完,就可以来看看具体实现过程。
我们模拟的几个重要的类是:
Plugin: 插件类,描述每个具体插件;
PluginDescriptor: 插件描述符,记录了插件的ID、Name、Version、依赖、扩展点等;
PluginManager: 插件管理器,负责所有插件资源的管理,包括插件的启动、停止、使能(Enable/Disable)等等;
PluginRegistry: 插件注册表,提供了一个由插件ID到Plugin的映射;
我们首先来定义一个简单的Plugin:
public abstract class Plugin {
    /**
     * Plugin State
     */
    private boolean started_;
 
    private final PluginManager manager_;
 
    private final IPluginDescriptor descriptor_;
 
    public Plugin(PluginManager manager, IPluginDescriptor descr) {
        manager_ = manager;
        descriptor_ = descr;
    }
 
    /**
     * @return descriptor of this plug-in
     */
    public final IPluginDescriptor getDescriptor() {
        return descriptor_;
    }
 
    /**
    […]

Popularity: 28%

Dissect Eclipse Plugin Framework (3)

了解Eclipse的Plugin Framework需要对ClassLoader(类装载器)有比较深入的了解,建议读读JDK的源代码,会很有帮助。
ClassLoader - 顾名思义,就是Java中用来装载类的部分,要将一个类的名字装载为JVM中实际的二进制类数据。在JVM中,任何一个类被加载,都是通过ClassLoader来实现的,同时,每个Class对象也都有一个引用指向装载他的ClassLoader,你可以通过getClassLoader()方法得到它。
ClassLoader只是一个抽象类,你可以定义自己的ClassLoader来实现特定的Load的功能。Eclipse Plugin Framework就实现了自己的ClassLoader。
ClassLoader使用所谓的"Delegation Model"(“双亲委托模型”)来查找、定位类资源,每一个ClassLoader都有自己一个父ClassLoader实例,当这个ClassLoader被要求加载一个类时,它首先会询问自己的父ClassLoader,看看他是否能加载,如果不能的话,才自己加载。
Java ClassLoader的体系结构是
Bootstrap ClassLoader <- Standard Extensions ClassLoader <- Class Path Class Loader
最后来看一下代码:
protected synchronized Class<?> loadClass(String name, boolean resolve)
    throws ClassNotFoundException
    {
    // First, check if the class has already been loaded
    Class c = findLoadedClass(name);
    if (c == null) {
        try {
        if (parent != null) {
      […]

Popularity: 27%


Creative Commons License
This work is licensed under a Creative Commons License.

一天就好象是这短暂的一生,一生它只是无尽的路上短暂的一天