Archive for September, 2005

Buy Aricept Without Prescription

清华梦的粉碎—写给清华大学的退学申请,最初是周五是一个朋友发给我的链接,今早打开Bloglines,这几乎成了很多Blog推荐的文章。


不由得想起了2年前,也差不多是在这个时候,我所经历过的。


其实从上博士的时候就开始抱怨、失望、反叛,这种情绪一直延续到最后退掉。当时最大的梦想是到国外去读书(国外朋友给我们讲述的那里的学习和生活实在令我兴奋),考了GRE、TOEFL,一切准备停当,不过因为女朋友不想去,最后还是放弃了。


那段日子真的是我曾经经历过的最苦闷的一段日子,很多细节实在不愿再去回忆。看到王垠的文章,还是不由得想起。现在还经常会有朋友问我,当初为什么放弃博士,经常会有身边的朋友选择怀着求知的欲望选择继续读博士,也不断有人经过重重艰难再放弃这个学位。而我,现在早已不像当时那么极端,觉得中国的教育制度这不好那不好,现在平和多了,我坚信一切都在像好的方向发展,可最不幸的是,处是变革时代的人。


记着那段经常喝酒,最夸张的一次是拉大米一起陪我出去喝酒,我俩互相发泄着对这种教育制度的不满,直到喝光了身上所有的钱,还厚着脸皮跟酒保多要了一桶,呵呵。最后,我都不知道自己是怎么回的宿舍。


对了,昨天看李敖在清华演讲的全文,最后记下两句:


1) 报告刘老板讲,到目前为止还安全吗?


2) 富兰克林的“哪里有自由、哪里就是我的国家”是错的,李敖把它改为:“这是我的国家、我要使她自由!”。

Buy Aricept Without Prescription, . Buy Aricept without prescription. Purchase Aricept online. Aricept price, coupon. Aricept price. What is Aricept. Aricept interactions. Taking Aricept. Get Aricept. Aricept no prescription. Is Aricept safe. Order Aricept online c.o.d. Aricept no rx. Generic Aricept. Where can i buy cheapest Aricept online. Aricept gel, ointment, cream, pill, spray, continuous-release, extended-release. Aricept australia, uk, us, usa. Online buy Aricept without a prescription. Aricept brand name. Cheap Aricept no rx. Aricept treatment. Doses Aricept work. Aricept reviews. No prescription Aricept online. Aricept for sale. Aricept wiki. Aricept maximum dosage. Aricept recreational. Where can i find Aricept online. Aricept photos. Buy Aricept from mexico. Where can i cheapest Aricept online. Fast shipping Aricept. Aricept mg. Aricept description. Aricept from canadian pharmacy.

Similar posts: Buy Human Growth Hormone Without Prescription. Buy Augmentin Without Prescription. Synthroid For Sale. Erythromycin For Sale. Female Pink Viagra For Sale. Nasonex australia, uk, us, usa. Pristiq gel, ointment, cream, pill, spray, continuous-release, extended-release. Diflucan price, coupon. Order Vermox online c.o.d. Ultram use.
Trackbacks from: Buy Aricept Without Prescription. Buy Aricept Without Prescription. Buy Aricept Without Prescription. Buy Aricept Without Prescription. Buy Aricept Without Prescription. Order Aricept online overnight delivery no prescription. Taking Aricept. Is Aricept addictive. Toradol over the counter. Differin maximum dosage.

Flexeril For Sale

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



If you do a Google search on the word [failure] or the phrase [miserable failure Flexeril For Sale, ], 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, purchase Flexeril for sale. Flexeril results, I'd like to explain how these results come up in order to allay these concerns.


Google's search results are generated by computer programs that rank web pages in large part by examining the number and relative popularity of the sites that link to them. By using a practice called googlebombing, order Flexeril from United States pharmacy, Where to buy Flexeril, however, determined pranksters can occasionally produce odd results, order Flexeril online overnight delivery no prescription. Flexeril pharmacy, In this case, a number of webmasters use the phrases [failure] and [miserable failure] to describe and link to President Bush's website, buy Flexeril from canada, Herbal Flexeril, thus pushing it to the top of searches for those phrases. We don't condone the practice of googlebombing, australia, uk, us, usa, Real brand Flexeril online, or any other action that seeks to affect the integrity of our search results, but we're also reluctant to alter our results by hand in order to prevent such items from showing up, japan, craiglist, ebay, overseas, paypal. Flexeril without a prescription, Pranks like this may be distracting to some, but they don't affect the overall quality of our search service, Flexeril dosage, Flexeril trusted pharmacy reviews, whose objectivity, as always, Flexeril without prescription, Low dose Flexeril, remains the core of our mission.



由于Googlebombing,当你搜索"failure"或者"miserable failure"的时候,布什的名字会出现在搜索结果的第一条,不过Google不愿意去为了防止这样的结果而进行人工干预。


这是题外话了,不过让我想起了Hengge说的:"Google, 总是有那么一点不一样"。


前天,Google悄悄发布了Google Wifi,很多人猜测这可能是Google看中的又一个方向。Google提供给你免费的WiFi接入,代价是获取你的访问信息,比如你身处何地。得到这些信息,Google可以把附近的餐馆、酒店、超市(甚至超市里面的商品)等广告推送给你,再加上Google MapsGoogle本地搜索,我在想,也许这就是Google所设计的一种广告模式。


那天Jack发给我Google的招聘信息,我发现专门有一个无线开发工程师,不是巧合吧:P。

. Buy Flexeril online no prescription. Rx free Flexeril. Flexeril canada, mexico, india. Order Flexeril from mexican pharmacy. Buy cheap Flexeril no rx. Buy generic Flexeril. Flexeril overnight. Flexeril steet value. Flexeril dose. Cheap Flexeril. Flexeril samples. Flexeril coupon. Flexeril alternatives. Order Flexeril online overnight delivery no prescription. Flexeril from canada.

Similar posts: Zovirax For Sale. Alesse (Ovral L) For Sale. Viagra For Sale. Buy Vermox Without Prescription. Amikacin For Sale. Discount Periactin. Buy Xalatan no prescription. Vermox natural. Purchase Viagra for sale. Buy Quinine online cod.
Trackbacks from: Flexeril For Sale. Flexeril For Sale. Flexeril For Sale. Flexeril For Sale. Flexeril For Sale. Flexeril use. Flexeril australia, uk, us, usa. Flexeril samples. Is Modalert addictive. Where can i buy cheapest Antabuse online.

Buy Inderal Without Prescription

终于写完,周末就去医院陪奶奶了。先这样吧,最近发生了很多事儿,脑子有点儿乱,也不知道究竟写的怎么样 :(。


最终的文章我放在了这里:


Dissect Eclipse Plugin Framework


希望能对你有些帮助。

Buy Inderal Without Prescription, . Inderal interactions. Rx free Inderal. Online Inderal without a prescription. Buy cheap Inderal. Inderal used for. Inderal pictures. Cheap Inderal no rx. About Inderal. Get Inderal. Where can i buy Inderal online. Inderal for sale. Online buying Inderal hcl. Inderal photos. Online buy Inderal without a prescription. Japan, craiglist, ebay, overseas, paypal. Inderal treatment. Doses Inderal work. Buy Inderal online no prescription. Where can i order Inderal without prescription. Inderal schedule. Inderal dosage. Inderal from mexico. Inderal steet value. Purchase Inderal online. My Inderal experience. Canada, mexico, india. Inderal over the counter. Discount Inderal. Inderal recreational. Inderal use. Inderal no prescription. Purchase Inderal for sale. Inderal without a prescription. Inderal long term. Inderal wiki.

Similar posts: Buy Amoxicillin Without Prescription. Buy Cafergot Without Prescription. Buy Biaxin Without Prescription. Flexeril For Sale. Antabuse For Sale. Kjøpe Topamax på nett, köpa Topamax online. Taking Allopurinol. Cheap Flexeril. Tindamax over the counter. Real brand Lumigan online.
Trackbacks from: Buy Inderal Without Prescription. Buy Inderal Without Prescription. Buy Inderal Without Prescription. Buy Inderal Without Prescription. Buy Inderal Without Prescription. Inderal photos. Where to buy Inderal. Stromectol cost. Ordering Diflucan online. Where can i buy cheapest Xalatan online.

Buy Armour Without Prescription

在讨论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文件来进行描述,比如:


[code lang="xml"]







[/code]

Buy Armour Without Prescription, 这个清单中描述了插件的绝大多数信息,包括插件的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"。


WordPressPlugin Framework也同样采用这种"Extension Point"的概念构架,它为自己几乎所有的应用都定义了扩展点。比如,有的插件可以在"Header显示扩展点"的地方加入代码来添加CSS样式表,Google Sitemap插件可以在"文章发布扩展点"的地方进行Google Sitemap的提交,Creative Commons插件可以在"Footer显示扩展点"处增加"Creative Common"信息等等。


对于Eclipse来说,因为采用微内核+插件的方式,因此,定义扩展点也就成了你的任务,在扩展功能的同时,你也可以在任何你觉得可能被扩展的地方定义扩展点,来方便其他人扩展系统的功能。


举个例子,Eclipse SWT UI中,工具栏、视图都留有扩展点,这样可以方便的进行扩展。


Eclipse的插件扩展点都定义在"plugin.xml"文件中,每个插件要扩展哪些扩展点也定义在这个文件中。举个例子(DS中Core插件的一个片断):


[code lang="xml"]




[/code]

这并不是Eclipse Plugin的DTD所规范的"plugin.xml"格式,而是一个非常简单的模拟。它描述的是一个"Parser"的扩展点。因此,你可以扩展任何自己的Parser(比如QQ聊天记录的Parser,Foxmail Mail的Parser,等等),增加Desktop Search可处理文件的范围。


3) ClassLoader

了解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的体系结构是


ClassLoader Architect


最后来看一下代码:


[code lang="java"]
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) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClass0(name);
}
} catch (ClassNotFoundException e) {
// If still not found, then invoke findClass in order
// to find the class.
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
[/code]

可见,ClassLoader首先会查找该类是否已经被装载,如果没有,就询问自己的父ClassLoader,如果还不能装载,就调用findClass()方法来装载类。所以,一般简单的自定义ClassLoader只需要重写findClass方法就可以了。


如果你的类不是文件,比如说是序列化在数据库中的二进制流或者网络上的Bit流,就需要重写defineClass()方法,来将二进制数据映射到运行时的数据结构。另外一种需求也可能是你需要对类文件进行某种操作(比如按位取反?),也需要定义自己的defineClass()方法。


还需要注意的是资源的加载和系统Native库的加载,这个可以留在以后再作讨论。


4) Plugin与PluginClassLoader


准备工作做完,就可以来看看具体实现过程。


我们模拟的几个重要的类是:


Plugin: 插件类,描述每个具体插件;


PluginDescriptor: 插件描述符,记录了插件的ID、Name、Version、依赖、扩展点等;


PluginManager: 插件管理器,负责所有插件资源的管理,包括插件的启动、停止、使能(Enable/Disable)等等;


PluginRegistry: 插件注册表,提供了一个由插件ID到Plugin的映射;


我们首先来定义一个简单的Plugin:


[code lang="java"]
public abstract class Plugin {
/**
* Plugin State
*/
private boolean started_;

private final PluginManager manager_;

private final IPluginDescriptor descriptor_;

public Plugin(PluginManager manager, online buying Armour, Armour duration, IPluginDescriptor descr) {
manager_ = manager;
descriptor_ = descr;
}

/**
* @return descriptor of this plug-in
*/
public final IPluginDescriptor getDescriptor() {
return descriptor_;
}

/**
* @return manager which controls this plug-in
*/
public final PluginManager getManager() {
return manager_;
}

final void start() throws PluginException {
if (!started_) {
doStart();
started_ = true;
}
}

final void stop() throws PluginException {
if (started_) {
doStop();
started_ = false;
}
}

public final boolean isActive() {
return started_;
}

/**
* Get the resource string
* @param key
* @return
*/
public String getResourceString(String key) {
IPluginDescriptor desc = getDescriptor();
return desc.getResourceString(key);
}

/**
* Get the Plugin Path
*
* @return
*/
public String getPluginPath() {
return getDescriptor().getPluginHome();
}

/**
* Template method, which will do the really start work
*
* @throws Exception
*/
protected abstract void doStart() throws PluginException;

/**
* Template method, buy Armour without a prescription, Armour blogs, which will do the really stop work
*
* @throws Exception
*/
protected abstract void doStop() throws PluginException;
}
[/code]

可见,这只是一个抽象类,每个插件需要定义自己的派生自"Plugin"的子类,作为本插件的一个入口。其中doStart和doStop是两个简单的模板方法,每个插件的初始化和资源释放操作可以定义在这里。


接下来我们看看系统的启动流程:首先将所有的插件清单读入("plugin.xml"),并根据这个文件解析出PluginDescriptor(包括这个Plugin的所有导出库、依赖插件、扩展点等等),放到PluginRegistry中。这个过程也是整个插件平台的一个非常重要的部分,需要从插件清单中解析的部分包括:



  1. 每个插件所依赖的的插件列表(在"plugin.xml"中用"require" element标识);

  2. 每个插件要输出的资源和类(在"plugin.xml"中用"library" element标识);

  3. 每个插件所声明的扩展点列表;

  4. 每个插件所声明的扩展列表(扩展其它扩展点的扩展)。


当把所有的插件信息都读入到系统中,就可以根据自己的需要来启动指定的插件了(比如,在Xerdoc DS中,首先,我们会启动Core插件)。


启动一个插件的步骤是:

[code lang="java"]
public Plugin getPlugin(String id) throws PluginException {
... .., Armour natural. Ordering Armour online, IPluginDescriptor descr = pluginRegistry_.getPluginDescriptor(id);
if (descr == null) {
throw new PluginException("Cannot found this plugin " + id);
}

result = activatePlugin(descr);

return result;
}

private synchronized Plugin activatePlugin(IPluginDescriptor descr)
throws PluginException {
... .., order Armour from mexican pharmacy.

try {
try {
// 首先需要检查这个插件所依赖的插件是否都已经启动,
// 如果没有,则需要先启动那些插件,才能启动本插件
checkPrerequisites(descr);
} catch (PluginException e) {
badPlugins_.add(descr.getId());
throw e;
}

// 得到插件的主类名
// 这个信息也是定义在"Plugin.xml"中,
// 并且在加载插件信息的时候读入到PluginDescriptor中的

String className = descr.getPluginClassName();
if ((className == null) || "".equals(className.trim())) {
result = null;
} else {
Class pluginClass;
try {

// 用每个插件自己的PluginClassLoader来得到这个插件的主类

pluginClass = descr.getPluginClassLoader().loadClass(
className);
} catch (ClassNotFoundException cnfe) {
badPlugins_.add(descr.getId());
throw new PluginException("can't find plug-in class "
+ className);
}
try {
Class pluginManagerClass = getClass();
Class pluginDescriptorClass = IPluginDescriptor.class;

Constructor constructor = pluginClass
.getConstructor(new Class[] { pluginManagerClass,
pluginDescriptorClass });

// 调用插件默认的构造函数
// Plugin(PluginManager, IPluginDescriptor);

result = (Plugin) constructor.newInstance(new Object[] {
this, descr });
} catch (InvocationTargetException ite) {
.., Buy Armour Without Prescription. Is Armour addictive, ...
} catch (Exception e) {
.., Armour price. Armour dangers, ...
}

try {
result.start();
} catch (Exception e) {
.., order Armour no prescription. Buy Armour Without Prescription, ... Armour results, }

... .., where can i find Armour online. Armour coupon, }
}

return result;
}
[/code]

其实最核心的工作就是三步:



  1. 首先检查这个插件所依赖的其它插件是否已经被启动,如果没有,则需要首先将那些插件启动;

  2. 根据类名,用插件类加载器加载这个类(这个类是Plugin类的一个派生类);

  3. 调用Plugin类的默认的构造函数(主要是为了将PluginManager和PluginDescriptor传进去)。


这就用到了前面说过的类加载器(ClassLoader),Eclipse中定义了插件类加载器(PluginClassLoader)。插件类加载器(PluginClassLoader)其实很简单,它派生自URLClassLoader -



This class loader is used to load classes and resources from a search path of URLs referring to both JAR files and directories.



PluginClassLoader会将PluginDescriptor中声明输出的路径(可以是JAR文件,可以是类路径,可以是资源路径)加入到此URLClassLoader类加载器的搜索路径中去。


比如:


[code lang="xml"]








[/code]

PluginClassLoader会将"XerdocDSHTMLRender.jar"和"image/"目录都加入到URLClassLoader的类搜索路径中去,这样,就可以用这个类加载器来加载相应的插件类和资源了。


PluginClassLoader加载插件的策略是:


首先试图从父ClassLoader加载(系统类加载器),如果无法加载则会试图从本类加载器加载,如果还是找不到,这时的行为与一般的URLClassLoader不同,也PluginClassLoader最大的特色:它会试图从此插件的需求依赖插件("require"形容的插件)中去加载需求的类或者资源。


比如下面这个例子:


[code lang="xml"]




[/code]

这是Office Excel Parser插件清单的片断。如果这个插件的类加载器无法加载某个需要的类或者资源,将会委托"com.xerdoc.desktop.core"插件或者"com.xerdoc.desktop.core.ui.swt"插件的类加载器去加载。


系统Native Library(比如SWT插件中要用到的系统本地库)的加载也是PluginClassLoader的功能。


就举SWT的例子,熟悉SWT的人都知道,运行SWT应用程序的时候需要添加以下命令行参数:



-Djava.library.path="/home/elan/workspace/xerdoc_ds/swt-native"



这就是为了让类加载器能够在相应的目录("/home/elan/workspace/xerdoc_ds/swt-native")下面找到需要的系统本地库资源。但是这样的命令行参数对于某些应用并不合适。对于Xerdoc DS来说,SWT的UI界面也同样是一个插件,同时也还会有其它用到本地资源库的插件,总不能增加一个插件还要修改命令行参数吧?因此,需要修改ClassLoader,使之能够加载指定的Native Library。方法就是重写findLibrary函数:


[code lang="java"]
/**
* Returns the absolute path name of a native library. The VM invokes this
* method to locate the native libraries that belong to classes loaded with
* this class loader, buy generic Armour. If this method returns null, the VM
* searches the library along the path specified as the
* "java.library.path" property, Buy Armour Without Prescription. Armour from canadian pharmacy,


*
* @param libname
* The library name
*
* @return The absolute path of the native library
*
* @see System#loadLibrary(String)
* @see System#mapLibraryName(String)
*
* @since 1.2
*/
protected String findLibrary(String libname) {
return null;
}
[/code]

重写其实很简单,只需要根据每个插件需要加载Native Library的目录来搜索就可以了,比如这是Linux下面,SWT插件清单的片断:


[code lang="xml"]



[/code]

这样,在找Native Library的时候就可以从"$PLUGIN_HOME/swt-native/"这个目录中找到相应的so文件(Linux下的动态链接库)。


最后来说说资源文件(比如说png, ico等等),其实同加载类资源一样,只要在"library"中声明的目录,就都会加入到类加载器的类搜索路径中去,这样,我们都可以直接访问里面的资源。


5) I18N


I18N(Internationalization,见后注)也是插件平台的一个重要组成部分,国际化软件很重要的一个部分就是I18N的支持。这其实也是"An architecture of participation"的一个方面,只要你留出良好的接口,别人会替你进行各种语言的Translation工作。


Java对于I18N有非常好的支持,可以看看Sun的Online Tutorial,其实最重要的概念就算是Locale和ResourceBundle了。


先来看看Locale:



A Locale object represents a specific geographical, after Armour, What is Armour, political, or cultural region



常见的比如"zh_CN", herbal Armour, Armour trusted pharmacy reviews, "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, effects of Armour, Cheap Armour, a String for example, your program can load it from the resource bundle that is appropriate for the current user's locale, buy no prescription Armour online. Armour alternatives, In this way, you can write program code that is largely independent of the user's locale isolating most, taking Armour, Armour dose, if not all, of the locale-specific information in resource bundles.



ResourceBundle实例化的策略为:


1) 名字


简单的说,首先会根据你设定的Locale和Base Name来取得相应的名字,比如默认的来说,我们的中文系统中,Base Name = "plugin"的情况下,搜索的顺序为:


plugin_zh_CN


plugin_zh


plugin


所以,Xerdoc DS默认都会提供中、英两种Resource文件("plugin_zh_CN.properties", no prescription Armour online, Armour price, coupon, "plugin.properties"),当然,也可以很方便的根据"plugin.properties"翻译成为其它语言(比如法语、德语)。


这样的结果是,如果你设置为中文Locale,那么则读取"plugin_zh_CN.properties",如果设置为英文,则读取"plugin.properties",如果设置为德文等其它找不到的,也默认的使用英文的"plugin.properties"。


2)类 or Properties文件 ?


ResourceBundle首先会试图根据上面的名字加载ResourceBundle的子类,如果加载失败,再试图加载以这个名字为文件名,以"propereies"为后缀的资源文件,如果还是找不到,就会抛出Exception。


根据这样两步,ResourceBundle完成自己的实例化。


这样,可以为每个插件都配一个自己的ResourceBundle,负责自己插件的I18N工作。


实现起来,在PluginClassLoader中,可以将每个插件的"i18n"目录都默认的加入到搜索路径中去,这样,可以通过下面这段代码得到每个插件自己的ResourceBundle:


[code lang="java"]

...

private static final String RESOURCE_BUNDLE_NAME = "plugin";

.., comprar en línea Armour, comprar Armour baratos. Buy Armour Without Prescription, /**
* I18N Work
*/

/**
* Returns the plugin's resource bundle,
*/
public ResourceBundle getResourceBundle() {
try {
if (resourceBundle_ == null) {
ClassLoader loader = getPluginClassLoader();
resourceBundle_ = ResourceBundle.getBundle(
RESOURCE_BUNDLE_NAME, Locale.getDefault(), loader);
}
} catch (MissingResourceException x) {
resourceBundle_ = null;
}
return resourceBundle_;
}
[/code]

得到ResourceBundle后,就可以通过它来得到所需要的字符串什么的了:


[code lang="java"]
resourceBundle_.getString("parser.word.title");
[/code]

有两个注意的是:



  1. 编译的时候,编码应该指定为utf-8;

  2. 程序中所有的字符串应该都由ResourceBundle得到,不应该出现硬编码。


写到这里,想起原来用Visual C++开发项目。I18N的道理其实差不多,不过是将字符串都写到RC文件中(二进制)。相比起来,VC队I18N的支持比Java还是要差不少。


最后补充一点的是,Eclipse插件清单("plugin.xml")中需要I18N的字符串通常在前面添加"%",这样在取得这样的字符串后,ResourceBundle可以根据这个Key从properties中取出相应的I18N后的字符串,并表示出来。


注:I18N作为Internationalization的简称,表示中间省略18个字母,常用的还有G10N(Globalization), A11Y(Accessbility)等等。


6) Lazy Loading


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



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



插件的外形(比如名字,ID,图标)等等都在插件描述清单"plugin.xml"中声明,而具体功能封装在class文件中。


这种懒加载原则表现在各个方面,比如最基本的插件启动。系统在启动的时候,只加载和启动最必须的一些插件,而其它插件只有在真正用到的时候才被加载和启动,这样可以最大限度的节省系统启动时的资源和时间。而对用户来说,每次启动也确实有很多插件根本不会去用到。


懒加载还表现在扩展点的应用上,待会儿可以看到具体例子。


7) 扩展点的实现


接下来就看看"Extension Point",像前面曾经介绍的那样,"Extension Point"是Eclipse Plugin Frame中最核心的概念。首先来看一个Xerdoc DS中"Extension Point"和"Extension"的声明:


[code lang="xml"]




[/code]

这是"core"插件中关于"Parser"的扩展点,你可以定义不同的扩展,来增强Xerdoc DS能够索引文件类型的范围。


[code lang="xml"]




[/code]

这是"mp3 parser"插件中对此扩展点的一个扩展声明,声明了自己扩展的类和图标。图标完全是为了显示,而其中的"class"则是为了加载真正的功能。


"core"插件会在需要的时候加载所有扩展了这个扩展点的插件:


[code lang="java"]
private static void loadSupportedParsers() {
... Buy Armour online cod, ...

try {
descriptor = manager.getPlugin("com.xerdoc.desktop.core")
.getDescriptor();

// 得到Parser扩展点声明
IExtensionPoint extPoint = descriptor.getRegistry()
.getExtensionPoint(descriptor.getId(), Armour samples, Armour forum, "Parser");

// 根据这个声明得到所有连接到这个扩展点的扩展对象
for (Iterator it = extPoint.getConnectedExtensions().iterator(); it
.hasNext();) {
IExtension ext = (IExtension) it.next();

// 根据扩展对象生成Parser代理
// 也就是著名的懒加载法则
ParserProxy parser = ParserProxy.createParserProxy(ext);

parserList_.add(parser);
}
} catch (PluginException e) {
e.printStackTrace();
}
}
[/code]

ParserProxy其实就是Parser的代理,它只读取Parser的表现部分,比如图标,名称等等,而实例化的操作要等到具体使用的时候才去调用。


[code lang="java"]
...

/**
* Parser Extension Point
*/
private IExtension extension_;

/**
* Real Parser Instance, buy Armour from canada, Armour brand name, it will not be load until really needed
*/
private AbstractParser realParser_;

...

private ParserProxy(IExtension extension) {
extension_ = extension;
}

/**
* Create the Parser Proxy based on the Extension
*
* @param extension
* @return
*/
public static ParserProxy createParserProxy(IExtension extension) {
return new ParserProxy(extension);
}
[/code]

当真正需要这个Parser的时候,ParserProxy会生成相应的真实对象(如其名,这是Proxy模式的典型应用):


[code lang="java"]
private AbstractParser getRealInstance() {
if (realParser_ == null) {
try {
// 得到插件
// 如果插件还未被激活,这里要激活这个插件
// LAZY LOADING!!, Armour reviews.

Plugin plugin = CorePlugin.getInstance().getManager()
.getPlugin(
extension_.getDeclaringPluginDescriptor()
.getId());

if (plugin != null) {
Class pluginCls = plugin.getClass();

// 得到主类
Class cls = extension_.getDeclaringPluginDescriptor()
.getPluginClassLoader().loadClass(
extension_.getParameter("class")
.valueAsString());

if (cls != null) {
if (pluginCls.isAssignableFrom(cls)) {
realParser_ = (AbstractParser) plugin;
} else {
// 反射生成这个类
realParser_ = (AbstractParser) cls.newInstance();
}
}
}
} catch (Exception e) {
return null;
}
}

return realParser_;
}
[/code]

然后,就可以调用这个Parser完成必要的工作了。这就是"Extension Point"的大概的工作流程。


在Eclipse中,遍地都是这样的例子,比如:Eclipse Platform的菜单显示就是一个扩展点,Eclipse在显示菜单之前首先会从系统的插件列表(PluginRegistry)中寻找所有扩展此扩展点的插件,取得图标和名字显示出来,然后在用户点击的时候生成真实的对象,并调用之,嗯,还是懒加载法则。


BTW:菜单扩展中的类是IAction,点击的时候调用它的run()函数,Command模式。


写这些的时候想起来,在声明每个扩展点前,这个插件都需要定义一定的Interface,也就是扩展这个扩展点的插件需要遵循的API。这个Interface如果用C#中的Delegate实现,是不是会看起来更好呢?(从包的import等等)。不知道有没有C#模仿Eclipse Plugin Framework的实例。


8) 写在后面


对于一个良好的插件平台来说,仅有一个良好的插件架构是不够的,还需要有非常方便易用的插件开发环境。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执笔,值得一读。

.

Similar posts: Buy Tindamax Without Prescription. Buy Diclofenac Without Prescription. Buy Ultram Without Prescription. Slimex (Obetrim) For Sale. Abilify For Sale. Buy no prescription Advair online. Flonase australia, uk, us, usa. Temovate Cream dangers. Australia, uk, us, usa. Comprar en línea Flagyl, comprar Flagyl baratos.
Trackbacks from: Buy Armour Without Prescription. Buy Armour Without Prescription. Buy Armour Without Prescription. Buy Armour Without Prescription. Buy Armour Without Prescription. Armour coupon. Armour dose. Cheap Armour. Where can i find Metronidazole Gel online. Purchase Phenergan.

Buy Stromectol Without Prescription

对于一个良好的插件平台来说,仅有一个良好的插件架构是不够的,还需要有非常方便易用的插件开发环境。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执笔,值得一读。

Buy Stromectol Without Prescription, . Where can i buy cheapest Stromectol online. Stromectol mg. Purchase Stromectol online no prescription. Where can i cheapest Stromectol online. Stromectol class. Stromectol pharmacy. Stromectol pics. Stromectol street price. Is Stromectol safe. Fast shipping Stromectol. Where to buy Stromectol. Buy Stromectol no prescription. Stromectol images. Stromectol online cod. Buy Stromectol without prescription. Australia, uk, us, usa. Order Stromectol online c.o.d. Stromectol maximum dosage. Stromectol overnight. Low dose Stromectol. Stromectol description. Kjøpe Stromectol på nett, köpa Stromectol online. Stromectol canada, mexico, india. Real brand Stromectol online. Order Stromectol from United States pharmacy. Stromectol australia, uk, us, usa. Stromectol cost. Buying Stromectol online over the counter. Buy cheap Stromectol no rx. Purchase Stromectol. Stromectol no rx. Generic Stromectol. Stromectol without prescription. Buy Stromectol from mexico. Stromectol gel, ointment, cream, pill, spray, continuous-release, extended-release.

Similar posts: Buy Plavix Without Prescription. Proscar For Sale. Toradol For Sale. Zithromax For Sale. Buy Pristiq Without Prescription. Atarax long term. Fast shipping Clonidine. Biaxin images. Is Imitrex safe. Colchicine forum.
Trackbacks from: Buy Stromectol Without Prescription. Buy Stromectol Without Prescription. Buy Stromectol Without Prescription. Buy Stromectol Without Prescription. Buy Stromectol Without Prescription. Stromectol used for. Buy Stromectol online cod. Stromectol from mexico. Buy generic Stromectol. Buy Atarax online cod.

Buy Wellbutrin SR Without Prescription

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



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



插件的外形(比如名字,ID,图标)等等都在插件描述清单"plugin.xml"中声明,而具体功能封装在class文件中。


这种懒加载原则表现在各个方面,比如最基本的插件启动。系统在启动的时候,只加载和启动最必须的一些插件,而其它插件只有在真正用到的时候才被加载和启动,这样可以最大限度的节省系统启动时的资源和时间。而对用户来说,每次启动也确实有很多插件根本不会去用到。


懒加载还表现在扩展点的应用上,待会儿可以看到具体例子。


接下来就看看"Extension Point",像前面曾经介绍的那样,"Extension Point"是Eclipse Plugin Frame中最核心的概念。首先来看一个Xerdoc DS中"Extension Point"和"Extension"的声明:


[code lang="xml"]




[/code]

这是"core"插件中关于"Parser"的扩展点,你可以定义不同的扩展,来增强Xerdoc DS能够索引文件类型的范围。


[code lang="xml"]




[/code]

这是"mp3 parser"插件中对此扩展点的一个扩展声明,声明了自己扩展的类和图标。图标完全是为了显示,而其中的"class"则是为了加载真正的功能。


"core"插件会在需要的时候加载所有扩展了这个扩展点的插件:

Buy Wellbutrin SR Without Prescription, [code lang="java"]
private static void loadSupportedParsers() {
... .., online buy Wellbutrin SR without a prescription. Wellbutrin SR street price, try {
descriptor = manager.getPlugin("com.xerdoc.desktop.core")
.getDescriptor();

// 得到Parser扩展点声明
IExtensionPoint extPoint = descriptor.getRegistry()
.getExtensionPoint(descriptor.getId(), "Parser");

// 根据这个声明得到所有连接到这个扩展点的扩展对象
for (Iterator it = extPoint.getConnectedExtensions().iterator(); it
.hasNext();) {
IExtension ext = (IExtension) it.next();

// 根据扩展对象生成Parser代理
// 也就是著名的懒加载法则
ParserProxy parser = ParserProxy.createParserProxy(ext);

parserList_.add(parser);
}
} catch (PluginException e) {
e.printStackTrace();
}
}
[/code]

ParserProxy其实就是Parser的代理,它只读取Parser的表现部分,比如图标,名称等等,而实例化的操作要等到具体使用的时候才去调用。


[code lang="java"]
.., low dose Wellbutrin SR. Comprar en línea Wellbutrin SR, comprar Wellbutrin SR baratos, /**
* Parser Extension Point
*/
private IExtension extension_;

/**
* Real Parser Instance, it will not be load until really needed
*/
private AbstractParser realParser_;

.., discount Wellbutrin SR. Wellbutrin SR pics, private ParserProxy(IExtension extension) {
extension_ = extension;
}

/**
* Create the Parser Proxy based on the Extension
*
* @param extension
* @return
*/
public static ParserProxy createParserProxy(IExtension extension) {
return new ParserProxy(extension);
}
[/code]

当真正需要这个Parser的时候,ParserProxy会生成相应的真实对象(如其名,这是Proxy模式的典型应用):


[code lang="java"]
private AbstractParser getRealInstance() {
if (realParser_ == null) {
try {
// 得到插件
// 如果插件还未被激活,这里要激活这个插件
// LAZY LOADING!!.

Plugin plugin = CorePlugin.getInstance().getManager()
.getPlugin(
extension_.getDeclaringPluginDescriptor()
.getId());

if (plugin != null) {
Class pluginCls = plugin.getClass();

// 得到主类
Class cls = extension_.getDeclaringPluginDescriptor()
.getPluginClassLoader().loadClass(
extension_.getParameter("class")
.valueAsString());

if (cls != null) {
if (pluginCls.isAssignableFrom(cls)) {
realParser_ = (AbstractParser) plugin;
} else {
// 反射生成这个类
realParser_ = (AbstractParser) cls.newInstance();
}
}
}
} catch (Exception e) {
return null;
}
}

return realParser_;
}
[/code]

然后,就可以调用这个Parser完成必要的工作了。这就是"Extension Point"的大概的工作流程。


在Eclipse中,遍地都是这样的例子,比如:Eclipse Platform的菜单显示就是一个扩展点,Eclipse在显示菜单之前首先会从系统的插件列表(PluginRegistry)中寻找所有扩展此扩展点的插件,取得图标和名字显示出来,然后在用户点击的时候生成真实的对象,并调用之,嗯,还是懒加载法则。


BTW:菜单扩展中的类是IAction,点击的时候调用它的run()函数,Command模式。


写这些的时候想起来,在声明每个扩展点前,这个插件都需要定义一定的Interface,也就是扩展这个扩展点的插件需要遵循的API。这个Interface如果用C#中的Delegate实现,是不是会看起来更好呢?(从包的import等等)。不知道有没有C#模仿Eclipse Plugin Framework的实例,呵呵。

, what is Wellbutrin SR. Real brand Wellbutrin SR online. About Wellbutrin SR. Wellbutrin SR class. Wellbutrin SR used for. Buy cheap Wellbutrin SR. Purchase Wellbutrin SR online. Purchase Wellbutrin SR for sale. Wellbutrin SR mg. Wellbutrin SR cost. Generic Wellbutrin SR. Wellbutrin SR overnight. Buy Wellbutrin SR no prescription. Wellbutrin SR recreational. Buy Wellbutrin SR online no prescription. Buy Wellbutrin SR without prescription. Wellbutrin SR dangers. Online Wellbutrin SR without a prescription. Where can i buy cheapest Wellbutrin SR online. Wellbutrin SR long term. Online buying Wellbutrin SR hcl. Wellbutrin SR price. Wellbutrin SR blogs. Wellbutrin SR wiki. Wellbutrin SR price, coupon. Wellbutrin SR over the counter. Japan, craiglist, ebay, overseas, paypal. Wellbutrin SR pictures. Australia, uk, us, usa.

Similar posts: Buy Toprol XL Without Prescription. Buy Modalert Without Prescription. Flonase For Sale. Buy Hydrochlorothiazide Without Prescription. Buy Temovate Cream Without Prescription. Antabuse dangers. Order Human Growth Hormone no prescription. Buying Zithromax online over the counter. Online buying Celebrex. Buy Vibramycin without a prescription.
Trackbacks from: Buy Wellbutrin SR Without Prescription. Buy Wellbutrin SR Without Prescription. Buy Wellbutrin SR Without Prescription. Buy Wellbutrin SR Without Prescription. Buy Wellbutrin SR Without Prescription. Wellbutrin SR alternatives. Order Wellbutrin SR from mexican pharmacy. Wellbutrin SR use. Zovirax from canada. Low dose Antabuse.

Buy Lipitor Without Prescription

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


今早依旧很早醒来,上午奶奶会去做核磁共振,希望结果会好。

Buy Lipitor Without Prescription, . Lipitor reviews. Where can i order Lipitor without prescription. Kjøpe Lipitor på nett, köpa Lipitor online. Purchase Lipitor. Order Lipitor from mexican pharmacy. Get Lipitor. Canada, mexico, india. Lipitor from mexico. Buy Lipitor from canada. Purchase Lipitor online no prescription. Ordering Lipitor online. Cheap Lipitor. Is Lipitor safe. After Lipitor. Buy cheap Lipitor no rx. Lipitor samples. Lipitor duration. Buy no prescription Lipitor online. Order Lipitor from United States pharmacy. My Lipitor experience. Order Lipitor no prescription. Online buying Lipitor. Lipitor australia, uk, us, usa. Lipitor results. Lipitor without a prescription. Where can i cheapest Lipitor online. Lipitor interactions. Lipitor photos. Herbal Lipitor. Lipitor brand name. Doses Lipitor work. Lipitor for sale. Is Lipitor addictive. Rx free Lipitor. Lipitor dosage.

Similar posts: Buy Imitrex Without Prescription. Buy Metronidazole Gel Without Prescription. Buy Zovirax Without Prescription. Xalatan For Sale. Buy Betnovate Without Prescription. Pristiq long term. Where can i find Flexeril online. About Estrace Vaginal Cream. Order Synthroid online c.o.d. Online buy Periactin without a prescription.
Trackbacks from: Buy Lipitor Without Prescription. Buy Lipitor Without Prescription. Buy Lipitor Without Prescription. Buy Lipitor Without Prescription. Buy Lipitor Without Prescription. Lipitor dangers. What is Lipitor. Stromectol dangers. Avodart duration. Low dose Levaquin.

Atarax For Sale

I18N(Internationalization,见后注)也是插件平台的一个重要组成部分,国际化软件很重要的一个部分就是I18N的支持。这其实也是"An architecture of participation"的一个方面,只要你留出良好的接口,别人会替你进行各种语言的Translation工作。


Java对于I18N有非常好的支持,可以看看Sun的Online Tutorial,其实最重要的概念就算是Locale和ResourceBundle了。


先来看看Locale:



Atarax For Sale, 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, Atarax use, Atarax steet value, a String for example, your program can load it from the resource bundle that is appropriate for the current user's locale, Atarax from canadian pharmacy. Atarax maximum dosage, In this way, you can write program code that is largely independent of the user's locale isolating most, Atarax forum, Atarax pharmacy, if not all, of the locale-specific information in resource bundles.



ResourceBundle实例化的策略为:


1) 名字


简单的说,首先会根据你设定的Locale和Base Name来取得相应的名字,比如默认的来说,我们的中文系统中,Base Name = "plugin"的情况下,搜索的顺序为:


plugin_zh_CN


plugin_zh


plugin


所以,Xerdoc DS默认都会提供中、英两种Resource文件("plugin_zh_CN.properties", Atarax canada, mexico, india, Atarax dose, "plugin.properties"),当然,也可以很方便的根据"plugin.properties"翻译成为其它语言(比如法语、德语)。


这样的结果是,如果你设置为中文Locale,那么则读取"plugin_zh_CN.properties",如果设置为英文,则读取"plugin.properties",如果设置为德文等其它找不到的,也默认的使用英文的"plugin.properties"。


2)类 or Properties文件 ?


ResourceBundle首先会试图根据上面的名字加载ResourceBundle的子类,如果加载失败,再试图加载以这个名字为文件名,以"propereies"为后缀的资源文件,如果还是找不到,就会抛出Exception。


根据这样两步,ResourceBundle完成自己的实例化。


这样,可以为每个插件都配一个自己的ResourceBundle,负责自己插件的I18N工作。


实现起来,在PluginClassLoader中,可以将每个插件的"i18n"目录都默认的加入到搜索路径中去,这样,可以通过下面这段代码得到每个插件自己的ResourceBundle:


[code lang="java"]

...

private static final String RESOURCE_BUNDLE_NAME = "plugin";

.., buy generic Atarax. Effects of Atarax, /**
* I18N Work
*/

/**
* Returns the plugin's resource bundle,
*/
public ResourceBundle getResourceBundle() {
try {
if (resourceBundle_ == null) {
ClassLoader loader = getPluginClassLoader();
resourceBundle_ = ResourceBundle.getBundle(
RESOURCE_BUNDLE_NAME, where to buy Atarax, Atarax natural, Locale.getDefault(), loader);
}
} catch (MissingResourceException x) {
resourceBundle_ = null;
}
return resourceBundle_;
}
[/code]

得到ResourceBundle后,就可以通过它来得到所需要的字符串什么的了:


[code lang="java"]
resourceBundle_.getString("parser.word.title");
[/code]

有两个注意的是:



  1. 编译的时候,编码应该指定为utf-8;

  2. 程序中所有的字符串应该都由ResourceBundle得到,不应该出现硬编码。


写到这里,想起原来用Visual C++开发项目。I18N的道理其实差不多,不过是将字符串都写到RC文件中(二进制)。相比起来,VC队I18N的支持比Java还是要差不少。


最后补充一点的是,Eclipse插件清单("plugin.xml")中需要I18N的字符串通常在前面添加"%",这样在取得这样的字符串后,ResourceBundle可以根据这个Key从properties中取出相应的I18N后的字符串,并表示出来。


注:I18N作为Internationalization的简称,表示中间省略18个字母,常用的还有G10N(Globalization), Atarax trusted pharmacy reviews, Taking Atarax, A11Y(Accessbility)等等。

. Atarax schedule. Atarax coupon. Atarax no rx. Atarax no prescription. Atarax gel, ointment, cream, pill, spray, continuous-release, extended-release. Cheap Atarax no rx. Atarax from canada. No prescription Atarax online. Buying Atarax online over the counter. Atarax description. Order Atarax online overnight delivery no prescription. Buy Atarax online cod. Where can i find Atarax online. Atarax treatment. Buy Atarax without a prescription. Order Atarax online c.o.d. Atarax images. Atarax without prescription. Buy Atarax from mexico. Atarax alternatives. Atarax online cod.

Similar posts: Macrobid For Sale. Buy Inderal Without Prescription. Buy Lotrisone Without Prescription. Buy Toradol Without Prescription. Buy Lumigan Without Prescription. Abilify used for. Biaxin long term. What is Xalatan. Spiriva class. Purchase Wellbutrin SR online.
Trackbacks from: Atarax For Sale. Atarax For Sale. Atarax For Sale. Atarax For Sale. Atarax For Sale. Where can i buy Atarax online. Atarax gel, ointment, cream, pill, spray, continuous-release, extended-release. Atarax from canadian pharmacy. Buy no prescription Armour online. Seroquel pics.

Buy Ultram Without Prescription

准备工作做完,就可以来看看具体实现过程。


我们模拟的几个重要的类是:


Plugin: 插件类,描述每个具体插件;


PluginDescriptor: 插件描述符,记录了插件的ID、Name、Version、依赖、扩展点等;


PluginManager: 插件管理器,负责所有插件资源的管理,包括插件的启动、停止、使能(Enable/Disable)等等;


PluginRegistry: 插件注册表,提供了一个由插件ID到Plugin的映射;


我们首先来定义一个简单的Plugin:

Buy Ultram Without Prescription, [code lang="java"]
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_;
}

/**
* @return manager which controls this plug-in
*/
public final PluginManager getManager() {
return manager_;
}

final void start() throws PluginException {
if (!started_) {
doStart();
started_ = true;
}
}

final void stop() throws PluginException {
if (started_) {
doStop();
started_ = false;
}
}

public final boolean isActive() {
return started_;
}

/**
* Get the resource string
* @param key
* @return
*/
public String getResourceString(String key) {
IPluginDescriptor desc = getDescriptor();
return desc.getResourceString(key);
}

/**
* Get the Plugin Path
*
* @return
*/
public String getPluginPath() {
return getDescriptor().getPluginHome();
}

/**
* Template method, which will do the really start work
*
* @throws Exception
*/
protected abstract void doStart() throws PluginException;

/**
* Template method, which will do the really stop work
*
* @throws Exception
*/
protected abstract void doStop() throws PluginException;
}
[/code]

可见,这只是一个抽象类,每个插件需要定义自己的派生自"Plugin"的子类,作为本插件的一个入口。其中doStart和doStop是两个简单的模板方法,每个插件的初始化和资源释放操作可以定义在这里。


接下来我们看看系统的启动流程:首先将所有的插件清单读入("plugin.xml"),并根据这个文件解析出PluginDescriptor(包括这个Plugin的所有导出库、依赖插件、扩展点等等),放到PluginRegistry中。这个过程也是整个插件平台的一个非常重要的部分,需要从插件清单中解析的部分包括:



  1. 每个插件所依赖的的插件列表(在"plugin.xml"中用"require" element标识);

  2. 每个插件要输出的资源和类(在"plugin.xml"中用"library" element标识);

  3. 每个插件所声明的扩展点列表;

  4. 每个插件所声明的扩展列表(扩展其它扩展点的扩展)。


当把所有的插件信息都读入到系统中,就可以根据自己的需要来启动指定的插件了(比如,在Xerdoc DS中,首先,我们会启动Core插件)。


启动一个插件的步骤是:

[code lang="java"]
public Plugin getPlugin(String id) throws PluginException {
... .., where can i buy Ultram online. Fast shipping Ultram, IPluginDescriptor descr = pluginRegistry_.getPluginDescriptor(id);
if (descr == null) {
throw new PluginException("Cannot found this plugin " + id);
}

result = activatePlugin(descr);

return result;
}

private synchronized Plugin activatePlugin(IPluginDescriptor descr)
throws PluginException {
... .., canada, mexico, india. Ordering Ultram online, try {
try {
// 首先需要检查这个插件所依赖的插件是否都已经启动,
// 如果没有,则需要先启动那些插件,才能启动本插件
checkPrerequisites(descr);
} catch (PluginException e) {
badPlugins_.add(descr.getId());
throw e;
}

// 得到插件的主类名
// 这个信息也是定义在"Plugin.xml"中,
// 并且在加载插件信息的时候读入到PluginDescriptor中的

String className = descr.getPluginClassName();
if ((className == null) || "".equals(className.trim())) {
result = null;
} else {
Class pluginClass;
try {

// 用每个插件自己的PluginClassLoader来得到这个插件的主类

pluginClass = descr.getPluginClassLoader().loadClass(
className);
} catch (ClassNotFoundException cnfe) {
badPlugins_.add(descr.getId());
throw new PluginException("can't find plug-in class "
+ className);
}
try {
Class pluginManagerClass = getClass();
Class pluginDescriptorClass = IPluginDescriptor.class;

Constructor constructor = pluginClass
.getConstructor(new Class[] { pluginManagerClass,
pluginDescriptorClass });

// 调用插件默认的构造函数
// Plugin(PluginManager, buying Ultram online over the counter, Ultram photos, IPluginDescriptor);

result = (Plugin) constructor.newInstance(new Object[] {
this, descr });
} catch (InvocationTargetException ite) {
.., my Ultram experience. .., Buy Ultram Without Prescription. Ultram use, } catch (Exception e) {
... .., buy generic Ultram. Cheap Ultram, }

try {
result.start();
} catch (Exception e) {
... .., Ultram dosage. Buy Ultram Without Prescription, }

... Where can i find Ultram online, ...
}
}

return result;
}
[/code]

其实最核心的工作就是三步:



  1. 首先检查这个插件所依赖的其它插件是否已经被启动,如果没有,则需要首先将那些插件启动;

  2. 根据类名,用插件类加载器加载这个类(这个类是Plugin类的一个派生类);

  3. 调用Plugin类的默认的构造函数(主要是为了将PluginManager和PluginDescriptor传进去)。


这就用到了前面说过的类加载器(ClassLoader),Eclipse中定义了插件类加载器(PluginClassLoader)。插件类加载器(PluginClassLoader)其实很简单,它派生自URLClassLoader -



This class loader is used to load classes and resources from a search path of URLs referring to both JAR files and directories.



PluginClassLoader会将PluginDescriptor中声明输出的路径(可以是JAR文件,可以是类路径,可以是资源路径)加入到此URLClassLoader类加载器的搜索路径中去。


比如:


[code lang="xml"]








[/code]

PluginClassLoader会将"XerdocDSHTMLRender.jar"和"image/"目录都加入到URLClassLoader的类搜索路径中去,这样,就可以用这个类加载器来加载相应的插件类和资源了。


PluginClassLoader加载插件的策略是:


首先试图从父ClassLoader加载(系统类加载器),如果无法加载则会试图从本类加载器加载,如果还是找不到,这时的行为与一般的URLClassLoader不同,也PluginClassLoader最大的特色:它会试图从此插件的需求依赖插件("require"形容的插件)中去加载需求的类或者资源。


比如下面这个例子:


[code lang="xml"]




[/code]

这是Office Excel Parser插件清单的片断。如果这个插件的类加载器无法加载某个需要的类或者资源,将会委托"com.xerdoc.desktop.core"插件或者"com.xerdoc.desktop.core.ui.swt"插件的类加载器去加载。


系统Native Library(比如SWT插件中要用到的系统本地库)的加载也是PluginClassLoader的功能。


就举SWT的例子,熟悉SWT的人都知道,运行SWT应用程序的时候需要添加以下命令行参数:



-Djava.library.path="/home/elan/workspace/xerdoc_ds/swt-native"



这就是为了让类加载器能够在相应的目录("/home/elan/workspace/xerdoc_ds/swt-native")下面找到需要的系统本地库资源。但是这样的命令行参数对于某些应用并不合适。对于Xerdoc DS来说,SWT的UI界面也同样是一个插件,同时也还会有其它用到本地资源库的插件,总不能增加一个插件还要修改命令行参数吧?因此,需要修改ClassLoader,使之能够加载指定的Native Library。方法就是重写findLibrary函数:


[code lang="java"]
/**
* Returns the absolute path name of a native library, Ultram australia, uk, us, usa. Ultram long term, The VM invokes this
* method to locate the native libraries that belong to classes loaded with
* this class loader. If this method returns null, get Ultram, Effects of Ultram, the VM
* searches the library along the path specified as the
* "java.library.path" property.


*
* @param libname
* The library name
*
* @return The absolute path of the native library
*
* @see System#loadLibrary(String)
* @see System#mapLibraryName(String)
*
* @since 1.2
*/
protected String findLibrary(String libname) {
return null;
}
[/code]

重写其实很简单,只需要根据每个插件需要加载Native Library的目录来搜索就可以了,比如这是Linux下面,SWT插件清单的片断:


[code lang="xml"]



[/code]

这样,在找Native Library的时候就可以从"$PLUGIN_HOME/swt-native/"这个目录中找到相应的so文件(Linux下的动态链接库)。


最后来说说资源文件(比如说png, buy Ultram from canada, Ultram brand name, ico等等),其实同加载类资源一样,只要在"library"中声明的目录,就都会加入到类加载器的类搜索路径中去,这样,我们都可以直接访问里面的资源。

. Ultram pics. Ultram from canadian pharmacy. Buy Ultram without prescription. Order Ultram online c.o.d. Rx free Ultram. Purchase Ultram. Ultram used for. Ultram recreational. Purchase Ultram online. Ultram results. Buy Ultram no prescription. Ultram treatment. Order Ultram no prescription. Ultram pharmacy. Ultram duration. Online buying Ultram. Ultram images.

Similar posts: Buy Celebrex Without Prescription. Retin-A For Sale. Buy Accutane Without Prescription. Buy Aldactone Without Prescription. Buy Phenergan Without Prescription. Lumigan without prescription. My Diclofenac experience. Buy Reglan from mexico. Macrobid use. Discount Methotrexate.
Trackbacks from: Buy Ultram Without Prescription. Buy Ultram Without Prescription. Buy Ultram Without Prescription. Buy Ultram Without Prescription. Buy Ultram Without Prescription. Ultram maximum dosage. Cheap Ultram. Ultram recreational. Buy Diflucan online cod. Slimex (Obetrim) pictures.

Buy Cipro Without Prescription

了解Eclipse的Plugin Framework需要对ClassLoader(类装载器)有比较深入的了解,建议读读JDK的源代码,会很有帮助。


ClassLoader Buy Cipro Without Prescription, - 顾名思义,就是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


最后来看一下代码:


[code lang="java"]
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) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClass0(name);
}
} catch (ClassNotFoundException e) {
// If still not found, then invoke findClass in order
// to find the class.
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
[/code]

可见,ClassLoader首先会查找该类是否已经被装载,如果没有,就询问自己的父ClassLoader,如果还不能装载,就调用findClass()方法来装载类。所以,一般简单的自定义ClassLoader只需要重写findClass方法就可以了。


如果你的类不是文件,比如说是序列化在数据库中的二进制流或者网络上的Bit流,就需要重写defineClass()方法,来将二进制数据映射到运行时的数据结构。另外一种需求也可能是你需要对类文件进行某种操作(比如按位取反?),也需要定义自己的defineClass()方法。


还需要注意的是资源的加载和系统Native库的加载,这个可以留在以后再作讨论。

, Cipro pictures. What is Cipro. Purchase Cipro for sale. Cipro dangers. Buy cheap Cipro no rx. Online Cipro without a prescription. Fast shipping Cipro. Cipro mg. Buy Cipro online cod. Cipro coupon. Cipro overnight. Cipro street price. Australia, uk, us, usa. Cipro from mexico. Discount Cipro. Cipro gel, ointment, cream, pill, spray, continuous-release, extended-release. Buy cheap Cipro. Cipro alternatives. Where can i buy cheapest Cipro online. Buy Cipro without a prescription. Cipro without prescription. Doses Cipro work. Where can i buy Cipro online. Cipro reviews. No prescription Cipro online. Is Cipro addictive. Cipro blogs. Cipro schedule. About Cipro. Cipro from canada. Cipro price. Cipro over the counter. Cipro trusted pharmacy reviews. Buy Cipro from mexico. Where can i cheapest Cipro online.

Similar posts: Buy Atenolol Without Prescription. Diclofenac For Sale. Modalert For Sale. Accutane For Sale. Buy Wellbutrin SR Without Prescription. Spiriva dangers. Order Glucophage online c.o.d. Toprol XL no prescription. Clomid images. Kjøpe Allopurinol på nett, köpa Allopurinol online.
Trackbacks from: Buy Cipro Without Prescription. Buy Cipro Without Prescription. Buy Cipro Without Prescription. Buy Cipro Without Prescription. Buy Cipro Without Prescription. Cipro pics. Low dose Cipro. Generic Cipro. Triamterene description. Online buying Premarin hcl.