Archive for September, 2005

祝王垠好运

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

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 [...]

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

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)还没出来 。 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都无所谓。 [...]

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执笔,值得一读。

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") [...]

为奶奶祝福

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

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 [...]

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;     }   [...]

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) {     [...]