使用 Quickr 服务开发 IBM Lotus Quickr Firefox 连接器

本白皮书将详细探讨如何使用 Lotus Quickr Representational State Transfer(REST)服务为 IBM Lotus Quickr 构建自定义的 Mozilla Firefox 连接器。示例的所有源代码都附带提供在本文档中。

Shun Zhang, 软件工程师, EMC

Shun Zhang 是 IBM 北京的一名软件工程师,主要关注 Lotus Quickr、Web 2.0 和 SOA 技术。


developerWorks 投稿作者

Hui Jian He, 资深软件工程师, EMC

Hui Jian He 是 IBM 北京的高级软件工程师,从 Lotus Quickr 产品诞生之初便一直致力于相关事宜。在此之前,他曾负责 IBM Workplace Collaboration Services、WebSphere Portal 和 Workplace Services Express 产品。



2010 年 3 月 05 日

1. 概述

IBM Lotus Quickr 是专用于知识共享和协作的 Web 2.0 团队协作软件。它提供了内容存储库、内容管理和团队协作功能以及一些连接器,允许用户在桌面应用程序中访问 Lotus Quickr。

借助 Quickr 连接器,用户可以在熟悉的桌面应用程序中操作 Lotus Quickr 服务器上的文档,这些应用程序包括 IBM Lotus Notes®、IBM Lotus Sametime®、Microsoft® Windows® Explorer、Microsoft Outlook、Microsoft Office 和 Lotus Symphony。

Quickr 连接器通过一组已发布的远程 Simple Object Access Protocol(SOAP)和 REST 接口与 Lotus Quickr 内容交互。Lotus Quickr 鼓励客户或业务合作伙伴基于这些开放接口构建应用程序。

本文将通过一个示例展示如何使用这些服务接口来构建自定义连接器。我们选择使用 Firefox 作为基本应用程序示例,因为 Firefox 的丰富的编程接口为其提供了良好的可扩展性;此外,还有一个成熟的开发人员社区为其提供支持。

通过这个 Firefox 连接器,客户可以在 Firefox 中操作多个 Quickr 服务器中的文档。此外,由于 Firefox 是跨平台的,因此它是第一款支持在非 Windows 平台上运行的连接器。并且,由于 Lotus Quickr、IBM FileNet® Content Manager Collaboration Edition 和 IBM Content Manager Collaboration Edition 也提供了一组相同的远程服务,因此该连接器也可以支持所有这些服务器。


2. Lotus Quickr 内容服务

Quickr 内容服务支持创建、管理、更新、搜索、查询和删除 Quickr 内容,允许用户访问和操作 Lotus Quickr 中的内容。

Lotus Quickr REST Services 是基于开放标准和 Web 2.0 技术而设计的,用户只需具备对现有 Web 技术(如 HTTP 和 XML)的基本理解便可构建应用程序。

这些服务基于 Atom 联合格式(由 RFC 427 定义,专用于访问 Lotus Quickr 中的内容),同时基于新兴的 Atom 发布协议(由 RFC 5023 定义,专用于向 Lotus Quickr 发布内容)。有关 REST 服务的更多详细信息,请参阅 developerWorks 文章:“IBM Lotus Quickr REST 服务简介”

目前,Lotus Quickr 提供的服务如表 1 所示。

表 1. Lotus Quickr 服务
发布服务支持功能:
8.0文档服务操作面向文档的组件类型(文档库)
8.0搜索服务发现多种内容组件类型的信息
8.1位置服务操作协作组件容器
8.1模板服务操作位置的初始结构
8.1策略服务控制服务器资源使用
 Web 内容 
8.1服务控制 Web 内容

在这个连接器中,我们将使用文档服务。如果您希望使用其他服务来扩展 Firefox 连接器,那么可以利用如表 1 所示的所有服务。


3. Firefox 扩展

Firefox 提供了一个扩展模型,可允许第三方代码模块,即扩展,修改核心浏览器的功能或外观,以及添加新特性或用户界面 (UI) 元素。

扩展包含 3 个部分:(1) XUL 文档,用于描述 UI 的布局,(2) CSS 指令,用于定义界面元素的外观,以及 (3) JavaTMScript 代码,用于确定这些元素的行为。有关更多信息,请参阅 Mozilla Extensions 页面。

连接器扩展架构如下所示(参见图 1):

  • XUL UI。使用 XUL 语言定义连接器用户界面,包括启动菜单项、主用户界面、上下文菜单、添加库对话框和属性对话框。
  • 控制模块。与用户界面 (UI) 输入及 IO 模块交互,接收用户输入并驱动 IO 模块从远程服务器获取数据,然后解析数据以便呈现在用户界面中。JavaScript 是实现语言。

IO 模块。首先,它使用 IBM dojo Atom 扩展与服务器通信,以便获取/发布 Atom 提要/条目。然后,它使用 Mozilla 编程接口读取/写入存储在本地文件系统中的库。

图 1. Firefox 连接器架构
图 1. Firefox 连接器架构

此连接器目前支持四种类型的服务器。另外,IBM 业务合作伙伴已经在其他平台上实现了 Quickr 内容服务(有关这些解决方案的更多信息,请参见 Lotus Business Partners and Solutions Catalog)。注意,针对 Domino 实现的 Quickr 服务应该为 8.2 或更高版本。


4. Lotus Quickr Connector for Firefox

Lotus Quickr Connector for Firefox 是一个 Firefox 扩展,它提供了 Lotus Quickr 连接器的许多特性。它可以根据服务器列出文档库,可以根据库名筛选库,并且可以方便地与 Quickr Web UI 交互。

此连接器的主要特性如下所示:

所支持的服务器/平台:

  • 服务器:Lotus Quickr、IBM FileNet Content Manager Collaboration Edition、IBM Content Manager Collaboration Edition
  • 操作系统:可运行 Firefox 的所有平台

基本连接器操作:

  • 浏览库内容
  • 通过邮件发送内容
  • 下载文档
  • 在多个服务器的库之间拖放文档

更多:

  • 将喜好内容添加到书签
  • 将 Web 内容(如来自 Google 的图像)直接拖放到库中

下载 “Screen record of Lotus Quickr connnector for Firefox”获取演示。


5. Quickr Firefox 连接器解析

现在,我们将讨论 Firefox 连接器的基础知识。

5.1 入门

首先,您可能需要了解关于构建 Firefox 连接的基本概念和技术需求,请访问 Mozilla.org 并阅读“构建扩展”。

然后,要为 Quickr 连接器部署源代码,请执行以下步骤:

  1. 使用喜好的集成开发环境(IDE)创建一个空项目。将项目名称指定为 quickrconnector@ibm.com。
  2. 从下载部分下载 quickrconnector@ibm.com.zip 文件。
  3. 将所有文件解压到项目的根文件夹中。项目结构应如图 2 所示。
图 2. 项目目录结构
图 2. 项目目录结构

所有 XUL 和 JavaScript 文件都位于 content 文件夹中,i1 8n 文件位于 locale 文件夹中,图像和 CSS 文件位于 skin 文件夹中。

Firefox 要识别和运行扩展需要 Chrome.manifestinstall.rdf 文件,并且这两个文件应该位于项目的根文件夹中。创建文件的方法如 5.2 节所示。

5.2 将扩展部署到 Fire fox

在将扩展部署到 Firefox 之前,我们需要查看上面提到的 chrome.manifestinstall.rdf 文件,然后在 Firefox 扩展目录下创建一个到扩展项目的链接。

chrome.manifest

chrome.manifest 位于项目根目录下,其内容如清单 1 所示。

清单 1. chrome.manifest 内容
content	quickrconnector content/
overlay	chrome: //browser/content/browser.xul
    chrome: //quickrconnector/content/overlay.xul
locale quickrconnector en-US locale/en-US/
locale quickrconnector zh-CN locale/zh-CN/ 
skin quickrconnector classic/1.0 skin/

content 元素声称,对于 chrome 包 quickrconnector,我们可以在 content/ 位置(注意,“/” 是必需的)找到其内容文件,它是相对 chrome.manifest.位置的路径。

在必要时,我们需要借助 Firefox 来合并覆盖层(overlay)和浏览器窗口。因此,添加 overlay 元素,通知 Firefox 在 browser.xul 加载时将 overlay.xul 合并到 browser.xul 中。由于我们只有一个启动条目,因此只需要添加一个 overlay 元素。

Locale 元素描述连接器所支持的语言,而 skin 元素则描述使用哪种皮肤。

install.rdf file

install.rdf 也位于项目根目录下,并且其内容如清单 2 所示。

清单 2. install.rdf 内容
<?xml version="1.0"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:em="http://www.mozilla.org/2004/em-rdf#">
    <Description about="urn:mozilla:install-manifest">
        <em:id>quickrconnector@ibm.com</em:id>
        <em:name>Quickr Connector Demo</em:name>
        <em:version>1.0.6</em:version>
        <em:description>Lotus Quickr Connector Firefox Plugin</em:description>
        <em:creator>Sean Zhang</em:creator>
        <em:contributor>Jeff He</em:contributor>
        <em:homepageURL>http://quickr.tap.ibm.com</em:homepageURL>
        <!-- Firefox -->
        <em:targetApplication>
            <Description>
                <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
                <em:minVersion>1.5</em:minVersion>
                <em:maxVersion>3.0.*.*</em:maxVersion>
            </Description>
        </em:targetApplication>
    </Description>
</RDF>

连接器的 em:id 元素必须为 GUID,或者采用电子邮件地址形式(无论是否有效)。目标应用程序的 em:id 是 Firefox 的 ID,并且是固定的。

创建链接文件

要部署扩展,在 <Firefox installation path> /extensions 目录下创建一个名称为 quickrconnector@ibm.com 的文件(注意,它与 install.rdf 文件中的 em:id 的名称相同),并添加项目文件夹的路径作为其内容。

测试和调试

目前为止,我们已经完成了部署简单扩展所需的所有步骤。重启 Firefox 之后,您应该可以在 Tools 菜单中找到 Quickr Connector 菜单项,并且

侧栏应该随主 UI XUL 文件 quickrconnector.xul 一同打开。

要调试 Firefox 扩展,首先建立一个扩展开发环境,比如 Extension Developer 扩展,以便于在重新载入 XUL 更改时能够节省时间。否则,您必须重新启动 Firefox 应用程序。

有关 chrome.manifest、install.rdf 和 构建 Firefox 扩展 的详细信息,请访问 Mozilla 开发中心。

5.3 添加用于启动连接器扩展的菜单项

现在,您已经基本理解了如何构建和部署 Firefox 连接器扩展。接下来,我们将讨论如何添加用于启动连接器的菜单项。

首先,我们需要创建一个覆盖 XUL 文件,以便于将 Quickr 菜单项添加到 Tools 菜单。该文件,即 overlay.xul,位于 content 目录中,其内容如清单 3 所示。

清单 3. XUL 文件内容
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://quickrconnector/skin/overlay.css" 
    type="text/css"?>
<!DOCTYPE overlay SYSTEM "chrome://quickrconnector/locale/overlay.dtd">
<overlay id="quickrconnector-overlay" 
    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
    <menupopup id="menu_ToolsPopup">
        <menuitem observes="viewQuickrSidebar" 
	    label="&quickrconnector;" accesskey="&quickrconnector.accesskey;" 
	    key="key_gotoQuickrConnector"/>
    </menupopup>
    <broadcasterset id="mainBroadcasterSet">
        <broadcaster id="viewQuickrSidebar" autoCheck="false" 
	    sidebartitle="&quickrconnector;" type="checkbox" group="sidebar" 
	    sidebarurl="chrome://quickrconnector/content/quickrconnector.xul" 
	    oncommand="toggleSidebar('viewQuickrSidebar');"/>
    </broadcasterset>
</overlay>

该文件通知 Mozilla 加入区域文件 chrome://quickrconnector/locale/overlay.dtd,默认在 Tools 末尾处添加一个菜单项,然后定义此菜单项的操作。

toggleSidebar 是用于打开侧栏的内置函数。sidebarurl 属性表示连接器主 UI XUL;单击菜单项之后,侧栏会随 sidebarurl 打开。我们将在稍后详细讨论主 UI。

区域文件

如果查看 overlay.xul 中的 menuitem 元素,您会发现 labelaccesskey 属性的值以 “&” 开头并以 “;” 结束。这表示该属性的实际值来自区域文件,并且 “&” 和 “;” 之间的字符串只是用于获取该值的键。

为了支持特定的语言和区域,您需要创建相应的区域文件。举例来说,要支持美国区域的英语,需要在 locale 目录下创建一个 en-US 文件夹,创建上面提到的 overlay.dtd 文件并输入以下内容:

<!ENTITY quickrconnector "Quickr Connector">
<!ENTITY quickrconnector.accesskey "Q">

5.4 连接器的主 UI

侧栏内部的主 UI 是一个 XUL 页面(参见图 3)。quickrconnector.xul 文件位于 content 目录中。当然,由于 UI 中必定有一些本地化的文本,因此 quickrconnector. dtd 用于将区域键值对数据添加到相应的区域目录中。

图 3. 连接器扩展主 UI
图 3. 连接器扩展主 UI

侧栏共有 4 个部分:

  • 标题。实际上,主 UI XUL 中并未设置标题;取而代之的是,它是在单击菜单项时设置的。
  • 工具栏。hbox 是一个可水平组织元素的容器。第一个功能元素是一个超时文本框,并且由它的 timeout 属性设置为 500ms,因此在编辑文本框时每隔 500ms 会触发一次 oncommand 操作。

    然后,我们将添加两个图像元素,并将它们的 onclick 值设置为 addLibrarycollapseAll,如清单 4 所示。(您可以通过函数名了解它们在单击后执行的任务。)

    清单 4. 工具栏内容
    <hbox align="center">
        <label value="&find.label;" control="search-box"/>
        <textbox id="search-box" flex="1" type="timed" timeout="500"
            oncommand="searchLibrary();"/>
        <image id="addLibraryImage" onclick="addLibrary();" 
            src="../skin/images/addLibrary.gif" />
        <image id="collapseAllImage" onclick="collapseAll();" 
            src="../skin/images/collapseAll.gif" />
    </hbox>
  • 库树。这是主 UI 中最为重要的元素。context 表示上下文菜单 id。onkeypress 值表示,按下 ENTER 键之后,节点的 URL 会在当前选项卡中打开。

    onclick 指示单击鼠标左键时的操作。您还可以设置另外两个选项,其一是 tab,用于打开一个新选项卡,其二是 window,用于打开一个新 Firefox 实例。

    由于树稍微有些复杂,因此我们决定使用自定义树视图,其中树的子元素仅仅是一些占位符(参见清单 5)。我们将通过编程来动态呈现树。

    清单 5. 自定义树视图
    <tree id="quickrTree" flex="1" class="plain"
        context="quickrContextMenu"
        onkeypress="if (event.keyCode == 13) openURLIn('current');"
        onclick="handleQuickrConClick(event);" hidecolumnpicker="true"
        ondraggesture="if (event.originalTarget.localName == 
        'treechildren') nsDragAndDrop.startDrag(event, quickrDNDObserver);"
        ondragdrop="nsDragAndDrop.drop(event,quickrDNDObserver)"
        canDrop="nsDragAndDrop.canDrop(event,quickrDNDObserver);">
        <treecols id="quickrTreeCols">
            <treecol flex="1" id="Name" persist="sortActive sortDirection"
                hideheader="true" primary="true"/>
            </treecols>
        <treechildren/>
    </tree>

    您可以访问 Mozilla 开发中心,了解关于 XUL 树和 自定义树视图 的更多信息。

  • 上下文菜单。当您单击鼠标右键时会弹出上下文菜单(或者由 Firefox 的设定决定)。弹出菜单是自动显示的,但在菜单呈现之前,您可以执行一些任务,比如隐藏特定菜单项,其方法是将 popupshowing 属性设置为需要调用的函数(参见清单 6)。
    清单 6. 上下文菜单示例
    <popup id="quickrContextMenu" popupshowing="buildContextMenu(event);">
        <menuitem id="miOpen" 
            label="&openLinkInWindow.label;" 
    	accesskey="&openLinkInWindow.accesskey;" 
    	default="true" oncommand="openURLIn('current');"/>
        …………
        …………
        <menuseparator id="pre-properties-separator"/>
        <menuitem id="miProperties" 
            label="&properties.label;" 
    	accesskey="&properties.accesskey;" 
    	oncommand="showProperties();"/>
    </popup>

目前为止,我们已经讨论了可在 UI 中显示的元素。我们还需要通知 Firefox 加载区域文件和一些独立的脚本文件,比如 dojo 文件:

<script type="application/x-javascript" src="dojo12/dojo/dojo.js"/>

控制模块

控制模块是在 UI 后台运行的一组功能。可以使用各种语言来实现这些功能,比如 C++、Java 和 JavaScript;但是,JavaScript 可能是最为方便的。

您不需要执行任何额外的编译或其他工作来通过 JavaScript 部署代码,并且由于它能满足我们的需求,因此我们使用它作为实现语言。注意,大多数控制代码都位于 content/quickrconnector.js

5.5 初始化连接器

目前为止,我们已经讨论了连接器的基本 UI 组件。现在,我们将讨论连接器与 Quickr 服务器的交互方式。

初始化函数 QuickrConnectorCommonInitquickrconnector.xul 中被设定为页面的 onload 属性值。最重要的地方是读取配置文件,以便获取 Quickr 文档库的列表。

库数据作为 JSON 对象存储在配置文件。FileIO.js 使用 Mozilla 文件 IO 封装文件读/写操作。读取配置文件中的数据时,其内容将转换为 JavaScript 变量,以便于通过连接器来访问它:

var filein = FileIO.open(gConfigFilePath); 
var data = FileIO.read(filein);
var data = eval(data);

其中引入了一个 quickrcon. QuickrLib 类来保存库的元数据(参见清单 7)。这里忽略了存取函数(即 setters 和 getters)。

清单 7. 文档库元数据
dojo.declare ("quickrcon.QuickrLib",null, {
    constructor: function(title,url,feedUrl,server,user,password){ 
        this.title = title;
        this.url = url;
        this.feedUrl = feedUrl;
        this.server = server;
        this.user = user;
        this.password = password;
    }
}

Quickr 文档库元数据包括库包、用于在浏览器中打开库的视图 URL、用于获取其子文件夹/文档的提要 URL、所属服务器以及登录凭证信息。

载入配置文件之后,库将被填充到一个数组中,即 quickrcon.QuickrLib 对象的 libs。然后,系统为树视图构建一个数据模型。我们将在 5.6.3 小节“构建数据模型”中详细讨论相关内容。

注意,quickrcon.QuickrLib 类的定义位于 content/dojo12/quickrcon/QuickrData.js 文件中。

5.6 树实现

树采用模型-视图-控制器 (MVC) 模式。我们将通过解析树视图接口来探究模型的本质。

5.6.1 树视图

树视图是树对象调用以便呈现树的接口。gTree View 实现了这个接口。表 2 选取自 nsITreeView 页面,其中显示了需要实现的方法和属性,以便于正确呈现 Quickr 内容的树视图。本节将在稍后详细讨论这些方法。

表 2. 方法概述

void getRowProperties(in long index, in nsISupportsArray properties);
void getCellProperties(in long row, in nsITreeColumn col, in nsISupportsArray properties);
void getColumnProperties(in nsITreeColumn col, in nsISupportsArrayproperties);
boolean isContainer(in long index);
boolean isContainerOpen(in long index);
boolean isContainerEmpty(in long index);
boolean isSeparator(in long index);
boolean isSorted();
boolean canDrop(in long index, in long orientation);
void drop(in long row, in long orientation);
long getParentIndex(in long rowIndex);
boolean hasNextSibling(in long rowIndex, in long afterIndex);
long getLevel(in long index);
AString getImageSrc(in long row, in nsITreeColumn col);
long getProgressMode(in long row, in nsITreeColumn col);
AString getCellValue(in long row, in nsITreeColumn col);
AString getCellText(in long row, in nsITreeColumn col);
void setTree(in nsITreeBoxObject tree);
void toggleOpenState(in long index);
void cycleHeader(in nsITreeColumn col);
void selectionChanged();
void cycleCell(in long row, in nsITreeColumn col);
boolean isEditable(in long row, in nsITreeColumn col);
boolean isSelectable(in long row, in nsITreeColumn col);
void setCellValue(in long row, in nsITreeColumn col, in AString value);
void setCellText(in long row, in nsITreeColumn col, in AString value);
void performAction(in wstring action);
void performActionOnRow(in wstring action, in long row);
void performActionOnCell(in wstring action, in long row, in nsITreeColumn col);

属性:

属性类型描述
rowCount long Readonly:树中的总行数(包括不在屏幕中的行)。
selection nsITreeSelection 选定此视图。

5.6.2 树模型分析

以下方法和属性对于数据模型分析非常实用:

  • rowCount:返回树所含节点的数量,包括所有的服务器、库、文件夹和文档节点。
  • isContainer():返回节点是否可包含子节点。数据模型中包含文件节点这样的窗口节点和文档节点这样的非容器节点。
  • getLevel():返回节点的级别,用于确定在呈现时的缩进水平。
  • getCellText():返回节点的标签。
  • getImageSrc():返回用于表示节点的图像。

清单 8 定义了通用树节点,其中省略了存取方法(setters和getters):

清单 8. 通用树节点
dojo.declare("quickrcon.TreeNode",null, {
    constructor: function(lib,title,nodeType,url,entry,parent,level) {
        this.lib = lib;
        this.title = title;
        this.url = url;
        this.nodeType = nodeType;
        this.parent = parent;
        this.entry = entry;
        this.level = level == null? 0 : level;
        this.imageSrc = null;
    }
}

有4 种类型的树节点:

quickrcon.TreeNode.DOCUMENT = "document";
quickrcon.TreeNode.FOLDER = "folder";
quickrcon.TreeNode.LIBRARY = "library";
quickrcon.TreeNode.SERVER = "server";

图 4 展示了树模型类的设计,其中文件夹和库几乎拥有相同的属性和方法,并且它们都可以是 FolderNode 实例。

ServerNode 中的属性要比 FolderNode 多一些,因为它还将存放服务器上的用户名和密码。ServerNode 也是树的根节点,这表示它的级别为 0。

图 4. 树模型类
图 4. 树模型类

注意,所有类定义都包含在 content/dojo12/quickrcon/Tree.js 中。

5.6.3 构建数据模型

配置文件中只包含库条目,不过可以通过传递库来计算服务器。相应的函数是 getAllServerNodes,它用于使用服务器 URL 作为键并使用服务器上的一组库作为值来建立映射关系。

用数据结果的术语来说,数据模型是一个“林”。根节点即服务器节点,二级子节点即库节点,低级节点则包括文件夹和文档节点。

gDataModel 是在初始化连接器并构建林之后构建的,其中包括两个层次,即服务器节点和库节点(参见清单 9)。

清单 9. gDataModel
gDataModel = new Array();
for(var i in serverNodesMap.keys) {
    var server = serverNodesMap.keys[i];
    var nodes = serverNodesMap.getServerNodes(server).nodes;
    var serverNode = new quickrcon.ServerNode(null,server,quickrcon.TreeNode.SERVER,null);
    serverNode.setLevel(0);
    serverNode.setChildren(new Array());
    serverNode.setUser(serverNodesMap.getServerNodes(server).user);
    serverNode.setPassword(serverNodesMap.getServerNodes(server).password);
    gDataModel.push(serverNode);
    for(var j = 0; j < nodes.length; j++){ 
        var node = nodes[j];
        serverNode.getChildren().push(node);
	node.setParent(serverNode);
    }
}

单击库或文件夹之后,数据模型将得到更新,这将触发从远程服务器获取提要/条目。

5.6.4 更新树视图

如上所述,树视图需要一个数组来存储树节点,以便行索引可用于获取节点数据。因此,我们需要预订数据模型的传递,这可以通过迭代调用 buildTreeData 函数来实现(参见清单 10)。

清单 10. buildTreeData 函数
gTreeData = new Array();
var buildTreeData = function(node) {
    if (node == null) return;
    gTreeData.push (node);
    if(node.isContainer() && node.getOpen() && node.getChildren() ) { 
	for (var i = 0; i < node.getChildren().length; i++) {
	    buildTreeData(node.getChildren()[i]);
        }
    }
};

gTreeData 就绪之后,我们将更新 gTree ViewrowCount 并刷新树视图。更新树视图的操作封装在 updateTree View 方法中。

5.6.5 使用 REST 服务

Quickr 提供了一些符合 ATOM 规范的 REST 服务。我们将使用 IBM 的 dojo Atom 扩展(在 1.3 版中贡献到 dojo 开源社区中)来简化 Atom 服务请求/响应的处理任务。清单 11 中的代码片段演示了如何使用它。

清单 11. 使用中的 dojo Atom 扩展
function getChildrenData(node,preventCache){
    var handle = new FeedHandler();
    handle.currentNode = node;
    var atomIO = new ibm_atom.io.atom.AtomIO();
    atomIO.user = node.getLib() .getUser();
    atomIO.password = node.getLib().getPassword();
    var url = null;
    if (node.getNodeType () == quickrcon.TreeNode.LIBRARY 
        || node.getNodeType() == quickrcon.TreeNode.FOLDER) {
        url = node.getFeedUrl();
        if(url == null)
            return;
        url += "?pagesize=10000&pageSize=10000";
        node.setStatus ("waiting");
        searchLibrary();
        atomIO.getFeed(url, dojo.hitch(handle, "handleFeed"), 
            function (err) { node.setStatus ("done") ;alert (err) ;} );
    }
}

Quickr 库提要服务默认返回 10 个条目,而 FileNet® 和 Content Manager 内容服务也是如此。由于我们需要在一个请求中返回所有条目,因此在以上代码中,我们添加了一个 pagesize 参数,并将它的值设定为很大(10000)。注意,Content Manager 服务器的页面大小参数是 pageSize。我们可以添加 pagesizepageSize 来支持所有服务器。此外还需要注意以下事项:

  • node.setStatus("waiting") 会通知树视图在树视图下次更新时为节点设置一个加载图像。
  • searchLibrary 将过滤掉要显示的库并更新树视图。
  • getFeed 使用 dojo.xhr 来调用 REST 服务。此函数的三个参数为服务 URL、响应正常时的回调以及出错时的错误回调。

FeedHandlerhandleFeed fu函数的包装器(参见清单 12)。当服务响应正常时,提要处理程序将解析响应 Atom 文档并创建文件夹/文档节点,将它们集成到数据模型中,将父节点的状态更改为完成并在最后调用 searchLibrary 来更新树视图。

清单 12. Feedhandler
var FeedHandler = function() {
    this.handleFeed = function(feed, ioArgs) {
        var cnode = this.currentNode;
        cnode.setOpen(true);
        cnode.setStatus("done");
        var entries = feed.entries;
        if (entries != null) {
            cnode.children = new Array();
            for(var i = 0; i < entries.length; i++) {
                var entry = entries[i];
                try{
                    var title = entry.title.value;
                    var category = entry.getCategories()[0];
                    var type = category.term.value;
                    var url = null;
                    if (entry. links) {
                        for(var j = 0; j < entry.links.length; j++) {
                            var link = entry.links[j];
                            if(link.rel && link.rel.value == "alternate") {
                	        url = link.href.value;
                                break;
                            }
                        }
                    }
                    var node = null;
                    if (type == quickrcon.TreeNode.FOLDER) {
                        node = new quickrcon.FolderNode(cnode.getLib(), 
			    title,quickrcon.TreeNode.FOLDER, url, entry, cnode, 
			    cnode.getLevel() + 1,null,false);
                    } else if (type == quickrcon.TreeNode.DOCUMENT) {
                        node = new quickrcon.DocumentNode(cnode.getLib(), title, 
			    quickrcon.TreeNode.DOCUMENT, url, entry, 
			    cnode, cnode.getLevel() + 1);
                    }
                    if(node != null)
                        cnode.getChildren() .push (node);
                }catch(e){}
            }
        cnode.getChildren().sort(function(a,b) {
            if(a.getNodeType() != b.getNodeType())
                return a.getNodeType() > b.getNodeType() ? 1 : -1;
	    else
                return a.getTitle().toLowerCase() > b.getTitle().toLowerCase() ? 1 : -1;
        } );
    }
    searchLibrary();
    };
};

构建上下文菜单

总共有 13 个菜单项,但一次并不会显示所有的菜单项。buildContextMenu 函数将确定上下文菜单弹出时显示的项目。首先,它会检查是否有选中的节点。如果没有,则只能显示添加库项目,如果有,则会检查节点类型并确定应该显示哪些项目。

5.6.6 操作函数

几乎所有连接器函数都是由菜单项触发的。选中某个菜单项之后会调用以下相应函数:

  • addLibrary。 为 Add Library 对话框准备参数并调用 window. openDialog 打开该对话框。单击此对话框的 OK 按钮时,程序会调用回调以便将添加的库保存到配置文件并更新数据模型和树视图:
    var params = {
        atomIO :atomIO, 
        callback:callback, 
        servers :gDataModel,
        out:null}; 
    
    window.openDialog("addLibrary.xul", "", "chrome, dialog, 
        centerscreen, resizable=yes", params).focus();
  • renameLibrary。对库重新命名。此操作仅能更改本地数据(即它不能重新命名服务器上的实际Document Library)。
  • deleteLibrary。 删除树视图和配置文件中的库。此操作仅能更改本地数据(即它不能删除服务器上的实际Document Library)。
  • collapseAll。 将所有节点的开放状态设置为False,然后更新树视图,以折叠树节点。
  • collapseExpand。 折叠或展开树节点。如果某个节点已经为打开状态,则将其折叠。如果为折叠状态,则应该检查是否已经获取子节点数据。如果尚未获取,则应该调用相应的调用服务以便先加载数据。
  • open URLIn。 打开某特定位置的 URL,该位置可以是当前选项卡中、新选择卡,也可以是新窗口。如果存在事件对象,如单击事件,则可以使用 whereToOpenLink 函数来确定要打开的位置。
  • Refresh。 刷新当前节点的子数据,并且将调用 REST 服务并重建子节点。
  • quickrAddBookmarks。 通过 Firefox 编程接口将当前节点的视图 URL 添加到书签。在 Firefox 3 中,它应如下所示:
    var ios = Components.classes["@mozilla.org/network/io-service; 1"]
        .getService(Components.interfaces.nsIIOService);
    var uri = ios.newURI(url, null, null);
  • quickrCopyL ink。 将当前节点的视图 URL 复制到剪贴板:
    var clipboard = Components.classes["@mozilla.org/widget/clipboardhelper; 1"]
        .getService(Components.interfaces.nsIClipboardHelper);
    clipboard.copyString (url);
  • Mailto。 将当前的节点链接发送给接收者。最简单的方法是使用 mailto 协议,这样您只需要以字符串的形式准备邮件的主题和主体内容,然后再将它们结合到一个邮件 URL 中并打开它(参见清单 13)。
    清单 13. mailto 示例
    var url = node.getUrl();
    var title = node.getTitle();
    var htmlString = "<A HREF='" + url + "'>" + title + "</A>"; 
    var mailUrl = 'mailto:?subject=' + escape(title) + '&body=' + escape (htmlString);
    var tab = openUILinkIn(mailUrl,"tab");
  • downloadDocument。 下载文档。它仅适用于文档节点,并且只能通过打开其下载 URL 来完成下载任务。
  • showProperties显示文件夹或文档的元数据。这些数据将存储到一个来自父提要服务的条目中。还将创建一个简单的 XUL 对话框,并创建一个 propertyDialog.xul 文件来显示这些属性。有关详细信息,请参见此文件。

5.6.7 向连接器添加库

要在此连接器显示的列表中添加文档库,用户需要采取两个步骤。首先,用户必须在 Add Library 对话框中输入服务器信息并单击 Next(参见图 5)。

图 5. 输入服务器信息
图 5. 输入服务器信息

此时,系统将调用文档提要服务 http://host:port/dm/atom/libraries 以便获取服务器托管的所有库,随后将显示如图 6 所示的库树视图。

图 6. 选择库
图 6. 选择库

此视图中的所有 XUL 元素都定义在 addLibrary.xul 中。启动对话框之后,初始化函数 addLibraryInit 将从第一个步骤中过滤出要显示的元素。当用户单击 Next 按钮时,系统将调用 doNext 隐藏一些元素显示剩下的元素。要隐藏或显示某个元素,可以将 hide 属性设置为真或假。

当用户单击 Save 按钮后,系统将调用 doOK 以准备数据并调用回调函数以保存本地库列表。


6. 结束语

Lotus Quickr 提供了丰富且功能强大的 REST/SOAP 服务来定制服务器的功能。本文演示了如何使用 Quickr 文档 REST 服务构建自定义 Firefox 连接器。通过这些编程接口,您应该可以轻松便捷地构建自己的 Quickr 连接器。

致谢

作者要感谢 Greg Melahn 为本文提供的技术审校工作。


下载

描述名字大小
本文 Firefox 连接器的演示视频how_to_use_FF_connector.exe4072 KB
本文 Firefox 连接器示例的源代码quickrconnector@ibm.com.zip1658 KB

参考资料

学习

获得产品和技术

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Lotus, Web development
ArticleID=471663
ArticleTitle=使用 Quickr 服务开发 IBM Lotus Quickr Firefox 连接器
publish-date=03052010