当前页面: 开发资料首页 → Eclipse 专题 → 使用 Update Manager 更新 RCP 应用程序
摘要: Rich Client Platform,顾名思义,是一个构建富客户端应用的平台,基于 Eclipse的插件体系结构,由一系列所需要的最小插件集合所组成。一般来说,一个 RCP 应用程序在发布时有两种类型:基于插件(Plug-in)和基于功能部件(Feature)的。为了使用 Eclipse平台所提供的丰富功能(比如 Update,Web Start),我们必须开发基于功能部件的 RCP 应用。两者之间的转换也是非常容易的。这篇文章使用 Eclipse3.2 版本作为开发平台,提供了一个小型的 RCP 应用例程,并使用 Update Manager 来实现产品的自动更新。
简介
Eclipse RCP 是 Eclipse Platform 的一个子集(如图),从 Eclipse3.0 版本开始,Eclipse项目组对代码进行了重构,将 IDE 与 Workbench(工作台)彻底分离,实现了一个 Generic Workbench,使得基本的 RCP 应用中不再有 IDE 的影子。构成 RCP 的最小插件集合包括Runtime,OSGi,SWT,JFace,Workbench 等一些必须的部件,还有一些是可选部件(比如 Help, Update 等,如下图所示),所有这些插件使得我们的 RCP 程序可以完成绝大部分的企业应用需求。
Update 是 RCP 的一个可选部件,它的主要功能包括:
1)更新已经安装了的功能部件;
2)寻找新的功能并进行安装;
3)对已安装的功能部件进行配置。
这篇文章会围绕 Update 这个可选插件,使用 PDE 来开发一个具有自动更新功能的小型 RCP 应用程序。
建议读者先阅读下面的一些链接,以便对 RCP 有一个清晰的概念:
http://www.eclipse.org/articles/Article-RCP-1/tutorial1.html
http://www.eclipse.org/articles/Article-RCP-2/tutorial2.html
http://www.eclipse.org/articles/Article-RCP-3/tutorial3.html
开始
首先,我们需要一个插件,用来启动 RCP 应用,这个插件会包含基本的应用扩展点,请参考上面的链接。这里,我们使用 PDE 来创建一个 Eclipse 自带的具有一个视图(View)的例子程序。
启动 Eclipse,打开菜单File->New->Project, 选中Plug-in Project 并且键入工程名,比如 com.ibm.csdl.guardian.examples.。在下一页中,填写此插件的基本属性信息,对于问题"Would you like to create a rich client application?" 选择Yes. 最后,使用所提供的模板 "RCP application with a view" 并接受缺省设置来创建一个RCP的插件工程。
浏览插件配置文件plugin.xml, 我们会发现PDE创建了一个application的扩展,这个扩展将会作为RCP应用的程序入口,并且会被另外一个扩展:Product所使用(见本文产品部分)。
</td></tr></table>
功能部件
为了使用应用程序的更新功能,我们必须为RCP定义一个或多个功能部件(Feature)。打开菜单File->New->Project, 选中 Feature Project 并且键入工程名称,比如 com.ibm.csdl.guardian.examples.feature。在下一页,选中刚才所创建的插件工程: com.ibm.csdl.guardian.examples,作为此功能部件所包含的插件。
对于Eclipse3.2版本,一个可执行的RCP应用至少应包含下面的这些插件(Windows平台):
com.ibm.icu,
org.eclipse.core.commands,
org.eclipse.core.contenttype,
org.eclipse.core.expressions,
org.eclipse.core.jobs,
org.eclipse.core.runtime,
org.eclipse.equinox.common,
org.eclipse.equinox.preferences,
org.eclipse.equinox.registry,
org.eclipse.help,
org.eclipse.jface,
org.eclipse.osgi,
org.eclipse.swt,
org.eclipse.swt.win32.win32.x86,
org.eclipse.ui.forms,
org.eclipse.ui.workbench,
org.eclipse.ui.
并且,为了使用RCP应用程序的更新功能,还需要包含下面的几个插件:
org.eclipse.update.configurator,
org.eclipse.update.core,
org.eclipse.update.ui.
所以,同时选中这些插件来完成功能部件工程的创建。
最后,键入一个更新站点的URL和站点名称,Update Manager会使用这些信息来连接一个或多个更新站点。在这里,URL既可以使用网络地址,也可以使用本地的文件系统地址。下面是功能部件的配置文件feature.xml的典型内容:
…</td></tr></table>[Enter Feature Description here.] [Enter Copyright Description here.] [Enter License Description here.] …
包装成产品
RCP应用程序在启动时,需要一个application的扩展点或一个product的扩展点作为入口。同时,为了简化RCP应用程序的打包过程,我们使用一个产品配置文件来对例子程序进行设置。其中product 扩展点是基于application扩展点的。
在PDE的Package Explorer视图中, 选中刚才所创建的RCP插件工程,打开菜单 File->New->Product Configuration,键入一个产品配置文件名称,比如examples.product ,并且使用缺省设置来完成产品配置的创建工作。
在产品配置编辑器(product configuration editor)中,指定产品名称,比如examples。点击New按钮,使用缺省设置或指定一个产品标识,在RCP启动时会使用这个ID作为应用程序的入口。特别地,对于产品配置类型,要选择基于功能部件(features),否则无法使用更新功能。概览(Overview)页内容大致如下图所示:
切换到配置页,将我们的功能部件com.ibm.csdl.guardian.examples.feature 添加到部件列表中。如果必要,可以对其它页的属性信息进行更改,这里我们使用缺省值。最后,在插件配置文件plugin.xml中,添加product扩展:
</td></tr></table>
现在,我们可以切换到概览页,点击 "Launch the product" 来测试我们的RCP应用:
Update Manager
这只是一个很简单的RCP应用,我们可以在此基础上添加透视图及视图以实现各种各样的功能,但这些不是本文的重点,请参考其它资料。这里,我们将在此应用的基础上添加软件更新功能。
添加更新菜单
首先,应该有一种方式,用来呼叫出更新管理器,我们使用菜单来实现这个功能。在类 ApplicationActionBarAdvisor中,修改 makeActions 方法,,添加一个Update Action:
… exitAction = ActionFactory.QUIT.create(window); register(exitAction); updateAction = createUpdateAction(window); register(updateAction); …</td></tr></table>
修改 fillMenuBar 方法,将Update菜单添加到Help主菜单下:
… MenuManager helpMenu = new MenuManager("&Help",IWorkbenchActionConstants.M_HELP); menuBar.add(helpMenu); helpMenu.add(updateAction); …实现软件更新功能
在类 UpdateAction 中,实现 run 方法如下: 记得将 ore.eclipse.update.ui 这个插件添加到com.ibm.csdl.guardian.examples 插件的所需插件列表中,否则上面的类将不能通过编译。 好了,我们的RCP应用已经具备了软件更新功能!是不是感觉很简单?是的,Eclipse平台一个优美的地方就是将很多功能部件都设计成为一个Framework,具有很高的可重用性,用户只需做很少量的工作就能实现很复杂的功能,Eclipse的Update Manager就是一个很好的例子。再次启动我们的RCP应用,已经可以使用软件更新功能了,如下图。不过,因为更新站点并没有准备好,所以不会发现新的版本,下面会详细介绍这方面的内容。 打包RCP应用
到目前为止,这个例子程序一直是作为一个Eclipse的运行时应用来运行的,我们需要将其打包到Eclipse之外,形成一个单独的可执行的应用程序。得益于Eclipse的插件体系结构,打包的过程将非常简单。当然,我们可以自己编写脚本代码去完成这个步骤,但是在PDE中,提供了一个导出工具,使得我们可以更加方便的实现这个过程。首先确认插件工程下的build.properties文件包含了所有必需的资源文件,因为PDE的导出向导将会使用Ant并读取这个配置文件来对每个插件进行打包工作。 现在使用产品配置编辑器打开examples.product文件,切换到概览页,点击 "Eclipse Product export wizard" ,弹出导出向导配置窗口。使用 examples.product 作为配置文件并键入应用程序的主目录,比如ExampleRCP,PDE在打包时将会创建这个应用程序的根目录。另外,建议将"Synchronize before exporting"选中,以便在打包时检查配置文件是否与所包含的插件相匹配。最后,指定存放此RCP应用的目的文件夹并开始导出过程: 现在,我们可以进入刚才所指定的目的文件夹,通过双击可执行文件(在Launcher页进行配置)来启动应用程序。 准备新版本
假设一下产品已经发布出去,但是客户却想在树上显示四个节点,我们使用Update Manager来实现这个新的需求。 首先,需要在类View 中更改源代码: 下一步需要创建一个更新站点的工程。打开菜单 File->New->Project,选择 Update Site Project,并且为此工程指定一个名称,比如com.ibm.csdl.guardian.examples.site. 在站点清单编辑器中,切换到Site Map页面,将不同的功能部件切分为类别。在Archives页面,设定更新站点的URL及描述信息,URL可以使用本地文件系统,或其它网络协议,比如HTTP等。为了方便测试,这里我们使用本地文件系统目录作为更新站点。 文件site.xml 最终的样子: 在新版本编译通过之后,修改RCP应用包含的所有插件及功能部件的版本号,确保比发布给客户的版本要高(不要修改插件的ID),以表示有更新版本可用。 在插件com.ibm.csdl.guardian.examples 的MANIFEST.MF文件中: 在feature.xml文件中: 因为我们在功能部件的配置中使用了缺省设置 "Synchronize versions on build" ,所以PDE的打包工具会自动为所生成的二进制Jar文件生成正确的文件名以显示新的版本号。 现在的site.xml 文件内容: 在站点清单编辑器的Site Map页面中,选中所要更新的功能部件并且点击 "Build" ,PDE会在此站点工程目录下生成所需要的更新功能部件及插件。将文件site.xml,目录features 和plugins 拷贝到feature.xml中所指定的URL(在这里是本地文件系统), 再次启动我们的例子RCP应用,现在即可以使用"Find and Install"菜单来对产品进行更新: 点击Next,会出现许可证描述信息(在feature.xml指定),只有选择接受许可证之后,下载更新包及安装过程才会继续:
下载并安装完毕之后,会提示重新启动RCP应用,这时即可以看到软件更新之后的效果: 自动更新
为了使更新过程更加智能,Update Manager还支持软件的自动更新,并提供了很多选项来对更新时间进行设置。我们所需要做的很简单,只需要将插件 org.eclipse.update.scheduler 添加到 feature.xml 的插件包含列表中并添加一个菜单来呼叫出自动更新的配置项页面: 从这里可以看出,Update Manager 使用org.eclipse.ui.preferencePages 这个扩展来对更新选项进行配置: 配置完成后,当更新条件满足时,RCP会自动弹出一个窗口,提示用户是否存在新的版本可用并进行安装。 有一点需要注意: 在更新到新的版本后(其实是下载新版本的插件Jar包),老版本的Jar 文件不会被自动删除,因为有时更新会出现问题,用户还可以再使用老的版本。对于这个问题,请参考下面这个链接来得到更多信息: https://bugs.eclipse.org/bugs/show_bug.cgi?id=70990. 管理所安装的功能部件
一个大型的企业级RCP应用通常会包含大量的功能部件,如果有的功能部件暂时不会被使用,刚可以将其置为不可用状态,这样既可以加速应用程序的启动过程,也会对RCP应用的性能有所提高。Update Manager也提供了这个功能,我们的例子程序使用一个菜单来呼叫出管理窗口: 在类 ManageAction 中,实现 run 方法如下: 当点击此菜单后,即会弹出产品配置窗口,可以方便的管理所安装的功能部件: 结论
使用Update Manager不仅可以方便的给RCP应用程序添加软件更新功能,还可以对所安装的功能部件进行方便的管理。得益于Update Manager的框架结构(其它Eclipse的组件也是如此),我们还可以利用其所提供的API,对产品的更新功能进行定制,使得产品具有自己的特色。 下载 参考资料
关于作者<table border="0" cellspacing="0" cellpadding="0" width="100%"><tr><td colspan="3"></td></tr><tr align="left" valign="top"><td> 马吉荣,IBM中国软件开发中心DB2 II Team,软件工程师,现主要从事GUI Test Automation的框架研究及开发,DB2相关产品的测试工作。研究兴趣包括Eclipse,MDA,XML及数据库等相关领域。联系方式:majirong@cn.ibm.com.
<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td class="code-outline">
BusyIndicator.showWhile(window.getShell().getDisplay(), new Runnable() {
public void run() {
UpdateJob job = new UpdateJob("Search for update", false, false);//$NON-NLS-1$
UpdateManagerUI.openInstaller(window.getShell(), job);
PlatformUI.getWorkbench().getProgressService().showInDialog(window.getShell(), job);
}
});
</td></tr></table>
<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td class="code-outline">
…
public Object[] getElements(Object parent) {
// add the fourth node to satisfy the customer's new requirement.
return new String[] { "One", "Two", "Three", "Four" };
}
…
</td></tr></table>
<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td class="code-outline">
</td></tr></table>
<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td class="code-outline">
…
Bundle-Version: 1.0.1
…
</td></tr></table>
<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td class="code-outline">
<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td class="code-outline">
</td></tr></table>
<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td class="code-outline">
…
preferencesAction = ActionFactory.PREFERENCES.create(window);
register(preferencesAction);
…
MenuManager windowMenu
= new MenuManager ("&Window", IWorkbenchActionConstants.M_WINDOW);
menuBar.add(windowMenu);
windowMenu.add(preferencesAction);
…
</td></tr></table>
<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td class="code-outline">
…
manageAction = createManageAction(window);
register(manageAction);
…
MenuManager helpMenu = new MenuManager("&Help", IWorkbenchActionConstants.M_HELP);
helpMenu.add(manageAction);
…
</td></tr></table>
<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td class="code-outline">
BusyIndicator.showWhile(window.getShell().getDisplay(), new Runnable() {
public void run() {
UpdateManagerUI.openConfigurationManager(window.getShell());
}
});
</td></tr></table>
<table border="0" cellspacing="0" cellpadding="0" width="100%"><tr><td>
</td></tr></table><table class="no-print" cellspacing="0" cellpadding="0" align="right"><tr align="right"><td>
<table border="0" cellpadding="0" cellspacing="0"><tr><td valign="middle">
</td><td valign="top" align="right"></td></tr></table></td></tr></table>
<table border="0" cellspacing="0" cellpadding="0" width="100%"><tr><td>
</td></tr></table><table class="no-print" cellspacing="0" cellpadding="0" align="right"><tr align="right"><td>
<table border="0" cellpadding="0" cellspacing="0"><tr><td valign="middle">
</td><td valign="top" align="right"></td></tr></table></td></tr></table>
↑返回目录
前一篇: 探索 Eclipse 的嵌入式富客户端平台
后一篇: IBM WebSphere 开发者技术期刊: 为 WebSphere 平台部署 Eclipse 富客户端应用程序