级别: 中级 Robert Schneider, IT 专家,IBM Software Services for Lotus,IBM Deutschland GmbH, IBM
2009 年 8 月 03 日 本文介绍了如何为 IBM® Lotus Notes® 8.0 以及更高版本创建一个扩展。该扩展使您能够通过在 Help 菜单中选择某个菜单项,就可以在新的窗口中打开一个预配置的 URL(例如,Lotus Notes Multimedia Library)。
Lotus Notes 8.0 以及更高版本的客户端为建立用户界面与内容页面之间的链接提供了非常出色的方法;比如,它将一个书签放在 launcher 栏上您最喜欢的文件夹中。但是,有时您希望内容启动程序可以以更加 “集成” 的方式显示在 Lotus Notes 客户端中,比如,通过将其链接到 Lotus Notes 菜单栏中的某个菜单项。对于新的 Lotus Notes Multimedia Library,一些客户表达了他们的愿望,希望使用这种集成方式从 Lotus Notes 客户端的 Help 菜单直接启动插件。
我们使用的扩展是一个插件,可用于扩展基于 IBM Lotus® Expeditor 的框架,该框架构成了新的 Lotus Notes 8.0 以及更高版本客户端的基础。该插件还利用了 Managed Settings 框架,此框架使您能够预配置打开的 URL 并锁定这些优选参数,此后用户就无法修改这些内容。本文提供了有关此插件的源代码。
本文向您展示了我们开发这个插件的过程,它使您能够在 Lotus Notes Help 菜单中创建一个菜单项,然后使用它打开一个浏览器窗口(可以在选项卡中打开,也可以在新打开的窗口中打开),在此浏览器窗口中将显示一些可配置的内容(Lotus Notes Multimedia Library URL),并可以通过 IBM Lotus Domino® 策略进行管理。
developerWorks® 的一些文章已经探讨了为 IBM Lotus Expeditor、IBM Lotus Sametime® 8.0(和更高版本)以及 Lotus Notes 8.0(和更高版本)创建插件的基本内容,这些内容全部涉及 Lotus Expeditor 和 Eclipse。从本文的参考资料部分可以找到这些文章的链接。
本文并不准备总结实现最终插件所需的每一个步骤,相反,我们将只关注关键的步骤。该插件的源代码包含在本文的下载小节中,您可能希望重用它们而不是从头编写。我们进行归档的主要步骤包括:
- 提供允许您输入设置的首选项页面;主要包含将被启动的 URL。
- 创建一个 Eclipse 用户界面(UI)命令,提供一个菜单项来调用命令处理程序。
- 打开一个浏览器窗口(可以在新的选项卡中打开,也可以在一个新打开的窗口中打开),加载该 URL 的内容。
- 提供一种方法来将插件部署到您的 Lotus Notes 用户。
先决条件
对于开发工作,我们使用 Lotus Expeditor 6.2 工具箱附带的 IBM Rational® Software Architect 版本 7.5.1。Lotus Expeditor 6.2 工具箱附带的任何 Eclipse 3.4+ 安装也可以工作得很好。开发插件的主要目的是启动 Lotus Notes Multimedia Library;但是,由于任何 URL 都可以通过它启动,我们为它起了一个更加中立的名称:com.ibm.notes.webview。
创建新的插件项目
要开始工作,首先选择 File - New - Project 并使用最喜欢的设置创建一个新的 Client Services Project。名称和说明符并不重要。例如,我们将项目命名为 com.ibm.notes.webview,其他值保留默认设置,并且只清除了一个选项,即 New Project 向导的最后一页中的 Create a plug-in using one of the templates 选项。
首选项、首选项页面、初始化程序以及如何遵从管理设置
Lotus Notes Multimedia Library 是客户经常在其内部服务器上提供给他们的 Lotus Notes 用户的内容,因此使用一个首选项页面将使您能够编辑该 URL。
创建好项目后,我们使用 Eclipse 扩展点向导(如图 1 所示)来使用首选项初始化程序创建一个首选项页面。
图 1. Extension Point Selection 窗口
图 2 展示了示例首选项页面。输入以下值:
- 在 Java Package Name 字段中,输入 com.ibm.notes.webview。
- 在 Page Class Name 字段中,输入 PreferencePage。
- 在 Page Name 字段中,输入 Web View。
图 2. Sample Preference Page 窗口
该向导生成一个 PreferencePage 类,该类将扩展 FieldEditorPreferencePage 类。由于我们希望更细粒度地控制该页面中的元素,因此将其修改为一个常规 PreferencePage 并创建必要的方法来使用所需的控件填充窗口。
由于客户可能希望修改首选项在窗口中显示的名称,我们稍后使用了 Eclipse 的插件本地化特性来将该页面的文本放到一个属性文件中。您现在可以在项目的插件的 plugin.properties 文件中编辑页面的名称。
[…]
prefpagename=Notes Multimedia Library
[…]
在 createContents 中,我们查询 Managed Settings 框架来确定设置是否被管理员锁定。如果设置没有被锁定,我们将为它们启用控件。清单 1 的代码片段展示了如何完成这一任务。
清单 1. 设置管理设置的启用标记
[...]
private ManagedSettingsScope scope = null;
[...]
scope = new ManagedSettingsScope();
[...]
// check whether this is a locked managed setting and if so,
// disable the buttons to prevent user input
if (scope.isReadOnly(Activator.PLUGIN_ID,
PreferenceConstants.P_OPENMODE))
{
newTabButton.setEnabled(false);
newWindowButton.setEnabled(false);
}
[...]
|
我们为此插件实现了两个设置:
- 使用一个标记来表示用户是否希望在新的选项卡或新显示的窗口中打开库内容
- 应当显示的内容的 URL
如果使用本文下载小节提供的文件中的代码,您的首选项页面应当如图 3 所示。
图 3. 首选项页面
Eclipse UI 命令
为插件创建了首选项功能之后,我们再次查看 plugin.xml 文件的扩展页面并使用另一个向导(如图 4 所示)实现所需的一切功能,使菜单项能够提供一种调用代码的方法。
图 4. 扩展点向导
图 5 展示了示例命令组成页面。输入以下值:
- 在 Java Package Name 字段内,输入 com.ibm.notes.webview。
- 在 Handler Class Name 字段内,输入 CommandHandler。
- 在 Message Box Text 字段内,输入 Hello, Eclipse world 作为占位符。您稍后很可能将删除这个消息框。
图 5. 示例命令构成页面
单击 Finish 后,您将发现已经为您填充了一些新的扩展点。参见图 6 和图 7 中的详细信息。
图 6. 比较向导选项与最终选项:扩展点由向导自动创建
图 7. 比较向导选项与最终选项:删除插件不需要的内容后的扩展点
Eclipse 提供了一种谨慎的方来来定义此类命令。在人们看来,Eclipse 过程类似于:
- 我希望执行某些任务,因此我将其命名为 do.it(org.eclipse.ui.commands/command)。
- 这是 do.it 的逻辑和实际代码(org.eclipse.ui.handlers/handler)。
- 我希望使用某些键盘快捷键来调用 do.it(org.eclipse.ui.bindings/key)。
- 我希望可以在 UI(org.eclipse.ui.menus/menuContribution)的菜单中的某个位置(org.eclipse.ui.menus/menu)和/或工具栏的某个位置(org.eclipse.ui.menus/toolbar)中选择 do.it。
可以看到,我们删除了工具栏项并只对命令使用一个菜单项。我们还修改了菜单项的显示位置。向导生成一个菜单 URL menu:org.eclipse.ui.main.menu?after=additions。这个菜单 URL 将在 Help 菜单之前显示一个新的顶级菜单,Help 菜单中包含一个菜单项和示例命令。将该命令修改为 menu:help?before=additions 之后,此菜单项将显示在 Help 菜单中的 Dynamic Help 项之下。
在对所有扩展点进行了适当定义后,您需要特别关注 CommandHandler 类的 execute() 方法中的代码。清单 2 展示了图 4 所示的扩展点页面中的向导生成的代码。
清单 2. org.eclipse.core.commands.AbstractHandler 类的 execute() 方法
/**
* the command has been executed, so extract the needed
* information from the application context.
*/
public Object execute(ExecutionEvent event) throws ExecutionException {
IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event);
MessageDialog.openInformation(
window.getShell(),
"Webview Plug-in",
"Hello, Eclipse world");
return null;
}
|
打开浏览器窗口以显示 URL 的内容
让我们复习一下:目前为止我们已经创建了一个首选项页面来保存希望显示给用户的 URL,并且有一个可以在 UI 中进行选择的操作,该操作可以执行其中一个类的某个方法。接下来,我们需要打开一个选项卡或一个新的窗口并嵌入一个浏览器的实例,该浏览器实例指向我们的 URL。
在 Eclipse 中,我们将为我们的内置浏览器实例创建一个视图,将它放到一个透视图中,并调用平台来打开这个透视图。但是 Eclipse 和 Lotus Notes and Lotus Expeditor 之间有一个不同之处。那就是透视图已经打开并且我们只需要在其中打开一个选项卡。为了执行这个步骤,Lotus Expeditor 提供了一个允许我们完成此步骤的特殊 API:SwitcherService-API。
此时,我们需要拓宽本文的内容来理解由 Eclipse 的 OSGi 框架提供的一些服务。如果您希望为其他人提供一些功能,那么可以创建一个扩展点,通过对它创建扩展,其他插件就可以链接到这个扩展点。这种方式就是用来扩展 Eclipse 功能的最著名方式。当然,还可以使用其他方法实现这一点;根据您的特定计划,这些方法可能在某些方面优于扩展点模式。其中一个备选方法就是 OSGi 平台的服务框架。该框架通过在平台内实现独立的类加载程序,可以控制向其他类提供某个类的实例。
通过使用 OSGi 框架的服务部分,您可以这样表示您的计划:“我拥有一些可以作为服务提供的功能,并且该功能在名为 a.b.c.MyService 的类中实现。”希望使用该服务的用户可以调用另一个 API 并表示,“我需要一个 a.b.c.MyService 服务,因此为我提供该服务的一个实例。”
Lotus Expeditor 团队就是采用这种方法实现了 SwitcherService,该服务允许您以新选项卡、分组选项卡或完整的新窗口的形式打开窗口。要获得该服务的特性的概述,请阅读 Javadoc,了解 com.ibm.rcp.ui.launcher 包,特别是接口 SwitcherService 和类 SwitcherParam。
要利用 SwitcherService API,首先需要获得该服务的一个实例。如果 BundleContext 的实例被传递给 Activator 类的 start()- 方法,那么您才可以获得服务实例。因为将 Activator 类作为插件内部服务实体是常见的做法,所以我们在 Activator 方法中放入一个公共方法,该方法允许插件的其他类请求 SwitcherService 的一个实例。清单 3 展示了这个方法的代码。
清单 3. 用来检索 SwitcherService 实例的代码
/**
* Obtain an instance of the SwitcherService from the Expeditor platform
*
* @return the ss
*/
public SwitcherService getSwitcherService()
{
if (ss == null)
{
ServiceTracker st;
// retrieve a SwitcherService instance through
// the ServiceTracker
st = new ServiceTracker(context,
"com.ibm.rcp.ui.launcher.SwitcherService",
null);
st.open();
ss = (SwitcherService) st.getService();
st.close();
}
return ss;
}
|
注意,这一方法在下面这些情况下会出错:
- 在平台初始化的早期
- 在 Lotus Sametime 而不是在完整的 Lotus Expeditor 或 Lotus Notes 版本上执行插件,因为 Lotus Sametime 并不提供 SwitcherService 服务
如果检测到返回值为 null,那么需要相应地检查方法和操作的结果。
在 command handler 类中,您现在必须做三件事:
- 读取您的首选项来获得要打开的 URL,以及一个用于表示是在新选项卡还是在新窗口中打开的标记。
- 设置一个内嵌的浏览器组件,将所有必需的组件包含到初始 URL 中。
- 以用户希望的方式打开窗口。
第一步,读取首选项,如清单 4 所示。
清单 4. 从首选项框架读取设置的代码
/**
* the command has been executed, so extract the needed information
* from the application context.
*/
public Object execute(ExecutionEvent event) throws ExecutionException
{
logger.entering(getClass().getName(), "execute");
ManagedSettingsScope scope = new ManagedSettingsScope();
IEclipsePreferences prefs = scope.getNode(Activator.PLUGIN_ID);
String url = prefs.get(PreferenceConstants.P_URL, "about:blank"); //$NON-NLS-1$
boolean isOpenInNewWindow = (prefs.get(PreferenceConstants.P_OPENMODE,
null)
.compareToIgnoreCase(PreferenceConstants.P_OPENMODE_WINDOW) == 0) ? true
: false; //$NON-NLS-1$
|
下一步是配置内嵌浏览器实例,如清单 5 所示。设置的名称及其值的含义应当十分清楚。如果希望读取有关这个浏览器组件的所有可能的设置,那么在 Javadoc 的 com.ibm.rcp.ui.browser.BrowserPreference-class 部分查找它们的名称和设置(参见相关 链接)。
清单 5. 设置内嵌浏览器的配置
Map<String, String> configMap = new HashMap<String, String>();
configMap.put(BrowserPreference.ID, Activator.PLUGIN_ID);
configMap.put(BrowserPreference.INITIAL_URL, url);
// TODO We could make all these settings configurable
configMap.put(BrowserPreference.ENABLE_BOOKMARKS, "false"); //$NON-NLS-1$
configMap.put(BrowserPreference.ENABLE_CONTEXT_MENU, "false"); //$NON-NLS-1$
configMap.put(BrowserPreference.ENABLE_HELP, "false"); //$NON-NLS-1$
configMap.put(BrowserPreference.SHOW_BOOKMARK, "false"); //$NON-NLS-1$
configMap.put(BrowserPreference.SHOW_HISTORY, "false"); //$NON-NLS-1$
configMap.put(BrowserPreference.SHOW_HOME, "false"); //$NON-NLS-1$
configMap.put(BrowserPreference.SHOW_PAGE_CONTROL, "false"); //$NON-NLS-1$
configMap.put(BrowserPreference.SHOW_PRINT, "false"); //$NON-NLS-1$
configMap.put(BrowserPreference.SHOW_TOOL_BAR, "false"); //$NON-NLS-1$
configMap.put(BrowserPreference.SHOW_URL_ENTRY, "false"); //$NON-NLS-1$
BrowserFactory.setBrowserConfigMap(Activator.PLUGIN_ID, configMap);
|
最后,需要命令 Lotus Expeditor 或 Lotus Notes 打开窗口。参见清单 6 中的代码。
清单 6. 在新透视图中打开一个视图的主要代码
try
{
SwitcherParam param;
SwitcherResult result;
IWorkbenchWindow currentWindow = HandlerUtil
getActiveWorkbenchWindowChecked(event);
switcherService = Activator.getDefault().getSwitcherService();
if (switcherService == null)
{
logger
.severe("Cannot obtain an instance of the SwitcherService!");
return null;
}
logger.fine("About to open URL " + url + " in new "
+ ((isOpenInNewWindow) ? "window" : "tab"));
// if you set twoCalls to true, the newly opened window will
// receive a tab. If you set it to false, the newly opened window
// will NOT have a tab.
boolean twoCalls = false;
if (twoCalls)
{
if (isOpenInNewWindow)
{
param = new SwitcherParam(null);
param.setMode(SwitcherParam.NEW_WINDOW);
param.setTitle(Messages.WindowTitle);
result = switcherService.show(param);
currentWindow = result.getWindow();
}
param = new SwitcherParam(currentWindow);
param.setViewId(Activator.VIEW_ID);
param.setSecondaryId(Activator.PLUGIN_ID);
param.setTitle(Messages.WindowTitle);
result = switcherService.show(param);
} else
{
param = new SwitcherParam(currentWindow);
if (isOpenInNewWindow)
{
param.setMode(SwitcherParam.NEW_WINDOW);
}
param.setViewId(Activator.VIEW_ID);
param.setSecondaryId(Activator.PLUGIN_ID);
param.setTitle(Messages.WindowTitle);
result = switcherService.show(param);
}
} catch (WorkbenchException e)
{
logger
.log(
Level.SEVERE,
"Error when trying to open the web view window in command handler",
e);
}
return null;
}
|
可以看到,有两种方式可以打开一个窗口。您可以使用一个调用打开窗口及其内容,或者可以使用另一个调用,其中包含两个调用,一个调用用来打开窗口,另一个调用用来显示内容。每种方法执行不同的任务,并且它们的功能未经过归档。图 8、9 和 10 将解释它们之间的不同之处。
图 8. 比较各种用来打开视图的模式:使用选项卡
图 9. 比较各种用来打开视图的模式:使用一个新窗口(一个调用)
图 10. 比较各种用来打开视图的模式:使用一个新窗口(两个调用)
将插件部署到一组 Lotus Notes 用户中
目前为止,您已经创建了插件的最重要部分,现在将其部署到用户中去。可以使用多种方法将这种插件分发和部署到不同社区。最基本的方法是创建一个更新站点,其中提供了一个包含有您的插件的特性并要求用户从更新站点安装此特性。这种更新站点可以是一个远程系统,用户可以通过 HTTP 访问特性和插件,也可以是一个压缩归档,在一个文件中包含了所有必需的内容,比如,这个文件可以从 USB 驱动中进行本地安装。
Lotus Notes 用户可以使用更加方便的方法部署这个特性;他们可以使用 Lotus Notes 客户端的小部件框架,在 Lotus Notes 8.0.1 及更高版本中都提供该框架。这种方法要求您在更新站点中提供自己的特性,但是该站点可以是一个基于 NSF 的更新站点。要通过小部件框架触发特性的安装,可以向用户发送一个 XML 文件,他们可以将这个文件拖拽到 My Widgets 侧栏中,或者在部件分类中为他们分配默认的小部件类别,部件分类是通过 Lotus Notes and Lotus Domino 策略自动安装到 Lotus Notes 客户端的。您将需要在其中一台 Lotus Domino 服务器上设置一个小部件类别。
在本例中,我们提供了一个 XML 文件,如清单 7 所示,您可以将其发送给用户。他们只需要将该文件拖拽到 My Widgets 侧栏。
清单 7. 小部件部署清单文件中的 XML 数据
<?xml version="1.0" encoding="UTF-8"?>
<webcontextConfiguration version="1.1">
<palleteItem contributeToSideshelfOnStartup="false"
id=" lotus.multimedia.library" imageUrl=""
modified="false" providerId="com.ibm.rcp.toolbox.prov.provider.ToolboxProvisioning"
title=" IBM Lotus Notes Multimedia Library"
url="http://www.yourhost.com/some/folder/com.ibm.notes.webview.
updatesite/site.xml">
<preferences/>
<data>
<installManifest>
<![CDATA[
<install version="1.0.0">
<installfeature default="true" id="com.ibm.notes.webview.feature"
name="notes.webview" required="false" show="true" version="1.0.0">
<requirements>
<feature download-size="1000" id="com.ibm.notes.webview.feature"
match="perfect" shared="true" size="1000"
url="http://www.yourhost.com/some/folder/com.ibm.notes.webview.
updatesite/site.xml"
version="1.0.0"/>
</requirements>
</installfeature>
</install>
]]>
</installManifest>
</data>
</palleteItem>
</webcontextConfiguration>
|
将清单 7 所示的代码放入到 XML 文件中并将文件发送给您的用户。如果他们将该文件拖拽到 My Widgets 侧栏,那么将自动触发来自更新站点的特性安装。重启 Lotus Notes 客户端后,菜单应当如图 11 所示。
图 11. 新菜单项的外观
本文的下载小节提供了插件的源代码、插件特性和更新站点。如果希望重新命名您的首选项页面和菜单项,只需要修改插件的 plugin.properties 文件中的两行代码。
该插件只能处理一个菜单项和一个 URL 的显示。您需要提供两个或更多个菜单项,以打开两个或更多个不同的 URL,您可以向 org.eclipse.ui.commands、org.eclipse.ui.bindings 和 org.eclipse.ui.menus 扩展点添加项。您可以处理一个命令处理程序;只需检查传入命令处理程序的命令 ID 并相应地采取操作。要在首选项页面中编辑另一个 URL,可以复制用来为 URL 生成编辑控件的代码并查看读取和写入值的位置,然后使用新 ID 复制代码。
结束语
在本文中可以看到,不需要编写大量代码就可以将内容集成到 Lotus Notes 客户端。了解如何使用底层 Eclipse 的出色扩展点框架和 Lotus Expeditor 框架,这是最重要的部分。该插件的代码可以帮助您理解其中一些特性,允许您使用新的 Lotus Notes 客户端更好地完成工作。
下载 | 名字 | 大小 | 下载方法 |
|---|
| com.ibm.notes.webview.updatesite.zip | 14KB | HTTP | | com.ibm.notes.webview.zip | 30KB | HTTP |
参考资料 学习
获得产品和技术
讨论
关于作者  | |  | Robert Schneider 是位于德国的 IBM Lotus 软件服务部门的 IT 专家。他是若干项目的首席架构师,这些项目在 Lotus Expeditor 和 Lotus Notes 8.0 以及更高版本的基础上为德国大型行业客户开发解决方案。Robert 在计算机行业拥有超过 20 年的经验,曾经在 Digital Research 和 Novell 等公司工作。自从 1993 年加入 Lotus 后,他曾担任过各种职位,全部与技术销售支持有关。最近,他转向了服务部门,主要研究新的基于 Java 的客户端平台。您可以通过 Robert.Schneider@de.ibm.com 联系他。
|
对本文的评价
|