12.07.2015 Views

VisiBroker Edition

VisiBroker Edition

VisiBroker Edition

SHOW MORE
SHOW LESS
  • No tags were found...

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

<strong>VisiBroker</strong> ® 开 发 者 指 南VERSION 5.1Borland ®Enterprise ServerBorland Software Corporation100 Enterprise Way, Scotts Valley, CA 95066-3249


美 国 Borland 软 件 公 司 可 能 对 本 文 档 中 所 提 到 的 有 关 项 目 拥 有 专 利 权 或 者 未 决 专 利 权 申 请 。 请 参 考 产 品 光盘 或 者 “ 关 于 ” 对 话 框 中 的 适 用 专 利 权 列 表 。 提 供 本 文 档 并 非 授 于 您 这 些 专 利 权 的 许 可 证 。版 权 所 有 © 1992-2002 美 国 Borland 软 件 公 司 。 保 留 所 有 权 利 。 所 有 Borland 品 牌 和 产 品 名 称 皆 为 美 国Borland 软 件 公 司 在 美 国 和 其 它 国 家 的 商 标 或 注 册 商 标 。 其 它 的 标 志 皆 为 各 自 所 有 者 的 资 产 。本 产 品 包 括 由 Apache Software Foundation (http://www.apache.org/) 开 发 的 软 件 。Printed in U.S.A.BES0051WW210020102030405-9 87654321D3


目 录第 1 章Borland Enterprise Server 简 介 1-1Borland Enterprise Server 说 明 文 件 . . 1-1说 明 文 件 惯 例 . . . . . . . . . . 1-2平 台 惯 例 . . . . . . . . . . 1-2与 Borland 支 持 服 务 联 系 . . . . . . 1-3联 机 资 源 . . . . . . . . . . 1-3万 维 网 . . . . . . . . . . . 1-4Borland 新 闻 组 . . . . . . . . 1-4第 2 章理 解 CORBA 模 型 2-1什 么 是 CORBA? . . . . . . . . 2-1什 么 是 <strong>VisiBroker</strong> <strong>Edition</strong>? . . . . . 2-2<strong>VisiBroker</strong> <strong>Edition</strong> 特 性 . . . . . . 2-2<strong>VisiBroker</strong> <strong>Edition</strong> 智 能 代 理 结 构 . . . 2-2定 位 服 务 提 供 的 增 强 型 对 象 定 位 . . . . 2-2实 现 和 对 象 激 活 支 持 . . . . . . . 2-3稳 健 的 线 程 和 连 接 管 理 . . . . . . 2-3IDL 编 译 程 序 . . . . . . . . . 2-3DII 和 DSI 的 动 态 调 用 . . . . . . 2-3接 口 和 实 现 仓 库 . . . . . . . . 2-4服 务 器 端 的 可 移 植 性 . . . . . . . 2-4使 用 接 收 器 和 对 象 封 装 器 自 定 义 <strong>VisiBroker</strong>ORB . . . . . . . . . . . . . . . . . 2-4事 件 队 列 . . . . . . . . . . 2-4命 名 服 务 中 的 后 备 存 储 器 . . . . . . 2-4Web 命 名 . . . . . . . . . . 2-5不 使 用 IDL 来 定 义 接 口 . . . . . . 2-5Gatekeeper . . . . . . . . . . . . . . 2-5<strong>VisiBroker</strong> <strong>Edition</strong> CORBA 兼 容 性 . . . 2-5<strong>VisiBroker</strong> <strong>Edition</strong> 开 发 环 境 . . . . . 2-5程 序 员 的 工 具 . . . . . . . . . 2-5CORBA 服 务 工 具 . . . . . . . 2-6管 理 工 具 . . . . . . . . . . 2-6Java 开 发 环 境 . . . . . . . . . 2-6Java 2 标 准 版 . . . . . . . . 2-7Java 运 行 期 环 境 . . . . . . . . 2-7<strong>VisiBroker</strong> <strong>Edition</strong> 的 要 求 是 什 么 . . . 2-7带 Java 功 能 的 Web 浏 览 器 . . . . 2-7与 C++ <strong>VisiBroker</strong> 或 Java <strong>VisiBroker</strong> 之 间的 互 操 作 性 . . . . . . . . . . 2-7与 其 它 ORB 产 品 之 间 的 互 操 作 性 。 . . . 2-8IDL 至 C++ 的 映 射 . . . . . . . . 2-8IDL 至 Java 的 映 射 . . . . . . . . 2-8第 3 章建 立 您 的 环 境 3-1设 置 路 径 环 境 变 量 . . . . . . . . 3-1在 Windows 平 台 上 更 新 路 径 . . . . 3-1在 Windows NT 平 台 上 更 新 路 径 . . . 3-1在 UNIX 平 台 上 设 置 PATH . . . . . . . . 3-2CLASSPATH . . . . . . . . . . . . . . . . 3-2设 置 VBROKER_ADM 环 境 变 量 . . . . 3-2在 Windows 平 台 上 设 置VBROKER_ADM . . . . . . . . . . . 3-2在 UNIX 平 台 上 设 置 VBROKER_ADM . . 3-3设 定 OSAGENT_PORT 环 境 变 量 . . . 3-3记 录 输 出 . . . . . . . . . . . 3-3第 4 章使 用 <strong>VisiBroker</strong> <strong>Edition</strong> 开 发 实 例应 用 4-1开 发 过 程 . . . . . . . . . . . 4-1步 骤 1: 定 义 对 象 接 口 . . . . . . . 4-3用 IDL 中 编 写 帐 户 接 口 . . . . . . 4-3步 骤 2: 生 成 客 户 存 根 和 服 务 器 服 务 对 象 . . 4-4由 idl 编 译 器 生 成 的 文 件 . . . . . . 4-4步 骤 3: 实 现 客 户 . . . . . . . . 4-5Client.C . . . . . . . . . . . . . . . . . 4-6Client.java . . . . . . . . . . . . . . . . 4-6AccountManagerHelper.java . . . . . . 4-8步 骤 4: 实 现 服 务 器 . . . . . . . . 4-8服 务 器 程 序 . . . . . . . . . 4-8理 解 Account 类 结 构 . . . . . . 4-10步 骤 5: 建 立 实 例 . . . . . . . . 4-10编 译 实 例 . . . . . . . . . . 4-11步 骤 6: 启 动 服 务 器 并 运 行 本 实 例 . . . . 4-11启 动 智 能 代 理 . . . . . . . . . 4-11启 动 服 务 器 . . . . . . . . . 4-12运 行 客 户 . . . . . . . . . . 4-12用 <strong>VisiBroker</strong> <strong>Edition</strong> 部 署 应 用 . . . . 4-12<strong>VisiBroker</strong> <strong>Edition</strong> 应 用 . . . . . 4-13第 5 章处 理 违 例 5-1CORBA 模 型 中 的 违 例 . . . . . . . 5-1系 统 违 例 . . . . . . . . . . . 5-1取 得 完 成 状 态 . . . . . . . . . 5-3取 得 和 设 置 minor code ( 次 要 代 码 ) . 5-3确 定 系 统 违 例 的 类 型 . . . . . . . 5-3i


捕 捉 系 统 违 例 . . . . . . . . . 5-3将 违 例 下 溯 造 型 (Downcasting) 到 一 个 系 统违 例 . . . . . . . . . . . 5-4用 户 违 例 . . . . . . . . . . . 5-6定 义 用 户 违 例 . . . . . . . . . 5-7第 6 章服 务 器 基 础 6-1概 述 . . . . . . . . . . . . 6-1初 始 化 <strong>VisiBroker</strong> ORB . . . . . . . . . . 6-1创 建 POA . . . . . . . . . . . . . . . . . 6-2取 得 根 POA 的 引 用 . . . . . . . 6-2创 建 子 POA . . . . . . . . . . . . . . 6-3实 现 服 务 对 象 方 法 . . . . . . . . 6-3激 活 POA. . . . . . . . . . . . . . . . 6-5激 活 对 象 . . . . . . . . . . . 6-6等 待 客 户 端 的 请 求 . . . . . . . . 6-6Complete example . . . . . . . . . . . . 6-6第 7 章使 用 POA 7-1什 么 是 可 移 植 适 配 器 ? . . . . . . . 7-1POA 术 语 . . . . . . . . . . 7-2创 建 和 使 用 POA 步 骤 . . . . . . 7-3POA 策 略 . . . . . . . . . . . 7-3线 程 策 略 . . . . . . . . . . 7-3生 命 周 期 策 略 . . . . . . . . . 7-3对 象 ID 唯 一 性 策 略 . . . . . . . 7-4ID 分 配 策 略 . . . . . . . . . 7-4服 务 对 象 保 留 策 略 . . . . . . . . 7-4请 求 处 理 策 略 . . . . . . . . . 7-4隐 式 激 活 策 略 . . . . . . . . . 7-5限 制 支 持 策 略 . . . . . . . . . 7-5创 建 POA . . . . . . . . . . . . . . . . . 7-5POA 命 名 惯 例 . . . . . . . . . 7-6取 得 rootPOA . . . . . . . . . . . . . 7-6设 置 POA 属 性 . . . . . . . . 7-7创 建 和 激 活 POA . . . . . . . . . . . . 7-7激 活 对 象 . . . . . . . . . . . 7-8显 式 激 活 对 象 . . . . . . . . . 7-8随 选 激 活 对 象 . . . . . . . . . 7-9隐 式 激 活 对 象 . . . . . . . . . 7-9默 认 服 务 对 象 的 激 活 . . . . . . 7-10去 激 活 对 象 . . . . . . . . . 7-12使 用 服 务 对 象 和 服 务 对 象 管 理 器 . . . 7-15ServantActivators . . . . . . . . . . . 7-16ServantLocators . . . . . . . . . . . . 7-20用 POA 管 理 器 管 理 POA . . . . . . . . . 7-24取 得 当 前 的 状 态 . . . . . . . 7-25保 持 状 态 . . . . . . . . . . 7-25活 动 状 态 . . . . . . . . . . 7-26丢 弃 状 态 . . . . . . . . . . 7-26不 活 动 状 态 . . . . . . . . . 7-26设 置 收 听 和 调 度 属 性 . . . . . . . . 7-27设 置 服 务 器 引 擎 属 性 . . . . . . . 7-28设 置 服 务 器 连 接 管 理 器 属 性 . . . . . 7-28什 么 时 候 使 用 这 些 属 性 . . . . . . 7-30适 配 器 激 活 器 . . . . . . . . . . 7-33处 理 请 求 . . . . . . . . . . . 7-33第 8 章管 理 线 程 和 连 接 8-1在 <strong>VisiBroker</strong> <strong>Edition</strong> 中 使 用 线 程 . . . 8-1<strong>VisiBroker</strong> <strong>Edition</strong> 提 供 哪 些 线 程 策 略 ?. . 8-1开 设 线 程 池 (thread pooling) 策 略 . . . 8-2一 个 会 话 一 个 线 程 (Thread-per-session) 策 略 8-5<strong>VisiBroker</strong> <strong>Edition</strong> 提 供 哪 些 连 接 管 理 ?. . 8-7设 置 调 度 策 略 和 属 性 . . . . . . . . 8-7开 设 线 程 池 (Thread pooling) . . . . . . . 8-8一 个 会 话 一 个 线 程 (Thread-per-session) . 8-8编 码 注 意 事 项 . . . . . . . . . 8-8第 9 章使 用 tie 机 制 9-1tie 机 制 是 如 何 工 作 的 ? . . . . . . . 9-1实 例 程 序 . . . . . . . . . . . 9-2使 用 tie 机 制 的 实 例 程 序 的 位 置 . . . 9-2查 看 tie 模 板 . . . . . . . . . 9-2修 改 服 务 器 使 其 使 用 _tie_account 类 . 9-3对 服 务 器 类 所 作 的 更 改 . . . . . . 9-4对 AccountManager 所 作 的 更 改 . . . 9-4对 Account 类 所 作 的 更 改 . . . . . 9-5建 立 tie 实 例 . . . . . . . . . 9-6第 10 章客 户 基 础 10-1初 始 化 <strong>VisiBroker</strong> ORB . . . . . . . . . . 10-1限 制 到 对 象 . . . . . . . . . . 10-2限 制 进 程 中 所 执 行 的 动 作 . . . . . 10-2调 用 对 象 上 的 操 作 . . . . . . . . 10-3处 理 对 象 引 用 . . . . . . . . . . 10-3检 查 是 否 是 nil 引 用 . . . . . . . 10-3获 得 nil 引 用 . . . . . . . . . 10-4复 制 对 象 引 用 . . . . . . . . . 10-4释 放 对 象 引 用 . . . . . . . . . 10-4得 到 引 用 数 . . . . . . . . . 10-5将 引 用 转 换 成 字 串 . . . . . . . 10-5取 得 目 标 和 界 面 名 称 . . . . . . . 10-5ii


确 定 对 象 引 用 的 类 型 . . . . . . 10-6确 定 限 制 的 对 象 的 位 置 和 状 态 . . . 10-6检 查 不 存 在 的 对 象 . . . . . . . 10-7窄 转 换 对 象 引 用 . . . . . . . 10-7拓 宽 对 象 引 用 . . . . . . . . 10-8使 用 服 务 质 量 . . . . . . . . . 10-8理 解 服 务 质 量 . . . . . . . . 10-8QoS 界 面 . . . . . . . . . 10-9QoS 违 例 . . . . . . . . . 10-15第 11 章使 用 IDL 11-1IDL 简 介 . . . . . . . . . . 11-1IDL 编 译 器 如 何 生 成 代 码 . . . . . 11-1实 例 IDL 规 范 . . . . . . . . 11-2查 看 Java 下 生 成 的 代 码 . . . . . . 11-2Stub.java . . . . . . 11-2.java . . . . . . . . 11-3Helper.java . . . . . 11-3Holder.java . . . . . 11-4Operations.java. . . 11-4POA.java . . . . . . 11-5POATie.java . . . . 11-5查 看 为 客 户 所 生 成 的 代 码 ( 在 C++ 下 ) 11-6编 译 器 生 成 的 方 法 ( 存 根 ) . . . . 11-6Pointer type _ptrdefinition . . . . . . . . . . . . . . . 11-7自 动 内 存 管 理 _var 类 11-7查 看 为 客 户 所 生 成 的 代 码 服 务 ( 在 C++ 下 ) 11-8IDL 编 译 器 生 成 的 方 法 ( 框 架 ). . . 11-8由 IDL 编 译 器 生 成 的 类 模 板 . . . . 11-9在 IDL 中 定 义 接 口 属 性 . . . . . . 11-9指 定 无 返 回 值 的 oneway 方 法 . . . . 11-10在 IDL 中 指 定 一 个 从 另 一 个 接 口 继 承 而 来 的 接 口 .11-10第 12 章使 用 智 能 代 理 12-1什 么 是 智 能 代 理 ? . . . . . . . 12-1定 位 智 能 代 理 . . . . . . . . 12-1由 智 能 代 理 协 作 定 位 对 象 . . . . . 12-2与 OAD 协 作 连 接 对 象 . . . . . 12-2启 动 智 能 代 理 (osagent) . . . . . . . . . 12-2保 证 智 能 代 理 的 可 用 性 . . . . . 12-3<strong>VisiBroker</strong> ORB 域 内 工 作 . . . . . 12-3在 不 同 局 域 网 中 连 接 智 能 代 理 . . . . 12-4智 能 代 理 如 何 相 互 检 测 . . . . . 12-5与 多 Home 主 机 配 合 工 作 . . . . . 12-5指 定 智 能 代 理 的 接 口 使 用 . . . . . 12-6使 用 点 对 点 通 讯 . . . . . . . . . 12-7指 定 主 机 为 运 行 参 数 . . . . . . . 12-7通 过 环 境 变 量 指 定 IP 地 址 . . . . . 12-8通 过 agentaddr 文 件 指 定 主 机 . . . . 12-8保 证 对 象 可 用 性 . . . . . . . . . 12-8调 用 无 状 态 对 象 方 法 . . . . . . . 12-8为 有 状 态 对 象 实 现 容 错 能 力 . . . . . 12-8复 制 在 OAD 注 册 上 的 对 象 . . . . . 12-9在 主 机 之 间 移 植 对 象 . . . . . . . . 12-9移 植 有 状 态 对 象 . . . . . . . . 12-9移 植 实 例 化 对 象 . . . . . . . . 12-9移 植 在 OAD 注 册 上 的 对 象 . . . . 12-10报 告 所 有 对 象 和 服 务 . . . . . . . 12-10限 制 到 对 象 . . . . . . . . . 12-11第 13 章使 用 定 位 服 务 13-1什 么 是 定 位 服 务 ? . . . . . . . . 13-1定 位 服 务 组 件 . . . . . . . . . . 13-2什 么 是 定 位 服 务 代 理 ? . . . . . . 13-2什 么 是 触 发 器 ? . . . . . . . . 13-5查 询 代 理 . . . . . . . . . . . 13-6找 出 接 口 的 所 有 实 例 . . . . . . . 13-7找 出 智 能 代 理 已 知 的 接 口 和 实 例 . . . 13-8编 写 和 注 册 触 发 器 处 理 器 . . . . . 13-12第 14 章使 用 命 名 服 务 14-1概 述 . . . . . . . . . . . . 14-1理 解 命 名 空 间 . . . . . . . . . . 14-2命 名 上 下 文 . . . . . . . . . 14-3命 名 上 下 文 工 厂 . . . . . . . . 14-3名 称 和 NameComponent . . . . . . . 14-4名 称 解 析 . . . . . . . . . . 14-4运 行 命 名 服 务 . . . . . . . . . . 14-5安 装 命 名 服 务 . . . . . . . . . 14-5配 置 命 名 服 务 . . . . . . . . . 14-6启 动 命 名 服 务 . . . . . . . . . 14-6从 命 令 行 调 用 命 名 服 务 . . . . . . . 14-6配 置 nsutil . . . . . . . . . . . . . . . 14-7运 行 nsutil . . . . . . . . . . . . . . . 14-7关 闭 nsutil . . . . . . . . . . . . . . . 14-8启 动 命 名 服 务 . . . . . . . . . . 14-8调 用 resolve_initial_references . . . . 14-8使 用 -DSVCnameroot . . . . . . . . . 14-9使 用 C++ -ORBInitRef 或 Java -DORBInitRef. . . . . . . . . . . . . 14-9-ORBDefaultInitRef (C++) 或 -DORBDefaultInitRef (Java). . 14-10iii


NamingContext . . . . . . . . . . . . . 14-11NamingContextExt . . . . . . . . . . . 14-11默 认 的 命 名 上 下 文 . . . . . . . 14-12在 C++ 下 取 得 默 认 的 上 下 文 . . . 14-12在 Java 下 取 得 默 认 的 命 名 上 下 文 . . 14-12命 名 服 务 属 性 . . . . . . . . . 14-13可 插 入 的 备 份 存 储 . . . . . . . 14-14备 份 存 储 的 类 型 . . . . . . . 14-14配 置 和 使 用 . . . . . . . . . 14-15集 群 . . . . . . . . . . . 14-18集 群 标 准 . . . . . . . . . . 14-18集 群 和 ClusterManager 接 口 . . . 14-19创 建 集 群 . . . . . . . . . 14-20负 载 平 衡 . . . . . . . . . 14-21失 效 恢 复 . . . . . . . . . . 14-21命 名 服 务 的 容 错 配 置 . . . . . . 14-22C++ 编 译 和 链 接 程 序 . . . . . . . 14-22Java 导 入 声 明 . . . . . . . . 14-23实 例 程 序 . . . . . . . . . . 14-23在 Java 下 限 制 名 称 . . . . . . 14-23第 15 章使 用 事 件 服 务 15-1概 述 . . . . . . . . . . . 15-1代 理 接 收 者 和 提 供 者 . . . . . . 15-2OMG 公 共 对 象 服 务 规 范 . . . . . 15-2通 信 模 型 . . . . . . . . . . 15-3推 式 模 型 . . . . . . . . . 15-3拉 式 模 型 . . . . . . . . . 15-4使 用 事 件 通 道 . . . . . . . . . 15-4推 型 提 供 者 和 接 收 者 的 实 例 . . . . . 15-6C++ 下 的 推 型 提 供 者 和 接 收 者 . . . 15-6Java 下 的 提 供 者 和 接 收 者 实 例 . . . 15-15运 行 推 式 模 型 实 例 . . . . . . . 15-16启 动 事 件 服 务 . . . . . . . . . 15-20设 置 队 列 长 度 . . . . . . . . 15-21进 程 内 事 件 通 道 (Java) . . . . . 15-21Java 用 法 . . . . . . . . . 15-22编 译 和 链 接 程 序 ( 仅 限 于 C++) . . . 15-23Java 导 入 声 明 . . . . . . . . 15-23接 口 引 用 . . . . . . . . . . 15-24EventChannel . . . . . . . . . . . . 15-24EventLibrary (Java) . . . . . 15-24ConsumerAdmin. . . . . . . . . . . 15-25SupplierAdmin . . . . . . . . . . . . 15-25ProxyPullConsumer . . . . . . . . . 15-26ProxyPushConsumer . . . . . . . . 15-26ProxyPullSupplier . . . . . . . . . . 15-26ProxyPushSupplier . . . . . . . . . 15-26PullConsumer . . . . . . . . . . . . 15-27PushConsumer . . . . . . . . . . . 15-27PullSupplier . . . . . . . . . . . . . 15-27PushSupplier . . . . . . . . . . . . 15-28第 16 章使 用 对 象 激 活 守 护 进 程(Daemon) 16-1对 象 和 服 务 器 的 自 动 激 活 . . . . . . 16-1定 位 实 现 库 数 据 . . . . . . . . 16-1激 活 服 务 器 . . . . . . . . . 16-2启 动 对 象 激 活 守 护 进 程 . . . . . . . 16-2在 Windows 平 台 上 启 动 对 象 激 活 守 护 进 程 .16-2在 UNIX 平 台 上 启 动 对 象 激 活 守 护 进 程 . 16-3使 用 对 象 激 活 守 护 进 程 实 用 工 具 . . . . 16-3用 oadutil list 列 出 对 象 . . . . . . 16-4用 oadutil 注 册 对 象 . . . . . . . 16-6区 分 一 个 对 象 的 多 个 实 例 . . . . . 16-8用 CreationImplDef 类 设 置 激 活 属 性 . . 16-8动 态 变 更 <strong>VisiBroker</strong> ORB 实 现 . . . 16-9使 用 OAD::reg_implementation 的 OAD注 册 . . . . . . . . . . . 16-9对 象 创 建 和 注 册 的 实 例 . . . . . 16-10由 OAD 传 递 的 变 量 . . . . . . 16-11反 注 册 对 象 . . . . . . . . . 16-11使 用 oadutil 工 具 反 注 册 对 象 . . . 16-11用 OAD 操 作 反 注 册 . . . . . . 16-12显 示 实 现 库 的 内 容 . . . . . . 16-13面 向 OAD 的 IDL 接 口 . . . . . . 16-13第 17 章使 用 接 口 仓 库 17-1什 么 是 接 口 仓 库 ? . . . . . . . . 17-1接 口 仓 库 中 包 含 的 是 什 么 ? . . . . . 17-2您 可 以 创 建 多 少 个 接 口 仓 库 ? . . . . 17-2用 irep 创 建 和 查 看 接 口 仓 库 . . . . . 17-2用 irep 创 建 接 口 仓 库 . . . . . . 17-2查 看 接 口 仓 库 的 内 容 . . . . . . . 17-4用 idl2ir 更 新 接 口 仓 库 . . . . . . . 17-4了 解 接 口 仓 库 的 结 构 . . . . . . . . 17-4识 别 接 口 仓 库 中 的 对 象 . . . . . . 17-5可 以 存 储 在 接 口 仓 库 中 的 对 象 的 类 型 . . 17-5继 承 的 接 口 . . . . . . . . . 17-7访 问 接 口 仓 库 . . . . . . . . . . 17-7实 例 程 序 . . . . . . . . . . . 17-8iv


第 18 章使 用 动 态 调 用 接 口 18-1什 么 是 动 态 调 用 接 口 ? . . . . . . 18-1主 要 DII 概 念 介 绍 . . . . . . . 18-2动 态 调 用 对 象 操 作 的 步 骤 . . . . . 18-4使 用 DII 的 实 例 程 序 的 位 置 . . . . 18-4使 用 idl2java 编 译 器 . . . . . . 18-5获 得 普 通 对 象 引 用 . . . . . . . 18-5创 建 与 初 始 化 请 求 . . . . . . . 18-6Request 类 . . . . . . . . 18-6Request 接 口 . . . . . . . . 18-6创 建 和 初 始 化 DII Request 的 方 法 . . 18-7使 用 create_request 方 法 . . . . 18-8使 用 _request 方 法 . . . . . . 18-8关 于 创 建 一 个 Request 对 象 的 实 例 . 18-8设 定 request 的 上 下 文 . . . . . 18-10设 定 request 的 变 量 . . . . . . 18-10用 Any 类 安 全 地 传 递 类 型 . . . . 18-12用 TypeCode 类 表 示 变 量 或 属 性 类 型 . 18-13发 送 DII 请 求 与 接 收 结 果 . . . . . 18-15调 用 请 求 . . . . . . . . . 18-15使 用 send_deferred 方 法 发 送 延 迟 的 DIIrequest . . . . . . . . . . . . . . . 18-16使 用 send_oneway 方 法 发 送 异 步 DII请 求 . . . . . . . . . . 18-18发 送 多 个 请 求 . . . . . . . . 18-18接 收 多 个 请 求 . . . . . . . . 18-19用 DII 使 用 接 口 仓 库 . . . . . . . 18-20第 19 章使 用 动 态 框 架 接 口 19-1什 么 是 动 态 框 架 接 口 ? . . . . . . 19-1使 用 idl2java 编 译 器 . . . . . . 19-1动 态 创 建 对 象 实 现 的 步 骤 . . . . . 19-2使 用 DSI 的 实 例 程 序 的 位 置 . . . . 19-2扩 展 DynamicImplementation 类 . . 19-2为 动 态 请 求 设 计 对 象 的 实 例 . . . . 19-3指 定 仓 库 ID . . . . . . . . . . . . . . . 19-7查 看 ServerRequest 类 . . . . . 19-7实 施 Account 对 象 . . . . . . . 19-8实 现 AccountManager 对 象 . . . . 19-8设 定 返 回 值 . . . . . . . . . 19-9服 务 器 实 现 . . . . . . . . . 19-9第 20 章使 用 可 移 植 接 收 器 20-1概 述 . . . . . . . . . . . 20-1可 移 植 接 收 器 和 信 息 接 口 . . . . . 20-2接 收 器 . . . . . . . . . . . 20-2请 求 接 收 器 : . . . . . . . . . 20-3IOR 接 收 器 . . . . . . . . . 20-6可 移 植 接 收 器 Current . . . . . . . . . 20-7Codec . . . . . . . . . . . . . . . . . 20-7CodecFactory . . . . . . . . . . . . . 20-8创 建 可 移 植 接 收 器 . . . . . . . 20-8注 册 可 移 植 接 收 器 . . . . . . 20-10注 册 ORBInitializer . . . . . . . . . 20-11<strong>VisiBroker</strong> <strong>Edition</strong> 朝 向 可 移 植 接 收 器 的扩 展 . . . . . . . . . . 20-13实 例 . . . . . . . . . . . 20-14实 例 代 码 . . . . . . . . . 20-14实 例 :client_server . . . . . . . . . 20-14第 21 章使 用 4.x 接 收 器 21-1概 述 . . . . . . . . . . . . 21-14.x 接 收 器 接 口 和 管 理 器 . . . . . . 21-1客 户 端 接 收 器 . . . . . . . . . 21-2服 务 器 接 收 器 . . . . . . . . . 21-3服 务 解 析 器 接 收 器 . . . . . . . 21-5默 认 接 收 器 类 . . . . . . . . . 21-5向 <strong>VisiBroker</strong> <strong>Edition</strong> ORB 注 册 接 收 器 . 21-5创 建 接 收 器 对 象 . . . . . . . . 21-6装 载 接 收 器 . . . . . . . . . 21-6接 收 器 实 例 . . . . . . . . . . 21-6实 例 代 码 . . . . . . . . . . 21-7代 码 列 表 . . . . . . . . . . 21-9在 4.x 接 收 器 之 间 传 递 信 息 . . . . . 21-13同 时 使 用 可 移 植 和 4.x 接 收 器 . . . . 21-14拦 截 点 调 用 的 顺 序 . . . . . . 21-14客 户 端 接 收 器 . . . . . . . . 21-14服 务 器 端 接 收 器 . . . . . . . 21-14POA 创 建 期 间 ORB 事 件 的 顺 序 . . 21-15对 象 引 用 创 建 期 间 ORB 事 件 的 顺 序 . 21-15第 22 章使 用 对 象 封 装 器 22-1概 述 . . . . . . . . . . . . 22-1型 别 和 非 型 别 对 象 封 装 器 . . . . . 22-2idl2cpp 特 别 要 求 . . . . . . . 22-2idl2java 特 别 要 求 . . . . . . . 22-2实 例 应 用 . . . . . . . . . . 22-2非 型 别 对 象 封 装 器 . . . . . . . . 22-2使 用 多 个 型 别 和 非 型 别 对 象 封 装 器 . . . 22-3pre_method 调 用 的 顺 序 . . . . . 22-3post_method 调 用 的 顺 序 . . . . . 22-4使 用 非 型 别 对 象 封 装 器 . . . . . . . 22-4v


实 现 非 型 别 对 象 封 装 器 工 厂 . . . . 22-4实 现 非 型 别 对 象 封 装 器 . . . . . 22-5创 建 和 注 册 非 型 别 对 象 封 装 器 工 厂 . . 22-7删 除 非 型 别 对 象 封 装 器 . . . . . 22-10型 别 对 象 封 装 器 . . . . . . . . 22-11使 用 多 个 型 别 对 象 封 装 器 . . . . . 22-11调 用 的 顺 序 . . . . . . . . . 22-12客 户 端 和 服 务 器 共 存 时 的 型 别 对 象 封 装 器 22-12使 用 型 别 对 象 封 装 器 . . . . . . . 22-13实 现 型 别 对 象 封 装 器 . . . . . . 22-13为 客 户 端 注 册 型 别 对 象 封 装 器 . . . 22-14为 服 务 器 注 册 型 别 对 象 封 装 器 . . . 22-15删 除 型 别 对 象 封 装 器 . . . . . . 22-18混 合 使 用 非 型 别 和 型 别 对 象 封 装 器 . . . 22-18用 于 型 别 封 装 器 的 命 令 行 变 量 . . . 22-18型 别 封 装 器 的 初 始 化 器 . . . . . 22-19用 于 非 型 别 封 装 器 的 命 令 行 变 量 . . . 22-21非 型 别 封 装 器 的 初 始 化 器 . . . . . 22-22执 行 应 用 样 本 . . . . . . . . 22-24第 23 章事 件 队 列 23-1事 件 类 型 . . . . . . . . . . 23-1连 接 事 件 . . . . . . . . . 23-1事 件 监 听 器 . . . . . . . . . 23-1IDL 定 义 . . . . . . . . . 23-1如 何 返 回 EventQueueManager? . 23-3代 码 示 例 . . . . . . . . . 23-3第 24 章在 IIOP 上 使 用 RMI 24-1概 述 . . . . . . . . . . . 24-1通 过 RMI-IIOP 设 置 Java applet . . . . 24-1java2iiop 和 java2idl 工 具 . . . . 24-1使 用 java2iiop . . . . . . . . . . . . . . . 24-2支 持 的 接 口 . . . . . . . . . 24-2运 行 java2iiop . . . . . . . . . . . . . 24-2完 成 开 发 过 程 . . . . . . . . 24-3RMI-IIOP 库 实 例 . . . . . . . . 24-4支 持 的 数 据 类 型 . . . . . . . . 24-5映 射 原 始 数 据 类 型 . . . . . . . 24-5映 射 复 杂 数 据 类 型 . . . . . . . 24-6接 口 . . . . . . . . . . . 24-6数 组 . . . . . . . . . . . 24-6第 25 章使 用 动 态 管 理 的 类 型 25-1概 述 . . . . . . . . . . . 25-1DynAny 类 型 . . . . . . . . . 25-1使 用 限 制 . . . . . . . . . . 25-2创 建 DynAny. . . . . . . . . . . . . . 25-2初 始 化 与 存 取 DynAny 值 . . . . . 25-3结 构 化 数 据 类 型 . . . . . . . . . 25-3切 换 具 有 结 构 化 数 据 类 型 的 组 件 . . . 25-3DynEnum . . . . . . . . . . . . . . . 25-3DynStruct . . . . . . . . . . . . . . . 25-4DynUnion . . . . . . . . . . . . . . . 25-4DynSequence 和 DynArray . . . . . . 25-4实 例 IDL . . . . . . . . . . . . . . . . . 25-4实 例 客 户 应 用 程 序 . . . . . . . . 25-5实 例 服 务 器 应 用 程 序 . . . . . . . . 25-7第 26 章使 用 valuetypes 26-1理 解 valuetypes. . . . . . . . . . . . . . 26-1具 体 valuetypes . . . . . . . . . . . . 26-1抽 象 valuetypes . . . . . . . . . . . . 26-2实 现 valuetypes. . . . . . . . . . . . . . 26-3定 义 valuetypes . . . . . . . . . . . . 26-3编 译 IDL 文 件 . . . . . . . . 26-3继 承 valuetype 基 础 类 . . . . . . 26-4实 现 工 厂 类 . . . . . . . . . 26-4向 <strong>VisiBroker</strong> ORB 注 册 工 厂 . . . . 26-5实 现 工 厂 . . . . . . . . . . . 26-5工 厂 和 valuetypes . . . . . . . . . . . 26-7注 册 valuetypes . . . . . . . . . . . . 26-7转 变 的 valuetypes . . . . . . . . . . . . 26-7抽 象 接 口 . . . . . . . . . . . 26-8客 户 valuetypes. . . . . . . . . . . . . . 26-8可 截 取 的 valuetypes . . . . . . . . . . . 26-9第 27 章使 用 URL 命 名 27-1URL 命 名 服 务 . . . . . . . . . 27-1注 册 对 象 . . . . . . . . . . . 27-2通 过 URL 定 位 对 象 . . . . . . . . 27-3第 28 章双 向 通 信 28-1使 用 双 向 IIOP . . . . . . . . . . . . . . . 28-1双 向 <strong>VisiBroker</strong> ORB 属 性 . . . . . 28-1关 于 实 例 . . . . . . . . . . . 28-2在 现 有 应 用 上 实 现 双 向 IIOP . . . . . . . . 28-3显 式 实 现 双 向 IIOP . . . . . . . . . . . . 28-3安 全 注 意 事 项 . . . . . . . . . . 28-6vi


viii


说 明 文 件 惯 例安 装 指 南 介 绍 如 何 在 您 的 网 络 上 安 装 Borland Enterprise Server。 它 适 用 于 熟 悉Windows NT、 2000 或 UNIX 操 作 系 统 的 系 统 管 理 员 。用 户 指 南 介 绍 有 关 使 用 Borland Enterprise Server 的 信 息 。 这 些 信 息 包 括 如 何使 用 图 形 界 面 工 具 来 启 动 、 停 止 和 管 理 服 务 器 和 服 务 ; 如 何 使 用 EJB 和 Web 容器 、 向 导 、 部 署 描 述 符 编 辑 器 以 及 应 用 程 序 组 装 工 具 。 本 指 南 还 将 介 绍 VisiClient和 Dreamweaver UtraDev 插 件 。开 发 者 指 南 介 绍 有 关 基 于 对 象 的 分 布 式 应 用 程 序 在 其 操 作 环 境 中 打 包 、 部 署 和 管 理的 详 细 信 息 。 其 中 还 提 到 调 整 服 务 、 建 立 连 接 和 常 见 问 题 的 高 级 解 决 方 法 。<strong>VisiBroker</strong> 开 发 者 指 南 介 绍 如 何 在 Java 或 C++ 下 开 发 <strong>VisiBroker</strong> 应 用 程 序 。 它通 过 控 制 台 和 属 性 文 件 使 您 熟 悉 Visibroker ORB 的 配 置 和 管 理 。 另 外 还 介 绍IDL 编 译 器 、 智 能 代 理 、 位 置 、 命 名 和 事 件 服 务 、 对 象 ActiActivationmon、 服务 质 量 和 接 口 仓 库 。<strong>VisiBroker</strong> VisiNotify 指 南 介 绍 Borland 的 OMG 标 准 - 通 知 服 务 的 实 现 。 本 指南 讨 论 如 何 使 用 通 知 消 息 框 架 的 主 要 功 能 , 特 别 是 服 务 质 量 (QoS) 属 性 、 筛 选 和 分布 / 订 阅 适 配 器 (PSA)。<strong>VisiBroker</strong> 程 序 员 参 考 介 绍 有 关 如 何 使 用 编 程 工 具 和 命 令 行 选 项 的 信 息 以 及<strong>VisiBroker</strong> for Java 和 C++ 所 提 供 的 类 和 接 口 。<strong>VisiBroker</strong> GateKeeper 指 南 介 绍 如 何 利 用 <strong>VisiBroker</strong> GateKeeper 使<strong>VisiBroker</strong> 客 户 能 够 与 网 络 中 的 服 务 器 通 信 , 而 又 不 超 越 Web 浏 览 器 和 防 火 墙 的安 全 限 制 。说 明 文 件 惯 例Borland Enterprise Server 说 明 文 件 使 用 下 述 字 样 和 符 号 表 示 特 殊 文 本 :惯 例 字 样 和 符 号 代 表 含 义斜 体用 户 或 应 用 程 序 提 供 的 信 息 , 如 语 法 图 例 中 的 变 量 。 也 用 于 代 表 新 术语 和 书 名 。计 算 机 命 令 行 和 代 码 样 本 。粗 体在 文 本 中 , 粗 体 表 示 用 户 键 入 的 信 息 。 在 代 码 样 本 中 , 粗 体 表 示 重 要声 明 。[ ] 可 选 项 目 。... 表 示 前 述 内 容 可 以 罗 列 。| 两 个 互 不 相 容 选 项 。键 名 键 盘 上 的 按 键 。 例 如 , 按 Esc 退 出 。平 台 惯 例Borland Enterprise Server 说 明 文 件 使 用 下 列 符 号 表 示 特 定 平 台 的 信 息 :Windows: Windows NT 和 Windows 2000WinNT: 仅 指 Windows NT1-2 <strong>VisiBroker</strong> 开 发 者 指 南


与 Borland 支 持 服 务 联 系用 户 服 务 站 : 要 订 阅 电 子 简 讯 , 请 联 机 填 写 下 列 网 址 中 的 表 格 :http://www.borland.com/contact/listserv.html ; 或 者 , 要 进 入 Borland 国 际 电 子论 坛 , 请 访 问 以 下 网 址 :http://www.borland.com/contact/intlist.html万 维 网定 期 访 问 http://www.borland.com。Borland Enterprise Server 产 品 小 组 会公 布 白 皮 书 、 竞 争 分 析 、 常 见 问 题 解 答 、 应 用 程 序 示 例 、 更 新 软 件 、 更 新 说 明 文 件以 及 有 关 新 的 和 现 有 产 品 的 信 息 。您 需 要 特 别 留 意 以 下 这 些 URL:● http://www.borland.com/bes ( 更 新 软 件 及 其 它 文 件 )● http://www.borland.com/techpubs/bes ( 更 新 说 明 文 件 及 其 它 文 件 )● http://community.borland.com ( 提 供 面 向 开 发 人 员 的 基 于 Web 的 新 闻杂 志 )Borland 新 闻 组您 可 以 加 入 专 门 针 对 Borland Enterprise Server 产 品 的 讨 论 组 。您 可 以 在 以 下 网 址 中 找 到 Enterprise Server 及 其 它 Borland 产 品 的 用 户 支 持 的新 闻 组 :http://www.borland.com/newsgroups。注 : 这 些 新 闻 组 是 由 用 户 维 护 的 , 并 不 是 Borland 的 官 方 站 点 。1-4 <strong>VisiBroker</strong> 开 发 者 指 南


第章理 解 CORBA 模 型第 2 章本 章 介 绍 了 <strong>VisiBroker</strong> <strong>Edition</strong> 版 本 , 它 由 <strong>VisiBroker</strong> for C++ 和 <strong>VisiBroker</strong>for Java 组 成 , 它 是 CORBA 2.4 规 范 的 完 整 实 现 。 本 节 说 明 了 <strong>VisiBroker</strong><strong>Edition</strong> 的 特 性 和 组 件 。什 么 是 CORBA?常 规 对 象 请 求 代 理 结 构 (CORBA) 允 许 分 布 式 应 用 进 行 互 操 作 ( 应 用 间 通 信 ), 无论 应 用 用 什 么 语 言 编 写 或 驻 留 在 什 么 地 方 。CORBA 规 范 被 对 象 管 理 组 所 采 用 , 用 来 解 决 开 发 分 布 式 对 象 应 用 的 复 杂 性 和 高 成本 等 问 题 。CORBA 使 用 面 向 对 象 的 方 法 来 创 建 可 在 应 用 之 间 重 复 使 用 和 共 享 的 软件 组 件 。 每 个 对 象 封 装 有 其 内 部 工 作 的 详 细 资 料 , 并 且 提 供 了 一 个 适 当 定 义 的 接口 , 这 样 可 减 少 应 用 的 复 杂 性 。 同 时 降 低 了 开 发 应 用 的 成 本 , 一 旦 实 现 了 对 象 并 通过 了 测 试 , 则 可 以 重 复 使 用 该 对 象 。下 图 中 的 对 象 请 求 代 理 (ORB) 将 客 户 端 应 用 和 它 要 使 用 的 对 象 连 接 起 来 。 客 户 端程 序 不 需 要 知 道 与 其 通 信 的 对 象 实 现 是 驻 留 在 同 一 计 算 机 上 , 还 是 位 于 网 络 中 某 处的 远 程 计 算 机 上 。 客 户 端 程 序 只 需 要 知 道 对 象 名 并 知 道 如 何 使 用 对 象 接 口 。 ORB会 管 理 有 关 寻 找 对 象 、 发 送 请 求 和 返 回 结 果 的 细 节 。图 2.1作 用 于 对 象 的 客 户 端 程 序注 意 :ORB 本 身 并 不 是 单 独 的 进 程 。 它 是 可 在 终 端 用 户 应 用 中 集 成 并 且 允 许 客 户端 程 序 查 找 和 使 用 对 象 的 一 批 程 序 库 和 网 络 资 源 。理 解 CORBA 模 型 2-1


什 么 是 <strong>VisiBroker</strong> <strong>Edition</strong>?什 么 是 <strong>VisiBroker</strong> <strong>Edition</strong>?<strong>VisiBroker</strong> <strong>Edition</strong> 提 供 了 完 整 的 CORBA 2.4 ORB 运 行 期 和 支 持 开 发 环 境 , 用于 构 建 、 部 署 和 管 理 开 放 、 灵 活 和 可 互 操 作 的 C++ 和 Java 分 布 式 应 用 。 使 用OMG 互 联 网 内 部 ORB 协 议 (IIOP) 标 准 通 信 的 基 于 Web 的 应 用 可 轻 易 访 问 使 用<strong>VisiBroker</strong> <strong>Edition</strong> 构 建 的 Java 和 C++ 对 象 , 从 而 可 以 通 过 互 联 网 和 本 地 内 联网 在 分 布 式 对 象 之 间 进 行 通 信 。 <strong>VisiBroker</strong> <strong>Edition</strong> 具 有 可 确 保 获 得 高 性 能 和 互操 作 性 的 IIOP 内 置 实 现 功 能 。图 2.2<strong>VisiBroker</strong> <strong>Edition</strong> 结 构<strong>VisiBroker</strong> <strong>Edition</strong> 特 性<strong>VisiBroker</strong> <strong>Edition</strong> 具 有 以 下 部 分 中 所 描 述 的 一 些 关 键 特 性 。<strong>VisiBroker</strong> <strong>Edition</strong> 智 能 代 理 结 构<strong>VisiBroker</strong> <strong>Edition</strong> 智 能 代 理 (osagent) 是 为 客 户 端 应 用 和 对 象 实 现 提 供 工 具 的 动态 分 布 式 目 录 服 务 。 网 络 上 的 多 个 智 能 代 理 可 以 合 作 提 供 负 载 平 衡 和 高 可 用 性 , 以便 客 户 端 访 问 服 务 器 对 象 。 智 能 代 理 会 跟 踪 网 络 中 的 可 用 对 象 , 并 在 调 用 时 为 客 户端 应 用 寻 找 对 象 。 <strong>VisiBroker</strong> <strong>Edition</strong> 可 以 确 定 客 户 端 应 用 和 服 务 器 对 象 之 间 的连 接 是 否 因 服 务 器 崩 溃 和 网 络 故 障 之 类 的 错 误 而 断 开 。 如 果 检 测 到 故 障 , 则 自 动 尝试 将 客 户 端 与 不 同 主 机 上 的 另 一 服 务 器 进 行 连 接 ( 如 果 是 这 样 配 置 的 )。 有 关 智 能代 理 的 详 情 , 请 参 阅 第 12 章 " 使 用 智 能 代 理 " 和 第 10-8 页 " 使 用 服 务 质 量 "。定 位 服 务 提 供 的 增 强 型 对 象 定 位<strong>VisiBroker</strong> <strong>Edition</strong> 提 供 了 强 大 的 定 位 服 务 - CORBA 规 范 的 扩 展 - 它 使 您 能 够 从多 个 智 能 代 理 中 访 问 信 息 。 通 过 与 网 络 上 的 智 能 代 理 配 合 工 作 , 定 位 服 务 可 以 发 现能 够 捆 绑 至 客 户 端 的 对 象 的 所 有 可 用 实 例 。 通 过 使 用 触 发 器 ( 一 种 回 调 机 制 ), 客户 端 应 用 可 立 即 获 得 有 关 对 象 可 用 性 更 改 的 通 知 。 通 过 将 定 位 服 务 和 接 收 器 一 起 使用 , 您 可 以 为 服 务 器 对 象 开 发 增 强 型 的 客 户 请 求 负 载 平 衡 。 有 关 信 息 , 请 参 阅 第13 章 " 使 用 定 位 服 务 "。2-2 <strong>VisiBroker</strong> 开 发 者 指 南


<strong>VisiBroker</strong> <strong>Edition</strong> 特 性Java:C++:实 现 和 对 象 激 活 支 持<strong>VisiBroker</strong> <strong>Edition</strong> 的 对 象 激 活 守 护 程 序 (OAD) 可 用 于 在 客 户 端 需 要 使 用 对 象实 现 时 自 动 启 动 对 象 实 现 。 另 外 , <strong>VisiBroker</strong> 提 供 了 一 种 能 够 使 您 在 接 收 到 客 户请 求 之 前 延 迟 对 象 激 活 的 功 能 。 您 可 以 对 服 务 器 上 的 特 定 对 象 或 者 对 象 的 完 整 类 延迟 激 活 。 有 关 服 务 管 理 器 的 详 细 信 息 , 请 参 阅 第 7 章 " 使 用 POA"。稳 健 的 线 程 和 连 接 管 理<strong>VisiBroker</strong> <strong>Edition</strong> 为 单 线 程 和 多 线 程 管 理 提 供 本 地 支 持 。 通 过 <strong>VisiBroker</strong><strong>Edition</strong> 的 “ 每 会 话 线 程 ” 模 型 , 在 每 个 客 户 端 的 服 务 器 连 接 至 服 务 的 多 个 请 求时 , 可 以 自 动 分 配 线 程 , 然 后 在 连 接 结 束 时 终 止 线 程 。 通 过 线 程 收 集 模 型 , 可 以 根据 请 求 通 信 量 将 线 程 分 配 给 服 务 器 对 象 。 这 意 味 着 多 个 线 程 将 向 高 效 客 户 端 提 供 服务 ( 确 保 快 速 执 行 请 求 ) 而 低 效 客 户 端 可 以 共 享 单 一 线 程 , 因 此 仍 可 使 其 请 求 立 即得 到 服 务 。<strong>VisiBroker</strong> <strong>Edition</strong> 的 连 接 管 理 可 以 使 连 接 至 服 务 器 的 客 户 端 连 接 数 最 小 。 驻 留在 同 一 服 务 器 上 的 对 象 的 所 有 客 户 端 请 求 通 过 同 一 连 接 进 行 多 路 传 输 , 即 使 它 们 来源 于 不 同 线 程 。 另 外 , 以 后 再 次 连 接 至 同 一 服 务 器 时 可 以 重 复 利 用 已 建 立 的 客 户 端连 接 , 因 此 客 户 端 在 与 同 一 服 务 器 建 立 新 连 接 时 无 需 开 销 。您 完 全 可 以 配 置 所 有 线 程 和 连 接 行 为 。 有 关 <strong>VisiBroker</strong> <strong>Edition</strong> 如 何 管 理 线 程 和连 接 的 详 情 , 请 参 阅 第 8 章 " 管 理 线 程 和 连 接 "。IDL 编 译 程 序<strong>VisiBroker</strong> <strong>Edition</strong> 附 带 了 两 个 便 于 对 象 开 发 的 IDL 编 译 程 序 。● idl2java:idl2java 编 译 程 序 会 将 IDL 文 件 作 为 输 入 , 并 在 Java 中 产 生 必 需的 客 户 端 存 根 和 服 务 器 框 架 。● idl2cpp:idl2cpp 编 译 程 序 会 将 IDL 文 件 作 为 输 入 , 并 在 C++ 中 产 生 必 需 的客 户 端 存 根 和 服 务 器 框 架 。Java 和 C++: ● idl2ir:idl2ir 编 译 程 序 会 获 得 一 个 IDL 文 件 并 将 其 内 容 植 入 接 口 仓 库 。有 关 这 些 编 译 程 序 的 详 情 , 请 参 阅 第 11 章 " 使 用 IDL" 和 第 17 章 " 使 用 接 口 仓 库 "。DII 和 DSI 的 动 态 调 用对 于 动 态 调 用 ,<strong>VisiBroker</strong> <strong>Edition</strong> 提 供 了 动 态 调 用 接 口 (DII) 实 现 和 动 态 框 架 接口 (DSI) 实 现 。 DII 允 许 客 户 端 应 用 动 态 创 建 非 编 译 时 定 义 的 对 象 请 求 。 DII 包 含在 第 18 章 " 使 用 动 态 调 用 接 口 " 中 。 DSI 允 许 服 务 器 向 非 编 译 时 定 义 的 对 象 发 送请 求 。 有 关 详 情 , 请 参 阅 第 19 章 " 使 用 动 态 框 架 接 口 "。理 解 CORBA 模 型 2-3


<strong>VisiBroker</strong> <strong>Edition</strong> 特 性接 口 和 实 现 仓 库接 口 仓 库 (IR) 是 有 关 <strong>VisiBroker</strong> ORB 对 象 的 元 数 据 信 息 联 机 数 据 库 。 为 对 象 存储 的 元 数 据 信 息 包 括 有 关 模 块 、 接 口 、 操 作 、 属 性 和 例 外 的 信 息 。 第 17 章 " 使 用接 口 仓 库 " 包 含 以 下 内 容 : 如 何 启 动 接 口 仓 库 实 例 、 如 何 从 IDL 文 件 中 将 信 息 添 加至 接 口 仓 库 以 及 如 何 从 接 口 仓 库 中 提 取 信 息 。实 现 仓 库 (IR) 是 有 关 <strong>VisiBroker</strong> ORB 对 象 实 现 的 元 数 据 信 息 联 机 数 据 库 。OAD是 <strong>VisiBroker</strong> <strong>Edition</strong> 的 实 现 仓 库 接 口 , 用 于 在 客 户 端 引 用 对 象 时 自 动 激 活 实现 。 请 参 阅 第 16 章 " 使 用 对 象 激 活 守 护 进 程 (Daemon) "。服 务 器 端 的 可 移 植 性<strong>VisiBroker</strong> <strong>Edition</strong> 支 持 CORBA 可 移 植 对 象 适 配 器 (POA), 该 适 配 器 是 基 本 对象 适 配 器 (BOA) 的 替 代 品 。POA 与 BOA 共 享 一 些 相 同 功 能 , 如 激 活 对 象 、 临 时或 永 久 对 象 支 持 等 等 。 POA 还 具 有 一 些 新 特 性 , 如 POA 管 理 器 和 能 够 创 建 和 管理 对 象 实 例 的 服 务 管 理 器 。 有 关 信 息 , 请 参 阅 第 7 章 " 使 用 POA"。使 用 接 收 器 和 对 象 封 装 器 自 定 义 <strong>VisiBroker</strong> ORB<strong>VisiBroker</strong> <strong>Edition</strong> 4.x 接 收 器 使 开 发 者 能 够 查 看 客 户 端 和 服 务 之 间 的 秘 密 通 信 。<strong>VisiBroker</strong> <strong>Edition</strong> 4.x 接 收 器 是 Borland 的 私 有 接 收 器 。 接 收 器 可 用 于 扩 展 具有 自 定 义 的 客 户 端 和 服 务 器 代 码 的 <strong>VisiBroker</strong> ORB, 自 定 义 的 客 户 端 和 服 务 器 代码 使 负 载 平 衡 、 监 控 或 安 全 性 能 够 满 足 分 布 式 应 用 的 专 门 要 求 。 有 关 信 息 , 请 参 阅第 20 章 " 使 用 可 移 植 接 收 器 "。<strong>VisiBroker</strong> <strong>Edition</strong> 还 包 括 可 移 植 的 接 收 器 , 该 接 收 器 基 于 OMG 标 准 化 特 性(OMG 标 准 化 特 性 允 许 为 接 收 器 编 写 可 移 植 的 代 码 ) 并 对 不 同 供 应 商 的 ORB 使用 此 特 性 。 有 关 详 情 , 请 参 阅 COBRA 2.4 规 范 的 第 21 节 。在 客 户 端 应 用 在 限 制 对 象 上 调 用 方 法 或 在 服 务 器 应 用 接 收 操 作 请 求 时 ,<strong>VisiBroker</strong><strong>Edition</strong> 的 对 象 封 装 器 允 许 您 定 义 要 调 用 的 方 法 。 有 关 信 息 , 请 参 阅 第 22 章 " 使用 对 象 封 装 器 "。事 件 队 列事 件 队 列 被 设 计 为 仅 限 于 服 务 器 端 的 特 性 。 服 务 器 可 以 根 据 其 感 兴 趣 的 事 件 类 型 将收 听 者 登 记 到 事 件 队 列 中 , 并 可 以 根 据 需 要 来 处 理 这 些 事 件 。 有 关 事 件 队 列 的 详情 , 请 参 阅 第 23 章 " 事 件 队 列 "。命 名 服 务 中 的 后 备 存 储 器新 的 可 互 操 作 的 命 名 服 务 与 可 插 入 的 后 备 存 储 器 集 成 以 使 其 状 态 为 “ 永 久 ”。 这 可以 确 保 命 名 服 务 具 有 简 单 的 容 错 和 故 障 结 束 功 能 。 有 关 详 情 , 请 参 阅 第 14-14 页 "可 插 入 的 备 份 存 储 "。2-4 <strong>VisiBroker</strong> 开 发 者 指 南


<strong>VisiBroker</strong> <strong>Edition</strong> CORBA 兼 容 性Web 命 名Java:Web 命 名 特 性 允 许 您 将 统 一 资 源 定 位 器 (URL) 与 对 象 关 联 起 来 , 并 且 允 许 引 用 通过 指 定 URL 获 得 的 该 对 象 。 有 关 信 息 , 请 参 阅 第 27 章 " 使 用 URL 命 名 "。不 使 用 IDL 来 定 义 接 口Java:<strong>VisiBroker</strong> <strong>Edition</strong> 的 java2iiop 编 译 程 序 允 许 您 使 用 Java 语 言 而 不 是 使 用 接 口定 义 语 言 (IDL) 来 定 义 接 口 。 如 果 您 愿 意 改 写 现 有 的 Java 代 码 以 便 能 与 CORBA分 布 式 对 象 互 操 作 , 或 者 不 愿 意 学 习 IDL, 则 可 以 使 用 java2iiop 编 译 程 序 。 有 关详 情 , 请 参 阅 第 24 章 " 在 IIOP 上 使 用 RMI"。Gatekeeper<strong>VisiBroker</strong> <strong>Edition</strong> Gatekeeper 允 许 客 户 端 程 序 向 驻 留 在 Web 服 务 器 上 的 对 象发 出 操 作 请 求 , 并 允 许 客 户 端 程 序 接 收 来 自 这 些 对 象 的 回 调 , 同 时 一 直 符 合 Web浏 览 器 所 实 现 的 安 全 限 制 。 Gatekeeper 还 可 透 过 防 火 墙 进 行 通 信 , 并 可 用 作HTTP 守 护 程 序 (daemon)。 它 完 全 符 合 OMG CORBA 防 火 墙 规 范 。 有 关 详情 , 请 参 阅 用 户 指 南 。<strong>VisiBroker</strong> <strong>Edition</strong> CORBA 兼 容 性<strong>VisiBroker</strong> <strong>Edition</strong> 完 全 符 合 对 象 管 理 组 (OMG) 的 CORBA 规 范 (2.4 版 )。有 关 详 情 , 请 参 阅 位 于 http://www.omg.org/ 中 的 CORBA 规 范 。<strong>VisiBroker</strong> <strong>Edition</strong> 开 发 环 境<strong>VisiBroker</strong> <strong>Edition</strong> 用 于 开 发 和 部 署 阶 段 。 开 发 环 境 包 括 以 下 组 件 :● 管 理 和 编 程 工 具● <strong>VisiBroker</strong> ORB程 序 员 的 工 具以 下 工 具 在 开 发 阶 段 使 用 :工 具idl2iridl2cpp用 途对 于 Java <strong>VisiBroker</strong> <strong>Edition</strong> 和 C++<strong>VisiBroker</strong> <strong>Edition</strong>, 该 工 具 允 许 您 将 IDL文 件 中 定 义 的 接 口 植 入 接 口 仓 库 。该 工 具 可 从 IDL 文 件 中 生 成 C++ 存 根 和框 架 。理 解 CORBA 模 型 2-5


Java 开 发 环 境工 具idl2java该 工 具 可 从 IDL 文 件 中 生 成 Java 存 根 和框 架 。java2iiop从 Java 文 件 中 生 成 Java 存 根 和 框 架 。 该 工 具允 许 您 在 Java 中 而 不 是 在 IDL 中 定 义 接 口 。java2idl 从 包 含 Java 字 节 代 码 文 件 中 生 成 IDL 文 件 。CORBA 服 务 工 具用 途以 下 工 具 用 于 在 开 发 过 程 中 管 理 <strong>VisiBroker</strong> ORB:工 具irepoadnameserv用 途用 于 管 理 接 口 仓 库 。 请 参 阅 第 17 章 " 使 用 接口 仓 库 "。用 于 管 理 对 象 激 活 守 护 程 序 (OAD)。请 参 阅 第 16 章 " 使 用 对 象 激 活 守 护 进 程(Daemon) "。用 于 启 动 命 名 服 务 实 例 。 请 参 阅 第 14 章 " 使用 命 名 服 务 "。管 理 工 具以 下 工 具 用 于 在 开 发 过 程 中 管 理 <strong>VisiBroker</strong> ORB:工 具用 途oadutil list列 出 在 OAD 上 注 册 的 <strong>VisiBroker</strong> ORB 对象 实 现 。oadutil reg 在 OAD 上 注 册 <strong>VisiBroker</strong> ORB 对 象 实 现 。oadutil unreg 在 OAD 上 注 销 <strong>VisiBroker</strong> ORB 对 象 实 现 。osagent用 于 管 理 智 能 代 理 。 请 参 阅 第 12 章 " 使 用 智能 代 理 "。osfind报 告 指 定 网 络 中 运 行 的 对 象Java 开 发 环 境<strong>VisiBroker</strong> <strong>Edition</strong> 在 Java 运 行 时 间 环 境 中 使 用 以 下 组 件 :● “Java 2 标 准 版 ”● “Java 运 行 期 环 境 ”● “<strong>VisiBroker</strong> <strong>Edition</strong> 的 要 求 是 什 么 ”2-6 <strong>VisiBroker</strong> 开 发 者 指 南


Java 2 标 准 版与 C++ <strong>VisiBroker</strong> 或 Java <strong>VisiBroker</strong> 之 间 的 互 操 作 性在 开 发 使 用 <strong>VisiBroker</strong> ORB 的 程 序 片 或 应 用 时 , 需 要 Java 开 发 环 境 , 如Borland Jbuilder。 JavaSoft 的 Java 开 发 者 套 件 (JDK) 也 包 括 Java 运 行 期环 境 。Sun Microsystems 已 使 JavaSoft JDK- 包 括 其 Java 运 行 时 间 环 境 - 可 用 于Solaris 和 Windows NT 平 台 。 您 可 以 从 以 下 Sun Microsystems 的 网 站 中 下 载JDK: http://java.sun.com/。JDK 也 已 被 移 植 到 IBM AIX、 OS/2、 SGI IRIX 和 HP-UX。 这 些 其 它 版 本 可 从各 自 的 硬 件 供 应 商 网 站 中 下 载 。 要 查 看 各 个 平 台 中 的 可 用 内 容 , 请 访 问 SunMicrosystems 的 JavaSoft 网 站 :http://java.sun.com/products/jdk/jdkports.html。Java 运 行 期 环 境任 何 想 要 执 行 <strong>VisiBroker</strong> 服 务 和 工 具 的 终 端 用 户 都 需 要 Java 运 行 时 间 环 境 。Java 运 行 时 间 环 境 是 解 释 和 执 行 Java 应 用 的 引 擎 。 通 常 , Java 运 行 时 间 环 境 与Java 开 发 环 境 捆 绑 在 一 起 。 有 关 详 情 , 请 参 阅 第 2-7 页 "Java 2 标 准 版 "。<strong>VisiBroker</strong> <strong>Edition</strong> 的 要 求 是 什 么为 了 使 用 <strong>VisiBroker</strong> <strong>Edition</strong> Gatekeeper, 您 需 要 使 用 在 JavaServer Web开 发 套 件 1.0.1 中 获 得 的 Servlet API 2.1。带 Java 功 能 的 Web 浏 览 器Java:程 序 片 可 运 行 于 任 何 带 Java 功 能 的 Web 浏 览 器 中 , 如 NetscapeCommunicator、 Netscape Navigator 或 Microsoft 的 Internet Explorer。通 过 定 位 至 以 下 一 个 URL, 您 可 以 获 得 这 些 带 Java 功 能 的 Web 浏 览 器 :● http://www.netscape.com/● http://microsoft.com/ie/与 C++ <strong>VisiBroker</strong> 或 Java <strong>VisiBroker</strong> 之 间 的 互 操 作 性通 过 Java <strong>VisiBroker</strong> <strong>Edition</strong>can 创 建 的 应 用 可 与 通 过 C++ <strong>VisiBroker</strong><strong>Edition</strong> 开 发 的 对 象 实 现 通 信 。 同 样 , 通 过 C++ <strong>VisiBroker</strong> <strong>Edition</strong> 创 建 的 应 用也 能 与 通 过 Java <strong>VisiBroker</strong> <strong>Edition</strong> 开 发 的 对 象 实 现 通 信 。 例 如 , 如 果 想 在C++ <strong>VisiBroker</strong> 中 使 用 Java 应 用 , 只 需 将 用 于 开 发 Java 应 用 的 IDL 用 作 输 入项 , 输 入 到 随 C++ <strong>VisiBroker</strong> <strong>Edition</strong> 一 起 提 供 的 <strong>VisiBroker</strong> <strong>Edition</strong> IDL 编译 程 序 中 。 然 后 您 可 以 使 用 由 此 而 产 生 的 C++ 框 架 来 开 发 对 象 实 现 。 要 对 Java<strong>VisiBroker</strong> <strong>Edition</strong> 使 用 C++ 应 用 , 请 重 复 该 过 程 。 但 是 , 您 需 要 使 用 随 Java<strong>VisiBroker</strong> <strong>Edition</strong> 一 起 提 供 的 <strong>VisiBroker</strong> <strong>Edition</strong> IDL。理 解 CORBA 模 型 2-7


与 其 它 ORB 产 品 之 间 的 互 操 作 性 。另 外 , 通 过 <strong>VisiBroker</strong> for Java 编 写 的 对 象 实 现 可 以 与 在 <strong>VisiBroker</strong> for C++中 编 写 的 客 户 端 一 起 工 作 。 事 实 上 , 通 过 <strong>VisiBroker</strong> for Java 编 写 的 服 务 器 可 以与 任 何 与 CORBA 兼 容 的 客 户 端 一 起 工 作 , 通 过 <strong>VisiBroker</strong> for Java 编 写 的 客 户端 也 可 以 与 任 何 与 CORBA 兼 容 的 服 务 器 一 起 工 作 。 这 也 适 用 于 任 何 <strong>VisiBroker</strong>for C++ 对 象 实 现 。与 其 它 ORB 产 品 之 间 的 互 操 作 性 。与 CORBA 兼 容 的 软 件 对 象 使 用 互 联 网 内 部 ORB 协 议 (IIOP) 进 行 通 信 , 并 且完 全 可 以 互 操 作 , 即 使 是 在 不 熟 悉 相 互 实 现 的 不 同 供 应 商 开 发 这 些 软 件 对 象 时 ,这 些 软 件 对 象 仍 可 以 互 操 作 。<strong>VisiBroker</strong> <strong>Edition</strong> 通 过 使 用 IIOP 允 许 客 户 端 和 服务 器 应 用 ( 通 过 <strong>VisiBroker</strong> <strong>Edition</strong> 来 开 发 ) 与 其 他 供 应 商 的 多 种 ORB 产 品 互操 作 。IDL 至 C++ 的 映 射C++:<strong>VisiBroker</strong> <strong>Edition</strong> 符 合 OMG IDL/C++ 语 言 映 射 规 范 。 有 关 通 过 idl2cpp 编 译程 序 实 现 的 当 前 <strong>VisiBroker</strong> <strong>Edition</strong> IDL 至 C++ 语 言 的 映 射 的 汇 总 , 请 参 阅<strong>VisiBroker</strong> <strong>Edition</strong> 程 序 员 参 考 。 对 于 每 个 IDL 构 造 , 都 存 在 描 述 相 应 的 C++构 造 以 及 代 码 示 例 的 小 节 。有 关 映 射 规 范 的 详 情 , 请 参 阅 OMG IDL/C++ 语 言 映 射 规 范 。IDL 至 Java 的 映 射Java:<strong>VisiBroker</strong> <strong>Edition</strong> 符 合 OMG IDL/ Java 语 言 映 射 规 范 。 有 关 通 过 idl2 java编 译 程 序 实 现 的 当 前 <strong>VisiBroker</strong> <strong>Edition</strong> IDL 至 java 语 言 的 映 射 的 汇 总 , 请 参 阅<strong>VisiBroker</strong> <strong>Edition</strong> 程 序 员 参 考 。 对 于 每 个 IDL 构 造 , 都 存 在 描 述 相 应 的 Java构 造 以 及 代 码 示 例 的 小 节 。有 关 映 射 规 范 的 详 情 , 请 参 阅 OMG IDL/ Java 语 言 映 射 规 范 。2-8 <strong>VisiBroker</strong> 开 发 者 指 南


第章建 立 您 的 环 境第 3 章在 使 用 <strong>VisiBroker</strong> <strong>Edition</strong> 之 前 , 您 必 须 先 设 置 几 个 环 境 变 量 。设 置 路 径 环 境 变 量注 :PATH 环 境 变 量 在 安 装 过 程 中 被 自 动 设 置 为 包 含 <strong>VisiBroker</strong> <strong>Edition</strong> 下 的 bin 目录 。 安 装 指 令 由 安 装 指 南 提 供 。如 果 您 选 择 显 式 设 置 PATH 环 境 变 量 , 请 查 看 以 下 各 节 以 了 解 如 何 进 行 设 置 。在 Windows 平 台 上 更 新 路 径假 设 <strong>VisiBroker</strong> <strong>Edition</strong> 安 装 在 c:\vbroker 下 , 您 可 以 用 以 下 的 DOS 命 令 来 设置 PATH。 另 外 一 个 方 法 是 将 PATH 设 置 在 autoexec.bat 文 件 中 。prompt> set PATH=c:\vbroker\bin;%PATH%如 果 <strong>VisiBroker</strong> 安 装 在 默 认 目 录 (C:\BES\) 之 下 , 您 可 以 用 以 下 方 法 来 设 置路 径 :prompt> set PATH=c:\BES\vbroker\bin;%PATH%在 Windows NT 平 台 上 更 新 路 径虽 然 DOS 的 set 命 令 可 以 用 于 在 Windows NT 下 设 置 环 境 变 量 , 但 您 可 能 会 发现 通 过 使 用 “ 系 统 ” 控 制 面 板 来 使 用 自 动 设 置 PATH 会 更 容 易 。 假 设 <strong>VisiBroker</strong><strong>Edition</strong> 安 装 于 c:\vbroker 目 录 下 , 执 行 以 下 步 骤 以 在 “ 系 统 ” 控 制 面 板 中 编 辑路 径 变 量 :1 打 开 “ 系 统 ” 控 制 面 板 。建 立 您 的 环 境 3-1


CLASSPATH2 在 “ 系 统 属 性 ” 窗 口 下 选 择 “ 环 境 变 量 ” 按 钮 。3 选 择 “PATH” 作 为 要 编 辑 的 变 量 。4 单 击 “ 编 辑 ” 按 钮 以 编 辑 变 量 的 值 。5 将 以 下 内 容 加 入 PATH:c:\vbroker\bin;如 果 <strong>VisiBroker</strong> 安 装 于 默 认 目 录 之 下 , 则 PATH 为 :注 意 :c:\BES\vbroker\bin;用 “ 系 统 ” 控 制 面 板 对 环 境 变 量 所 作 的 变 更 不 会 反 映 在 当 前 正 在 运 行 的 应 用 中 , 但随 后 启 动 的 应 用 和 DOS 命 令 将 使 用 新 的 设 置 。在 UNIX 平 台 上 设 置 PATH如 果 您 在 使 用 csh 而 且 已 将 <strong>VisiBroker</strong> <strong>Edition</strong> 安 装 在 /usr/local/vbroker 目 录下 , 则 可 以 用 以 下 的 命 令 来 更 新 PATH 环 境 :prompt> setenv PATH /usr/local/vbroker/bin:$PATH如 果 您 在 使 用 Bourne shell 而 且 已 将 <strong>VisiBroker</strong> <strong>Edition</strong> 安 装 在 /usr/local/vbroker 目 录 下 , 则 可 以 用 以 下 的 命 令 来 更 新 PATH 环 境 :prompt> PATH=$PATH:/usr/local/vbroker/binprompt> export PATHCLASSPATHJava:这 个 环 境 变 量 定 义 您 的 系 统 中 所 使 用 的 各 种 Java 包 的 位 置 。 在 安 装 或 配 置<strong>VisiBroker</strong> <strong>Edition</strong> 时 , 无 须 设 置 CLASSPATH 变 量 。设 置 VBROKER_ADM 环 境 变 量VBROKER_ADM 环 境 变 量 定 义 存 储 管 理 目 录 , 该 目 录 存 储 <strong>VisiBroker</strong> <strong>Edition</strong> 的 接 口仓 库 、 对 象 激 活 守 护 程 序 和 智 能 代 理 的 重 要 配 置 信 息 。在 Windows 平 台 上 设 置 VBROKER_ADM在 您 安 装 <strong>VisiBroker</strong> <strong>Edition</strong> 的 过 程 中 , VBROKER_ADM 环 境 变 量 被 设 置 在Windows 注 册 表 上 。 您 可 以 使 用 vregedit 工 具 变 更 注 册 表 的 设 置 。您 可 以 通 过 设 置 VBROKER_ADM 环 境 变 量 覆 盖 注 册 表 。 假 设 您 想 使 用 自 己 的 c:\my\adm 目 录 , 您 可 以 用 以 下 命 令 来 设 置 VBROKER_ADM 环 境 变 量 :prompt> set VBROKER_ADM=c:\my\adm3-2 <strong>VisiBroker</strong> 开 发 者 指 南


在 UNIX 平 台 上 设 置 VBROKER_ADM设 定 OSAGENT_PORT 环 境 变 量如 果 您 在 使 用 csh , 而 且 已 将 <strong>VisiBroker</strong> <strong>Edition</strong> 安 装 在 /usr/local 目 录 下 , 则可 以 用 以 下 的 命 令 来 设 置 VBROKER_ADM 环 境 变 量 :prompt> setenv VBROKER_ADM /usr/local/vbroker/adm如 果 您 在 使 用 Bourne shell, 而 且 已 将 <strong>VisiBroker</strong> <strong>Edition</strong> 安 装 在 /usr/local目 录 下 , 则 可 以 用 以 下 的 命 令 来 设 置 VBROKER_ADM 环 境 变 量 :prompt> VBROKER_ADM=/usr/local/vbroker/admprompt> export VBROKER_ADM设 定 OSAGENT_PORT 环 境 变 量OSAGENT_PORT 环 境 变 量 定 义 智 能 代 理 被 听 取 的 端 口 号 。 虽 然 您 可 以 将 端 口 号 设 定 为5000 ~ 65355 间 的 任 意 值 , 但 在 默 认 情 况 下 智 能 代 理 在 端 口 号 14000 上 听 取 。在 您 安 装 <strong>VisiBroker</strong> <strong>Edition</strong> 的 过 程 中 , OSAGENT_PORT 变 量 被 设 置 在 Windows注 册 表 上 。 您 可 以 使 用 vregedit 工 具 变 更 注 册 表 的 设 置 。您 可 以 通 过 设 置 OSAGENT_PORT 环 境 变 量 覆 盖 注 册 表 。 假 设 您 想 要 智 能 代 理 在 端 口号 10000 听 取 , 则 可 以 使 用 以 下 的 命 令 来 设 置 OSAGENT_PORT 环 境 变 量 :prompt> set OSAGENT_PORT=10000如 果 您 在 使 用 csh 而 您 想 要 智 能 代 理 在 端 口 号 10000 听 取 , 则 可 以 使 用 以 下 的 命 令来 设 置 OSAGENT_PORT 环 境 变 量 :prompt> setenv OSAGENT_PORT 10000如 果 您 在 使 用 Bourne shell, 而 您 想 要 智 能 代 理 在 端 口 号 10000 听 取 , 则 可 以 使用 以 下 的 命 令 来 设 置 OSAGENT_PORT 环 境 变 量 :prompt> OSAGENT_PORT=10000prompt> export OSAGENT_PORT记 录 输 出许 多 <strong>VisiBroker</strong> <strong>Edition</strong> 工 具 提 供 详 细 模 式 以 在 工 具 执 行 的 时 候 显 示 它 的 信 息 。另 外 , 任 何 与 <strong>VisiBroker</strong> <strong>Edition</strong> 库 链 接 的 应 用 也 可 以 产 生 输 出 。 在 UNIX系 统 中 , 该 输 出 被 写 入 控 制 台 。 在 Windows 系 统 中 , 该 输 出 被 写 入 几 个 日 志文 件 之 一 。下 表 总 结 出 了 Windows 上 可 能 产 生 的 各 种 日 志 文 件 的 名 称 。表 3.1Windows 平 台 上 产 生 的 日 志 文 件 的 总 结文 件 名 称说 明oad.log当 以 -v 标 志 开 始 时 , 由 对 象 激 活 守 护 程 序 产生 。osagent.log 当 以 -v 标 志 开 始 时 , 由 智 能 代 理 产 生 。建 立 您 的 环 境 3-3


记 录 输 出这 些 日 志 文 件 的 位 置 由 以 下 的 规 则 来 确 定 :1 尝 试 将 文 件 写 入 由 VBROKER_ADM 变 量 指 定 目 录 下 的 日 志 目 录 。 以 下 的 实 例 说 明 如何 在 Windows 上 将 VBROKER_ADM 变 量 设 定 到 一 个 特 定 的 目 录 :SET VBROKER_ADM=c:\my\adm\log2 如 果 应 用 或 工 具 没 有 该 目 录 的 写 入 许 可 , 则 尝 试 将 文 件 写 入 启 动 应 用 或 工 具 的 驱动 器 上 的 \vbroker\log 目 录 。如 果 步 骤 2 失 败 , 则 尝 试 将 文 件 写 入 当 前 目 录 。3-4 <strong>VisiBroker</strong> 开 发 者 指 南


第章使 用 <strong>VisiBroker</strong> <strong>Edition</strong> 开 发 实第 4 章例 应 用本 节 使 用 实 例 来 描 述 创 建 Java 和 C++ 下 的 分 布 式 、 基 于 对 象 的 应 用 程 序 的 开 发过 程 。该 实 例 应 用 的 Java 和 C++ 代 码 由 bank_agent.html 文 件 来 提 供 。 您 可 以 在 安 装<strong>VisiBroker</strong> for Java 或 <strong>VisiBroker</strong> for C++ 软 件 包 的 examples/basic/bank_agent 目 录 下 找 到 该 文 件 。 如 果 您 不 知 道 各 软 件 包 的 位 置 , 则 查 看 系 统 管理 器 。开 发 过 程当 您 使 用 <strong>VisiBroker</strong> <strong>Edition</strong> 开 发 分 布 式 应 用 时 , 您 必 须 首 先 确 定 应 用 程 序 所 需要 的 对 象 。 下 图 示 范 开 发 一 个 实 例 银 行 应 用 的 步 骤 。 以 下 是 开 发 该 实 例 银 行 所 采 取的 步 骤 的 概 要 描 述 :1 使 用 接 口 定 义 语 言 (IDL) 为 每 个 对 象 编 写 说 明 。IDL 是 实 现 者 用 来 指 定 一 个 对 象 所 要 提 供 的 操 作 以 及 如 何 调 用 这 些 操 作 的 语 言 。在 本 实 例 中 , 我 们 使 用 IDL 以 balance() 方 式 来 定 义 Account 接 口 , 以 open()方 式 来 定 义 AccountManager 接 口 。2 使 用 IDL 编 译 器 生 成 客 户 存 根 代 码 和 服 务 器 POA 服 务 对 象 代 码 。根 据 步 骤 1 中 所 描 述 的 接 口 说 明 , 使 用 (Java) idl2java 或 (C++)idl2cpp编 译 器 生 成 客 户 存 根 ( 这 为 Account 和 AccountManager 对 象 方 式 提 供 接 口 ) 和服 务 器 类 ( 这 为 远 端 对 象 的 实 现 提 供 类 )。3 编 写 客 户 程 序 代 码 。使 用 <strong>VisiBroker</strong> <strong>Edition</strong> 开 发 实 例 应 用 4-1


开 发 过 程要 完 成 客 户 程 序 的 实 现 过 程 , 先 初 始 化 <strong>VisiBroker</strong> ORB, 绑 定 到 Account 和AccountManager 对 象 , 调 用 这 些 对 象 上 的 方 法 , 然 后 打 印 余 额 。4 编 写 服 务 器 对 象 代 码 。要 完 成 服 务 器 对 象 代 码 的 实 现 过 程 , 我 们 必 须 从 AccountPOA 和AccountManagerPOA 类 派 生 , 提 供 interface 方 法 的 实 现 , 然 后 实 现 服 务 器 的main 例 程 。5 编 写 客 户 和 服 务 器 端 代 码 。C++: 要 创 建 客 户 程 序 , 编 写 客 户 程 序 代 码 并 用 客 户 存 根 链 接 。C++: 要 创 建 Account 服 务 器 , 编 写 服 务 器 对 象 代 码 并 用 服 务 器 框 架 链 接 。Java: 要 创 建 客 户 程 序 , 编 写 客 户 程 序 代 码 并 用 客 户 存 根 链 接 。Java: 要 创 建 Account 服 务 器 , 编 写 客 户 程 序 代 码 并 用 服 务 器 端 存 根 链 接 。6 启 动 服 务 器 。7 运 行 服 务 器 程 序 。4-2 <strong>VisiBroker</strong> 开 发 者 指 南


步 骤 1 : 定 义 对 象 接 口图 4.1开 发 实 例 库 应 用步 骤 1: 定 义 对 象 接 口用 <strong>VisiBroker</strong> <strong>Edition</strong> 创 建 应 用 的 第 一 步 是 使 用 OMG 的 接 口 定 义 语 言 (IDL)说 明 您 所 有 的 对 象 及 其 接 口 。 IDL 可 以 被 映 射 到 多 种 编 程 语 言 。然 后 您 可 以 使 用 (C++)idl2cpp 或 Java idl2java 编 译 器 从 IDL 说 明 生 成 存 根 例程 和 服 务 对 象 代 码 。 存 根 例 程 被 您 的 客 户 程 序 用 来 调 用 对 象 上 的 操 作 。 您 使 用 服 务对 象 代 码 以 及 您 编 写 的 代 码 来 创 建 执 行 对 象 的 服 务 器 。 一 旦 客 户 和 对 象 代 码 完 成后 , 即 被 用 作 您 的 C++ 或 Java 编 译 器 的 输 入 来 产 生 一 个 客 户 Java 程 序 片 或 应 用和 一 个 对 象 服 务 器 。用 IDL 中 编 写 帐 户 接 口IDL 的 语 法 与 C++ 相 似 , 可 以 用 以 定 义 模 块 、 接 口 、 数 据 结 构 等 。使 用 <strong>VisiBroker</strong> <strong>Edition</strong> 开 发 实 例 应 用 4-3


步 骤 2 : 生 成 客 户 存 根 和 服 务 器 服 务 对 象下 面 的 实 例 显 示 了 bank_agent 实 例 的 中 的 Bank.idl 文 件 的 内 容 。 Account 接 口 用C++ 提 供 单 独 的 成 员 函 数 或 用 Java 提 供 单 独 的 方 法 , 以 取 得 当 前 的 余 额 。 如 果 不存 在 现 有 帐 户 , 则 AccountManager 接 口 为 用 户 创 建 一 个 帐 户 。module Bank{interface Account {float balance();};interface Account {Account open (in string name);};};步 骤 2: 生 成 客 户 存 根 和 服 务 器 服 务 对 象您 用 IDL 创 建 的 接 口 说 明 被 <strong>VisiBroker</strong> <strong>Edition</strong> idl2cpp 用 来 生 成 C++ 存 根 例程 , 或 被 idl2java 编 译 器 用 以 生 成 客 户 程 序 的 Java 类 和 对 象 实 现 的 框 架 代 码 。C++: 客 户 程 序 将 存 根 例 程 用 于 所 有 的 成 员 函 数 调 用 。Java: 客 户 程 序 将 Java 类 用 于 所 有 的 方 法 调 用 。您 使 用 框 架 代 码 以 及 您 编 写 的 代 码 来 创 建 执 行 对 象 的 服 务 器 。C++: 一 旦 客 户 程 序 和 服 务 器 对 象 的 代 码 完 成 后 , 即 被 用 于 您 的 C++ 编 译 器 和 链 接 器 的输 入 以 生 成 客 户 和 服 务 器 。Java:C++:Java:一 旦 客 户 程 序 和 服 务 器 对 象 的 代 码 完 成 后 , 即 被 用 于 您 的 Java 编 译 器 的 输 入 以 生成 客 户 和 服 务 器 可 执 行 类 。下 图 示 范 的 是 生 成 客 户 存 根 和 服 务 器 服 务 对 象 的 步 骤 。因 为 Bank.idl 文 件 不 需 要 任 何 特 殊 处 理 , 您 可 以 用 下 列 命 令 来 编 写 该 文 件 。prompt> idl2cpp Bank.idlprompt> idl2cpp Bank.idl要 取 得 关 于 idl2cpp and idl2java 编 译 器 命 令 行 选 项 的 详 情 , 请 参 阅 第 11 章 " 使用 IDL"。由 idl 编 译 器 生 成 的 文 件C++: idl2cpp 编 译 器 可 以 从 Bank.idl 文 件 产 生 四 个 文 件 :● Bank_c.hh: 包 括 Account 和 AccountManager 类 的 定 义 。● Bank_c.cc: 包 括 由 客 户 所 使 用 的 内 部 存 根 例 程 。● Bank_c.hh: 包 括 AccountPOA 和 AccountManagerPOA 服 务 对 象 类 的 定 义 。● Bank_c.hh: 包 括 由 服 务 器 使 用 的 内 部 例 程 。4-4 <strong>VisiBroker</strong> 开 发 者 指 南


Windows:步 骤 3: 实 现 客 户您 将 使 用 Bank_c.hh 和 Bank_c.cpp 文 件 来 建 立 客 户 应 用 。Bank_s.hh 和 Bank_s.cpp文 件 用 于 建 立 服 务 器 对 象 。 所 有 生 成 的 文 件 都 具 有 一 个 .cpp 或 .hh 后 缀 以 帮 助 您 将它 们 与 源 文 件 区 别 开 来 。从 idl2cpp 编 译 器 生 成 的 文 件 的 默 认 后 缀 是 .cpp。 但 是 , 与 <strong>VisiBroker</strong> <strong>Edition</strong>实 例 相 关 连 的 Makefiles 使 用 -src 后 缀 以 将 输 出 变 更 到 指 定 的 扩 展 文 件 。小 心 : 切 勿 修 改 由 idl2cpp 编 译 器 生 成 的 文 件 的 内 容 。Java:因 为 仅 允 许 每 个 文 件 中 有 一 个 公 共 接 口 或 类 , 编 译 IDL 文 件 会 生 成 数 个 .java 文件 。 这 些 文 件 存 储 在 一 个 被 称 为 Bank 的 次 级 目 录 下 , 这 是 一 个 用 IDL 定 义 的 模块 名 , 是 生 成 的 文 件 所 属 的 文 件 包 。 以 下 是 生 成 的 .java 文 件 列 表 :● _AccountManagerStub.java: 客 户 AccountManager 对 象 的 存 根 代 码 。● _AccountStub.java: 客 户 Account 对 象 的 存 根 代 码 。● Account.java:Account 接 口 声 明 。● AccountHelper.java: 声 明 AccountHelper 类 , 定 义 有 用 的 实 用 工 具 方 法 。● AccountHolder.java: 声 明 AccountHolder 类 , 这 为 传 递 Account 对 象 提 供 容 器 。● AccountManager.java:AccountManager 接 口 声 明 。● AccountManagerHelper.java: 说 明 AccountManagerHelper 类 , 这 定 义 有 用 的 实用 工 具 方 法 。● AccountManagerHolder.java: 声 明 AccountManagerHolder 类 , 这 为 传 递AccountManager 对 象 提 供 一 个 容 器 。● AccountManagerOperation.java: 本 接 口 说 明 Bank.idl 文 件 中 的 AccountManager接 口 中 所 定 义 的 方 法 签 名 。● AccountManagerPOA.java: 服 务 器 端 AccountManager 对 象 实 现 的 POA 服 务 对 象代 码 ( 实 现 基 础 代 码 )。● AccountManagerPOATie.java: 通 过 使 用 tie 机 制 , 在 服 务 器 端 用 以 实 现AccountManager 对 象 的 类 , 描 述 详 见 第 9 章 " 使 用 tie 机 制 "。● AccountOperations.java: 本 接 口 说 明 在 Bank.idl 文 件 中 的 Account 接 口 中 所 定义 的 方 法 签 名 。● AccountPOA.java: 服 务 器 端 的 Account 对 象 实 现 的 POA 服 务 对 象 代 码 ( 实 现基 础 代 码 )。● AccountPOATie.java: 通 过 使 用 tie 机 制 , 在 服 务 器 端 用 以 实 现 Account 对 象 的类 , 详 见 第 9 章 " 使 用 tie 机 制 "。要 取 得 关 于 Helper、 Holder 和 Operations 类 的 详 情 , 请 参 阅 程 序 员 参 考 。步 骤 3: 实 现 客 户许 多 用 以 实 现 bank 客 户 的 类 包 含 在 由 idl2cpp (C++) 所 生 成 的 Bank 代 码 中 或者 由 (Java) idl2java 编 译 器 所 生 成 的 文 件 包 中 , 如 以 上 实 例 所 示 。使 用 <strong>VisiBroker</strong> <strong>Edition</strong> 开 发 实 例 应 用 4-5


步 骤 3: 实 现 客 户(C++) Client.C 文 件 和 (Java) Client.java 文 件 示 范 本 实 例 , 包 含 在bank_agent 目 录 下 。 通 常 , 您 要 创 建 这 个 文 件 。Client.CC++:Client 程 序 实 现 取 得 银 行 帐 户 当 前 余 额 的 客 户 应 用 。 银 行 客 户 程 序 执 行 这 些 步 骤 :1 初 始 化 <strong>VisiBroker</strong> ORB。2 绑 定 到 一 个 AccountManager 对 象 。3 使 用 由 bind() 返 回 的 对 象 引 用 , 取 得 Account 的 余 额 。4 通 过 调 用 Account 对 象 上 的 余 额 得 到 余 额 。#include "Bank_c.hh"int main(int argc, char* const* argv) {try {// 初 始 化 ORB。CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);// 得 到 管 理 器 IdPortableServer::ObjectId_var managerId =PortableServer::string_to_ObjectId("BankManager");// 找 到 一 个 管 理 器 。 给 出 POA 全 名 和 服 务 对 象 ID。Bank::AccountManager_ptr manager =Bank::AccountManager::_bind("/bank_agent_poa", managerId);// 使 用 argv[1] 作 帐 户 名 称 , 或 使 用 默 认 值 。const char* name = argc > 1 ? argv[1] :"Jack B. Quick";// 要 求 帐 户 管 理 器 打 开 一 个 命 名 的 帐 户 。Bank::Account_ptr account = manager->open(name);// 得 到 帐 户 的 余 额 。float balance = account->balance();// 打 印 余 额 。cout


步 骤 3: 实 现 客 户// 初 始 化 ORB。org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);// 得 到 管 理 器 Idbyte[] managerId = "BankManager".getBytes();// 找 到 一 个 帐 户 管 理 器 。 给 出 POA 全 名 及 服 务 对 象 ID。Bank.AccountManager manager =Bank.AccountManagerHelper.bind(orb, "/bank_agent_poa", managerId);// 使 用 args[0] 作 为 帐 户 名 称 , 或 使 用 默 认 值 。String name = args.length > 0 ? args[0] :"Jack B. Quick";// 要 求 帐 户 管 理 器 打 开 一 个 命 名 的 帐 户 。Bank.Account account = manager.open(name);// 得 到 帐 户 的 余 额 。float balance = account.balance();// 打 印 余 额 。System.out.println("The balance in " + name + "'s account is $" + balance);}}绑 定 到 AccountManager 对 象C++:Java:在 您 的 客 户 程 序 可 以 调 用 open (String name) 成 员 函 数 (C++) 或 方 法 (Java)之 前 , 客 户 必 须 首 先 使 用 bind() 成 员 函 数 (C++) 或 方 法 (Java) 来 建 立 一 个到 实 现 AccountManager 对 象 的 服 务 器 的 连 接 。bind() 成 员 函 数 的 实 现 由 idl2cpp 自 动 实 现 。 bind() 成 员 函 数 要 求 <strong>VisiBroker</strong>ORB 定 位 并 建 立 一 个 到 服 务 器 的 连 接 。bind() 方 法 的 实 现 由 idl2java 编 译 器 自 动 生 成 。 bind() 方 法 要 求 <strong>VisiBroker</strong>ORB 定 位 建 立 一 个 到 服 务 器 的 连 接 。如 果 服 务 器 成 功 定 位 并 建 立 一 个 连 接 , 则 一 个 代 理 对 象 会 被 创 建 以 代 表 服 务 器 的AccountManagerPOA 对 象 。 一 个 AccountManager 对 象 的 指 针 (C++) 或 目 标 引 用被 返 回 到 您 的 客 户 程 序 。得 到 一 个 帐 户 对 象C++:Java:接 下 来 , 您 的 客 户 程 序 需 要 调 用 AccountManager 对 象 上 的 open() 成 员 函 数 以 得 到指 向 指 定 用 户 名 称 的 Account 对 象 的 指 针 。然 后 , 您 的 客 户 类 需 要 调 用 AccountManager 对 象 上 的 open() 方 法 以 得 到 一 个 指 定用 户 名 称 的 Account 对 象 的 对 象 引 用 。取 到 余 额C++:Java:一 旦 您 的 客 户 程 序 与 一 个 Account 对 象 建 立 起 连 接 , balance() 成 员 函 数 就 可 以 被用 来 获 得 余 额 。 客 户 的 balance() 成 员 函 数 实 际 上 是 由 idl2cpp 编 译 器 生 成 的 存根 , 该 编 译 器 收 集 请 求 所 必 需 的 所 有 数 据 , 并 把 它 们 送 到 服 务 器 对 象 。一 旦 您 的 客 户 程 序 与 一 个 Account 对 象 建 立 起 连 接 , balance() 成 员 函 数 就 可 以 被用 来 获 得 余 额 。 客 户 的 balance() 成 员 函 数 实 际 上 是 由 idl2java 编 译 器 生 成 的 存根 , 该 编 译 器 收 集 请 求 所 必 需 的 所 有 数 据 , 并 把 它 们 送 到 服 务 器 对 象 。使 用 <strong>VisiBroker</strong> <strong>Edition</strong> 开 发 实 例 应 用 4-7


步 骤 4: 实 现 服 务 器AccountManagerHelper.javaJava:Java:本 文 件 位 于 Bank 文 件 包 内 。 它 包 含 一 个 AccountManagerHelper 对 象 , 定 义 用 于 绑定 到 实 现 该 对 象 的 服 务 器 的 数 种 方 法 。 bind() 类 方 法 与 指 定 的 POA 管 理 器 联 系 以解 析 该 对 象 。 我 们 的 实 例 使 用 接 受 一 个 对 象 名 称 的 bind 方 法 版 本 , 但 是 , 客 户 可能 要 随 意 指 定 一 个 特 殊 的 主 机 和 特 殊 的 绑 定 选 项 。 要 取 得 关 于 Helper 类 的 详 情 ,请 参 阅 程 序 员 参 考 。package Bank;public final class AccountManagerHelper {. . .public static Bank.AccountManager bind(org.omg.CORBA.ORB orb) {return bind(orb, null, null, null);. . .}}其 它 成 员 函 数C++: 有 数 种 其 它 成 员 函 数 提 供 , 它 们 允 许 您 的 客 户 程 序 处 理 AccountManager 对 象 引 用 。Java: 有 数 种 其 它 方 法 提 供 , 它 们 允 许 您 的 客 户 程 序 处 理 AccountManager 对 象 引 用 。这 些 方 法 和 成 员 函 数 中 的 大 部 分 在 示 例 的 客 户 程 序 中 没 有 用 到 , 但 <strong>VisiBroker</strong><strong>Edition</strong> 程 序 员 参 考 中 对 它 们 有 详 细 描 述 。步 骤 4: 实 现 服 务 器与 客 户 一 样 , 实 现 银 行 服 务 器 的 许 多 类 包 含 在 由 (C++) idl2cpp 或 (C++)idl2java 编 译 器 生 成 的 头 文 件 Bank 文 件 包 中 。 Server.C and Server.java 文 件 是包 含 的 服 务 器 实 现 , 用 于 示 范 本 实 例 。 通 常 , 您 ( 程 序 员 ) 要 创 建 这 个 文 件 。服 务 器 程 序这 个 文 件 实 现 我 们 的 银 行 事 务 实 例 中 的 服 务 器 端 的 Server 类 。 下 面 的 代 码 实 例 是服 务 器 端 的 C++ 和 Java 程 序 实 例 。 服 务 器 程 序 执 行 以 下 操 作 :● 初 始 化 ORB。● 用 要 求 的 策 略 创 建 可 移 植 对 象 适 配 器 。● 创 建 帐 户 管 理 器 服 务 对 象 。● 激 活 服 务 对 象 。● 激 活 POA 管 理 器 ( 和 POA)。C++:● 等 待 进 入 的 请 求 。#include "BankImpl.h"int main(int argc, char* const* argv) {try {4-8 <strong>VisiBroker</strong> 开 发 者 指 南


步 骤 4: 实 现 服 务 器// 初 始 化 ORB。CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);// 取 得 根 POA 的 引 用PortableServer::POA_var rootPOA = PortableServer::POA::_narrow(orb->resolve_initial_references("RootPOA"));CORBA::PolicyList policies;policies.length(1);policies[(CORBA::ULong)0] =rootPOA->create_lifespan_policy(PortableServer::PERSISTENT);// 得 到 POA 管 理 器PortableServer::POAManager_var poa_manager = rootPOA->the_POAManager();// 用 正 确 的 策 略 创 建 myPOAPortableServer::POA_var myPOA = rootPOA->create_POA("bank_agent_poa",poa_manager, policies);// 创 建 服 务 对 象AccountManagerImpl managerServant;// 确 定 服 务 对 象 IDPortableServer::ObjectId_var managerId =PortableServer::string_to_ObjectId("BankManager");// 用 myPOA 上 的 ID 激 活 服 务 对 象myPOA->activate_object_with_id(managerId, &managerServant);// 激 活 POA 管 理 器poa_manager->activate();cout servant_to_reference(&managerServant)


步 骤 5: 建 立 实 例// 用 myPOA 上 的 ID 激 活 服 务 对 象myPOA.activate_object_with_id(managerId, managerServant);// 激 活 POA 管 理 器rootPOA.the_POAManager().activate();System.out.println(myPOA.servant_to_reference(managerServant) + " isready."};// 等 待 进 入 的 请 求 。orb.run();} catch (Exception e) {e.printStackTrace();}}}理 解 Account 类 结 构C++:您 实 现 的 Account 类 是 从 idl2cpp 编 译 器 生 成 的 POA_Bank::Account 派 生 的 。 近 看Bank_c.hh 中 所 定 义 的 POA_Bank::Account 类 定 义 , 可 以 看 到 它 是 从 Account 类 派生 的 。 下 图 显 示 了 类 结 构 。图 4.2AccountImpl 接 口 的 类 结 构步 骤 5: 建 立 实 例C++:C++:C++:您 所 创 建 的 Client.C 和 生 成 的 Bank_c.cc 文 件 被 编 译 并 链 接 在 一 起 , 以 创 建 客 户 程序 。 您 所 建 立 的 Server.C 文 件 , 以 及 生 成 的 Bank_s.cpp 和 Bank_c.cpp 文 件 , 经 过编 译 链 接 , 创 建 银 行 帐 户 服 务 器 。 客 户 程 序 和 服 务 器 均 必 须 与 <strong>VisiBroker</strong> ORB 库链 接 。您 的 <strong>VisiBroker</strong> <strong>Edition</strong> examples 目 录 包 含 一 个 用 于 本 实 例 和 其 它 <strong>VisiBroker</strong><strong>Edition</strong> 实 例 的 (C++) Makefile.cpp 或 (Java) vbmake.bat。examples 目 录 也 包 含 一 个 命 名 为 stdmk ( 用 于 UNIX) 或 stdmk_nt ( 用 于Windows NT) 的 文 件 , 定 义 文 件 位 置 和 由 Makefile 使 用 的 变 量 设 置 。如 果 您 的 编 译 器 不 支 持 指 定 的 标 志 , 您 可 能 需 要 对 stdmk 或 stdmk_nt 文 件 进 行 自定 义 。4-10 <strong>VisiBroker</strong> 开 发 者 指 南


用 <strong>VisiBroker</strong> <strong>Edition</strong> 部 署 应 用Windows:C++:Java:启 动 服 务 器打 开 一 个 DOS 命 令 窗 口 , 然 后 使 用 下 列 的 C++ 和 Java DOS 命 令 来 启 动 您 的 服务 器 :prompt> start Serverprompt> start vbj ServerUNIX: 键 入 下 列 命 令 以 启 动 您 的 Account 服 务 器 :C++:Java:C++:Java:prompt> Server&prompt> vbj Server&运 行 客 户Windows: 打 开 一 个 单 独 的 DOS 命 名 窗 口 , 然 后 使 用 下 列 的 DOS 命 令 来 启 动您 的 客 户 :prompt> Clientprompt> vbj ClientUNIX: 要 启 动 您 的 客 户 程 序 , 键 入 下 列 命 令 :C++: prompt> ClientJava: prompt> vbj Client您 应 该 看 到 与 下 列 的 显 示 类 似 的 输 出 ( 帐 户 余 额 是 随 机 计 算 的 )。帐 户 中 的 余 额 是 168.38 元 。用 <strong>VisiBroker</strong> <strong>Edition</strong> 部 署 应 用<strong>VisiBroker</strong> <strong>Edition</strong> 也 使 用 于 部 署 阶 段 。 当 开 发 人 员 创 建 的 客 户 程 序 或 服 务 器 应用 已 通 过 测 试 并 准 备 好 生 产 的 时 候 , 需 要 进 行 这 一 阶 段 的 工 作 。 此 时 , 系 统 管 理 器准 备 好 将 客 户 程 序 部 署 到 终 端 用 户 的 桌 面 或 服 务 器 类 机 器 的 服 务 器 应 用 上 。要 进 行 这 一 部 署 工 作 , <strong>VisiBroker</strong> ORB 须 支 持 前 端 的 客 户 程 序 。 您 必 须 将<strong>VisiBroker</strong> ORB 安 装 在 每 一 台 运 行 客 户 程 序 的 机 器 上 。 同 一 台 主 机 上 的 客 户 ( 使用 <strong>VisiBroker</strong> ORB) 共 享 <strong>VisiBroker</strong> ORB。 <strong>VisiBroker</strong> ORB 也 支 持 中 间 层 上的 服 务 器 应 用 。 您 必 须 将 全 套 <strong>VisiBroker</strong> ORB 安 装 在 每 一 台 运 行 服 务 器 应 用 的 机器 上 。 同 一 台 机 器 上 的 服 务 器 应 用 或 对 象 ( 使 用 <strong>VisiBroker</strong> ORB) 共 享<strong>VisiBroker</strong> ORB。 客 户 可 以 使 用 GUI 前 端 、 applet ( 程 序 片 )、 或 客 户 程 序 。服 务 器 实 现 包 括 中 间 层 上 的 业 务 逻 辑 。4-12 <strong>VisiBroker</strong> 开 发 者 指 南


用 <strong>VisiBroker</strong> <strong>Edition</strong> 部 署 应 用图 4.3用 <strong>VisiBroker</strong> <strong>Edition</strong> ORB 部 署 的 客 户 和 服 务 器 程 序<strong>VisiBroker</strong> <strong>Edition</strong> 应 用展 开 应 用为 了 展 开 用 <strong>VisiBroker</strong> <strong>Edition</strong> 所 开 发 的 应 用 , 您 必 须 首 先 在 要 执 行 应 用 的 主 机上 安 装 运 行 期 环 境 , 并 确 保 局 域 网 上 必 要 的 支 持 服 务 可 用 。C++: 用 <strong>VisiBroker</strong> for C++ 开 发 的 应 用 所 需 要 的 运 行 期 环 境 包 括 下 列 组 件 :● <strong>VisiBroker</strong> <strong>Edition</strong> C++ 库 , 位 于 安 装 产 品 的 bin 次 级 目 录 。● 应 用 所 要 求 的 支 持 服 务 的 可 用 性 。<strong>VisiBroker</strong> ORB 库 必 须 安 装 在 要 执 行 部 署 的 应 用 程 序 的 主 机 上 。 这 些 库 的 位 置 必须 包 含 在 应 用 环 境 的 PATH 中 。Java: 用 Java 开 发 的 应 用 所 需 要 的 运 行 期 环 境 包 括 下 列 组 件 :● Java 运 行 期 环 境 。● <strong>VisiBroker</strong> <strong>Edition</strong> Java 包 , 存 储 于 vbjorb.jar 文 件 , 位 于 您 安 装<strong>VisiBroker</strong> <strong>Edition</strong> 的 lib 子 目 录 下 。● 应 用 所 要 求 的 支 持 服 务 的 可 用 性 。Java 运 行 期 环 境 必 须 安 装 在 要 执 行 部 署 的 应 用 的 主 机 上 , <strong>VisiBroker</strong> <strong>Edition</strong>Java 软 件 包 必 须 安 装 在 要 执 行 部 署 的 应 用 的 主 机 上 。Java: 当 您 使 用 vbj 可 执 行 文 件 时 , 环 境 变 量 会 自 动 建 立 。如 果 部 署 的 应 用 要 使 用 特 定 主 机 上 的 智 能 代 理 (osagent), 则 您 必 须 在 运 行 应 用之 前 先 设 定 OSAGENT_ADDR 环 境 变 量 。 您 可 以 使 用 ORBagentAddr (C++) 或vbroker.agent.addr 属 性 (Java) 作 为 命 令 行 变 量 来 指 定 主 机 名 或 IP 地 址 。 下表 列 出 了 用 于 C++ 应 用 的 命 令 行 变 量 。使 用 <strong>VisiBroker</strong> <strong>Edition</strong> 开 发 实 例 应 用 4-13


用 <strong>VisiBroker</strong> <strong>Edition</strong> 部 署 应 用如 果 部 署 的 应 用 在 与 智 能 代 理 (osagent) 沟 通 时 要 使 用 特 定 的 UDP 端 口 , 则 您必 须 在 运 行 应 用 之 前 先 设 定 OSAGENT_PORT 环 境 变 量 。C++: 您 可 以 使 用 ORBagentPort (C++) 命 令 行 变 量 来 指 定 IP 端 口 号 。Java: 您 可 以 使 用 vbroker.agent.port (Java) 命 令 行 变 量 来 指 定 IP 端 口 号 。关 于 环 境 变 量 的 详 情 , 请 参 阅 第 3 章 " 建 立 您 的 环 境 "。支 持 服 务 可 用 性在 要 运 行 部 署 的 应 用 的 网 络 上 , 必 须 有 智 能 代 理 (osagent) 正 在 运 行 。 随 着 部 署的 应 用 的 要 求 的 不 同 , 您 可 能 需 要 确 保 还 要 确 保 其 它 <strong>VisiBroker</strong> <strong>Edition</strong> 运 行 期支 持 服 务 是 可 用 的 。 这 些 服 务 包 括 :支 持 服 务 需 要 的 条 件 :对 象 激 活 守 护 程 序 (oad)接 口 仓 库 (irep)Gatekeeper使 用 vbjJava: 您 可 以 使 用 vbj 命 令 来 启 动 您 的 应 用 , 并 进 入 控 制 您 应 用 状 态 的 命 令 行 变 量 。vbj -Dvbroker.agent.port=10000 运 行 应 用一 个 部 署 的 应 用 是 一 个 实 现 对 象 所 要 求 的 启 动对 象 的 服 务 器 。一 个 部 署 的 应 用 使 用 动 态 框 架 接 口 或 动 态 实 现接 口 。 参 阅 第 17 章 " 使 用 接 口 仓 库 " 以 查 看这 些 接 口 的 描 述 。一 个 部 署 的 应 用 需 要 在 使 用 防 火 墙 来 确 保 网 络安 全 的 环 境 下 执 行 。C++:您 已 经 编 译 了 您 的 客 户 程 序 和 服 务 器 实 现 , 您 已 准 备 就 绪 , 可 以 运 行 您 的 第 一 个<strong>VisiBroker</strong> <strong>Edition</strong> 应 用 程 序 了 。在 您 尝 试 运 行 <strong>VisiBroker</strong> <strong>Edition</strong> 客 户 程 序 或 服 务 器 实 现 之 前 , 您 必 须 先 在 您 的局 域 网 中 的 至 少 一 台 主 机 上 启 动 智 能 代 理 。 有 关 智 能 代 理 的 详 情 , 请 参 阅 第 4-11页 " 启 动 智 能 代 理 "。执 行 客 户 应 用客 户 应 用 是 使 用 <strong>VisiBroker</strong> ORB 对 象 的 客 户 应 用 , 但 它 不 将 任 何 自 己 的<strong>VisiBroker</strong> ORB 对 象 提 供 给 其 它 客 户 应 用 。Java: 客 户 可 以 从 vbj 命 令 开 始 , 或 从 一 个 Java 支 持 的 网 络 浏 览 器 内 部 开 始 。4-14 <strong>VisiBroker</strong> 开 发 者 指 南


用 <strong>VisiBroker</strong> <strong>Edition</strong> 部 署 应 用C++: 下 表 总 结 出 了 可 以 指 定 给 客 户 应 用 的 命 令 行 变 量 。 这 些 变 量 也 适 用 于 服 务 器 。表 4.1适 用 于 C++ 客 户 应 用 的 命 令 行 变 量选 项-ORBagentAddr -ORBagentPort -ORBbackcompat -ORBbackdii -ORBir_name -ORBir_ior -ORBnullstring -ORBrcvbufsize -ORBsendbufsize -ORBshmsize -ORBtcpnodelay 说 明指 定 运 行 本 客 户 应 该 使 用 的 智 能 代 理 的 主 机 的主 机 名 称 和 IP 地 址 。 如 果 指 定 的 地 址 上 没 有智 能 代 理 或 者 该 选 项 未 被 指 定 , 广 播 消 息 将 被用 来 定 位 智 能 代 理 。指 定 智 能 代 理 的 端 口 号 。 当 需 要 多 个<strong>VisiBroker</strong> ORB 域 时 , 该 选 项 会 很 有 用 。 如要 未 作 指 定 , 则 使 用 默 认 端 口 号 14000。如 果 设 置 为 1, 则 该 选 项 规 定 应 该 提 供 对 于<strong>VisiBroker</strong> for C++ 2.0 的 后 向 兼 容 。 默 认 值是 0。如 果 设 置 为 1, 则 该 选 项 规 定 应 该 提 供 对 于1.0 IDL 到 C++ 映 射 的 支 持 。 如 果 设 置 为 0或 未 作 指 定 , 则 使 用 新 的 1.1 映 射 。 默 认 设 置为 0。 如 果 -ORBbackcompat 设 置 为 1, 则 该 选项 会 自 动 被 设 置 为 1。当 Object::get_interface() 方 法 在 对 象 实 现上 被 调 用 时 , 指 定 要 访 问 的 接 口 仓 库 的 名 称 。当 Object::get_interface() 方 法 在 对 象 实 现上 被 调 用 时 , 指 定 要 访 问 的 接 口 仓 库 的 IOR。如 果 设 置 为 1, 则 该 选 项 规 定 <strong>VisiBroker</strong>ORB 允 许 C++ NULL 字 符 串 可 以 被 流 式 传 递 。NULL 字 符 串 被 汇 集 为 长 度 为 0 的 字 符 串 ( 而相 对 的 空 字 符 串 ( “” ) 将 会 被 汇 集 为 长 度 为1 的 字 符 串 ), 具 有 单 一 的 字 符 “\0”。 如 果设 置 为 0, 尝 试 排 列 出 一 个 NULL 字 符 串 将 会掷 出 CORBA::BAD_PARAM 违 例 。 尝 试 汇 集 到 一个 NULL 字 符 串 将 会 掷 出 CORBA::MARSHAL 违例 。 默 认 设 置 为 0。 如 果 -ORBbackcompat 设 置为 1, 则 该 选 项 会 自 动 被 设 置 为 1。指 定 用 于 接 受 响 应 的 TCP 缓 冲 器 ( 以 字 节 数表 示 ) 的 大 小 。 如 要 未 作 指 定 , 则 使 用 默 认 缓冲 器 大 小 。 该 变 量 可 以 用 以 大 幅 度 地 影 响 性 能或 基 准 结 果 。指 定 用 于 发 送 客 户 请 求 的 TCP 缓 冲 器 ( 以 字节 数 表 示 ) 的 大 小 。 如 要 未 作 指 定 , 则 使 用 默认 缓 冲 器 大 小 。 该 变 量 可 以 用 以 大 幅 度 地 影 响性 能 或 基 准 结 果 。指 定 共 享 存 储 器 中 的 发 送 和 接 收 段 ( 以 字 节表 示 ) 的 大 小 。 如 果 您 的 客 户 程 序 和 对 象 通 过共 享 的 存 储 器 沟 通 , 您 可 以 用 该 选 项 来 增 强 性能 。 本 选 项 仅 受 Windows 平 台 支 持 。当 设 置 为 1 时 , 它 设 定 所 有 的 套 接 字 立 即 发 送请 求 。 默 认 值 0 允 许 套 接 字 在 缓 冲 器 充 满 的 情况 下 成 批 地 发 送 请 求 。 该 变 量 可 以 大 幅 度 地 影响 性 能 或 基 准 结 果 。使 用 <strong>VisiBroker</strong> <strong>Edition</strong> 开 发 实 例 应 用 4-15


用 <strong>VisiBroker</strong> <strong>Edition</strong> 部 署 应 用Java: 下 表 总 结 出 了 可 以 指 定 给 客 户 应 用 的 命 令 行 变 量 。表 4.2适 用 于 Java 客 户 应 用 的 命 令 行 变 量选 项-DORBagentAddr=-DORBagentPort= -DORBmbufSize= -DORBtcpNoDelay=-DORBconnectionMax=-DORBconnectionMaxIdle= 说 明指 定 运 行 本 客 户 应 该 使 用 的 智 能 代 理 的 主 机 的主 机 名 称 和 IP 地 址 。 如 果 指 定 的 地 址 上 没 有智 能 代 理 或 者 该 选 项 未 被 指 定 , 广 播 消 息 将 被用 来 定 位 智 能 代 理 。指 定 智 能 代 理 的 端 口 号 。 当 需 要 多 个 ORB 域时 , 该 选 项 会 很 有 用 。 如 果 未 指 定 端 口 号 , 则默 认 值 被 设 定 为 4000。指 定 由 <strong>VisiBroker</strong> <strong>Edition</strong> 用 于 操 作 请 求 过程 的 中 间 缓 冲 器 的 大 小 。 为 了 改 善 性 能 , 本 版的 <strong>VisiBroker</strong> ORB 可 以 进 行 比 以 往 的<strong>VisiBroker</strong> <strong>Edition</strong> 版 本 更 为 复 杂 的 缓 冲 器管 理 。 发 送 和 接 收 缓 冲 器 的 默 认 大 小 为 4 K。如 果 发 送 或 收 到 的 数 据 大 于 默 认 值 , 则 新 的 缓冲 器 会 被 分 配 给 每 个 请 求 / 回 答 。 如 果 您 的 应用 经 常 发 送 大 于 4 K 的 数 据 , 而 您 想 利 用 缓 冲器 管 理 , 则 您 可 以 使 用 这 种 系 统 属 性 来 指 定 一个 更 多 字 节 的 默 认 缓 冲 器 大 小 。当 设 定 为 true 时 , 所 有 的 网 络 连 接 将 立 即 发送 数 据 。 默 认 值 是 false, 此 值 允 许 网 络 连 接在 缓 冲 器 充 满 的 情 况 下 成 批 地 发 送 数 据 。指 定 在 OAid TSession 被 选 定 的 情 况 下 每 个 对象 实 现 所 允 许 的 连 接 的 最 大 数 量 。 如 果 未 作 指定 , 则 默 认 值 为 无 限 制 。指 定 每 个 网 络 连 接 在 被 <strong>VisiBroker</strong> <strong>Edition</strong>关 闭 前 可 以 处 于 空 闲 状 态 的 毫 秒 数 。 在 默 认 情况 下 , 此 值 被 认 为 定 360, 这 意 味 着 连 接 不 可能 超 时 。 Internet 应 用 应 该 设 置 该 选 项 。执 行 服 务 器 应 用Java:服 务 器 应 用 是 提 供 一 个 或 多 个 <strong>VisiBroker</strong> ORB 对 象 给 客 户 应 用 的 应 用 。 一 个 服 务器 应 用 可 以 从 vbj 命 令 开 始 , 或 者 由 对 象 激 活 守 护 进 程 (oad) 激 活 。下 表 总 结 出 了 可 以 指 定 给 服 务 器 应 用 的 命 令 行 变 量 。表 4.3适 用 于 Java 服 务 器 应 用 的 命 令 行 变 量选 项-DOAipAddr -DOAport -DOAid 说 明指 定 用 于 对 象 适 配 器 的 主 机 名 或 IP 地 址 。 如果 您 的 主 机 有 多 个 网 络 接 口 而 BOA 仅 与 其 中一 个 接 口 连 接 , 则 使 用 选 项 。 如 果 未 指 定 任 何选 项 , 则 使 用 主 机 的 默 认 地 址 。指 定 在 听 取 新 连 接 时 对 象 适 配 器 所 使 用 的 端口 号 。指 定 BOA 所 使 用 的 线 程 策 略 。 如 果 您 不 是 处于 后 向 兼 容 模 式 , 则 默 认 值 是 Tpool ; 如 果您 处 于 后 向 兼 容 模 式 , 则 默 认 值 是 TSession。4-16 <strong>VisiBroker</strong> 开 发 者 指 南


用 <strong>VisiBroker</strong> <strong>Edition</strong> 部 署 应 用表 4.3适 用 于 Java 服 务 器 应 用 的 命 令 行 变 量选 项-DOAthreadMax -DOAthreadMin -DOAthreadMaxIdle-DOAconnectionMax -DOAconnectionMaxIdle说 明指 定 在 选 定 了 OAid TPool 的 情 况 下 所 允 许的 线 程 的 最 大 数 量 。 如 果 您 未 作 指 定 或 指 定0, 这 意 味 着 选 择 无 数 个 线 程 , 更 确 切 地 说 ,线 程 数 量 仅 受 制 于 您 的 系 统 资 源 。指 定 线 程 池 中 可 用 的 线 程 的 最 小 数 量 。 如 果 未作 指 定 , 则 默 认 值 为 0。 仅 当 OAid TPool 被 选定 时 , 您 才 可 以 指 定 该 选 项 。该 选 项 指 定 一 个 线 程 在 不 服 务 于 任 何 请 求 的 情况 下 可 以 存 在 的 时 间 。 超 出 指 定 的 时 间 后 空 闲的 线 程 可 以 被 返 回 到 系 统 。 在 默 认 情 况 下 , 该选 项 被 设 定 为 300s。指 定 在 选 定 了 OAid TSession 的 情 况 下 所 允许 的 连 接 的 最 大 数 量 。 如 果 未 作 指 定 , 则 默 认值 为 无 限 制 。该 选 项 指 定 一 个 连 接 在 没 有 通 信 量 的 情 况 下 可以 空 闲 的 时 间 。 超 出 此 时 限 后 空 闲 的 连 接 可 以被 <strong>VisiBroker</strong> <strong>Edition</strong> 关 闭 。 在 默 认 情 况下 , 此 值 被 设 为 定 0, 这 意 味 着 连 接 不 可 能 自动 超 时 。 对 于 Internet 应 用 , 应 该 设 定 该选 项 。使 用 <strong>VisiBroker</strong> <strong>Edition</strong> 开 发 实 例 应 用 4-17


4-18 <strong>VisiBroker</strong> 开 发 者 指 南


第章处 理 违 例第 5 章CORBA 模 型 中 的 违 例CORBA 模 型 中 的 违 例 包 括 系 统 违 例 和 用 户 违 例 。 CORBA 规 范 定 义 了 一 组 系 统违 例 , 在 处 理 客 户 请 求 的 过 程 中 发 生 错 误 时 , 这 些 违 例 可 能 会 被 掷 出 。 另 外 , 出 现通 信 故 障 时 , 系 统 违 例 也 会 被 掷 出 。 系 统 违 例 可 以 被 随 时 掷 出 , 它 们 不 需 要 在 接 口中 声 明 。 您 可 以 在 IDL 中 为 您 创 建 的 对 象 定 义 用 户 违 例 并 指 定 违 例 被 掷 出 的 环 境 。它 们 包 含 在 方 法 签 名 下 。 如 果 在 处 理 客 户 请 求 时 , 一 个 对 象 掷 出 一 个 违 例 , 则<strong>VisiBroker</strong> ORB 负 责 将 该 信 息 反 馈 给 客 户 。系 统 违 例系 统 违 例 通 常 由 <strong>VisiBroker</strong> ORB 掷 出 , 不 过 , 对 象 实 现 通 过 接 收 器 掷 出 违 例 也 是可 能 的 。 当 <strong>VisiBroker</strong> ORB 掷 出 一 个 SystemException 时 , 则 会 显 示 以 下 所 示 的CORBA 定 义 的 出 错 状 态 之 一 。表 5.1CORBA 定 义 的 系 统 违 例违 例 名 称说 明BAD_CONTEXT 处 理 上 下 文 对 象 时 出 错 。BAD_INV_ORDER 例 程 调 用 失 序 。BAD_OPERATION 非 法 操 作 。BAD_PARAM 传 递 了 一 个 非 法 的 参 数 。BAD_TYPECODE非 法 的 typecode。COMM_FAILURE 通 信 故 障 。DATA_CONVERSION 数 据 转 换 错 误 。FREE_MEM 无 法 释 放 内 存 。IMP_LIMIT 实 现 限 制 被 覆 盖 。INITIALIZE<strong>VisiBroker</strong> ORB 初 始 化 失 败 。处 理 违 例 5-1


系 统 违 例表 5.1CORBA 定 义 的 系 统 违 例违 例 名 称说 明INTERNAL<strong>VisiBroker</strong> ORB 内 部 错 误 。INTF_REPOS 访 问 接 口 仓 库 时 出 错 。INV_FLAG 指 定 了 非 法 的 标 志 。INV_INDENT 标 识 符 语 法 错 误 。INV_OBJREF 指 定 了 非 法 的 对 象 参 考 。MARSHAL 汇 集 参 数 或 结 果 时 出 错 。INVALID_TRANSACTION指 定 的 事 务 不 合 法 ( 与 ITS/OTS 一 起 使用 )。NO_IMPLEMENT 操 作 实 现 不 可 用 。NO_MEMORY 动 态 内 存 分 配 失 败 。NO_PERMISSION 尝 试 的 操 作 不 被 允 许 。NO_RESOURCES 没 有 足 够 的 资 源 来 处 理 请 求 。NO_RESPONSE 给 请 求 的 回 答 不 可 用 。OBJ_ADAPTOR 对 象 适 配 器 侦 测 到 故 障 。OBJECT_NOT_EXIST 对 象 不 可 用 。PERSIST_STORE 永 久 存 储 故 障 。TRANSIENT 临 时 故 障 。TRANSACTION_REQUIRED 需 要 事 务 ( 与 ITS/OTS 一 起 使 用 )。TRANSACTION_ROLLEDBACK 事 务 被 拒 绝 ( 与 ITS/OTS 一 起 使 用 )。TIMEOUT 请 求 超 时 。UNKNOWN 未 知 的 违 例 。C++ 下 的 SystemException 类 :class SystemException : public CORBA::Exception {public:static const char *_id;virtual ~SystemException();CORBA::ULong minor() const;void minor(CORBA::ULong val);CORBA::CompletionStatus completed() const;void completed(CORBA::CompletionStatus status);...static SystemException *_downcast(Exception *);...};Java 下 的 SystemException 类 :public abstract class org.omg.CORBA.SystemException extendsjava.lang.RuntimeException {protected SystemException(java.lang.String reason,int minor, CompletionStatus completed) { . . . }public String toString() { . . . }public CompletionStatus completed;public int minor;}5-2 <strong>VisiBroker</strong> 开 发 者 指 南


系 统 违 例取 得 完 成 状 态系 统 违 例 有 一 个 完 成 状 态 来 说 明 掷 出 违 例 的 操 作 是 否 已 完 成 。 以 下 的 代 码 示 例 说 明CompletionStatus 的 CompletionStatus 枚 举 型 值 。 如 果 不 能 确 定 操 作 状 态 , 则返 回 COMPLETED_MAYBE。enum CompletionStatus {COMPLETED_YES = 0;COMPLETED_NO = 1;COMPLETED_MAYBE = 2;};C++: 您 可 以 使 用 这 些 SystemException 方 法 来 检 索 完 成 状 态 。CompletionStatus completed();取 得 和 设 置 minor code ( 次 要 代 码 )C++:您 可 以 使 用 这 些 SystemException 方 法 来 检 索 和 设 置 minor code。 Minor code 用于 提 供 关 于 错 误 类 型 的 更 详 尽 的 信 息 。ULong minor() const;void minor(ULong val);确 定 系 统 违 例 的 类 型C++:<strong>VisiBroker</strong> <strong>Edition</strong> 违 例 类 型 的 设 计 允 许 您 编 程 来 捕 捉 任 何 类 型 的 违 例 , 然 后 再通 过 使 用 _downcast() 方 法 确 定 它 的 类 型 。 静 态 方 法 _downcast() 接 受 到 任 何Exception 对 象 的 指 针 。 与 CORBA::Object 上 定 义 的 _downcast() 方 法 一 样 , 如 果指 针 是 SystemException 类 型 , 则 _downcast() 将 把 指 针 返 回 给 您 。 如 果 指 针 不 是SystemException 类 型 , _downcast() 将 返 回 一 个 NULL 指 针 。 请 参 阅 第 24 章 " 在IIOP 上 使 用 RMI" 查 看 详 情 。捕 捉 系 统 违 例C++:您 的 应 用 应 该 将 <strong>VisiBroker</strong> ORB 和 远 端 调 用 装 入 一 个 “try catch”( 尝 试 捕 捉 )程 序 块 中 。 以 下 的 代 码 示 例 说 明 帐 户 客 户 程 序 ( 参 见 第 4 章 " 使 用 <strong>VisiBroker</strong><strong>Edition</strong> 开 发 实 例 应 用 ") 如 何 在 C++ 和 Java 下 打 印 一 个 违 例 。#include "Bank_c.hh"int main(int argc, char* const* argv) {try {CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);PortableServer::ObjectId_var managerId =PortableServer::string_to_ObjectId("BankManager");Bank::AccountManager_var manager =Bank::AccountManager::_bind("/bank_agent_poa", managerId);const char* name = argc > 1 ? argv[1] : "Jack B. Quick";Bank::Account_var account = manager->open(name);CORBA::Float balance = account->balance();处 理 违 例 5-3


系 统 违 例cout


系 统 违 例CORBA::Float acct_balance = account->balance();// 打 印 余 额 。cout


用 户 违 例捕 捉 特 定 类 型 的 系 统 违 例您 可 以 专 门 选 择 捕 捉 您 所 期 望 的 每 种 类 型 的 违 例 , 而 不 必 捕 捉 所 有 类 型 的 违 例 。 以下 的 代 码 示 例 分 别 显 示 该 方 法 在 C++ 和 Java 下 的 应 用 。C++: ...int main(int argc, char* const* argv) {try {// 初 始 化 ORB。CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);// 限 制 到 帐 户 。Account_var account = Account::_bind();// 取 得 帐 户 余 额 。CORBA::Float acct_balance = account->balance(); 1/19/01 Vijay says change toaccount->balance// 打 印 余 额 。cout


用 户 违 例C++: class UserException: public Exception {public:...static const char *_id;virtual ~UserException();static UserException *_downcast(Exception *);};Java: public abstract class UserException extends java.lang.Exception {protected UserException();protected UserException(String reason);}定 义 用 户 违 例假 定 您 要 改 进 帐 户 应 用 ( 如 第 4 章 " 使 用 <strong>VisiBroker</strong> <strong>Edition</strong> 开 发 实 例 应 用 " 中所 述 ) 以 便 account 对 象 可 以 掷 出 一 个 违 例 。 如 果 account 对 象 中 的 资 金 不 足 时 ,您 希 望 掷 出 一 个 命 名 为 AccountFrozen 的 用 户 违 例 。 将 用 户 违 例 添 加 到 Account 接口 的 IDL 规 范 时 所 需 要 用 的 新 增 程 序 部 分 用 粗 体 表 示 。// Bank.idlmodule Bank {interface Account {exception AccountFrozen {};float balance() raises(AccountFrozen);};};The idl2cpp) (C++) 或 idl2java (Java) 编 译 器 将 为 AccountFrozen 违 例 类生 成 以 下 的 代 码 。class Account : public virtual CORBA::Object {...class AccountFrozen: public CORBA_UserException {public:static const CORBA_Exception::Description description;AccountFrozen() {}static CORBA::Exception *_factory() {return new AccountFrozen();}~AccountFrozen() {}virtual const CORBA_Exception::Description& _desc() const;static AccountFrozen *_downcast(CORBA::Exception *exc);CORBA::Exception *_deep_copy() const {return new AccountFrozen(*this);}void _raise() const {raise *this;}...}由 idl2java 编 译 器 生 成 的 AccountFrozen 类 :处 理 违 例 5-7


用 户 违 例Java:package Bank;public interface Account extends com.inprise.vbroker.CORBA.Object,Bank.AccountOperations, org.omg.CORBA.portable.IDLEntity {}package Bank;public interface AccountOperations {public float balance () throws Bank.AccountPackage.AccountFrozen;}package Bank.AccountPackage;public final class AccountFrozen extends org.omg.CORBA.UserException {public AccountFrozen () { . . . }public AccountFrozen (java.lang.String _reason) { . . . }public synchronized java.lang.String toString() { . . . }}C++:修 改 对 象 以 掷 出 违 例要 使 用 违 例 以 便 在 适 当 的 出 错 环 境 下 能 够 掷 出 违 例 , 必 须 修 改 AccountImpl 对 象 。CORBA::Float AccountImpl::balance(){if( _balance < 50 ) {raise Account::AccountFrozen();} else {return _balance;}修 改 对 象 实 现 以 便 掷 出 违 例 ( 在 Java 下 ):Java: public class AccountImpl extends Bank.AccountPOA {public AccountImpl(float balance) {_balance = balance;}public float balance() throws AccountFrozen {if (_balance < 50) {throws AccountFrozen();} else {return _balance;}private float _balance;}捕 捉 用 户 违 例当 对 象 实 现 掷 出 违 例 时 , <strong>VisiBroker</strong> ORB 负 责 将 违 例 反 映 给 您 的 客 户 端 程 序 。 检查 是 否 是 UserException 与 检 查 是 否 有 SystemException 类 似 。 要 修 改 帐 户 客 户 程序 以 捕 捉 AccountFrozen 违 例 , 对 代 码 作 以 下 修 改 。C++: ...try {// 初 始 化 ORB。CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);// 限 制 到 帐 户 。Account_var account = Account::_bind();5-8 <strong>VisiBroker</strong> 开 发 者 指 南


用 户 违 例// 得 到 帐 户 的 余 额 。CORBA::Float acct_balance = account->balance();}catch(const Account::AccountFrozen& e) {cerr


5-10 <strong>VisiBroker</strong> 开 发 者 指 南


第章服 务 器 基 础第 6 章本 节 介 绍 设 置 服 务 器 接 收 客 户 端 请 求 时 需 要 做 的 工 作 。概 述设 置 服 务 器 时 需 要 执 行 的 基 本 步 骤 如 下 :● 初 始 化 <strong>VisiBroker</strong> ORB● 创 建 和 设 置 POA● 激 活 POA 管 理 器● 激 活 对 象初 始 化 <strong>VisiBroker</strong> ORB● 等 待 客 户 端 请 求本 节 从 全 局 上 介 绍 每 项 工 作 , 使 您 清 楚 必 须 考 虑 的 因 素 。 每 个 步 骤 的 具 体 内 容 取 决于 个 人 的 要 求 。如 下 节 中 所 述 , <strong>VisiBroker</strong> ORB 会 在 客 户 端 请 求 和 对 象 实 现 之 间 建 立 一 条 通 讯 链接 。 每 个 应 用 程 序 必 须 首 先 初 始 化 <strong>VisiBroker</strong> ORB, 才 能 与 其 通 讯 。在 C++ 下 初 始 化 <strong>VisiBroker</strong> ORB:// 初 始 化 <strong>VisiBroker</strong> ORB。CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);在 Java 下 初 始 化 <strong>VisiBroker</strong> ORB:// 初 始 化 <strong>VisiBroker</strong> ORB。org.ogm.CORBA.ORB orb=org.omg.CORBA.ORB.init(args,null);服 务 器 基 础 6-1


创 建 POA创 建 POA注 意 :旧 版 CORBA 对 象 适 配 器 ( 基 本 对 象 适 配 器 [ 或 称 为 BOA]) 不 允 许 使 用 可 移 植对 象 服 务 器 代 码 。 OMG 开 发 的 新 规 范 解 决 了 这 些 问 题 , 并 创 建 了 可 移 植 对 象 适 配器 ( 或 称 为 POA)。POA 涉 及 的 内 容 相 当 广 泛 。 本 节 为 您 介 绍 POA 的 一 些 基 本 功 能 。 有 关 详 情 , 请参 阅 第 7 章 " 使 用 POA" 和 OMG 规 范 。基 本 来 说 , POA ( 及 其 组 件 ) 决 定 在 收 到 客 户 端 请 求 时 应 该 调 用 的 服 务 对 象 , 然后 调 用 该 服 务 对 象 。 服 务 对 象 是 一 个 编 程 对 象 , 它 提 供 抽 象 对 象 的 实 现 。 服 务 务 对象 不 是 CORBA 对 象 。每 个 <strong>VisiBroker</strong> ORB 提 供 一 个 POA ( 称 为 “ 根 POA”)。 您 可 以 创 建 更 多 的POA 并 为 它 们 配 置 不 同 的 行 为 。 也 可 以 定 义 POA 控 制 的 对 象 的 特 征 。设 置 具 有 一 个 服 务 对 象 的 POA 的 步 骤 如 下 :● 取 得 根 POA 的 引 用● 定 义 POA 策 略● 创 建 一 个 根 POA 的 子 POA● 创 建 服 务 对 象 并 激 活● 通 过 其 管 理 器 激 活 POA部 份 步 骤 对 您 的 应 用 程 序 可 能 会 有 所 不 同 。取 得 根 POA 的 引 用所 有 服 务 器 应 用 程 序 必 须 取 得 根 POA 的 引 用 , 才 能 管 理 对 象 或 创 建 新 的 POA。C++:Java:// 取 得 根 POA 的 引 用CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");// 窄 转 换 POA 引 用 的 对 象 引 用PortableServer::POA_var rootPOA = PortableServer::POA::_narrow(obj);//2. 取 得 根 POA 的 引 用org.omg.CORBA.Object obj = orb.reseolve_initial_reference("RootPOA");// 窄 转 换 POA 引 用 的 对 象 引 用POA rootPoa = org.omg.PortableServer.POAHelper.narrow(obj);您 可 以 使 用 resolve_initial_references 取 得 根 POA 的 引 用 。resolve_initial_references 会 返 回 一 个 CORBA::Object 类 型 的 值 。 您 负 责 将 返 回的 对 象 引 用 窄 转 换 为 所 需 的 类 型 , 在 上 例 中 所 需 类 型 是 PortableServer::POA。然 后 , 您 可 以 利 用 该 引 用 创 建 其 它 POA ( 如 果 需 要 )。6-2 <strong>VisiBroker</strong> 开 发 者 指 南


创 建 POA创 建 子 POA根 POA 有 一 组 预 定 义 的 策 略 , 该 策 略 不 能 更 改 。 策 略 是 一 个 对 象 , 它 控 制 POA及 其 管 理 的 对 象 的 行 为 。 如 果 需 要 不 同 的 行 为 ( 例 如 不 同 的 生 命 周 期 策 略 ) 必 须 创建 新 的 POA。使 用 create_POA 可 创 建 现 有 POA 的 子 POA。 您 可 以 根 据 自 己 的 需 要 创 建 任 意 多个 POA。注 意 : 子 POA 不 继 承 其 父 POA 的 策 略 。在 以 下 实 例 中 , 子 POA 是 从 根 POA 创 建 的 , 它 具 有 持 久 的 生 命 周 期 策 略 。 根POA 的 POA 管 理 器 用 于 控 制 该 子 POA 的 状 态 。 有 关 POA 管 理 器 的 详 细 信 息在 本 节 后 面 介 绍 。在 C++ 下 创 建 策 略 和 子 POA:CORBA::PolicyList policies;policies.length(1);policies[(CORBA::ULong)0] = rootPOA->create_lifespan_policy(PortableServer::PERSISTENT);// 用 正 确 的 策 略 创 建 myPOAPortableServer::POAManager_var rootManager = rootPOA->the_POAManager();PortableServer::POA_var myPOA = rootPOA->create_POA("bank_agent_poa",rootManager, policies );在 Java 下 创 建 策 略 和 子 POA:// 为 持 久 POA 创 建 策 略org.omg.CORBA.Policy[] policies = {rootPOA.create_lifespan_policy(LifespanPolicyValue.PERSISTENT)};// 用 正 确 的 策 略 创 建 myPOAPOA myPOA = rootPOA.create_POA( "bank_agent_poa", rootPOA.the_POAManager(),policies );实 现 服 务 对 象 方 法IDL 的 语 法 与 C++ 相 似 , 可 以 用 于 定 义 模 块 、 接 口 、 数 据 结 构 等 。 在 编 译 含 有 接口 的 IDL 时 , 会 生 成 一 个 类 , 该 类 作 为 服 务 对 象 的 基 础 类 。 例 如 , 在 Bank.IDL文 件 中 , 描 述 了 AccountManager 接 口 。module Bank{interface Account {float balance();};interface AccountManager {Account open ( 按 字 符 串 名 称 ) ;};};以 下 实 例 显 示 了 服 务 器 端 的 AccountManager 实 现 。C++: class AccountManagerImpl :public POA_Bank::AccountManager {private:服 务 器 基 础 6-3


创 建 POAJava:Java:Dictionary _accounts;public:virtual Bank::Account_ptr open(const char* name) {// 在 帐 户 字 典 中 查 找 帐 户 。Bank::Account_ptr account = (Bank::Account_ptr) _accounts.get(name);if(account == Bank::Account::_nil()) {// 准 备 帐 户 余 额 ( 在 0 到 1000 美 元 之 间 )。float balance = abs(rand()) % 100000 / 100.0;// 创 建 帐 户 实 现 , 给 出 余 额 。AccountImpl *accountServant = new AccountImpl(balance);try{// 在 默 认 POA 上 激 活 它 , 该 POA 是 该 服 务 对 象 的 根POAPortableServer::POA_var rootPOA = _default_POA();CORBA::Object_var obj =rootPOA->servant_to_reference(accountServant);account = Bank::Account::_narrow(obj);} catch(const CORBA::Exception& e) {cerr


创 建 POA_accounts.put(name, account);}// 返 回 帐 户 。return account;}private Dictionary _accounts = new Hashtable();private Random _random = new Random();}Java:必 须 创 建 AccountManager 实 现 并 将 其 在 服 务 器 代 码 中 激 活 。 在 本 实 例 中 ,AccountManager 是 使 用 activate_object_with_id 激 活 的 , 该 操 作 将 对 象 ID传 递 给 激 活 对 象 映 射 表 记 录 下 来 。 激 活 对 象 映 射 表 只 是 一 个 表 格 , 它 将 ID 映 射 给服 务 对 象 。 该 方 法 保 证 在 POA 处 于 活 动 状 态 时 该 对 象 始 终 可 用 , 称 为 “ 显 式 对 象激 活 ”。在 C++ 下 创 建 和 激 活 服 务 对 象 :// 创 建 服 务 对 象AccountManagerImpl managerServant;// 确 定 服 务 对 象 IDPortableServer::ObjectId_var managerId =PortableServer::string_to_ObjectId("BankManager");// 用 myPOA 上 的 ID 激 活 服 务 对 象myPOA->activate_object_with_id(managerId, &managerServant);在 Java 下 创 建 和 激 活 服 务 对 象 :// 创 建 服 务 对 象AccountManagerImpl managerServant = new AccountManagerImpl();// 确 定 服 务 对 象 IDbyte[] managerId = "BankManager".getBytes();// 用 myPOA 上 的 ID 激 活 服 务 对 象myPOA.activate_object_with_id(managerId, managerServant);激 活 POA最 后 一 个 步 骤 是 激 活 与 POA 关 联 的 POA 管 理 器 。 根 据 默 认 值 , POA 管 理 器 是在 “ 等 待 ” 状 态 下 创 建 的 。 在 这 种 状 态 下 , 所 有 请 求 都 被 路 由 到 一 个 等 待 队 列 并 不作 处 理 。 要 使 请 求 能 够 传 送 , 必 须 将 与 POA 关 联 的 POA 管 理 器 从 等 待 状 态 更 改为 激 活 状 态 。 POA 管 理 器 只 是 一 个 对 象 , 它 控 制 POA 的 状 态 ( 是 将 请 求 排 入 队列 , 还 是 处 理 或 丢 弃 )。 在 POA 创 建 期 间 , POA 管 理 器 与 POA 相 关 联 。 您 可 以指 定 一 个 要 使 用 的 POA 管 理 器 , 或 者 让 系 统 为 您 创 建 一 个 新 管 理 器 ( 在create_POA() 中 输 入 NULL [ 在 C++ 下 ] 或 null [ 在 Java 下 ] 作 为 POA 管 理 器的 名 称 .在 C++ 下 激 活 POA 管 理 器 :// 激 活 POA 管 理 器rootPOA.the_POAManager().activate();在 Java 下 激 活 POA 管 理 器 :// 激 活 POA 管 理 器PortablServer::POAManager_var mgr=rootPoa ->the_POAManager();mgr->activate();服 务 器 基 础 6-5


激 活 对 象激 活 对 象在 上 一 节 中 , 曾 简 单 提 及 显 式 对 象 激 活 。 激 活 对 象 的 方 法 有 几 种 :● 显 式 : 所 有 对 象 都 通 过 调 用 到 POA 在 服 务 器 启 动 时 激 活● 指 定 : 在 收 到 请 求 要 求 提 供 仍 未 与 对 象 ID 关 联 的 服 务 对 象 时 , 服 务 管 理 器 激 活对 象 。● 隐 式 : 对 象 由 服 务 器 在 对 POA 操 作 作 出 响 应 时 隐 式 激 活 。● 默 认 服 务 对 象 :POA 会 使 用 默 认 服 务 对 象 处 理 客 户 端 的 请 求 。对 象 激 活 在 第 7 章 " 使 用 POA" 中 详 细 讨 论 。 这 里 , 只 要 知 道 对 象 激 活 有 多 种 方 法就 可 以 了 。等 待 客 户 端 的 请 求设 置 POA 之 后 , 您 可 以 使 用 orb.run() 等 待 客 户 端 的 请 求 。 该 进 程 会 一 直 运 行 ,直 到 服 务 器 被 终 止 。C++: // 等 待 进 入 的 请 求 。orb.run();Java: // 等 待 进 入 的 请 求 。orb->run();完 整 实 例C++:以 下 实 例 为 C++ 和 Java 下 的 完 整 代 码 。// Server.C#include "Bank_s.hh"#include class Dictionary {private:struct Data {const char* name;void* value;};unsigned _count;Data* _data;public:Dictionary() {_count = 0;}void put(const char* name, void* value) {Data* oldData = _data;_data = new Data[_count + 1];for(unsigned i = 0; i < _count; i++) {_data[i] = oldData[i];6-6 <strong>VisiBroker</strong> 开 发 者 指 南


完 整 实 例}_data[_count].name = strdup(name);_data[_count].value = value;_count++;}void* get(const char* name) {for(unsigned i = 0; i < _count; i++) {if(!strcmp(name, _data[i].name)) {return _data[i].value;}}return 0;}};class AccountImpl :public POA_Bank::Account {private:float _balance;public:AccountImpl(float balance) {_balance = balance;}virtual float balance() {return _balance;}};class AccountManagerImpl :public POA_Bank::AccountManager {private:Dictionary _accounts;public:virtual Bank::Account_ptr open(const char* name) {// 在 帐 户 字 典 中 查 找 帐 户 。Bank::Account_ptr account = (Bank::Account_ptr) _accounts.get(name);if(account == Bank::Account::_nil()) {// 计 算 帐 户 余 额 ( 在 0 到 1000 美 元 之 间 )。float balance = abs(rand()) % 100000 / 100.0;// 创 建 帐 户 实 现 , 给 出 余 额 。AccountImpl *accountServant = new AccountImpl(balance);try{// 在 默 认 POA 上 激 活 它 , 该 POA 是 该 服 务 对 象 的 根POAPortableServer::POA_var rootPOA = _default_POA();CORBA::Object_var obj =rootPOA->servant_to_reference(accountServant);account = Bank::Account::_narrow(obj);} catch(const CORBA::Exception& e) {cerr


完 整 实 例Java:}};int main(int argc, char* const* argv) {try{// 初 始 化 ORB。CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);// 取 得 根 POA 的 引 用CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");// 窄 转 换 POA 引 用 的 对 象 引 用PortableServer::POA_var rootPOA = PortableServer::POA::_narrow(obj);CORBA::PolicyList policies;policies.length(1);policies[(CORBA::ULong)0] = rootPOA->create_lifespan_policy(PortableServer::PERSISTENT);// 用 正 确 的 策 略 创 建 myPOAPortableServer::POAManager_var rootManager = rootPOA->the_POAManager();PortableServer::POA_var myPOA = rootPOA->create_POA("bank_agent_poa",rootManager, policies );// 创 建 服 务 对 象AccountManagerImpl managerServant;// 确 定 服 务 对 象 IDPortableServer::ObjectId_var managerId =PortableServer::string_to_ObjectId("BankManager");// 用 myPOA 上 的 ID 激 活 服 务 对 象myPOA->activate_object_with_id(managerId, &managerServant);// 激 活 POA 管 理 器rootPOA->the_POAManager()->activate();cout servant_to_reference(&managerServant)


完 整 实 例byte[] managerId = "BankManager".getBytes();// 用 myPOA 上 的 ID 激 活 服 务 对 象myPOA.activate_object_with_id(managerId, managerServant);// 激 活 POA 管 理 器rootPOA.the_POAManager().activate();System.out.println(myPOA.servant_to_reference(managerServant) + " is ready.");// 等 待 进 入 的 请 求 。orb.run();} catch (Exception e) {e.printStackTrace();}}服 务 器 基 础 6-9


6-10 <strong>VisiBroker</strong> 开 发 者 指 南


第章使 用 POA第 7 章什 么 是 可 移 植 适 配 器 ?可 移 植 对 象 适 配 器 取 代 了 基 本 对 象 适 配 器 ; 它 们 在 服 务 器 端 提 供 可 移 植 性 。POA 是 对 象 的 实 现 与 <strong>VisiBroker</strong> ORB 之 间 的 中 介 。 在 其 所 担 当 的 中 介 角 色 中 ,POA 将 请 求 发 送 到 服 务 对 象 , 其 结 果 可 能 会 使 服 务 对 象 运 行 并 在 必 要 时 创 建 子POA。服 务 器 可 支 持 多 个 POA。 至 少 应 该 有 一 个 POA 存 在 , 该 POA 被 称 为 rootPOA( 根 POA)。 rootPOA 是 自 动 创 建 的 。 POA 集 是 层 次 结 构 的 ; 所 有 POA 都 将rootPOA 视 为 它 们 的 “ 祖 先 ”。服 务 对 象 管 理 器 定 位 服 务 对 象 , 并 把 它 们 分 配 给 POA 的 对 象 。 当 把 一 个 抽 象 对 象分 配 给 一 个 服 务 对 象 时 , 该 抽 象 对 象 被 称 为 活 动 对 象 , 而 服 务 对 象 被 称 为 实 例 化 了该 活 动 对 象 。 每 个 POA 都 有 一 个 活 动 对 象 图 , 该 图 记 录 活 动 对 象 的 对 象 ID 及 其相 关 联 的 活 动 服 务 对 象 。注 : 本 节 仅 说 明 与 POA 相 关 的 主 要 主 题 。 有 关 的 完 整 描 述 , 请 参 阅 OMG 规 范 。使 用 POA 7-1


什 么 是 可 移 植 适 配 器 ?图 7.1POA 概 览POA 术 语以 下 是 一 些 术 语 的 定 义 , 在 您 阅 读 本 章 的 过 程 中 , 您 会 对 它 们 更 加 熟 悉 。表 7.1术 语可 移 植 对 象 适 配 器 术 语说 明活 动 对 象 图图 示 活 动 <strong>VisiBroker</strong> CORBA 对 象 ( 通 过 其 ID)和 服 务 对 象 联 结 关 系 的 表 格 。 每 个 POA 仅 有 一 个活 动 对 象 图 。适 配 器 激 活 器对 象 , 当 收 到 对 于 不 存 在 的 子 POA 的 请 求 时 , 可以 根 据 要 求 创 建 一 个 POA。气 化删 除 一 个 服 务 对 象 和 一 个 抽 象 CORBA 对 象 之 间 的联 结 。实 例 化将 一 个 服 务 对 象 与 一 个 抽 象 CORBA 对 象 联 结 在 一起 。ObjectID方 法 , 用 于 识 别 对 象 适 配 器 内 的 一 个 CORBA 对象 。 ObjectID 可 以 由 对 象 适 配 器 来 分 配 , 在 创 建它 的 对 象 适 配 器 内 , 它 是 唯 一 的 。 服 务 对 象 通 过ObjectID 与 抽 象 对 象 联 结 在 一 起 。永 久 对 象在 创 建 它 们 的 服 务 器 进 程 之 后 , 依 然 存 在 的CORBA 对 象 。POA 管 理 器控 制 POA 状 态 的 对 象 , 例 如 , POA 是 否 要 接 收或 放 弃 进 入 的 请 求 。策 略对 象 , 控 制 关 联 的 POA 和 POA 所 管 理 的 对 象 的行 为 。rootPOA每 个 <strong>VisiBroker</strong> ORB 都 创 建 了 一 个 称 之 为rootPOA 的 POA。 您 可 以 通 过 rootPOA 创 建 额外 的 POA ( 如 有 必 要 )。服 务 对 象实 现 CORBA 对 象 的 方 法 的 代 码 , 但 不 是CORBA 对 象 本 身 。服 务 对 象 管 理 器对 象 , 负 责 管 理 对 象 与 服 务 对 象 关 联 并 负 责 确 定 对象 是 否 存 在 。 可 以 有 一 个 以 上 的 服 务 对 象 存 在 。临 时 对 象 仅 存 在 于 其 创 建 进 程 内 的 CORBA 对 象 。7-2 <strong>VisiBroker</strong> 开 发 者 指 南


POA 策 略创 建 和 使 用 POA 步 骤虽 然 确 切 的 进 程 可 能 不 同 , 但 以 下 步 骤 是 出 现 在 POA 生 命 周 期 内 的 基 本 步 骤 :1 定 义 POA 的 策 略 。2 创 建 POA。3 通 过 POA 管 理 器 激 活 POA。4 创 建 并 激 活 服 务 对 象 。5 创 建 并 使 用 服 务 对 象 管 理 器 。6 使 用 适 配 器 激 活 器 。随 您 的 需 要 的 不 同 , 有 些 步 骤 是 可 选 的 。 例 如 , 如 果 您 想 要 POA 处 理 请 求 , 您 只需 要 激 活 它 。POA 策 略每 个 POA 都 有 一 套 策 略 来 定 义 它 的 特 性 。 当 创 建 新 的 POA 时 , 您 可 以 使 用 默 认的 策 略 集 或 使 用 不 同 的 值 来 满 足 您 的 要 求 。 仅 在 创 建 POA 时 , 您 才 可 设 置 策 略 ;您 不 能 变 更 现 有 POA 的 策 略 。 POA 不 从 其 父 POA 上 继 承 策 略 。以 下 几 节 列 出 了 POA 策 略 、 它 们 的 值 、 及 默 认 值 ( 由 rootPOA 使 用 )。线 程 策 略线 程 策 略 指 定 由 POA 使 用 的 线 程 模 型 。 线 程 策 略 可 以 具 有 下 列 值 :ORB_CTRL_MODEL: ( 默 认 ) POA 负 责 分 配 请 求 给 线 程 。 在 多 线 程 环 境 中 ,并 发 请 求 可 以 用 多 个 线 程 来 传 送 。 注 意 : <strong>VisiBroker</strong> <strong>Edition</strong> 使 用 多 线 程 模 型 。SINGLE_THREAD_MODEL: POA 按 顺 序 处 理 请 求 。 在 多 线 程 环 境 中 , 由POA 对 服 务 对 象 和 服 务 管 理 器 的 调 用 都 是 线 程 安 全 的 。MAIN_THREAD_MODEL: 调 用 在 最 高 层 的 “ 主 ” 线 程 上 处 理 。 对 所 有 主 线程 POA 的 请 求 都 是 按 顺 序 来 处 理 的 。 在 多 线 程 环 境 下 , 由 所 有 POA 用 该 策 略 处理 的 所 有 调 用 都 是 线 程 安 全 的 。 应 用 程 序 员 通 过 调 用 ORB::run() 或ORB::perform_work() 来 指 定 主 线 程 。 有 关 这 些 方 法 的 详 情 , 请 参 阅 第 7-8 页 "激 活 对 象 "。生 命 周 期 策 略生 命 周 期 策 略 指 定 在 POA 中 实 现 的 对 象 的 生 命 周 期 。 生 命 周 期 策 略 可 以 具 有 以 下值 :TRANSIENT: ( 默 认 ) 由 POA 激 活 的 对 象 不 能 比 创 建 它 的 POA 存 在 更 久 。POA 被 激 活 后 , 如 果 尝 试 使 用 任 何 由 POA 生 成 的 对 象 引 用 , 则 会 掷 出OBJECT_NOT_EXIST 违 例 。使 用 POA 7-3


POA 策 略PERSISTENT: 由 POA 激 活 的 一 个 永 久 对 象 可 以 比 首 次 创 建 它 的 进 程 存 在 更久 。 在 永 久 对 象 上 调 用 的 请 求 可 能 会 导 致 对 进 程 、 POA 和 实 现 对 象 的 服 务 对 象 的隐 式 激 活 。对 象 ID 唯 一 性 策 略对 象 ID 唯 一 性 策 略 允 许 单 个 服 务 对 象 由 多 个 抽 象 对 象 共 享 。 对 象 ID 唯 一 性 策 略可 以 具 有 以 下 值 :UNIQUE_ID:( 默 认 ) 激 活 的 服 务 对 象 仅 可 支 持 一 个 对 象 ID。MULTIPLE_ID: 激 活 的 服 务 对 象 可 以 具 有 一 个 或 多 个 对 象 ID。 对 象 ID 必 须 在运 行 期 内 所 调 用 的 方 法 之 内 确 定 。ID 分 配 策 略ID 分 配 策 略 指 定 对 象 ID 是 由 服 务 器 应 用 生 成 还 是 由 POA 生 成 。 ID 分 配 策 略 可以 具 有 以 下 值 :USER_ID: 由 应 用 给 对 象 分 配 对 象 ID。SYSTEM_ID:( 默 认 ) 由 POA 给 对 象 分 配 对 象 ID。 如 果 同 时 设 定 了PERSISTENT 策 略 , 则 对 象 ID 在 同 一 POA 的 所 有 实 例 中 必 须 是 唯 一 的 。通 常 , USER_ID 用 于 永 久 对 象 , 而 SYSTEM_ID 用 于 临 时 对 象 。 如 果 您 要 将SYSTEM_ID 用 于 永 久 对 象 , 您 可 以 从 服 务 对 象 或 对 象 引 用 中 将 它 们 提 取 出 来 。服 务 对 象 保 留 策 略服 务 对 象 保 留 策 略 指 定 POA 是 否 将 活 动 服 务 对 象 保 留 在 活 动 对 象 图 中 。 服 务 对 象策 略 可 以 具 有 以 下 值 :RETAIN: ( 默 认 ) POA 追 踪 活 动 对 象 图 中 的 对 象 激 活 。 RETAIN 通 常 用 于ServantActivators 或 POA 上 的 显 式 激 活 方 法 。NON_RETAIN: POA 不 将 活 动 服 务 对 象 保 留 在 活 动 对 象 图 。NON_RETAIN必 须 与 ServantLocators 一 起 使 用 。ServantActivators 和 ServantLocators 是 服 务 对 象 管 理 器 的 类 型 。 有 关 服 务 对象 管 理 器 的 详 情 , 请 参 阅 第 7-15 页 " 使 用 服 务 对 象 和 服 务 对 象 管 理 器 "。请 求 处 理 策 略请 求 处 理 策 略 指 定 POA 处 理 请 求 的 方 式 。USE_ACTIVE_OBJECT_MAP_ONLY:( 默 认 ) 如 果 对 象 ID 未 列 入 活 动 对象 图 , 则 返 回 一 个 OBJECT_NOT _EXIST 违 例 。 POA 也 必 须 使 用 具 有 该 值 的RETAIN 策 略 。7-4 <strong>VisiBroker</strong> 开 发 者 指 南


创 建 POAUSE_DEFAULT_SERVANT: 如 果 对 象 ID 未 列 入 活 动 对 象 图 或 设 定 了NON_RETAIN 策 略 , 则 请 求 被 发 送 到 默 认 的 服 务 对 象 。 如 果 未 注 册 默 认 服 务 对象 , 则 返 回 一 个 OBJ_ADAPTER 违 例 。 POA 也 必 须 使 用 具 有 该 值 的MULTIPLE_ID 策 略 。USE_SERVANT_MANAGER: 如 果 对 象 ID 未 列 在 活 动 对 象 图 中 或 设 置 了NON_RETAIN 策 略 , 则 使 用 服 务 对 象 管 理 器 来 取 得 服 务 对 象 。隐 式 激 活 策 略隐 式 激 活 策 略 指 定 POA 是 否 支 持 服 务 对 象 的 隐 式 激 活 。 隐 式 激 活 策 略 可 以 具 有 以下 值 :IMPLICIT_ACTIVATION:POA 支 持 服 务 对 象 的 隐 式 激 活 。 有 如 下 两 种 方 法可 以 激 活 服 务 对 象 :● 使 用 C++ POA::servant_to_reference() 或 Javaorg.omg.PortableServer.POA.servant_to_reference() 将 它 们 转 换 成 对 象 引 用 。● 调 用 服 务 对 象 上 的 _this()。POA 也 必 须 使 用 SYSTEM_ID 和 具 有 该 值 的 RETAIN 策 略 。NO_IMPLICIT_ACTIVATION:( 默 认 ) POA 不 支 持 服 务 对 象 的 隐 式 调 用 。限 制 支 持 策 略限 制 支 持 策 略 ( 与 <strong>VisiBroker</strong> <strong>Edition</strong> 相 关 的 策 略 ) 控 制 POA 和 活 动 对 象 在<strong>VisiBroker</strong> <strong>Edition</strong> osagent 上 的 注 册 。 如 果 您 有 数 千 个 对 象 , 将 它 们 全 都 注 册在 osagent 上 是 不 可 行 的 。 您 可 以 将 POA 注 册 在 osagent 上 。 当 有 客 户 请 求 提出 时 , POA 名 称 和 对 象 ID 被 包 含 在 限 制 请 求 中 , 以 便 osagent 可 以 正 确 地 前 转请 求 。BindSupport 策 略 可 以 具 有 以 下 值 :BY_INSTANCE: 所 有 活 动 对 象 都 在 osagent 上 注 册 。 POA 也 必 须 使 用PERSISTENT 和 具 有 该 值 的 RETAIN 策 略 。BY_POA:( 默 认 ) 仅 有 POA 注 册 在 osagent 上 。POA 也 必 须 使 用 具 有 该 值 的PERSISTENT 策 略 。NONE:POA 和 活 动 对 象 都 不 在 智 能 代 理 上 注 册 。创 建 POA要 使 用 POA 实 现 对 象 , 服 务 器 上 至 少 必 须 有 一 个 POA 对 象 。 为 确 保 有 POA 存在 , 在 <strong>VisiBroker</strong> ORB 初 始 化 过 程 中 , 提 供 了 一 个 rootPOA。 该 POA 使 用 本章 前 面 部 分 所 描 述 的 默 认 POA 策 略 。一 旦 取 得 取 rootPOA, 您 就 可 以 创 建 用 于 实 现 特 定 服 务 器 端 策 略 集 的 子 POA。使 用 POA 7-5


创 建 POAPOA 命 名 惯 例C++:每 个 POA 记 录 其 名 称 和 POA 全 名 ( 层 次 结 构 路 径 全 名 )。 层 次 由 斜 杠 表 示(/)。 例 如 , /A/B/C 表 示 POA C 是 POA B 的 孩 子 , 反 过 来 , POA B 又 是POA A 的 孩 子 。 第 一 个 斜 杠 ( 参 见 以 上 的 实 例 ) 表 示 rootPOA。 如 果 将 BindSupport:BY_POA 策 略 设 置 在 POA C 上 , 则 /A/B/C 注 册 在 osagent 上 , 客 户与 /A/B/C 限 制 。如 果 您 的 POA 名 称 中 包 含 转 义 字 符 或 其 它 定 界 符 , 则 在 内 部 记 录 这 些 名 称 时 ,<strong>VisiBroker</strong> <strong>Edition</strong> 将 会 在 这 些 字 符 之 前 放 置 双 反 斜 杠 (\\)。 例 如 , 如 果 您 有两 个 在 如 下 层 次 结 构 中 的 POA:PortableServer::POA_var myPOA1 = rootPOA->create_POA("A/B",poa_manager,policies);PortableServer::POA_var myPOA2 = myPOA1->create_POA("\t",poa_manager,policies);客 户 将 用 以 下 命 令 来 限 制 :Bank::AccountManager_var manager = Bank::AccountManager::_bind("/A\\/B/\t",managerId);或 在 Java 下 :org.omg.PortableServer.POA myPOA1 = rootPOA.create_POA("A/B",poaManager,policies);org.omg.PortableServer.POA myPOA2 = myPOA1.create_POA("\t",poaManager,policies);客 户 将 用 以 下 命 令 来 限 制 :org.omg.CORBA.Object manager = ((com.inprise.vbroker.orb.ORB) orb).bind("/A\\/B/\t",managerId,null,null);取 得 rootPOA以 下 的 代 码 示 例 示 范 服 务 器 应 用 如 何 取 得 它 的 rootPOA。// 初 始 化 ORB。CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");// 取 得 根 POA 的 引 用PortableServer::POA_var rootPOA = PortableServer::POA::_narrow(obj);以 下 的 代 码 示 例 示 范 服 务 器 如 何 在 Java 下 取 得 rootPOA。// 初 始 化 ORB。org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null);// 取 得 rootPOA 的 引 用7-6 <strong>VisiBroker</strong> 开 发 者 指 南


创 建 POA注 :org.omg.PortableServer.POA rootPOA =POAHelper.narrow(orb.resolve_initial_references("RootPOA"));resolve_initial_references 方 法 返 回 C++ CORBA::object 类 型 的 值 或 Javaorg.omg.CORBA.Object 类 型 的 值 。 您 负 责 将 返 回 的 对 象 引 用 窄 转 换 成 所 需 要 的 类型 , 该 类 型 为 上 例 中 的 C++ PortableServer::POA 或 Javaorg.omg.PortableServer.POA 。设 置 POA 属 性策 略 不 是 父 POA 上 继 承 而 来 的 。 如 果 您 想 要 POA 具 有 一 个 特 定 的 特 性 , 您 必 须识 别 所 有 与 默 认 值 不 同 的 策 略 。 有 关 POA 策 略 的 详 情 , 请 参 阅 第 7-3 页 "POA策 略 "。CORBA::PolicyList policies;policies.length(1);policies[(CORBA::ULong)0] = rootPOA->create_lifespan_policy(PortableServer::PERSISTENT);在 Java 下 为 POA 创 建 策 略 的 实 例 :org.omg.CORBA.Policy[] policies = {rootPOA.create_lifespan_policy(LifespanPolicyValue.PERSISTENT)};创 建 和 激 活 POAPOA 是 使 用 create_POA 在 其 父 POA 上 创 建 的 。 您 可 以 将 POA 命 名 为 任 何 您 喜欢 的 名 称 , 但 是 , 对 同 一 父 POA 下 的 所 其 它 所 有 POA 而 言 , 该 名 称 必 须 是 唯 一的 。 如 果 您 尝 试 给 两 个 POA 起 同 样 的 名 称 , 则 会 掷 出 一 个 CORBA 违 例(AdapterAlreadyExists)。要 创 建 新 的 POA, 可 按 以 下 方 式 使 用 create_POAPOA create_POA(POA_Name, POAManager, PolicyList);POA 管 理 器 控 制 POA 的 状 态 ( 例 如 , POA 是 否 处 理 请 求 )。 如 果 将 null 作 为POA 管 理 器 名 传 递 到 create_POA, 则 会 创 建 一 个 新 的 POA 管 理 器 对 象 , 并 与POA 关 联 。 通 常 , 您 要 为 所 有 POA 使 用 同 一 POA 管 理 器 。 有 关 POA 管 理 器的 详 情 , 请 参 阅 第 7-24 页 " 用 POA 管 理 器 管 理 POA"。POA 管 理 器 ( 及 POA) 不 是 一 经 创 建 就 被 自 动 激 活 的 。 使 用 activate() 激 活 与您 的 POA 关 联 的 POA 管 理 器 。CORBA::PolicyList policies;policies.length(1);policies[(CORBA::ULong)0] =rootPOA->create_lifespan_policy(PortableServer::PERSISTENT);// 用 正 确 的 策 略 创 建 myPOAPortableServer::POAManager_var rootManager = rootPOA->the_POAManager();PortableServer::POA_var myPOA =rootPOA->create_POA("bank_agent_poa", rootManager, policies);使 用 POA 7-7


激 活 对 象以 下 的 代 码 示 例 是 在 Java 下 创 建 POA 的 实 例 。// 为 永 久 POA 创 建 策 略org.omg.CORBA.Policy[] policies = {rootPOA.create_lifespan_policy(LifespanPolicyValue.PERSISTENT)};// 用 正 确 的 策 略 创 建 myPOAorg.omg.PortableServer.POA myPOA =rootPOA.create_POA( "bank_agent_poa", rootPOA.the_POAManager(), policies);激 活 对 象当 CORBA 对 象 与 一 个 活 动 服 务 对 象 关 联 在 一 起 时 , 如 果 POA 的 服 务 保 留 策 略为 RETAIN, 则 关 联 的 对 象 ID 将 被 记 录 在 活 动 对 象 图 中 , 而 该 对 象 被 激 活 。 激 活会 以 下 列 方 式 之 下 出 现 :● 显 式 激 活服 务 器 应 用 本 身 通 过 调 用 activate_object 或 activate_object_with_id, 显 式 激 活对 象 。● 随 选 激 活服 务 器 应 用 通 过 用 户 提 供 的 服 务 对 象 管 理 器 , 指 示 POA 激 活 对 象 。 服 务 对 象 管 理器 必 须 先 通 过 set_servant_manager 在 POA 注 册 。● 隐 式 激 活服 务 器 独 自 通 过 响 应 特 定 的 操 作 来 激 活 对 象 。 如 果 服 务 对 象 是 不 活 动 的 , 客 户 无 论如 何 也 不 可 能 激 活 它 ( 例 如 , 对 一 个 不 活 动 的 对 象 发 出 请 求 不 会 激 活 它 。)● 默 认 的 服 务 对 象POA 使 用 单 个 服 务 对 象 来 实 现 其 所 有 对 象 。显 式 激 活 对 象通 过 在 POA 上 设 置 IdAssignmentPolicy::SYSTEM_ID, 可 以 显 式 激 活 对 象 而 无 需 指定 对 象 ID。 服 务 器 调 用 激 活 、 分 配 并 返 回 对 象 的 对 象 ID 的 POA 上 的activate_object。 这 种 类 型 的 激 活 对 临 时 对 象 很 常 用 。 不 需 要 任 何 服 务 对 象 管 理器 , 因 为 需 要 对 象 和 服 务 对 象 的 时 间 都 不 会 太 久 。仅 可 以 使 用 对 象 ID 将 对 象 显 式 激 活 。 常 见 的 一 种 情 况 发 生 在 服 务 器 初 始 化 过 程中 , 在 此 过 程 中 , 用 户 调 用 activate_object_with_id 以 激 活 所 有 由 服 务 器 管 理 的对 象 。 不 需 要 任 何 服 务 对 象 管 理 器 , 这 是 因 为 所 有 的 对 象 已 被 激 活 。 如 果 收 到 对 不存 在 的 对 象 的 一 个 请 求 , 则 掷 出 OBJECT_NOT_EXIST 违 例 。 如 果 您 的 服 务 器 管 理 大 量的 对 象 , 则 这 一 现 象 会 产 生 明 显 的 负 作 用 。// 创 建 服 务 对 象AccountManagerImpl managerServant;// 确 定 服 务 对 象 IDPortableServer::ObjectId_var managerId =PortableServer::string_to_ObjectId("BankManager");7-8 <strong>VisiBroker</strong> 开 发 者 指 南


激 活 对 象// 用 myPOA 上 的 ID 激 活 服 务 对 象myPOA->activate_object_with_id(managerId,&managerServant);// 激 活 POA 管 理 器PortableServer::POAManager_var rootManager = rootPOA->the_POAManager();rootManger->activate();以 下 的 代 码 示 例 示 范 在 Java 下 使 用 activate_object_with_id 完 成 的 显 式 激 活// 创 建 帐 户 管 理 器 服 务 对 象 。Servant managerServant = new AccountManagerImpl(rootPoa);// 激 活 新 创 建 的 服 务 对 象 。testPoa.activate_object_with_id("BankManager".getBytes(), managerServant);// 激 活 POAtestPoa.the_POAManager().activate();随 选 激 活 对 象随 选 激 活 发 生 在 客 户 请 求 一 个 没 有 关 联 的 服 务 对 象 的 对 象 过 程 中 。 在 收 到 请 求 之后 , POA 在 活 动 对 象 图 上 搜 索 与 对 象 ID 相 关 联 的 活 动 服 务 对 象 。 如 果 找 不 到 ,则 POA 调 用 服 务 对 象 管 理 器 上 的 incarnate 方 法 , 该 方 法 将 ID 值 传 递 给 服 务 对象 管 理 器 。 服 务 管 理 器 可 以 做 以 下 三 件 事 之 一 :● 找 到 适 当 的 服 务 对 象 , 使 其 随 后 可 以 为 请 求 执 行 相 应 的 操 作 。● 掷 出 返 回 给 客 户 的 OBJECT_NOT_EXIST 违 例C++:Java:● 将 请 求 前 转 到 另 外 一 个 对 象POA 策 略 决 定 任 何 可 能 发 生 的 额 外 步 骤 。 以 下 是 在 Java 和 C++ 下 的 示 例 :如 果 启 用 RequestProcessingPolicy::USE_SERVANT_MANAGER 和ServantRetentionPolicy::RETAIN, 则 使 用 服 务 对 象 ID 和 ID 关 联 来 更 新 活 动对 象 图 。如 果 开 启 RequestProcessingPolicy.USE_SERVANT_MANAGER 和ServantRetentionPolicy.RETAIN, 则 使 用 服 务 对 象 和 对 象 ID 更 新 活 动 对 象 图 。以 下 所 示 为 随 选 激 活 的 一 个 实 例 。隐 式 激 活 对 象C++:如 果 POA 是 使 用 ImplicitActivationPolicy::IMPLICIT_ACTIVATION、IdAssignmentPolicy::SYSTEM_ID 和 ServantRetentionPolicy::RETAIN 创 建 的 , 则可 以 通 过 特 定 的 操 作 来 隐 式 激 活 服 务 对 象 。 隐 式 调 用 出 现 在 以 下 函 数 调 用 过 程 中● POA::servant_to_reference 成 员 函 数● POA::servant_to_id 成 员 函 数● _this() 服 务 对 象 成 员 函 数如 果 POA 已 设 定 了 ObjectIdUniquenessPolicy::UNIQUE_ID , 则 当 在 一 个 不 活 动服 务 对 象 上 执 行 以 上 操 作 时 , 会 出 现 隐 式 激 活 。使 用 POA 7-9


激 活 对 象Java:如 果 POA 已 设 定 了 ObjectIdUniquenessPolicy::MULTIPLE_ID, 则servant_to_reference 和 servant_to_id 操 作 始 终 执 行 隐 式 激 活 , 即 使 用 服 务 对 象已 处 于 活 动 状 态 。如 果 POA 是 使 用 ImplicitActivationPolicy.IMPLICIT_ACTIVATION、IdAssignmentPolicy.SYSTEM_ID 和 ServantRetentionPolicy.RETAIN 创 建 的 , 则 服务 对 象 可 以 由 特 定 的 操 作 激 活 。 隐 式 激 活 可 以 出 现 在 以 下 的 方 法 调 用 过 程 中 :● POA.servant_to_reference 方 法● POA.servant_to_id 方 法● _this() 服 务 对 象 方 法如 果 POA 已 设 定 了 ObjectIdUniquenessPolicy.UNIQUE_ID, 则 当 在 一 个 不 活 动 的服 务 对 象 上 执 行 以 上 任 何 操 作 时 , 会 出 现 隐 式 激 活 。如 果 POA 已 设 定 了 ObjectIdUniquenessPolicy.MULTIPLE_ID, 则servant_to_reference 和 servant_to_id 操 作 将 始 终 执 行 隐 式 激 活 , 即 使 服 务 对 象已 经 处 于 活 动 状 态 。默 认 服 务 对 象 的 激 活使 用 C++ RequestProcessing::USE_DEFAULT_SERVANT 策 略 或 JavaRequestProcessing.USE_DEFAULT_SERVANT 策 略 以 便 让 POA 调 用 同 一 服 务 对 象 , 而不 论 对 象 ID 是 什 么 。 这 在 每 个 对 象 的 关 联 数 据 很 少 时 是 很 有 用 的 。C++: int main(int argc, char* const* argv) {try {// 初 始 化 ORB。CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);PortableServer::Current_var cur = PortableServer::Current::_instance();DataStore::_create();// 取 得 根 POA 的 引 用CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");PortableServer::POA_var rootPOA = PortableServer::POA::_narrow(obj);CORBA::PolicyList policies;policies.length(3);// 为 永 久 POA 创 建 策 略policies[(CORBA::ULong)0] =rootPOA->create_lifespan_policy(PortableServer::PERSISTENT);policies[(CORBA::ULong)1] =rootPOA>create_request_processing_policy(PortableServer::USE_DEFAULT_SERVANT);policies[(CORBA::ULong)2] =rootPOA->create_id_uniqueness_policy(PortableServer::MULTIPLE_ID);// 用 正 确 的 策 略 创 建 myPOAPortableServer::POAManager_var rootManager = rootPOA->the_POAManager();PortableServer::POA_var myPOA =rootPOA->create_POA("bank_default_servant_poa",rootManager,policies);// 设 置 默 认 服 务 对 象AccountManagerImpl * managerServant = new AccountManagerImpl(cur);7-10 <strong>VisiBroker</strong> 开 发 者 指 南


激 活 对 象myPOA->set_servant( managerServant );// 激 活 POA 管 理 器rootManager->activate();// 生 成 两 个 引 用 : 一 个 用 于 支 票 而 另 一 个 用 于 储 蓄 。// 注 意 : 这 里 我 们 没 有 在 创 建 任 何 服 务 对 象 ,// 只 是 在 制 作 服 务 对 象 尚 不 支 持 的// 引 用PortableServer::ObjectId_var an_oid =PortableServer::string_to_ObjectId("CheckingAccountManager");CORBA::Object_var cref = myPOA->create_reference_with_id(an_oid.in(),"IDL:Bank/AccountManager:1.0");an_oid = PortableServer::string_to_ObjectId("SavingsAccountManager");CORBA::Object_var sref = myPOA->create_reference_with_id(an_oid.in(),"IDL:Bank/AccountManager:1.0");// 写 出 支 票 引 用CORBA::String_var string_ref = orb->object_to_string(cref.in());ofstream crefFile("cref.dat");crefFile


激 活 对 象};// 用 正 确 的 策 略 创 建 myPOAPOA myPOA = rootPOA.create_POA( "bank_default_servant_poa",rootPOA.the_POAManager(),policies );// 创 建 服 务 对 象AccountManagerImpl managerServant = new AccountManagerImpl();// 在 我 们 的 POA 上 设 置 默 认 的 服 务 对 象myPOA.set_servant(managerServant);org.omg.CORBA.Object ref;// 激 活 POA 管 理 器rootPOA.the_POAManager().activate();// 生 成 并 写 出 引 用 。 支 票 和存 储// 帐 户 类 型 各 一 。 注 意 : 这 里 我 们 没 有 在 创 建 任 何 服 务 对 象 ,// 只 是 在 制 作 服 务 对 象 尚 不 支 持 的// 引 用 。try {ref =myPOA.create_reference_with_id("CheckingAccountManager".getBytes(),"IDL:Bank/AccountManager:1.0");// 写 出 支 票 对 象 IDjava.io.PrintWriter pw = new java.io.PrintWriter(new java.io.FileWriter("cref.dat") );pw.println(orb.object_to_string(ref));pw.close();ref =myPOA.create_reference_with_id("SavingsAccountManager".getBytes(),"IDL:Bank/AccountManager:1.0");// 写 出 储 蓄 对 象 IDpw = new java.io.PrintWriter( new java.io.FileWriter("sref.dat") );System.gc();pw.println(orb.object_to_string(ref));pw.close();} catch ( java.io.IOException e ) {System.out.println("Error writing the IOR to file ");return;}System.out.println("Bank Manager is ready.");// 等 待 进 入 的 请 求 。orb.run();} catch (Exception e) {e.printStackTrace();}}}去 激 活 对 象POA 可 以 从 其 活 动 对 象 图 上 删 除 一 个 服 务 对 象 。 例 如 , 这 可 以 以 垃 圾 收 集 计 划 的形 式 出 现 。 当 服 务 对 象 被 从 活 动 对 象 图 上 删 除 以 后 , 它 就 被 去 激 活 。 您 可 以 使 用7-12 <strong>VisiBroker</strong> 开 发 者 指 南


激 活 对 象C++:deactivate_object() 来 去 激 活 一 个 对 象 。 当 一 个 对 象 被 去 激 活 后 , 并 不 意 味 着 该对 象 会 永 远 消 失 。 它 随 后 始 终 都 可 以 被 重 新 激 活 。// DeActivatorThreadclass DeActivatorThread: public VISThread {private :PortableServer::ObjectId _oid;PortableServer::POA_ptr _poa;public :virtual ~DeActivatorThread(){}// 构 建 器DeActivatorThread(const PortableServer::ObjectId& oid,PortableServer::POA_ptr poa ): _oid(oid), _poa(poa) {// 启 动 线 程run();}// 实 现 begin() 回 调void begin() {// 休 眠 15sVISPortable::vsleep(15);CORBA::String_var s = PortableServer::ObjectId_to_string (_oid);// 去 激 活 对 象cout


激 活 对 象PortableServer::POA_ptr adapter,PortableServer::Servant servant,CORBA::Boolean cleanup_in_progress,CORBA::Boolean remaining_activations) {// 如 果 没 能 其 它 与 服 务 对 象 关 联 的 激 活 ( 即 ObjectIds ),// 则 删 除 该 服 务 对 象 。CORBA::String_var s = PortableServer::ObjectId_to_string (oid);cout


使 用 服 务 对 象 和 服 务 对 象 管 理 器}}}e.printStackTrace();使 用 服 务 对 象 和 服 务 对 象 管 理 器服 务 对 象 管 理 器 执 行 两 类 操 作 : 寻 找 并 返 回 服 务 对 象 ; 去 激 活 服 务 对 象 。 当 收 到 对于 不 活 动 对 象 的 请 求 时 , 它 们 允 许 POA 激 活 对 象 。 服 务 对 象 管 理 器 是 可 选 的 。 例如 , 当 您 的 服 务 器 在 启 动 过 程 中 装 载 所 有 对 象 时 , 服 务 对 象 是 不 必 要 的 。 服 务 对 象管 理 器 也 可 以 通 知 客 户 使 用 ForwardRequest 将 请 求 前 转 到 另 外 一 个 对 象 。服 务 对 象 实 现 的 不 活 动 实 例 。 POA 保 存 有 一 张 关 于 活 动 服 务 对 象 和 服 务 对 象 的 对象 ID 的 图 。 当 收 到 客 户 请 求 时 , POA 首 先 检 查 该 图 , 以 查 看 对 象 ID ( 嵌 在 客 户请 求 中 ) 是 否 已 记 录 在 图 中 。 如 对 象 ID 存 在 , 则 POA 将 请 求 前 转 到 服 务 对 象 。如 果 图 中 找 不 到 对 象 ID, 则 要 求 服 务 对 象 定 位 并 激 活 相 应 的 服 务 对 象 。 这 只 是 一个 示 范 方 案 , 确 切 的 方 案 取 决 于 您 所 使 用 的 POA 策 略 。图 7.2实 例 服 务 对 象 管 理 器 功 能C++:Java:有 两 种 服 务 对 象 管 理 器 :ServantActivator 和 ServantLocator。 正 在 使 用 的 策 略 的类 型 确 定 所 要 使 用 的 回 调 。 有 关 POA 策 略 的 详 情 , 请 参 阅 第 7-3 页 "POA 策 略"。 通 常 , ServantActivator 激 活 永 久 对 象 , 而 ServantLocator 激 活 临 时 对 象 。C++ 下 使 用 服 务 对 象 管 理 器要 使 用 服 务 对 象 管 理 器 , 不 仅 必 须 设 置 用 以 定 义 服 务 对 象 (ServantActivator 的ServantRetentionPolicy::RETAIN 或 ServantLocator 的ServantRetentionPolicy::NON_RETAIN) 类 型 的 策 略 , 而 且 必 须 设 置RequestProcessingPolicy::USE_SERVANT_MANAGER。在 要 Java 下 使 用 服 务 对 象 管 理 器 , 不 仅 必 须 设 置 用 以 定 义 服 务 对 象(ServantActivator 的 ServantRetentionPolicy.RETAIN 或 ServantLocator 的ServantRetentionPolicy.NON_RETAIN) 类 型 的 策 略 , 而 且 必 须 设 置RequestProcessingPolicy.USE_SERVANT_MANAGER。使 用 POA 7-15


使 用 服 务 对 象 和 服 务 对 象 管 理 器C++:Java:ServantActivators当 设 置 了 ServantRetentionPolicy::RETAIN 和RequestProcessingPolicy::USE_SERVANT_MANAGER, 需 要 使 用 ServantActivators。当 设 置 了 ServantRetentionPolicy.RETAIN 和RequestProcessingPolicy.USE_SERVANT_MANAGER 时 , 需 要 使 用ServantActivators。由 该 类 服 务 对 象 管 理 器 激 活 的 服 务 对 象 被 记 录 在 活 动 对 象 图 中 。当 使 用 服 务 对 象 激 活 器 处 理 请 求 时 , 会 发 生 以 下 事 件 :1 收 到 一 个 客 户 请 求 ( 客 户 请 求 包 含 POA 名 称 、 对 象 ID 等 )。2 POA 首 先 检 查 活 动 对 象 图 。 如 果 可 以 在 该 图 中 找 到 对 象 ID, 则 将 操 作 传 递 给服 务 对 象 , 并 将 响 应 返 回 给 客 户 。3 如 果 活 动 对 象 图 中 找 不 到 对 象 ID, 则 POA 在 服 务 对 象 上 调 用 incarnate 。incarnate 传 递 对 象 ID 和 对 象 被 激 活 时 所 处 的 POA 。4 服 务 对 象 管 理 器 定 位 适 用 的 合 适 的 服 务 对 象 。5 服 务 对 象 ID 被 输 入 活 动 对 象 图 , 而 响 应 被 返 回 给 客 户 。注 : etherealize 和 incarnate 方 法 实 现 是 用 户 提 供 的 代 码 。随 后 , 服 务 对 象 可 以 被 激 活 。 有 数 个 引 发 该 操 作 的 原 因 , 其 中 包 括deactivate_object 操 作 , 与 该 POA 关 联 的 POA 管 理 器 的 去 激 活 , 等 。 有 关 去激 活 对 象 的 详 情 , 请 参 阅 第 7-12 页 " 去 激 活 对 象 "。int main(int argc, char* const* argv) {try {// 初 始 化 ORB。CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);DataStore::_create();// 取 得 根 POA 的 引 用CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");PortableServer::POA_var rootPOA = PortableServer::POA::_narrow(obj);CORBA::PolicyList policies;policies.length(2);policies[(CORBA::ULong)0] =rootPOA->create_lifespan_policy(PortableServer::PERSISTENT);policies[(CORBA::ULong)1] =rootPOA->create_request_processing_policy(PortableServer::USE_SERVANT_MANAGER);// 用 正 确 的 策 略 创 建 myPOAPortableServer::POAManager_var rootManager = rootPOA->the_POAManager();PortableServer::POA_var myPOA =rootPOA->create_POA("bank_servant_activator_poa", rootManager,policies);// 创 建 服 务 对 象 激 活 器AccountManagerActivator servant_activator_impl;// 设 定 服 务 对 象 激 活 器myPOA->set_servant_manager(&servant_activator_impl);7-16 <strong>VisiBroker</strong> 开 发 者 指 南


使 用 服 务 对 象 和 服 务 对 象 管 理 器// 生 成 两 个 引 用 : 一 个 用 于 支 票 而 另 一 个 用 于 储 蓄 。// 注 意 : 这 里 我 们 没 有 在 创 建 任 何 服 务 对 象 ,// 只 是 在 制 作 服 务 对 象 尚 不 支 持 的// 引 用PortableServer::ObjectId_var an_oid =PortableServer::string_to_ObjectId("CheckingAccountManager");CORBA::Object_var cref = myPOA->create_reference_with_id(an_oid.in(),"IDL:Bank/AccountManager:1.0");an_oid = PortableServer::string_to_ObjectId("SavingsAccountManager");CORBA::Object_var sref = myPOA->create_reference_with_id(an_oid.in(),"IDL:Bank/AccountManager:1.0");// 激 活 POA 管 理 器rootManager->activate();// 写 出 支 票 引 用CORBA::String_var string_ref = orb->object_to_string(cref.in());ofstream crefFile("cref.dat");crefFile


使 用 服 务 对 象 和 服 务 对 象 管 理 器rootPOA.the_POAManager(),policies );// 创 建 服 务 对 象 激 活 器 服 务 对 象 并 取 得 它 的 引 用ServantActivator sa = new AccountManagerActivator()._this(orb);// 在 我 们 的 POA 上 设 置 服 务 对 象 激 活 器myPOA.set_servant_manager(sa);org.omg.CORBA.Object ref;// 激 活 POA 管 理 器rootPOA.the_POAManager().activate();// 生 成 并 写 出 引 用 。 支 票 和储 蓄// 帐 户 类 型 各 一 。 注 意 : 这 里 我 们 没 有 在 创 建 任 何 服 务 对 象// 只 是 在 制 作 服 务 对 象 尚 不 支 持 的// 引 用try {ref =myPOA.create_reference_with_id("CheckingAccountManager".getBytes(),"IDL:Bank/AccountManager:1.0");// 写 出 支 票 对 象 IDjava.io.PrintWriter pw =new java.io.PrintWriter( new java.io.FileWriter("cref.dat"));pw.println(orb.object_to_string(ref));pw.close();ref =myPOA.create_reference_with_id("SavingsAccountManager".getBytes(),"IDL:Bank/AccountManager:1.0");// 写 出 储 蓄 对 象 IDpw = new java.io.PrintWriter( new java.io.FileWriter("sref.dat") );System.gc();pw.println(orb.object_to_string(ref));pw.close();} catch ( java.io.IOException e ) {System.out.println("Error writing the IOR to file ");return;}System.out.println("Bank Manager is ready.");// 等 待 进 入 的 请 求 。orb.run();} catch (Exception e) {e.printStackTrace();}}}本 例 的 服 务 对 象 管 理 器 如 下 。C++:// 服 务 对 象 激 活 器class AccountManagerActivator : public PortableServer::ServantActivator {public:virtual PortableServer::Servant incarnate (constPortableServer::ObjectId&oid,PortableServer::POA_ptr poa) {CORBA::String_var s = PortableServer::ObjectId_to_string (oid);cout


使 用 服 务 对 象 和 服 务 对 象 管 理 器


使 用 服 务 对 象 和 服 务 对 象 管 理 器System.out.println("\nAccountManagerActivator.etherealize called with ID =" + new String(oid) + "\n");System.gc();}}class DeactivateThread extends Thread {byte[] _oid;POA _adapter;public DeactivateThread(byte[] oid, POA adapter) {_oid = oid;_adapter = adapter;}public void run() {try {Thread.currentThread().sleep(15000);System.out.println("\nDeactivating the object with ID = " +ServantLocators在 很 多 情 况 下 , POA 的 活 动 对 象 图 可 能 会 变 得 非 常 大 , 因 而 占 用 相 当 大 的 内 存 。要 减 少 内 存 的 消 耗 , 可 以 使 用 C++RequestProcessingPolicy::USE_SERVANT_MANAGER 和ServantRetentionPolicy::.NON_RETAIN 或 JavaRequestProcessingPolicy.USE_SERVANT_MANAGER 和ServantRetentionPolicy.NON_RETAIN 来 创 建 POA, 这 意 味 着 , 服 务 对 象 到 对 象 的关 联 不 存 储 在 活 动 对 象 图 中 。 因 为 未 存 储 任 何 关 联 , 所 以 要 为 个 请 求 调 用ServantLocator 服 务 对 象 管 理 器 。在 使 用 服 务 对 象 定 位 器 处 理 请 求 的 过 程 中 , 会 出 现 以 下 事 件 :1 收 到 客 户 请 求 , 其 中 包 含 POA 名 和 对 象 ID。2 由 于 使 用 了 C++ ServantRetentionPolicy::NON_RETAIN 或 JavaServantRetentionPolicy.NON_RETAIN , 所 以 POA 不 在 活 动 对 象 图 中 搜 索 对 象ID。3 POA 在 服 务 对 象 管 理 器 上 调 用 preinvoke 。 preinvoke 传 递 对 象 ID、 激 活 对 象时 其 所 处 的 POA、 及 其 它 几 个 参 数 。4 服 务 对 象 定 位 器 定 位 相 应 的 服 务 对 象 。5 该 操 作 在 服 务 对 象 上 执 行 , 而 响 应 被 返 回 给 客 户 。6 POA 在 服 务 管 理 器 上 调 用 postinvoke。注 : preinvoke 和 postinvoke 方 法 是 用 户 提 供 的 代 码 。C++: int main(int argc, char* const* argv) {try {// 初 始 化 ORB。CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);// 数 据 源7-20 <strong>VisiBroker</strong> 开 发 者 指 南


使 用 服 务 对 象 和 服 务 对 象 管 理 器DataStore::_create();// 取 得 根 POA 的 引 用CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");PortableServer::POA_var rootPOA = PortableServer::POA::_narrow(obj);CORBA::PolicyList policies;policies.length(3);// 创 建 一 个 具 有 永 久 生 命 周 期 的 子 POA policy,// 该 策 略 使 用 具 有 non-retain ( 非 保 留 )( 无 活 动 对 象 图 ) 保 留 策 略 的 服 务 对 象管 理 器 ,// 从 而 使 POA 使 用// 服 务 对 象 定 位 器 。policies[(CORBA::ULong)0] =rootPOA->create_lifespan_policy(PortableServer::PERSISTENT);policies[(CORBA::ULong)1] =rootPOA->create_servant_retention_policy(PortableServer::NON_RETAIN);policies[(CORBA::ULong)2] =rootPOA>create_request_processing_policy(PortableServer::USE_SERVANT_MANAGER);PortableServer::POAManager_var rootManager = rootPOA->the_POAManager();PortableServer::POA_var myPOA =rootPOA->create_POA("bank_servant_locator_poa",rootManager,policies);// 创 建 服 务 对 象 定 位 器AccountManagerLocator servant_locator_impl;myPOA->set_servant_manager(&servant_locator_impl);// 生 成 两 个 引 用 : 一 个 用 于 支 票 , 另 一 个 用 于 储 蓄 。// 注 意 : 这 里 我 们 没 有 在 创 建 任 何 服 务 对 象 ,// 只 是 在 制 作 服 务 对 象 尚 不 支 持 的// 引 用PortableServer::ObjectId_var an_oid =PortableServer::string_to_ObjectId("CheckingAccountManager");CORBA::Object_var cref = myPOA->create_reference_with_id(an_oid.in(),"IDL:Bank/AccountManager:1.0");an_oid = PortableServer::string_to_ObjectId("SavingsAccountManager");CORBA::Object_var sref = myPOA->create_reference_with_id(an_oid.in(),"IDL:Bank/AccountManager:1.0");// 激 活 POA 管 理 器rootManager->activate();// 写 出 支 票 引 用CORBA::String_var string_ref = orb->object_to_string(cref.in());ofstream crefFile("cref.dat");crefFile


使 用 服 务 对 象 和 服 务 对 象 管 理 器DataStore::_destroy();}catch(const CORBA::Exception& e) {cerr


使 用 服 务 对 象 和 服 务 对 象 管 理 器ref =myPOA.create_reference_with_id("SavingsAccountManager".getBytes(),"IDL:Bank/AccountManager:1.0");// 写 出 储 蓄 对 象 IDpw = new java.io.PrintWriter( new java.io.FileWriter("sref.dat") );System.gc();pw.println(orb.object_to_string(ref));pw.close();} catch ( java.io.IOException e ) {System.out.println("Error writing the IOR to file ");return;}System.out.println("BankManager is ready.");// 等 待 进 入 的 请 求 。orb.run();} catch (Exception e) {e.printStackTrace();}}}本 例 的 服 务 对 象 管 理 器 如 下 。C++:// 服 务 对 象 定 位 器class AccountManagerLocator :public PortableServer::ServantLocator {public:AccountManagerLocator (){}// 预 调 用 与 ServantActivator 的 incarnate ( 实 例 化 ) 方 法 非 常 相 似 , 但 是 , 每 当 有请 求 进 入 时// 被 调 用 , 这 一 点 与 incarnate() 方 法 不 同 , 该 方 法 是 每 当// POA 在 活 动 对 象 图 上 找 不 到 一 个 服 务 对 象 时 被 调 用 的virtual PortableServer::Servant preinvoke (const PortableServer::ObjectId& oid,PortableServer::POA_ptr adapter,const char* operation,PortableServer::ServantLocator::Cookie& the_cookie) {CORBA::String_var s = PortableServer::ObjectId_to_string (oid);cout


用 POA 管 理 器 管 理 POA// 返 回 服 务 对 象return servant;}virtual void postinvoke (const PortableServer::ObjectId& oid,PortableServer::POA_ptr adapter,const char* operation,PortableServer::ServantLocator::Cookie the_cookie,PortableServer::Servant the_servant) {CORBA::String_var s = PortableServer::ObjectId_to_string (oid);cout


PortableServer::POA_var myPOA = rootPOA->create_POA("bank_servant_locator_poa",null,policies );命 名 Java 中 的 POA 和 POA 管 理 器 :POA myPOA = rootPOA.create_POA( "bank_agent_poa",rootPOA.the_POAManager(),policies );POA myPOA = rootPOA.create_POA( "bank_agent_poa",null,policies );用 POA 管 理 器 管 理 POA当 与 一 个 POA 管 理 器 关 联 的 所 有 POA 被 销 毁 时 , 该 POA 管 理 器 就 被 销 毁POA 管 理 器 可 以 有 以 下 四 种 状 态 :● 保 持● 活 动● 丢 弃● 不 活 动这 些 状 态 反 过 来 又 确 定 POA 的 状 态 。 它 们 分 别 在 后 续 几 节 中 详 述 。取 得 当 前 的 状 态要 取 得 POA 管 理 器 当 前 的 状 态 , 请 使 用enum State{HOLDING, ACTIVE, DISCARDING, INACTIVE};State get_state();保 持 状 态在 默 认 情 况 下 , 当 POA 管 理 器 被 创 建 时 , 它 处 于 保 持 状 态 。 当 POA 管 理 器 处 于保 持 状 态 时 , POA 将 所 有 进 入 的 请 求 排 入 队 列 。当 POA 管 理 器 处 于 保 持 状 态 时 , 需 要 适 配 器 激 活 器 的 请 求 也 被 排 入 队 列 。要 改 变 POA 管 理 器 的 状 态 , 请 使 用void hold_requests (in boolean wait_for_completion)raises (AdapterInactive);wait_for_completion 是 Boolean。 如 果 设 置 为 FALSE, 则 在 将 状 态 变 为 保 持 后 , 该操 作 立 即 返 回 。 如 果 设 置 为 TRUE, 则 仅 当 所 有 在 状 态 改 变 之 前 启 动 的 请 求 已 完 成或 当 POA 管 理 器 的 状 态 变 更 为 一 个 非 保 持 状 态 时 , 该 操 作 才 会 返 回 。 如 果 在 调 用该 操 作 之 前 , POA 管 理 器 处 于 不 活 动 状 态 , 则 会 掷 出 AdapterInactive 违 例 。注 : 处 于 不 活 动 状 态 的 POA 管 理 器 不 能 变 更 为 保 持 状 态 。所 有 已 排 入 队 列 但 尚 未 启 动 的 请 求 , 在 保 持 状 态 期 间 , 将 继 续 排 队 等 待 。使 用 POA 7-25


用 POA 管 理 器 管 理 POA活 动 状 态当 POA 管 理 器 处 于 活 动 状 态 时 , 与 它 关 联 的 POA 处 理 请 求 。要 将 POA 管 理 器 变 更 为 活 动 状 态 , 请 使 用void activate()raises (AdapterInactive);如 果 在 调 用 该 操 作 之 前 ,POA 管 理 器 处 于 不 活 动 状 态 , 则 会 掷 出 AdapterInactive违 例 。注 : 当 前 处 于 不 活 动 状 态 的 POA 管 理 器 不 能 变 更 为 活 动 状 态 。丢 弃 状 态当 POA 管 理 器 处 于 丢 弃 状 态 时 , 与 它 关 联 的 POA 将 丢 弃 所 有 未 启 动 的 请 求 。 另外 , 在 关 联 的 POA 上 注 册 的 适 配 器 激 活 器 将 不 被 调 用 。 当 POA 在 接 收 过 多 的 请求 时 , 这 一 状 态 非 常 有 用 。 您 需 要 通 知 客 户 , 它 们 的 请 求 已 被 丢 弃 , 要 它 们 重 发 请求 。 没 有 固 有 的 行 为 来 确 定 POA 是 否 在 接 收 太 多 的 请 求 或 什 么 时 候 在 接 收 太 多 的请 求 这 取 决 于 您 设 置 线 程 监 控 的 方 式 ( 如 果 您 想 要 这 么 做 )。要 将 POA 管 理 器 变 更 为 丢 弃 状 态 , 请 使 用void discard_requests(in boolean wait_for_completion)raises (AdapterInactive);wait_for_completion 选 项 是 Boolean ( 布 尔 型 )。 如 果 设 置 为 FALSE, 则 在 将 状态 变 为 保 持 后 , 该 操 作 立 即 返 回 。 如 果 设 置 为 TRUE, 则 仅 当 所 有 在 状 态 改 变 之 前启 动 的 请 求 已 完 成 或 当 POA 管 理 器 的 状 态 变 更 为 一 个 非 丢 弃 状 态 时 , 该 操 作 才 会返 回 。 如 果 在 调 用 该 操 作 之 前 , POA 管 理 器 处 于 不 活 动 状 态 , 则 会 掷 出AdapterInactive 违 例 。注 : 当 前 处 于 不 活 动 状 态 的 POA 管 理 器 不 能 变 更 为 丢 弃 状 态 。不 活 动 状 态当 POA 管 理 器 处 于 不 活 动 状 态 时 , 与 它 关 联 的 POA 拒 绝 进 入 的 请 求 。 当 关 联 的POA 将 要 关 闭 时 , 使 用 该 状 态 。注 : 处 于 不 活 动 状 态 的 POA 管 理 器 不 能 变 更 为 其 它 任 何 状 态 。要 将 POA 管 理 器 变 更 为 不 活 动 状 态 , 请 使 用 :void deactivate (in boolean etherealize_objects, in booleanwait_for_completion)raises (AdapterInactive);C++:在 状 态 变 化 之 后 , 如 果 etherealize_objects 是 TRUE, 则 所 有 关 联 的 、 已 设 置 了Servant RetentionPolicy::RETAIN 和RequestProcessingPolicy::USE_SERVANT_MANAGER 的 POA, 为 所 有 活 动 对 象 调 用servantmanager 的 etherealize。 如 果 etherealize_objects 是 FALSE, 则 不 调 用etherealize。 wait_for_completion 选 项 是 Boolean ( 布 尔 型 )。 如 果 设 置 为7-26 <strong>VisiBroker</strong> 开 发 者 指 南


设 置 收 听 和 调 度 属 性Java:FALSE, 则 该 操 作 在 状 态 变 为 不 活 动 时 立 即 返 回 。 如 果 设 置 为 TRUE, 则 仅 当 在 状 态改 变 之 前 启 动 的 所 有 请 求 已 完 成 , 或 者 已 在 所 有 关 联 的 POA ( 具 有 ServantRetentionPolicy::RETAIN 和 RequestProcessingPolicy::USE_SERVANT_MANAGER) 调用 了 etherealize 之 后 , 该 操 作 才 会 返 回 。 如 果 在 调 用 该 操 作 之 前 , POA 管 理 器处 于 不 活 动 状 态 , 则 会 掷 出 AdapterInactive 违 例 。在 状 态 改 变 之 后 , 如 果 etherealize_objects 为 TRUE, 则 所 有 关 联 的 、 已 设 定 了Servant RetentionPolicy.RETAIN 和RequestProcessingPolicy.USE_SERVANT_MANAGER 的 POA 为 所 有 活 动 的 对 象 调 用 服务 对 象 管 理 器 上 的 etherealize。 如 果 etherealize_objects 是 FALSE, 则 不 调 用etherealize。 wait_for_completion 选 项 是 Boolean ( 布 尔 型 )。 如 果 设 置 为FALSE, 则 该 操 作 在 状 态 变 为 不 活 动 时 立 即 返 回 。 如 果 设 置 为 TRUE, 则 仅 当 在 状 态改 变 之 前 启 动 的 所 有 请 求 已 被 完 成 或 已 在 所 有 关 联 的 POA ( 具 有ServantRetentionPolicy.RETAIN 和RequestProcessingPolicy.USE_SERVANT_MANAGER) 上 调 用 了 etherealize 之 后 , 该操 作 才 会 返 回 。 如 果 在 调 用 该 操 作 之 前 POA 管 理 器 处 于 不 活 动 状 态 , 则 会 掷 出AdapterInactive 违 例 。设 置 收 听 和 调 度 属 性POA 不 支 持 先 前 由 BOA 支 持 的 与 监 听 器 和 调 度 器 有 关 的 特 性 。 要 提 供 这 些 特 性 ,可 以 使 用 与 <strong>VisiBroker</strong> <strong>Edition</strong> 有 关 的 策 略 (ServerEnginePolicy)。服 务 器 引 擎 由 下 列 组 件 构 成 :● 主 机 名● 代 理 主 机 名● 服 务 器 连 接 管 理 器 或 服 务 器 连 接 管 理 器 列 表下 图 示 范 这 些 组 件 如 何 配 合 工 作 。图 7.3 服 务 器 引 擎 概 览最 简 单 的 例 子 是 POA 具 有 它 们 各 自 唯 一 的 服 务 器 引 擎 。 在 这 里 , 对 不 同 POA 的请 求 在 不 同 的 端 口 上 到 达 。 一 个 POA 可 以 具 有 多 个 服 务 器 引 擎 。 在 这 种 情 况 下 ,单 个 POA 支 持 从 多 个 输 入 端 口 进 入 的 请 求 。使 用 POA 7-27


设 置 收 听 和 调 度 属 性注 意 :POA 可 以 共 享 服 务 器 引 擎 。 当 服 务 器 引 擎 被 共 享 时 , POA 收 听 同 一 端 口 。即 使 用 对 多 个 POA 的 请 求 到 达 同 一 端 口 , 它 们 也 可 以 被 正 确 地 分 配 , 这 是 因 为POA 名 称 嵌 入 在 请 求 中 。 例 如 , 当 您 使 用 默 认 的 服 务 器 引 擎 来 创 建 多 个 POA 时( 在 POA 创 建 过 程 中 , 不 指 定 新 的 服 务 器 引 擎 ), 会 出 现 上 述 的 情 况 。设 置 服 务 器 引 擎 属 性C++:Java:以 下 的 属 性 确 定 默 认 的 服 务 器 引 擎 :vbroker.se..hostvbroker.se..proxyHostvbroker.se..scms如 果 您 未 指 定 服 务 器 引 擎 策 略 , 则 POA 假 定 服 务 器 引 擎 名 为 iiop, 使 用 下 列默 认 值 :vbroker.se.iiop_tp.host=nullvbroker.se.iiop_tp.proxyHost=nullvbroker.se.iiop_tp.scms=iiopvbroker.se.liop_tp.host=nullvbroker.se.liop_tp.proxyHost=nullvbroker.se.liop_tp.scms=liopvbroker.se.iiop_tp.host=nullvbroker.se.iiop_tp.proxyHost=nullvbroker.se.iiop_tp.scms=iiop要 变 更 默 认 的 服 务 器 引 擎 策 略 , 使 用 vbroker.se.default 属 性 输 入 它 的 名 称 ,并 定 义 新 服 务 器 引 擎 所 有 组 件 的 值 。 例 如 ,vbroker.se.default=abc,defvbroker.se.abc.host=cobvbroker.se.abc.proxyHost=nullvbroker.se.abc.scms=cobscm1, cobscm2vbroker.se.def.host=gobvbroker.se.def.proxyHost=nullvbroker.se.def.scms=gobscm1有 关 如 何 设 置 属 性 的 信 息 , 请 参 阅 第 3 章 " 建 立 您 的 环 境 "。设 置 服 务 器 连 接 管 理 器 属 性服 务 器 连 接 管 理 器 包 含 三 个 属 性 组 : 管 理 器 、 监 听 器 、 调 度 器 。管 理 器 属 性您 可 以 设 置 以 下 的 管 理 器 属 性 :● vbroker.se..scm..manager.type标 识 连 接 管 理 器 类 型 。C++ 支 持 的 连 接 管 理 器 类 型 有 Socket 和 Local。Socket是 Java 支 持 的 唯 一 的 连 接 管 理 器 。● vbroker.se..scm..manager.connectionMax7-28 <strong>VisiBroker</strong> 开 发 者 指 南


设 置 收 听 和 调 度 属 性定 义 所 允 许 的 并 发 和 进 入 连 接 的 最 大 数 量 默 认 值 为 0, 含 义 为 不 限 制 连 接 数 量 。● vbroker.se..scm..manager.connectionMaxIdle定 义 连 接 被 关 闭 前 的 最 大 空 闲 秒 数 。 默 认 值 是 0, 含 义 为 不 设 超 时 时 限 。监 听 器 属 性您 可 以 设 置 以 下 的 监 听 器 属 性 :● vbroker.se..scm..listener.type标 识 监 听 器 类 型 。 C++ 支 持 的 监 听 器 类 型 为 IIOP 和 LIOP。 IIOP 是 Java 唯一 支 持 的 监 听 器 。● vbroker.se..scm..listener.port定 义 POA 和 连 接 管 理 器 使 用 的 服 务 器 所 关 联 的 端 口 。 默 认 值 为 0, 含 义 为 系 统挑 选 一 个 随 机 端 口 号 。C++: 如 果 监 听 器 类 型 为 LIOP, 则 该 属 性 没 有 意 义 。● vbroker.se..scm..listener.proxyPort指 定 与 代 理 主 机 名 属 性 一 起 使 用 的 代 理 端 口 号 码 。 默 认 值 为 0 , 其 含 义 为 系 统挑 选 一 个 随 机 端 口 号 。C++: 如 果 监 听 器 类 型 为 LIOP, 则 该 属 性 没 有 意 义 。调 度 器 属 性您 可 以 设 置 以 下 调 度 器 属 性 :● vbroker.se..scm..dispatcher.type识 别 调 度 器 类 型 。 当 前 , 仅 支 持 ThreadPool 和 ThreadSession 类 型 。 但 是 , 如果 在 C++ 下 连 接 管 理 器 的 类 型 是 Local, 则 ThreadPool 是 唯 一 支 持 的 调 度 器类 型 。● vbroker.se..scm..dispatcher.threadMax仅 当 类 型 设 置 为 ThreadPool 时 使 用 。● vbroker.se..scm..dispatcher.threadMaxIdle仅 当 类 型 设 置 为 ThreadPool 时 使 用 。● vbroker.se..scm..dispatcher.threadMin仅 当 类 型 设 置 为 ThreadPool 时 使 用 。使 用 POA 7-29


设 置 收 听 和 调 度 属 性什 么 时 候 使 用 这 些 属 性有 许 多 地 方 都 需 要 您 变 更 一 些 服 务 器 引 擎 的 属 性 。 变 更 这 些 属 性 的 方 法 取 决 于 您 的需 要 。 例 如 , 假 如 您 要 变 更 端 口 号 。 您 可 采 用 如 下 方 法 来 完 成 :● 变 更 默 认 的 listener.port 属 性● 创 建 新 的 服 务 器 引 擎变 更 默 认 的 listener.port 属 性 是 最 简 单 的 方 法 , 但 这 会 对 使 用 默 认 服 务 器 引 擎 的所 有 POA 造 成 影 响 。 这 可 能 是 也 可 能 不 是 您 所 想 要 的 。如 果 您 想 要 改 变 特 定 POA 上 的 端 口 号 , 则 您 必 须 创 建 新 的 服 务 器 引 擎 , 为 新 的 服务 器 引 擎 定 义 属 性 , 然 后 在 创 建 的 POA 时 引 用 新 的 服 务 器 引 擎 。 前 几 节 说 明 了 如何 更 新 服 务 器 引 擎 属 性 。 以 下 的 代 码 片 断 示 范 如 何 定 义 服 务 器 引 擎 的 属 性 和 使 用 用户 自 定 义 的 服 务 器 引 擎 策 略 来 创 建 POA。// static initialization 静 态 初 始 化AccountRegistry AccountManagerImpl::_accounts;int main(int argc, char* const* argv){try {// 初 始 化 ORBCORBA::ORB_var orb = CORBA::ORB_init(argc, argv);// 取 得 属 性 管 理 器 ; 注 意 : 返 回 值 不 是 放 在“var” 类 型 中 。VISPropertyManager_ptr pm = orb->getPropertyManager();pm->addProperty("vbroker.se.mySe.host", "");pm->addProperty("vbroker.se.mySe.proxyHost", "");pm->addProperty("vbroker.se.mySe.scms", "scmlist");pm->addProperty("vbroker.se.mySe.scm.scmlist.manager.type","Socket");pm->addProperty("vbroker.se.mySe.scm.scmlist.manager.connectionMax", 100UL);pm->addProperty("vbroker.se.mySe.scm.scmlist.manager.connectionMaxIdle",300UL);pm->addProperty("vbroker.se.mySe.scm.scmlist.listener.type","IIOP");pm->addProperty("vbroker.se.mySe.scm.scmlist.listener.port",55000UL);pm->addProperty("vbroker.se.mySe.scm.scmlist.listener.proxyPort",0UL);pm->addProperty("vbroker.se.mySe.scm.scmlist.dispatcher.type","ThreadPool");pm->addProperty("vbroker.se.mySe.scm.scmlist.dispatcher.threadMax", 100UL);pm->addProperty("vbroker.se.mySe.scm.scmlist.dispatcher.threadMin", 5UL);pm->addProperty("vbroker.se.mySe.scm.scmlist.dispatcher.threadMaxIdle",300UL);// 取 得 根 POA 的 引 用CORBA::Object_var obj = orb-7-30 <strong>VisiBroker</strong> 开 发 者 指 南


设 置 收 听 和 调 度 属 性>resolve_initial_references("RootPOA");PortableServer::POA_var rootPOA =PortableServer::POA::_narrow(obj);// 创 建 策 略CORBA::Any_var seAny(new CORBA::Any);// SERVER_ENGINE_POLICY_TYPE 需 要 一 个 序 列 , 即 使 用// 仅 指 定 了 一 个 引 擎 。CORBA::StringSequence_var engines = newCORBA::StringSequence(1UL);engines->length(1UL);engines[0UL] = CORBA::string_dup("mySe");seAny length(2UL);policies[0UL] = orb->create_policy(PortableServerExt::SERVER_ENGINE_POLICY_TYPE,seAny);policies[1Ul] = rootPOA->create_lifespan_policy(PortableServer::PERSISTENT);// 用 我 们 的 策 略 创 建 POAPortableServer::POAManager_var manager = rootPOA->the_POAManager();PortableServer::POA_var myPOA = rootPOA->create_POA("bank_se_policy_poa", manager, policies);// 创 建 服 务 对 象AccountManagerImpl* managerServant = new AccountManagerImpl();// 激 活 服 务 对 象PortableServer::ObjectId_var oid =PortableServer::string_to_ObjectId("BankManager");myPOA->activate_object_with_id(oid ,managerServant);// 取 得 引 用CORBA::Object_var ref = myPOA->servant_to_reference(managerServant);CORBA::String_var string_ref = orb->object_to_string(ref.in());ofstream refFile("ref.dat");refFile activate();// 等 待 进 入 的 请 求cout run();}catch(const CORBA::Exception& e) {cerr在 Java 下 使 用 特 定 的 服 务 器 引 擎 创 建 POA:// Server.javaimport org.omg.PortableServer.*;public class Server {public static void main(String[] args) {try {// 初 始 化 ORB。org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);// 取 得 属 性 管 理 器com.inprise.vbroker.properties.PropertyManager pm =((com.inprise.vbroker.orb.ORB)orb).getPropertyManager();使 用 POA 7-31


设 置 收 听 和 调 度 属 性pm.addProperty("vbroker.se.mySe.host", "");pm.addProperty("vbroker.se.mySe.proxyHost", "");pm.addProperty("vbroker.se.mySe.scms", "scmlist");pm.addProperty("vbroker.se.mySe.scm.scmlist.manager.type", "Socket");pm.addProperty("vbroker.se.mySe.scm.scmlist.manager.connectionMax", 100);pm.addProperty("vbroker.se.mySe.scm.scmlist.manager.connectionMaxIdle",300);pm.addProperty("vbroker.se.mySe.scm.scmlist.listener.type", "IIOP");pm.addProperty("vbroker.se.mySe.scm.scmlist.listener.port", 55000);pm.addProperty("vbroker.se.mySe.scm.scmlist.listener.proxyPort", 0);pm.addProperty("vbroker.se.mySe.scm.scmlist.dispatcher.type","ThreadPool");pm.addProperty("vbroker.se.mySe.scm.scmlist.dispatcher.threadMax", 100);pm.addProperty("vbroker.se.mySe.scm.scmlist.dispatcher.threadMin", 5);pm.addProperty("vbroker.se.mySe.scm.scmlist.dispatcher.threadMaxIdle",300);// 取 得 根 POA 的 引 用POA rootPOA =POAHelper.narrow(orb.resolve_initial_references("RootPOA"));// 创 建 我 们 的 服 务 器 引 擎 策 略org.omg.CORBA.Any seAny = orb.create_any();org.omg.CORBA.StringSequenceHelper.insert(seAny, new String[]{"mySe"});org.omg.CORBA.Policy sePolicy =orb.create_policy(com.inprise.vbroker.PortableServerExt.SERVER_ENGINE_POLICY_TYPE.value,seAny);// 为 永 久 POA 创 建 策 略org.omg.CORBA.Policy[] policies = {rootPOA.create_lifespan_policy(LifespanPolicyValue.PERSISTENT),sePolicy};// 用 正 确 的 策 略 创 建 myPOAPOA myPOA = rootPOA.create_POA("bank_se_policy_poa",rootPOA.the_POAManager(),policies );// 创 建 服 务 对 象AccountManagerImpl managerServant = new AccountManagerImpl();// 启 动 服 务 对 象myPOA.activate_object_with_id("BankManager".getBytes(), managerServant);// 取 得 引 用org.omg.CORBA.Object ref = myPOA.servant_to_reference(managerServant);// 现 在 写 出 IORtry {java.io.PrintWriter pw =new java.io.PrintWriter( new java.io.FileWriter("ior.dat") );pw.println(orb.object_to_string(ref));pw.close();} catch ( java.io.IOException e ) {System.out.println("Error writing the IOR to file ior.dat");return;}// 激 活 POA 管 理 器rootPOA.the_POAManager().activate();7-32 <strong>VisiBroker</strong> 开 发 者 指 南


适 配 器 激 活 器System.out.println(ref + " is ready.");// 等 待 进 入 的 请 求 。orb.run();} catch (Exception e) {e.printStackTrace();}}}适 配 器 激 活 器适 配 器 激 活 器 与 POA 关 联 在 一 起 , 它 们 提 供 创 建 随 选 子 POA 的 能 力 。 这 可 以 在find_POA 操 作 中 完 成 , 或 者 在 收 到 一 个 给 特 定 的 子 POA 命 名 的 请 求 时 执 行 。在 接 收 给 子 POA ( 或 其 子 代 POA 之 一 ) 命 名 的 请 求 时 , 或 当 用 activate 参 数值 TRUE 调 用 find_POA 时 , 适 配 器 激 活 器 可 以 为 POA 提 供 创 建 随 选 子 POA 的能 力 。 在 执 行 之 初 创 建 其 所 有 需 要 的 POA 的 应 用 服 务 器 不 需 要 使 用 或 提 供 适 配 器激 活 器 ; 仅 当 需 要 在 请 求 处 理 过 程 中 创 建 POA 时 才 需 适 配 器 激 活 器 。在 POA 发 送 请 求 到 适 配 器 激 活 器 的 过 程 中 , 所 有 对 由 新 POA ( 或 其 任 何 子POA) 管 理 的 对 象 的 请 求 都 将 被 排 入 队 列 。 这 个 序 列 化 操 作 允 许 适 配 器 激 活 器 在 请求 被 传 递 到 POA 之 前 , 完 成 新 POA 的 所 有 初 始 化 过 程 。有 关 使 用 适 配 器 激 活 器 的 实 例 , 请 参 阅 要 产 品 中 所 包 含 的 POA adaptor_activator实 例 。处 理 请 求请 求 包 含 目 标 对 象 的 对 象 ID 和 创 建 目 标 引 用 的 POA。 当 客 户 发 送 请 求 时 ,<strong>VisiBroker</strong> ORB 首 先 定 位 适 当 的 服 务 器 , 或 在 需 要 时 启 动 服 务 器 。 然 后 , 它 在 服务 器 内 定 位 适 当 的 POA。一 旦 <strong>VisiBroker</strong> ORB 找 到 适 当 的 POA, 它 就 将 请 求 发 到 该 POA 上 。 请 求 在 那里 如 何 处 理 决 定 于 POA 的 策 略 和 对 象 的 激 活 状 态 。 有 关 对 象 激 活 的 详 情 , 请 参 阅第 7-8 页 " 激 活 对 象 "。● 如 果 POA 具 有 C++ ServantRetentionPolicy::RETAIN 或 JavaServantRetentionPolicy.RETAIN, 则 POA 查 看 活 动 对 象 图 以 定 位 与 请 求 中 所包 含 的 对 象 ID 关 联 服 务 对 象 。 如 果 服 务 对 象 存 在 , 则 POA 在 服 务 对 象 上 调 用适 当 的 方 法 。● 如 果 POA 在 C++ 下 具 有 ServantRetentionPolicy::NON_RETAIN 或ServantRetentionPolicy::RETAIN, 及 如 果 POA 在 Java 下 具 有ServantRetentionPolicy.NON_RETAIN 或 ServantRetentionPolicy.RETAIN , 但 不能 找 到 适 当 的 服 务 对 象 , 则 会 发 生 下 列 现 象 :● 如 果 POA 具 有 C++ RequestProcessingPolicy::USE_DEFAULT_SERVANT 或RequestProcessingPolicy.USE_DEFAULT_SERVANT, 则 POA 在 默 认 的 服 务 对象 上 调 用 适 当 的 方 法 。使 用 POA 7-33


处 理 请 求● 如 果 POA 具 有 C++ RequestProcessingPolicy::USE_SERVANT_MANAGER 或Java RequestProcessingPolicy.USE_SERVANT_MANAGER, 则 POA 在 服 务 对 象管 理 器 上 调 用 incarnate 或 preinvoke 。● 如 果 POA 具 有 C++ RequestProcessingPolicy::USE_OBJECT_MAP_ONLY 或Java RequestProcessingPolicy.USE_OBJECT_MAP_ONLY, 则 会 掷 出 违 例 。如 果 服 务 对 象 管 理 器 已 被 调 用 但 不 能 将 对 象 实 例 化 , 则 服 务 对 象 会 掷 出ForwardRequest 违 例 。7-34 <strong>VisiBroker</strong> 开 发 者 指 南


第章管 理 线 程 和 连 接第 8 章本 章 介 绍 客 户 端 程 序 和 对 象 实 现 中 多 线 程 的 使 用 , 并 帮 助 您 了 解 <strong>VisiBroker</strong><strong>Edition</strong> 所 使 用 的 线 程 和 连 接 模 型 。在 <strong>VisiBroker</strong> <strong>Edition</strong> 中 使 用 线 程线 程 ( 或 一 个 进 程 中 一 小 段 连 续 控 制 流 ) 也 称 为 轻 量 级 进 程 , 它 通 过 与 其 它 线 程 共享 基 础 部 件 减 少 资 源 开 销 。 线 程 是 轻 量 级 的 , 因 此 一 个 进 程 中 可 以 包 含 许 多 线 程 。利 用 多 线 程 可 在 应 用 程 序 中 提 供 并 发 能 力 并 改 善 性 能 。 利 用 多 个 线 程 同 时 执 行 多 个独 立 的 计 算 , 可 以 使 应 用 程 序 结 构 更 有 效 率 。 例 如 , 数 据 库 系 统 可 以 在 支 持 多 个 用户 互 动 操 作 的 同 时 执 行 几 个 文 件 和 网 络 操 作 。 虽 然 可 以 将 软 件 编 写 成 从 一 个 请 求 到另 一 个 请 求 异 步 移 动 的 一 个 控 制 线 程 , 但 是 , 如 果 将 每 个 请 求 编 写 为 一 个 单 独 序列 , 而 由 基 本 系 统 处 理 不 同 操 作 的 同 步 交 错 , 就 可 以 简 化 代 码 。在 以 下 情 况 下 使 用 多 线 程● 有 多 组 较 长 的 操 作 且 这 些 操 作 不 一 定 要 依 赖 其 它 处 理 ( 如 窗 口 着 色 、 打 印 文 档 、对 按 动 鼠 标 作 出 响 应 、 计 算 电 子 表 格 列 和 信 号 处 理 )。● 对 数 据 锁 定 极 少 ( 共 享 数 据 量 可 以 确 定 且 很 少 )。● 工 作 可 以 细 分 。 例 如 , 一 个 线 程 处 理 信 号 , 而 另 一 个 线 程 处 理 用 户 界 面 。<strong>VisiBroker</strong> <strong>Edition</strong> 提 供 哪 些 线 程 策 略 ?<strong>VisiBroker</strong> <strong>Edition</strong> 提 供 两 种 线 程 策 略 : 开 设 线 程 池 (thread pooling) 或 一 个 会 话一 个 线 程 (thread-per-session)。 开 设 线 程 池 (thread pooling) 和 一 个 会 话 一 个 线程 (thread-per-session) 模 型 有 以 下 几 方 面 基 本 区 别 :● 创 建 的 环 境管 理 线 程 和 连 接 8-1


开 设 线 程 池 (thread pooling) 策 略● 处 理 同 一 客 户 端 的 同 时 请 求 的 方 式● 释 放 线 程 的 时 间 和 方 式默 认 线 程 策 略 是 开 设 线 程 池 (thread pooling)。 有 关 设 置 一 个 会 话 一 个 线 程(thread-per-session) 策 略 或 更 改 开 设 线 程 池 (thread pooling) 策 略 中 属 性 的 信息 , 请 参 阅 第 8-7 页 " 设 置 调 度 策 略 和 属 性 "。开 设 线 程 池 (thread pooling) 策 略服 务 器 使 用 开 设 线 程 池 (thread pooling) 策 略 时 , 它 会 定 义 可 分 配 用 于 处 理 客 户端 请 求 的 最 大 线 程 数 。 每 个 客 户 端 请 求 会 得 到 一 个 工 作 线 程 , 但 是 仅 用 于 该 特 定 请求 的 时 段 。 请 求 完 成 后 , 分 配 给 该 请 求 的 工 作 线 程 就 会 放 回 可 用 线 程 池 内 , 准 备 重新 分 配 , 处 理 以 后 来 自 任 何 客 户 端 的 请 求 。在 此 模 型 中 , 线 程 是 根 据 向 服 务 器 对 象 发 出 的 请 求 的 通 信 量 分 配 的 。 这 意 味 着 同 时向 服 务 器 发 出 很 多 请 求 的 非 常 活 跃 的 客 户 端 会 分 配 到 多 个 线 程 ( 保 证 请 求 得 到 迅 速执 行 ), 而 不 活 跃 的 多 个 客 户 端 可 能 共 享 一 个 线 程 , 但 是 其 请 求 仍 能 够 立 即 得 到 处理 。 另 外 , 这 样 可 以 减 少 与 创 建 和 撤 消 工 作 线 程 相 关 的 资 源 开 销 , 因 为 线 程 得 到 重新 利 用 而 不 是 撤 消 了 , 而 且 线 程 可 以 分 配 给 多 个 连 接 。<strong>VisiBroker</strong> <strong>Edition</strong> 根 据 并 发 客 户 端 请 求 的 数 量 动 态 分 配 线 程 池 中 的 线 程 数 , 从而 节 约 系 统 资 源 。 如 果 客 户 端 很 活 跃 , 可 以 分 配 线 程 满 足 其 需 要 。 如 果 线 程 使 用 效率 不 高 , <strong>VisiBroker</strong> <strong>Edition</strong> 会 释 放 它 们 , 只 保 留 足 够 的 线 程 , 满 足 客 户 端 的 当前 需 要 。 这 样 使 服 务 器 中 的 线 程 数 始 终 保 持 在 最 佳 状 态 。线 程 池 的 大 小 根 据 服 务 器 活 动 情 况 变 化 , 而 且 可 以 按 照 特 定 分 布 式 系 统 的 需 要 自 由配 置 ( 无 论 是 在 执 行 前 , 还 是 在 执 行 后 )。 采 用 开 设 线 程 池 (thread pooling) 策略 , 您 可 以 配 置 以 下 参 数 :● 最 大 和 最 小 线 程 数● 最 大 空 闲 时 间每 次 收 到 客 户 端 请 求 时 , 都 会 尝 试 从 线 程 池 分 配 线 程 来 处 理 请 求 。 如 果 这 是 第 一 个客 户 端 请 求 且 池 为 空 , 则 创 建 一 个 线 程 。 同 样 , 如 果 所 有 线 程 均 忙 , 就 会 创 建 新 线程 来 处 理 请 求 。服 务 器 可 以 定 义 可 分 配 用 于 处 理 客 户 端 请 求 的 最 大 线 程 数 。 如 果 池 中 没 有 线 程 可 用且 已 经 创 建 最 大 线 程 数 , 请 求 就 会 受 到 阻 挡 , 直 到 有 当 前 正 在 使 用 的 线 程 被 释 放回 池 。开 设 线 程 池 (thread pooling) 是 默 认 线 程 策 略 。 不 必 做 任 何 设 置 来 定 义 此 环 境 。如 果 要 设 置 开 设 线 程 池 (thread pooling) 策 略 的 属 性 , 请 参 阅 第 8-7 页 " 设 置 调度 策 略 和 属 性 "。8-2 <strong>VisiBroker</strong> 开 发 者 指 南


开 设 线 程 池 (thread pooling) 策 略图 8.1线 程 池 可 用上 图 所 示 为 使 用 开 设 线 程 池 (thread pooling) 策 略 的 对 象 实 现 。 诚 如 其 名 , 在 此策 略 中 , 有 一 个 工 作 线 程 池 。图 8.2客 户 端 应 用 程 序 #1 发 出 请 求在 上 图 中 , 客 户 端 应 用 程 序 #1 建 立 与 对 象 实 现 的 连 接 , 而 服 务 器 创 建 一 个 线 程 处理 请 求 。 在 开 设 线 程 池 (thread pooling) 策 略 中 , 每 个 客 户 端 对 应 一 个 连 接 , 每条 连 接 对 应 一 个 线 程 。 有 请 求 到 来 时 , 某 工 作 线 程 会 接 收 请 求 ; 同 时 该 工 作 线 程离 池 。管 理 线 程 和 连 接 8-3


开 设 线 程 池 (thread pooling) 策 略工 作 线 程 被 从 线 程 池 中 删 除 , 同 时 始 终 监 听 请 求 。 有 请 求 到 来 时 , 工 作 线 程 会 读 入请 求 并 将 请 求 调 度 到 相 应 的 对 象 实 现 。 调 度 请 求 之 前 , 工 作 线 程 会 唤 醒 另 一 个 工 作线 程 , 由 这 个 工 作 线 程 监 听 下 一 个 请 求 。图 8.3客 户 端 应 用 程 序 #2 发 出 请 求如 上 图 所 示 , 客 户 端 应 用 程 序 #2 建 立 自 己 的 连 接 并 发 出 请 求 时 , 服 务 器 创 建 第 二个 工 作 线 程 。 现 在 工 作 线 程 #3 开 始 监 听 到 来 的 请 求 。8-4 <strong>VisiBroker</strong> 开 发 者 指 南


一 个 会 话 一 个 线 程 (Thread-per-session) 策 略图 8.4客 户 端 应 用 程 序 #1 发 出 第 二 个 请 求上 图 表 明 , 当 第 二 个 请 求 从 客 户 端 应 用 程 序 #1 进 入 服 务 器 时 , 该 请 求 使 用 工 作 线程 #4。 新 建 的 工 作 线 程 #5 监 听 新 请 求 。 如 果 有 更 多 来 自 客 户 端 应 用 程 序 #1 的 请求 到 来 , 服 务 器 会 分 配 更 多 的 线 程 处 理 这 些 请 求 , 每 个 线 程 都 是 在 监 听 线 程 接 到 请求 后 新 建 。 工 作 线 程 完 成 其 工 作 后 , 服 务 器 将 其 放 回 池 中 , 准 备 处 理 来 自 任 何 客 户端 的 请 求 。一 个 会 话 一 个 线 程 (Thread-per-session) 策 略在 一 个 会 话 一 个 线 程 (Thread-per-session) 策 略 中 , 线 程 的 建 立 是 由 客 户 端 和 服务 器 进 程 之 间 的 连 接 驱 动 的 。 服 务 器 选 择 一 个 会 话 一 个 线 程 (Thread-persession)策 略 后 , 每 次 有 新 客 户 端 连 接 到 服 务 器 时 服 务 器 都 会 分 配 一 个 新 线 程 。 一个 线 程 专 门 处 理 从 特 定 客 户 端 收 到 的 所 有 请 求 。 正 因 为 如 此 , 一 个 会 话 一 个 线 程(Thread-per-session) 也 称 为 “ 一 个 连 接 一 个 线 程 ”。 客 户 端 从 服 务 器 断 开 连 接时 , 线 程 亦 撤 消 。 您 可 以 设 置vbroker.se.iiop_ts.scm.iiop_ts.manager.connectionMax 属 性 , 限 制 可 分 配 用 于客 户 端 连 接 的 最 大 线 程 数 。管 理 线 程 和 连 接 8-5


一 个 会 话 一 个 线 程 (Thread-per-session) 策 略图 8.5使 用 一 个 会 话 一 个 线 程 (Thread-per-session) 的 对 象 实 现上 图 所 示 为 一 个 会 话 一 个 线 程 (Thread-per-session) 策 略 的 使 用 。 客 户 端 应 用 程序 #1 与 对 象 实 现 建 立 连 接 。 客 户 端 应 用 程 序 #2 和 对 象 实 现 之 间 存 在 一 个 单 独 的 连接 。 当 请 求 从 客 户 端 应 用 程 序 #1 进 入 对 象 实 现 时 , 工 作 线 程 会 处 理 请 求 。 当 请 求从 客 户 端 应 用 程 序 #2 进 入 时 , 另 外 一 个 工 作 线 程 专 门 处 理 此 请 求 。图 8.6第 二 个 请 求 来 自 同 一 客 户 端在 上 图 中 , 第 二 个 请 求 从 客 户 端 应 用 程 序 #1 进 入 对 象 实 现 。 处 理 请 求 1 的 线 程 将处 理 请 求 2。 线 程 会 阻 挡 请 求 2, 直 到 自 己 处 理 完 请 求 1 ( 在 一 个 会 话 一 个 线 程[Thread-per-session] 策 略 中 , 不 并 行 处 理 来 自 同 一 客 户 端 的 请 求 )。 请 求 #1 处理 完 后 , 线 程 可 以 处 理 来 自 客 户 端 应 用 程 序 #1 的 请 求 2。 来 自 客 户 端 应 用 程 序 #1的 请 求 可 能 有 多 个 , 但 是 都 按 照 先 后 顺 序 处 理 , 并 不 给 客 户 端 应 用 程 序 #1 分 配 额外 的 线 程 。8-6 <strong>VisiBroker</strong> 开 发 者 指 南


<strong>VisiBroker</strong> <strong>Edition</strong> 提 供 哪 些 连 接 管 理 ?<strong>VisiBroker</strong> <strong>Edition</strong> 提 供 哪 些 连 接 管 理 ?总 的 来 说 , <strong>VisiBroker</strong> <strong>Edition</strong> 的 连 接 管 理 可 以 最 大 限 度 地 减 少 客 户 端 与 服 务 器之 间 连 接 的 数 量 。 换 句 话 说 , 每 个 服 务 器 进 程 对 应 一 个 连 接 , 该 连 接 共 享 。 所 有 客户 端 请 求 在 同 一 连 接 上 多 路 复 用 , 而 不 管 是 否 来 自 相 同 的 线 程 。 另 外 , 已 释 放 的 客户 端 连 接 会 回 收 起 来 , 准 备 以 后 重 新 连 接 到 同 一 服 务 器 , 这 样 客 户 端 就 不 会 由 于 要建 立 新 连 接 而 增 加 服 务 器 资 源 开 销 。在 以 下 这 种 情 况 下 , 客 户 端 应 用 程 序 限 制 到 服 务 器 进 程 中 的 两 个 对 象 上 。 每 个bind() 共 享 一 个 与 服 务 器 进 程 的 连 接 , 而 不 管 bind() 是 否 针 对 服 务 器 进 程 中 的 不同 对 象 。图 8.7限 制 到 同 一 服 务 器 进 程 中 的 两 个 对 象下 图 所 示 为 某 个 客 户 端 的 连 接 , 该 客 户 端 使 用 多 线 程 , 但 是 有 些 线 程 限 制 到 服 务 器中 的 对 象 上 。图 8.8限 制 到 服 务 器 进 程 中 的 对 象如 上 图 所 示 , 来 自 所 有 线 程 的 所 有 调 用 都 由 同 一 连 接 支 持 。 在 这 种 情 况 下 , 可 以 使用 的 最 有 效 的 多 线 程 模 型 是 开 设 线 程 池 (thread pooling) 模 型 ( 默 认 值 )。 如 果在 这 种 情 况 下 使 用 一 个 会 话 一 个 线 程 (thread-per-session) 模 型 , 服 务 器 上 只 会有 一 个 线 程 分 配 用 于 处 理 来 自 所 有 客 户 端 应 用 程 序 中 所 有 线 程 的 所 有 请 求 , 这 样 很容 易 降 低 性 能 。到 服 务 器 和 从 客 户 端 的 最 大 连 接 数 可 以 配 置 。 达 到 最 大 值 后 将 回 收 非 活 动 连 接 , 以节 约 资 源 。设 置 调 度 策 略 和 属 性多 线 程 对 象 服 务 器 中 的 每 个 POA 可 以 选 择 两 种 调 度 模 型 之 中 的 一 种 : 一 个 会 话 一个 线 程 (thread-per-session) 或 开 设 线 程 池 (thread pooling) 调 度 策 略 是 通 过 设 置ServerEngine 的 dispatcher.type 属 性 选 择 的 。vbroker.se..scm..dispatcher.type="ThreadPool"管 理 线 程 和 连 接 8-7


设 置 调 度 策 略 和 属 性vbroker.se..scm..dispatcher.type="ThreadSession"有 关 这 些 属 性 的 详 细 信 息 , 请 参 阅 第 7 章 " 使 用 POA" 和 程 序 员 参 考 。开 设 线 程 池 (Thread pooling)ThreadPool ( 开 设 线 程 池 ) 是 创 建 POA 而 不 指 定 ServerEnginePolicy 时 的 默 认 调度 策 略 。对 于 ThreadPool, 您 可 以 设 置 以 下 属 性 :● vbroker.se.default.dispatcher.tp.threadMax● vbroker.se.default.dispatcher.tp.threadMin● vbroker.se.default.dispatcher.tp.threadMaxIdle一 个 会 话 一 个 线 程 (Thread-per-session)如 果 使 用 ThreadSession 作 为 调 度 程 序 类 型 , 必 须 将 se.default 属 性 设 置 为iiop_ts。vbroker.se.default=iiop_ts编 码 注 意 事 项实 现 <strong>VisiBroker</strong> ORB 对 象 的 服 务 器 内 的 所 有 代 码 必 须 达 到 线 程 级 安 全 。 访 问 对象 实 现 中 的 系 统 级 资 源 时 一 定 要 特 别 注 意 。 例 如 , 很 多 数 据 库 访 问 方 法 没 有 达 到 线程 级 安 全 。 对 象 实 现 尝 试 访 问 此 类 资 源 时 , 首 先 必 须 通 过 同 步 化 阻 挡 锁 定 对 资 源 的访 问 。如 果 需 要 序 列 化 访 问 某 个 对 象 , 必 须 创 建 POA, 在 此 POA 上 激 活 此 对 象 , 并 将ThreadPolicy 的 值 设 置 为 SINGLE_THREAD_MODEL。8-8 <strong>VisiBroker</strong> 开 发 者 指 南


第章使 用 tie 机 制第 9 章本 章 介 绍 如 何 使 用 tie 机 制 将 现 有 的 Java 和 C++ 代 码 集 成 到 分 布 式 对 象 系 统 。 本节 将 引 导 创 建 委 托 实 现 或 提 供 实 现 继 承 。tie 机 制 是 如 何 工 作 的 ?对 象 实 现 类 一 般 从 idl2cpp 或 idl2java 编 译 器 生 成 的 服 务 对 象 类 继 承 。 反 过 来 , 服务 对 象 类 从 org.omg.PortableServer.Servant (Java) 或PortableServer.Servant::Servant (C++) 继 承 。 在 不 方 便 或 不 可 能 更 改 现 有 类 使 其从 <strong>VisiBroker</strong> <strong>Edition</strong> 服 务 对 象 类 继 承 时 , tie 机 制 可 提 供 一 种 好 方 法 。tie 机 制 为 对 象 服 务 器 提 供 一 种 从 org.omg.PortableServer.Servant (Java) 或PortableServer::Servant(C++) 继 承 的 委 托 者 实 现 类 。 委 托 者 实 现 不 具 有 任 何 自 己的 语 义 。 委 托 者 实 现 只 是 将 委 托 者 自 己 收 到 的 所 有 请 求 委 托 给 可 以 单 独 实 现 的 真 实实 现 类 。 真 实 实 现 类 不 需 要 从 org.omg.PortableServer::.Servant (Java) orPortableServer::Servant(C++) 继 承 。通 过 tie 机 制 , IDL 编 译 器 会 额 外 生 成 两 个 文 件 。● POATie 在 所 有 IDL 定 义 方 法 的 实 现 中 均 依 从 某 委 托 对 象 。 委托 对 象 会 实 现 操 作 接 口 。 继 承 实 现 可 轻 松 扩 展 用 于 实 现 操作 , 并 反 过 来 委 托 给 真 实 实 现 。● 操 作 定 义 对 象 实 现 必 须 实 现 的 所 有 方 法 。 在 使 用 tie 机 制 时 ,该 接 口 用 作 相 关 POATie 类 的 委 托 对 象 。使 用 tie 机 制 9-1


实 例 程 序实 例 程 序使 用 tie 机 制 的 实 例 程 序 的 位 置在 examples/basic/bank_tie 目 录 下 Java 和 C++ 版 <strong>VisiBroker</strong> <strong>Edition</strong> 中 可 以找 到 一 个 使 用 tie 机 制 的 Bank ( 银 行 ) 实 例 。查 看 tie 模 板C++: idl2cpp 编 译 器 会 自 动 生 成 _tie_Account 模 板 类 , 如 下 列 代 码 样 本 所 示 。POA_Bank_Account_tie 类 是 由 对 象 服 务 器 实 例 化 并 通 过 AccountImpl 实 例 初 始 化的 。 POA_Bank_Account_tie 数 据 将 自 己 收 到 的 所 有 操 作 请 求 委 托 给 真 实 实 现 类AccountImpl。 在 该 实 例 中 , AccountImpl 类 不 从 POA_Bank::Account 类 继 承 。...template class POA_Bank_Account_tie :public POA_Bank::Account {private:CORBA::Boolean _rel;PortableServer::POA_ptr _poa;T *_ptr;POA_Bank_Account_tie(const POA_Bank_Account_tie&) {}void operator=(const POA_Bank_Account_tie&) {}public:POA_Bank_Account_tie (T& t):_ptr(&t), _poa(NULL), _rel((CORBA::Boolean)0) {}POA_Bank_Account_tie (T& t, PortableServer::POA_ptr poa):_ptr(&t),_poa(PortableServer::_duplicate(poa)), _rel((CORBA::Boolean)0) {}POA_Bank_Account_tie (T *p, CORBA::Boolean release= 1) :_ptr(p),_poa(NULL), _rel(release) {}POA_Bank_Account_tie (T *p, PortableServer::POA_ptr poa, CORBA::Boolean release=1): _ptr(p), _poa(PortableServer::_duplicate(poa)), _rel(release) {}virtual ~POA_Bank_Account_tie() {CORBA::release(_poa);if (_rel) {delete _ptr;}}T* _tied_object() { return _ptr; }void _tied_object(T& t) {if (_rel) {delete _ptr;}_ptr = &t;_rel = 0;}void _tied_object(T *p, CORBA::Boolean release=1) {if (_rel) {delete _ptr;}_ptr = p;9-2 <strong>VisiBroker</strong> 开 发 者 指 南


实 例 程 序_rel = release;}CORBA::Boolean _is_owner() { return _rel; }void _is_owner(CORBA::Boolean b) { _rel = b; }CORBA::Float balance() {return _ptr->balance();}PortableServer::POA_ptr _default_POA() {if ( !CORBA::is_nil(_poa) ) {return _poa;} else {return PortableServer_ServantBase::_default_POA();}}};修 改 服 务 器 使 其 使 用 _tie_account 类C++: 以 下 代 码 样 本 显 示 对 使 用 _tie_account 类 所 需 修 改 的 Server.C 文 件 的 修 改 。#include "Bank_s.hh"#include . . .int main(int argc, char* const* argv) {try{// 初 始 化 ORB。CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);// 取 得 根 POA 的 引 用PortableServer::POA_var rootPOA = PortableServer::POA::_narrow(orb->resolve_initial_references("RootPOA"));CORBA::PolicyList policies;policies.length(1);policies[(CORBA::ULong)0] = rootPOA->create_lifespan_policy(PortableServer::PERSISTENT};// 取 到 POA 管 理 器PortableServer::POAManager_var poa_manager = rootPOA->the_POAManager();// 用 正 确 的 策 略 创 建 myPOAPortableServer::POA_var myPOA = rootPOA->create_POA("bank_agent_poa",poa_manager, policies);// 创 建 服 务 对 象AccountManagerImpl managerServant(rootPOA);// 创 建 委 托 者POA_Bank_AccountManager_tie tieServer(managerServant);// 确 定 服 务 对 象 IDPortableServer::ObjectId_var managerId =PortableServer::string_to_ObjectId("BankManager");// 用 myPOA 上 的 ID 激 活 服 务 对 象myPOA->activate_object_with_id(managerId, &tieServer);// 激 活 POA 管 理 器poa_manager->activate();cout servant_to_reference(&tieServer)


实 例 程 序} catch(const CORBA::Exception& e) {cerr


import org.omg.PortableServer.*;import java.util.*;public class AccountManagerImpl implements Bank.AccountManagerOperations {public AccountManagerImpl(POA poa) {_accountPOA = poa;}public synchronized Bank.Account open(String name) {// 在 帐 户 字 典 中 查 找 帐 户 。Bank.Account account = (Bank.Account) _accounts.get(name);// 如 果 字 典 中 没 有 帐 户 , 则 创 建 一 个 。if(account == null) {// 计 算 帐 户 余 额 ( 在 0 到 1000 元 之 间 )。float balance = Math.abs(_random.nextInt()) % 100000 / 100f;// 创 建 委 托 给 AccountImpl 实 例 的 帐 户 tieBank.AccountPOATie tie =new Bank.AccountPOATie(new AccountImpl(balance));try{// 在 默 认 POA 上 激 活 它 , 该 POA 是 该 服 务 对 象 的 根 POAaccount =Bank.AccountHelper.narrow(_accountPOA.servant_to_reference(tie));} catch (Exception e) {e.printStackTrace();}// 打 印 新 帐 户 。System.out.println("Created " + name + "'s account:" + account);// 将 帐 户 存 储 在 帐 户 字 典 中 。_accounts.put(name, account);}// 返 回 帐 户 。return account;}private Dictionary _accounts = new Hashtable();private Random _random = new Random();private POA _accountPOA = null;}实 例 程 序对 Account 类 所 作 的 更 改Java:对 Account 类 所 作 的 更 改 ( 与 Bank 实 例 相 比 ) 是 它 不 再 扩 展 Bank.AccountPOA。// Server.javapublic class AccountImpl implements Bank.AccountOperations {public AccountImpl(float balance) {_balance = balance;}public float balance() {return _balance;}private float _balance;}使 用 tie 机 制 9-5


实 例 程 序建 立 tie 实 例也 可 以 采 用 第 4 章 " 使 用 <strong>VisiBroker</strong> <strong>Edition</strong> 开 发 实 例 应 用 " 中 所 述 说 明 建 立 tie实 例 。9-6 <strong>VisiBroker</strong> 开 发 者 指 南


第章客 户 基 础第 10 章本 章 描 述 客 户 端 程 序 如 何 访 问 和 使 用 分 布 式 对 象 。初 始 化 <strong>VisiBroker</strong> ORB仅 适 用 于 Java:对 象 请 求 代 理 (ORB) 提 供 客 户 与 服 务 器 之 间 的 通 信 链 接 。 当 一 个 客 户 作 出 请 求之 后 , <strong>VisiBroker</strong> ORB 定 位 目 标 实 现 , 必 要 时 激 活 对 象 , 将 请 求 传 送 到 对 象 , 然后 将 响 应 返 回 给 客 户 。 客 户 不 知 道 对 象 是 在 同 一 台 机 器 上 还 是 在 网 络 上 。建 议 您 在 每 个 进 程 中 只 创 建 一 个 <strong>VisiBroker</strong> ORB 实 例 , 因 为 <strong>VisiBroker</strong> ORB对 系 统 资 源 的 使 用 非 常 集 中 。虽 然 <strong>VisiBroker</strong> ORB 所 作 的 很 多 工 作 对 您 是 透 明 的 , 但 是 您 的 客 户 端 程 序 必 须 显式 地 初 始 化 <strong>VisiBroker</strong> ORB。 程 序 员 参 考 中 所 描 述 的 <strong>VisiBroker</strong> ORB 选 项 可以 被 指 定 为 命 令 行 变 量 。 所 以 , 您 必 须 将 argc 和 argv 传 递 到 C++ ORB_init , 或将 args 传 递 到 Java ORB.init 以 确 保 这 些 选 项 生 效 。 以 下 的 代 码 示 例 显 示 了 C++和 Java 下 的 <strong>VisiBroker</strong> ORB 初 始 化 。在 C++ 下 初 始 化 <strong>VisiBroker</strong> ORB:#include #include "Bank_c.hh"int main(int argc, char* const* argv) {CORBA::ORB_var orb;CORBA::Float balance;try {// 初 始 化 ORB。orb = CORBA::ORB_init(argc, argv);. . .}在 Java 下 初 始 化 <strong>VisiBroker</strong> ORB:客 户 基 础 10-1


限 制 到 对 象public class Client {public static void main (String[] args) {org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null);. . .}限 制 到 对 象客 户 端 程 序 通 过 取 得 远 端 对 象 的 引 用 来 使 用 远 端 对 象 。 对 象 引 用 通 常 是 通 过 使 用C++ 下 的 _bind() 静 态 成 员 函 数 或 Java 下 的 Helper 的bind() 方 法 而 取 得 的 。 <strong>VisiBroker</strong> ORB 隐 藏 了 与 取 得 对 象 引 用 有 关 的 大 部 分 细节 , 例 如 , 定 位 实 现 对 象 的 服 务 器 和 建 立 到 此 服 务 器 的 连 接 。限 制 进 程 中 所 执 行 的 动 作当 服 务 器 进 程 启 动 时 , 它 执 行 C++ 下 的 CORBA::ORB.init() 或 者 Java 下 的ORB.init() , 并 将 自 已 通 知 给 网 络 上 的 智 能 代 理 。客 户 端 程 序 调 用 C++ 下 的 _bind() 静 态 成 员 函 数 或 Java 下 的 _bind() 方 法 时 ,<strong>VisiBroker</strong> ORB 会 代 表 您 的 程 序 执 行 几 种 功 能 。● <strong>VisiBroker</strong> ORB 与 智 能 代 理 通 讯 , 找 到 提 供 所 需 接 口 的 对 象 实 现 。 如 果 对 象名 称 是 在 调 用 C++ 下 的 _bind() 或 Java 下 的 bind() 时 指 定 的 , 则 该 名 称 会用 于 进 一 步 限 定 目 录 服 务 搜 索 。 如 果 服 务 器 对 象 已 经 注 册 到 OAD 上 , 则 对 象激 活 守 护 进 程 (OAD) ( 如 “ 使 用 对 象 激 活 守 护 进 程 " 中 所 述 ) 可 能 会 参 与 这 一过 程 。● 找 到 对 象 实 现 后 , <strong>VisiBroker</strong> ORB 会 尝 试 在 找 到 的 对 象 实 现 与 您 的 客 户 端 程序 之 间 建 立 连 接 。● 一 旦 成 功 建 立 连 接 , <strong>VisiBroker</strong> ORB 将 创 建 一 个 代 理 对 象 并 将 一 个 引 用 值 返回 到 该 对 象 。 客 户 端 将 调 用 代 理 对 象 上 的 方 法 , 而 代 理 对 象 继 而 与 服 务 器 对 象互 动 。图 10.1与 智 能 代 理 的 客 户 端 互 动注 :客 户 端 程 序 永 远 不 会 调 用 服 务 器 类 的 构 建 器 。 相 反 , 对 象 引 用 是 通 过 调 用 C++ 下的 静 态 _bind() 静 态 成 员 函 数 或 Java 下 的 静 态 _bind() 方 法 获 得 的 。10-2 <strong>VisiBroker</strong> 开 发 者 指 南


调 用 对 象 上 的 操 作. . .PortableServer::ObjectId_var manager_id =PortableServer::string_to_ObjectId("BankManager");Bank::AccountManager_var = Bank::AccountManager::_bind("/bank_agent_poa",manager_id);Java 下 的 限 制 调 用 实 例 :Bank.AccountManager manager =Bank.AccountManagerHelper.bind(orb, "/bank_agent_poa","BankManager".getBytes());. . .调 用 对 象 上 的 操 作客 户 端 使 用 对 象 引 用 调 用 对 象 上 的 操 作 或 引 用 对 象 内 的 数 据 。 第 10-3 页 " 处 理 对象 引 用 " 介 绍 处 理 对 象 引 用 的 各 种 方 法 。在 C++ 下 使 用 对 象 引 用 调 用 操 作 :. . .// 调 用 余 额 操 作 。balance = account->balance();cout


处 理 对 象 引 用获 得 nil 引 用仅 适 用 于 C++:您 可 以 使 用 CORBA::Object 类 _nil() 成 员 函 数 获 得 nil 对 象 引 用 。 它 返 回 一 个NULL 值 , 该 值 被 造 型 成 为 Object_ptr。class Object {. . .static CORBA::Object_ptr _nil();. . .};复 制 对 象 引 用仅 适 用 于 C++:注 :您 的 客 户 端 程 序 调 用 _duplicate 成 员 函 数 时 , 对 象 引 用 的 引 用 数 递 增 一 个 并 返 回同 一 对 象 引 用 。 您 的 客 户 端 程 序 可 以 使 用 _duplicate() 成 员 函 数 增 加 对 象 引 用 的引 用 数 , 这 样 引 用 就 可 以 存 储 在 数 据 结 构 中 或 作 为 参 数 来 传 递 。 增 加 引 用 数 可 确 保与 对 象 引 用 相 关 的 内 存 在 引 用 数 达 到 零 之 前 不 会 被 释 放 。IDL 编 译 器 为 您 所 指 定 的 每 个 对 象 界 面 生 成 一 个 _duplicate() 成 员 函 数 。_duplicate() 成 员 函 数 接 受 并 返 回 一 个 普 通 的 Object_ptr。class Object {. . .static CORBA::Object_ptr _duplicate(CORBA::Object_ptr obj);. . .};_duplicate() 成 员 函 数 对 POA 和 <strong>VisiBroker</strong> ORB 而 言 没 有 意 义 , 因 为 这 些 对 象不 支 持 引 用 计 算 。释 放 对 象 引 用仅 适 用 于 C++:小 心 :当 不 再 需 要 一 个 对 象 引 用 时 , 您 应 该 将 它 释 放 。 释 放 对 象 引 用 的 一 种 方 法 是 调 用CORBA::Object 类 _release() 成 员 函 数 。务 必 使 用 release() 成 员 函 数 。 切 勿 在 对 象 引 用 上 调 用 operator delete。class CORBA {class Object {. . .void _release();. . .};};您 也 可 以 使 用 CORBA 类 release() 成 员 函 数 , 提 供 该 功 能 是 为 了 与 CORBA 规 范兼 容 。class CORBA {. . .static void release();. . .};10-4 <strong>VisiBroker</strong> 开 发 者 指 南


处 理 对 象 引 用得 到 引 用 数仅 适 用 于 C++:每 个 对 象 引 用 都 有 一 个 引 用 数 , 您 可 以 用 它 来 确 定 引 用 被 复 制 了 多 少 次 。 当 您 首 次通 过 调 用 _bind() 得 到 一 个 对 象 引 用 时 , 引 用 数 设 定 为 1。 释 放 一 个 对 象 引 用 会 使引 用 数 递 减 1 。 一 旦 引 用 数 达 到 0, <strong>VisiBroker</strong> <strong>Edition</strong> 会 自 动 删 除 该 对 象 引 用 。以 下 代 码 示 例 示 范 的 是 用 于 检 索 引 用 数 的 _ref_count() 成 员 函 数 。注 : 当 远 端 客 户 复 制 或 删 除 一 个 对 象 引 用 时 , 服 务 器 的 对 象 引 用 数 不 受 影 响 。class Object {. . .CORBA::Long _ref_count() const;. . .};将 引 用 转 换 成 字 串<strong>VisiBroker</strong> <strong>Edition</strong> 为 <strong>VisiBroker</strong> ORB 类 提 供 成 员 函 数 ( 在 C++ 下 ) 或 方 法( 在 Java 下 ), 它 们 允 许 您 将 对 象 引 用 转 换 成 字 串 或 者 将 字 串 转 换 回 对 象 引 用 。CORBA 规 范 将 此 进 程 称 为 字 串 化 。表 10.1成 员 函 数 (C++) 或 方 法 (Java) 字 串 化 和 去 字 串 化方 法object_to_stringstring_to_object说 明将 对 象 引 用 转 换 成 字 串将 对 字 串 转 换 成 对 象 引 用客 户 端 程 序 可 以 使 用 object_to_string 成 员 函 数 ( 在 C++ 下 ) 或 方 法 ( 在 Java下 ) 将 对 象 引 用 转 换 成 字 串 并 将 它 传 送 给 另 一 个 客 户 端 程 序 。 然 后 , 第 二 个 客 户 可以 通 过 使 用 string_to_object 成 员 函 数 ( 在 C++ 下 ) 或 方 法 ( 在 Java 下 ) 将 该对 象 引 用 去 字 串 化 , 然 后 使 用 该 对 象 而 无 须 显 式 地 限 制 到 该 对 象 。注 :仅 适 用 于 C++: object_to_string 的 调 用 程 序 负 责 在 返 回 的 字 串 上 调 用 CORBA::string_free() 。注 :象 <strong>VisiBroker</strong> ORB 和 POA 这 样 的 局 部 作 用 域 对 象 引 用 不 能 字 串 化 。 如 果 尝 试 这样 做 , 由 会 掷 出 MARSHAL 违 例 , 其 中 包 含 次 要 代 码 (minor code) 4。取 得 目 标 和 界 面 名 称下 表 显 示 了 由 Object 类 提 供 的 成 员 函 数 (C++) 和 方 法 (Java), 您 可 以 用 它 们来 得 到 界 面 名 、 对 象 名 、 以 及 与 引 用 对 象 相 关 的 仓 库 ID。 有 关 的 接 口 仓 库 的 描 述 ,请 参 阅 第 17 章 " 使 用 接 口 仓 库 "注 :如 果 您 在 未 指 定 对 象 名 的 情 况 下 调 用 C++ 下 的 _bind() 静 态 成 员 函 数 或 者 Java 下的 _bind() 方 法 , 则 使 用 结 果 对 象 引 用 调 用 _object_name() 成 员 函 数 ( 在 C++客 户 基 础 10-5


处 理 对 象 引 用下 ) 或 者 _object_name() 方 法 ( 在 Java 下 ) 将 会 返 回 NULL ( 在 C++) 或 null( 在 Java 下 )。表 10.2方 法取 得 界 面 名 和 对 象 名 的 方 法 (Java) 或 成 员 函 数说 明_interface_name ( 仅 适 用 于 C++ ) 返 回 该 对 象 的 界 面 名 称 。_object_name 返 回 该 对 象 的 名 称 。_repository_id 返 回 该 仓 库 的 类 型 标 识 。仅 适 用 于 C++:确 定 对 象 引 用 的 类 型您 可 以 使 用 _hash() 成 员 函 数 得 到 对 象 引 用 的 一 个 散 列 值 。 虽 然 不 能 保 证 该 值 的 唯一 性 , 但 该 值 将 在 对 象 引 用 的 整 个 生 存 期 内 保 持 一 致 , 并 可 以 保 存 在 散 列 表 中 。您 可 以 使 用 C++ 下 的 _is_a() 成 员 函 数 或 Java 下 的 _is_a() 方 法 来 检 查 对 象 引 用是 否 具 有 一 个 特 定 的 类 型 。 您 必 须 使 用 C++ 下 的 _repository_id() 成 员 函 数 或Java 下 的 _repository_id() 方 法 来 取 得 该 类 型 的 仓 库 ID. 如 果 该 对 象 是 由repository_id() 表 示 的 类 型 的 实 例 或 者 是 一 个 子 类 型 , 则 该 方 法 返 回 1 ( 在 C++下 ) 或 true ( 在 Java 下 )。 如 果 对 象 不 属 于 所 指 定 的 类 型 , 则 该 成 员 函 数 返 回0, 或 该 方 法 返 回 false ( 在 Java 下 )。 注 意 : 这 可 能 需 要 远 端 调 用 以 确 定 类 型 。仅 适 用 于 Java: 您 不 能 使 用 instanceof 关 键 字 来 确 定 运 行 期 类 型 。您 可 以 使 用 C++ 下 的 _is_equivalent() 成 员 函 数 或 Java 下 的 _is_equivalent()方 法 来 检 查 两 个 对 象 引 用 是 否 在 引 用 同 一 对 象 实 现 。 如 果 对 象 引 用 相 同 , 则 该 成 员函 数 返 回 1 ( 在 C++ 下 ) 或 该 方 法 返 回 true ( 在 Java 下 )。 如 果 对 象 引 用 不同 , 则 该 成 员 函 数 返 回 0 ( 在 C++ 下 ) 或 该 方 法 返 回 false ( 在 Java 下 ), 但这 并 一 定 表 示 对 象 引 用 是 两 个 截 然 不 同 的 对 象 。 这 是 一 个 轻 量 级 的 成 员 函 数 ( 在C++ 下 ) 或 者 轻 量 级 的 方 法 ( 在 Java 下 ), 它 不 包 括 与 服 务 器 对 象 之 间 的 实 际 的沟 通 。表 10.3方 法用 于 确 定 对 象 引 用 类 型 的 方 法 (Java) 或 成 员 函 数 (C++)确 定 限 制 的 对 象 的 位 置 和 状 态说 明_hash ( 仅 适 用 于 C++ ) 返 回 对 象 引 用 的 散 列 值 。_is_a 确 定 对 象 是 否 实 现 指 定 的 界 面 。_is_equivalent如 果 两 个 对 象 引 用 同 一 个 界 面 实 现 , 则 返 回true 。在 给 定 合 法 的 对 象 引 用 的 情 况 下 , 您 的 客 户 端 应 用 程 序 可 以 使 用 C++ 下 的_is_bound() 成 员 函 数 或 者 _is_bound() 方 法 来 确 定 对 象 是 否 被 限 制 。 如 果 对 象 被限 制 , 则 该 方 法 返 回 1 ( 在 C++ 下 ) 或 true ( 在 Java 下 ); 如 果 对 象 未 被 限制 , 则 该 方 法 返 回 0 ( 在 C++ 下 ) 或 false。如 果 客 户 端 程 序 和 对 象 实 现 驻 留 在 同 一 进 程 或 地 址 空 间 内 , 则 _is_local() 成 员 函数 返 回 1 ( 在 C++ 下 ) 或 者 _is_local() 方 法 返 回 true ( 在 Java 下 )。10-6 <strong>VisiBroker</strong> 开 发 者 指 南


处 理 对 象 引 用如 果 客 户 端 程 序 和 对 象 实 现 驻 留 在 不 同 的 进 程 内 ( 可 能 在 同 一 主 机 上 , 也 可 能 不 在同 一 主 机 上 ), 则 _is_remote() 成 员 函 数 返 回 1 ( 在 C++ 下 ) 或 者 _is_remote()方 法 返 回 true ( 在 Java 下 )。表 10.4用 于 确 定 对 象 引 用 位 置 和 状 态 的 方 法 (Java) 或 成 员 函 数 (C++)方 法_is_bound_is_local_is_remote说 明如 果 有 到 该 对 象 的 活 动 连 接 。 则 返 1 ( 在 C++ 下) 或 true ( 在 Java) 下 。如 果 该 对 象 在 本 地 地 址 空 间 实 现 , 则 返 回 1 ( 在C++ 下 ) 或 true ( 在 Java 下 )。如 果 该 对 象 的 实 现 不 驻 留 在 本 地 地 址 空 间 内 , 则返 回 1 ( 在 C++ 下 ) 或 true ( 在 Java 下 )。注 :如 果 该 对 象 处 于 调 用 的 该 方 法 的 进 程 , 则 _is_local() 返 回 1 ( 在 C++ 下 ) 或 者true ( 在 Java 下 )。检 查 不 存 在 的 对 象C++:您 可 以 使 用 _non_existent() 成 员 函 数 来 确 定 与 对 象 引 用 相 关 的 对 象 实 现 是 否 仍 然存 在 。 这 种 方 法 实 际 上 是 “ping” 该 对 象 以 确 定 它 是 否 仍 然 存 在 ; 如 果 该 对 象 不存 在 , 则 返 回 1。窄 转 换 对 象 引 用将 对 象 引 用 的 类 型 从 常 规 的 超 级 类 型 转 换 成 更 具 体 的 次 级 类 型 的 过 程 称 做 窄 转 换 。C++:_narrow() 成 员 函 数 可 能 会 构 建 一 个 新 的 C++ 对 象 , 并 返 回 一 个 指 针 到 该 对 象 。 当您 不 再 需 要 该 对 象 时 , 您 必 须 释 放 由 _narrow() 返 回 的 对 象 引 用 。Java: 您 不 能 使 用 Java 造 型 工 具 来 实 现 窄 转 换 。<strong>VisiBroker</strong> <strong>Edition</strong> 为 每 个 对 象 界 面 保 留 一 个 typegraph, 以 便 可 以 通 过 使 用 对象 的 narrow() 方 法 来 实 现 窄 转 换 。C++:Java:C++:如 果 narrow 成 员 函 数 确 定 不 可 能 将 对 象 转 换 为 您 所 要 求 的 类 型 , 它 将 返 回 NULL。如 果 窄 转 换 失 败 , 则 会 掷 出 IDL 违 例 CORBA::BAD_PARAM , 这 是 因 为 对 象 引 用 不 支持 所 要 求 的 类 型 。Account *acct;Account *acct2;Objec *obj;acct = Account::_bind();obj = (CORBA::Object *)acct;acct2 = Account::_narrow(obj);在 Java 下 为 AccountManager 生 成 的 窄 转 换 方 法 :public abstract class AccountManagerHelper {. . .public static Bank.AccountManager narrow(org.omg.CORBA.Object object) {. . .客 户 基 础 10-7


使 用 服 务 质 量}}. . .拓 宽 对 象 引 用将 对 象 引 用 的 类 型 转 换 成 超 级 类 型 的 过 程 称 做 拓 宽 。 以 下 的 代 码 示 例 显 示 的 是 将Account 指 针 分 别 拓 宽 为 C++ 和 Java 下 的 Object 指 针 的 实 例 。 acct 指 针 可 以 被造 型 为 Object 指 针 , 因 为 Account 类 是 从 Object 类 继 承 而 来 。在 C++ 下 拓 宽 对 象 引 用 :. . .Account *acct;CORBA::Object *obj;acct = Account::_bind();obj = (CORBA::Object *)acct;. . .在 Java 下 拓 宽 对 象 引 用. . .Account account;org.omg.CORBA.Object obj;account = AccountHelper.bind();obj = (org.omg.CORBA.Object) account;. . .使 用 服 务 质 量服 务 质 量 (QoS) 使 用 策 略 来 定 义 和 管 理 在 您 的 客 户 程 序 及 与 它 们 所 连 接 的 服 务 器之 间 的 连 接 。理 解 服 务 质 量服 务 质 量 策 略 管 理 是 通 过 在 以 下 上 下 文 中 可 用 的 操 作 来 实 现 的 :● <strong>VisiBroker</strong> ORB 级 策 略 是 通 过 局 部 受 限 的 PolicyManager 来 处 理 的 , 通 过 它 您可 以 设 定 策 略 并 查 看 当 前 的 Policy 门 限 值 。 在 <strong>VisiBroker</strong> ORB 级 设 定 的 策 略会 覆 盖 系 统 的 默 认 值 。● 线 程 级 的 策 略 是 通 过 PolicyCurrent 设 定 的 , 它 包 含 查 看 和 设 定 线 程 级 的Policy 门 限 的 操 作 。 在 线 程 级 设 定 的 策 略 会 覆 盖 系 统 默 认 值 以 及 在 <strong>VisiBroker</strong>ORB 级 设 定 的 值 。● 对 象 级 的 策 略 可 以 通 过 访 问 基 础 对 象 界 面 的 服 务 质 量 操 作 来 应 用 。 在 对 象 级 设 定的 策 略 会 覆 盖 系 统 默 认 值 以 及 在 <strong>VisiBroker</strong> ORB 级 和 线 程 级 设 定 的 值 。10-8 <strong>VisiBroker</strong> 开 发 者 指 南


使 用 服 务 质 量策 略 门 限 和 有 效 策 略有 效 策 略 指 的 是 在 所 有 适 用 的 策 略 门 限 被 应 用 之 后 , 可 用 于 请 求 的 策 略 。 有 效 策 略可 以 通 过 比 较 由 IOR 指 定 的 策 略 和 有 效 的 门 限 来 确 定 。 有 效 策 略 是 有 效 的 门 限 所允 许 的 值 和 IOR 指 定 的 Policy 的 交 集 。 如 果 该 交 集 为 空 集 , 则 会 有 一 个org.omg.CORBA.INV_POLICY 违 例 出 现 。QoS 界 面以 下 的 界 面 可 用 以 取 得 和 设 定 QoS 策 略 。C++ CORBA::Object, 或Java org.omg.CORBA.ObjectCORBA::Object (C++) 和 org.omg.CORBA.Object (Java) 包 含 以 下 用 于 取 得 有 效 策略 和 取 得 或 设 定 策 略 门 限 的 方 法 。● _get_policy 为 对 象 引 用 返 回 有 效 策 略 。● _set_policy_override 返 回 一 个 新 的 对 象 引 用 和 所 要 求 的 对 象 级 上 的 Policy 门限 列 表 。C++ CORBA::Object, 或Java com.inprise.vbroker.CORBA.Object (Borland)仅 适 用 于 Java:为 了 使 用 这 一 界 面 , 您 必 须 将 org.omg.CORBA.Object 造 型 为com.inprise.vbroker.CORBA.Object。 因 为 这 一 界 面 是 从 org.omg.CORBA.Object 派生 的 , 除 了 org.omg.CORBA.Object 中 所 定 义 的 方 法 之 外 , 以 下 的 方 法 也 是 可 用 的 。● _get_client_policy 为 对 象 引 用 返 回 有 效 的 Policy , 而 无 须 与 服 务 器 端 的 策 略产 生 交 集 。 有 效 门 限 是 通 过 以 下 方 式 取 得 的 : 首 先 检 查 对 象 级 上 指 定 的 门 限 , 然后 检 查 线 程 级 上 指 定 的 门 限 , 最 后 检 查 <strong>VisiBroker</strong> ORB 级 上 指 定 的 门 限 。 如果 未 给 所 要 求 的 PolicyType 指 定 门 限 , 则 使 用 PolicyType 的 系 统 默 认 值 。● _get_policy_overrides 返 回 对 象 级 上 设 置 的 指 定 的 策 略 类 型 的 Policy 门 限 清单 。 如 果 所 指 定 的 序 列 为 空 , 则 对 象 级 上 的 所 有 门 限 都 将 被 返 回 。 如 果 在 对 象 级上 没 有 PolicyTypes 被 覆 盖 , 则 返 回 一 个 空 序 列 。● _validate_connection 根 据 对 象 的 当 前 有 效 策 略 是 否 允 许 调 用 , 返 回 一 个 布 尔值 。 如 果 对 象 引 用 未 限 制 , 则 会 出 现 一 个 限 制 。 如 果 对 象 引 用 已 限 制 , 但 当 前 的策 略 门 限 已 发 生 了 变 化 , 或 该 限 制 已 不 再 有 效 , 则 不 论 RebindPolicy 门 限 设 置如 何 , 都 将 尝 试 重 新 限 制 。 如 果 当 前 的 有 效 策 略 引 发 一 个 INV_POLICY 违 例 , 则会 出 现 一 个 false 返 回 值 。 如 果 当 前 的 有 效 策 略 不 兼 容 , 则 返 回 一 个 罗 列 不 兼 容策 略 的 PolicyList 类 型 序 列 。客 户 基 础 10-9


使 用 服 务 质 量C++ CORBA::PolicyManager, 或Java org.omg.CORBA.PolicyManagerPolicyManager 是 为 取 得 和 设 置 <strong>VisiBroker</strong> ORB 级 上 的 Policy 门 限 提 供 方 法 的 界面 。● get_policy_overrides 返 回 一 个 请 求 的 PolicyTypes 中 所 有 被 覆 盖 的 策 略 的PolicyList 序 列 如 果 指 定 的 序 列 为 空 , 则 当 前 环 境 级 上 的 所 有 Policy 门 限 均 被返 回 。 如 果 在 目 标 PolicyManager 中 任 何 请 求 的 PolicyTypes 都 未 被 覆 盖 , 则 返回 一 个 空 序 列 。● set_policy_overrides 用 请 求 的 Policy 清 单 编 辑 门 限 的 当 前 设 置 。 输 入 的 第 一个 参 数 policies 是 Policy 对 象 的 引 用 序 列 。 第 二 个 参 数 set_add 属 于SetOverrideType (C++) 或 org.omg.CORBA.SetOverrideType (Java) 类 , 它表 示 是 否 应 该 通 过 使 用 ADD_OVERRIDE 将 这 些 策 略 添 加 到 PolicyManager 已 经 存在 的 其 它 任 何 门 限 上 , 或 者 是 否 应 该 通 过 使 用 SET_OVERRIDES 将 它 们 添 加 到 不 含任 何 门 限 的 PolicyManager 上 。 如 果 用 一 个 空 的 策 略 序 列 和 SET_OVERRIDES 方 式调 用 set_policy_overrides, 则 会 从 PolicyManager 上 删 除 所 有 门 限 。 如 果 您 尝试 覆 盖 不 适 用 于 您 的 客 户 的 策 略 , 则 会 引 发 一 个 NO_PERMISSION ( 在 C++ 下 )或 org.omg.CORBA.NO_PERMISSION ( 在 Java 下 ) 违 例 。 如 果 请 求 导 致 指 定 的PolicyManager 处 于 不 一 致 的 状 态 , 则 不 会 改 变 或 增 加 任 何 策 略 , 并 会 引 发 一 个InvalidPolicies 违 例 。C++ CORBA::PolicyCurrent, 或Java org.omg.CORBA.PolicyCurrentPolicyCurrent 界 面 从 PolicyManager 衍 生 而 来 的 , 没 有 增 加 新 方 法 。 它 提 供 对 在线 程 级 上 覆 盖 的 策 略 的 访 问 。 线 程 的 PolicyCurrent 的 引 用 是 通 过 调 用 C++ 下 的resolve_initial_references 或 Java 下 的org.omg.CORBA.ORB.resolve_initial_references 和 指 定 “PolicyCurrent” 的标 识 来 实 现 的 。C++ QoSExt::DeferBindPolicy, 或Java com.inprise.vbroker.QoSExt.DeferBindPolicyC++:DeferBindPolicy 确 定 <strong>VisiBroker</strong> ORB 是 在 首 次 被 创 建 时 尝 试 与 远 端 对 象 联 络 ,还 是 直 到 第 一 次 调 用 发 生 时 才 进 行 联 系 。 DeferBindPolicy 的 值 是 true 和 false。如 果 DeferBindPolicy 被 设 定 为 true, 则 所 有 的 限 制 都 将 被 延 迟 到 第 一 次 调 用 一 个限 制 实 例 。 默 认 值 是 false。如 果 您 创 建 一 个 客 户 对 象 , 并 将 DeferBindPolicy 设 置 为 true, 则 您 可 以 将 服 务 器的 启 动 延 迟 到 第 一 次 调 用 。 该 选 项 以 前 是 作 为 生 成 的 helper 类 上 的 Bind 方 法 的一 个 选 项 。以 下 的 代 码 示 例 示 范 的 是 在 C++ 下 创 建 DeferBindPolicy 并 在 <strong>VisiBroker</strong> ORB上 设 定 策 略 的 实 例 。// 初 始 化 标 志 和 引 用CORBA::Boolean deferMode = (CORBA::Boolean) 1;10-10 <strong>VisiBroker</strong> 开 发 者 指 南


使 用 服 务 质 量CORBA::Any policy_value;policy_value resolve_initial_references("ORBPolicyManager");CORBA::PolicyManager_var orb_mgr = CORBA::PolicyManager::_narrow(obj);// 在 ORB 级 上 设 定 策 略orb_mgr->set_policy_overrides(policies, CORBA::SET_OVERRIDE);Java:这 个 代 码 示 例 示 范 的 是 在 Java 下 创 建 DeferBindPolicy 并 在 <strong>VisiBroker</strong> ORB、线 程 及 对 象 级 上 设 定 策 略 的 实 例 。以 下 的 实 例 用 于 创 建 DeferBindPolicy 并 在 <strong>VisiBroker</strong> ORB、 线 程 及 对 象 级 上设 定 策 略 。// 初 始 化 标 志 和 引 用boolean deferMode = true;Any policyValue= orb.create_any();policyValue.insert_boolean(deferMode);Policy policies =orb.create_policy(DEFER_BIND_POLICY_TYPE.value, policyValue);// 取 得 线 程 管 理 器 的 引 用PolicyManager orbManager =PolicyManagerHelper.narrow(orb.resolve_initial_references("ORBPolicyManager"));// 在 ORB 级 上 设 定 策 略orbManager.set_policy_overrides(new Policy[] {policies},SetOverrideType.SET_OVERRIDE);// 取 得 限 制 方 法byte[] managerId = "BankManager".getBytes();Bank.AccountManager manager =Bank.AccountManagerHelper.bind(orb, "/qos_poa", managerId);com.inprise.vbroker.QoSExt.ExclusiveConnectionPolicyJava:ExclusiveConnectionPolicy 是 一 个 与 Visibroker 相 关 的 策 略 , 它 可 以 给 您 提 供 建立 独 占 的 ( 非 共 享 的 ) 的 连 接 到 指 定 的 服 务 器 对 象 上 的 能 力 。 您 给 这 个 策 略 分 配 一个 布 尔 值 true 或 false。 如 果 策 略 被 设 定 为 true , 则 到 服 务 器 对 象 的 连 接 是 独 占的 。 如 果 策 略 被 设 定 为 false, 则 现 有 的 连 接 在 可 能 时 会 重 新 投 入 使 用 , 仅 当 重 新使 用 不 可 能 时 , 才 会 打 开 一 个 新 的 连 接 。 默 认 值 是 false。该 策 略 提 供 与 Visibroker 3.x 中 的 Object._clone() 相 同 的 功 能 。客 户 基 础 10-11


使 用 服 务 质 量CloneClient.java example 中 提 供 了 一 个 关 于 如 何 建 立 独 占 的 和 非 独 占 的 连 接 的实 例 。QoSExt::RelativeConnectionTimeoutPolicy, 或com.inprise.vbroker.QoSExt::RelativeConnectionTimeoutPolicyJava:Java:RelativeConnectionTimeoutPolicy 表 示 一 个 时 限 , 在 该 时 限 之 后 , 如 果 尝 试 使 用一 个 可 用 的 端 点 连 接 到 一 个 对 象 , 则 操 作 将 被 中 止 。 超 时 现 象 很 可 能 发 生 在 由 防 火墙 保 护 的 对 象 上 , 其 中 HTTP 隧 道 是 连 接 到 该 对 象 的 唯 一 通 道 。下 列 的 代 码 示 例 示 范 如 何 创 建 RelativeConnectionTimeoutPolicy:Any policyValue= orb.create_any();// 是 以 10^7 纳 秒 为 单 位 来 输 入 。// 要 指 定 一 个 20 秒 的 值 , 使 用 20 * 10^7 纳 秒 作 为 输 入int connTimeout = 20;connTimeoutPolicyValue.insert_ulonglong(connTimeout * 10000000);org.omg.CORBA.Policy ctoPolicy =orb.create_policyRELATIVE_CONN_TIMEOUT_POLICY_TYPE.value,connTimeoutPolicyValue);PolicyManager orbManager = PolicyManagerHelper.narrow (orb.resolve_initial_references("ORBPolicyManager"));orbManager.set_policy_overrides(new Policy[] \{ctoPolicy\},SetOverrideType.SET_OVERRIDE);C++ Messaging::RebindPolicy, orJava org.omg.Messaging.RebindPolicyRebindPolicy 接 受 C++ 下 的 Messaging::RebindMode 类 型 或 者 Java 下 的org.omg.Messaging.RebindMode 类 型 以 定 义 对 象 在 重 新 限 制 时 的 行 为 。RebindPolicies 仅 在 客 户 端 作 设 定 。 在 断 接 、 对 象 前 转 请 求 或 对 象 失 败 的 情 况 下 ,它 可 以 具 有 6 个 确 定 行 为 的 值 。 当 前 支 持 的 值 为 :● Messaging::TRANSPARENT (C++) 或 org.omg.Messaging.TRANSPARENT(Java), 允 许 <strong>VisiBroker</strong> ORB 在 作 远 端 请 求 的 过 程 中 隐 式 地 处 理 对 象 前 转 和必 要 的 再 连 接 。 以 下 的 代 码 示 例 示 范 如 何 创 建 Java 下 的 TRANSPARENT 类型 的 RebindPolicy 并 在 <strong>VisiBroker</strong> ORB、 线 程 和 对 象 级 上 设 定 策 略 。● Messaging::NO_REBIND(C++) 或 org.omg.Messaging.NO_REBIND(Java) 允 许<strong>VisiBroker</strong> ORB 在 作 远 端 请 求 的 过 程 中 以 隐 式 重 新 打 开 关 闭 的 连 接 , 但 不 允许 任 何 显 式 的 、 可 能 会 导 到 用 户 可 见 的 有 效 QoS 策 略 发 生 变 化 的 对 象 前 转 。 当RebindMode 被 设 定 为 NO_REBIND 时 , 仅 允 许 显 式 再 限 制 。● Messaging::NO_RECONNECT (C++) 或 org.omg.Messaging.NO_REBIND(Java) 不 允 许 <strong>VisiBroker</strong> ORB 显 式 处 理 对 象 前 转 或 关 闭 连 接 的 重 开 。 当RebindMode 被 设 定 为 NO_RECONNECT 时 , 您 必 须 透 明 地 执 行 再 限 制 和 重 新 连 接 。● QoSExt::VB_TRANSPARENT (C++) 或com.inprise.vbroker.QoSExt.VB_TRANSPARENT (Java) 是 默 认 的 策 略 。 它 允 许对 隐 式 和 显 式 限 制 作 透 明 的 再 限 制 , 以 拓 展 TRANSPARENT 的 功 能 。VB_TRANSPARENT 旨 在 与 <strong>VisiBroker</strong> <strong>Edition</strong> 3.x 中 的 对 象 失 效 恢 复 实 现 兼 容 。10-12 <strong>VisiBroker</strong> 开 发 者 指 南


使 用 服 务 质 量注 :仅 适 用 于 C++:● QoSExt::VB_NOTIFY_REBIND (C++) 或com.inprise.vbroker.QoSExt.VB_NOTIFY_REBIND (Java) 在 有 必 要 进 行 再 限 制时 , 掷 出 一 个 违 例 。 客 户 捕 获 这 个 违 例 , 并 限 制 在 第 二 个 调 用 上 。● QoSExt::VB_NO_REBIND (C++) 或 com.inprise.vbroker.QoSExt.VB_NO_REBIND(Java) 不 允 许 失 效 恢 复 。 它 仅 允 许 客 户 端 <strong>VisiBroker</strong> ORB 将 关 闭 的 连 接 重开 到 同 一 服 务 器 上 , 不 允 许 任 何 形 式 的 对 象 前 转 。如 果 您 的 客 户 的 有 效 策 略 是 VB_TRANSPARENT 而 您 的 客 户 正 在 与 保 存 状 态 数 据 的 服 务器 一 起 工 作 , VB_TRANSPARENT 可 以 在 客 户 对 服 务 器 变 化 不 知 情 的 情 况 下 将 客 户 连 接到 一 个 新 的 服 务 器 , 任 何 由 原 来 的 服 务 器 保 存 的 状 态 数 据 都 可 能 会 被 丢 失 。在 NO_REBIND 或 NO_RECONNECT 状 态 下 , 可 以 通 过 调 用 CORBA::Object 界 面 上 的_validate_connection 来 显 式 地 允 许 对 关 闭 的 连 接 的 重 开 或 前 转 操 作 。下 表 列 出 了 不 同 RebindMode 类 型 的 行 为 清 单 。表 10.5RebindMode 策 略RebindMode 类 型NO_RECONNECT是 否 在 同 一 对 象 上重 建 关 闭 的 连 接 ?不 , 掷 出 REBIND违 例 。是 否 允 许 对 象 前转 ? 对 象 失 效 恢 复 ? 1不 , 掷 出 REBIND违 例 。NO_REBIND 是 是 , 如 果 策 略 匹 配 。 不不 , 掷 出 REBIND违 例 。TRANSPARENT 是 是 不VB_NOTIFY_REBIND 是 是 是VB_NOTIFY_REBIND 在 故 障 侦 测 之 后会 掷 出 一 个 违 例 , 然后 在 下 一 个 请 求 上 尝试 失 效 恢 复 。VB_TRANSPARENT 是 是 是 , 透 明 地 。1在 出 现 通 信 问 题 或 对 象 故 障 时 , 会 掷 出 相 应 的 CORBA 违 例 。以 下 的 实 例 用 于 创 建 一 个 TRANSPARENT 类 型 的 RebindPolicy 并 在<strong>VisiBroker</strong> ORB、 线 程 和 对 象 级 上 设 置 策 略 。Any policyValue= orb.create_any();RebindModeHelper.insert(policyValue, org.omg.Messaging.TRANSPARENT.value);Policy myRebindPolicy = orb.create_policy(REBIND_POLICY_TYPE.value,policyValue);// 取 得 根 ORB 策 略 的 引 用org.omg.CORBA.PolicyManager manager;try {manager =PolicyManagerHelper.narrow(orb.resolve_initial_references("ORBPolicyManager"));}catch(org.omg.CORBA.ORBPackage.InvalidName e) {}// 取 得 根 每 线 程 管 理 器 的 引 用org.omg.CORBA.PolicyManager current;try不客 户 基 础 10-13


使 用 服 务 质 量{current=PolicyManagerHelper.narrow(orb.resolve_initial_references("PolicyCurrent"));}catch(org.omg.CORBA.ORBPackage.InvalidName e) {}// 在 orb 级 上 设 定 策 略try{manager.set_policy_overrides(myRebindPolicy,SetOverrideType.SET_OVERRIDE);}catch (InvalidPolicies e){}// 在 线 程 级 上 设 定 策 略try{current.set_policy_overrides(myRebindPolicy,SetOverrideType.SET_OVERRIDE);}catch (InvalidPolicies e){}// 在 对 象 级 上 设 定 策 略 :org.omg.CORBA.Object oldObjectReference=bind(...);org.omg.CORBA.ObjectnewObjectReference=oldObjectReference._set_policy_override(myRebindPolicy, SetOverrideType.SET_OVERRIDE);有 关 QoS 策 略 和 类 型 的 详 情 , 请 参 阅 程 序 员 参 考 和 CORBA 2.4 规 范 的 消 息 传 递一 章 。C++ Messaging::RelativeRequestTimeoutPolicy, 或Java org.omg.CORBA.Messaging.RelativeRequestTimeout PolicyRelativeRequestTimeoutPolicy 指 示 可 以 传 送 一 个 请 求 及 其 相 应 的 回 答 的 相 对 时 间段 。 在 该 时 间 段 之 后 , 请 求 将 被 取 消 。 这 一 策 略 对 同 步 和 异 步 调 用 均 适 用 。 如 果 请求 在 指 定 的 时 限 内 完 成 , 则 回 答 绝 不 会 因 为 时 限 的 原 因 而 被 丢 弃 。 时 限 值 是 以10^7 纳 秒 为 单 位 来 指 定 的 。以 下 的 代 码 显 示 了 如 何 创 建 RelativeRequestTimeoutPolicy:// 以 10^7 纳 秒 为 单 位 来 输 入// 要 设 定 一 个 20 秒 的 时 限 时 , 设 定 为 20 * 10^7 纳 秒int reqTimeout = 20;RelativeRequestTimeoutPolicyImpl relReq =new RelativeRequestTimeoutPolicyImpl(reqTimeout * 10000000);Any policyValue = orb.create_any();\parRelativeRequestTimeoutPolicyHelper.insert(policyValue,(RelativeRequestTimeoutPolicy)relReq);// 设 定 RelativeRequestTimeoutPolicyorg.omg.CORBA.Policy reqPolicy = orb.create_policy(RELATIVE_REQ_TIMEOUT_POLICY_TYPE.value, policyValue);PolicyManager orbManager = PolicyManagerHelper.narrow(orb.resolve_initial_references("ORBPolicyManager"))orbManager.set_policy_overrides(new Policy[]SetOverrideType.SET_OVERRIDE);10-14 <strong>VisiBroker</strong> 开 发 者 指 南


C++ Messaging::RelativeRoundTripTimeoutPolicy, 或Java org.omg.CORBA.Messaging.RelativeRoundtripPolicy使 用 服 务 质 量JAVA:RelativeRoundtripTimeoutPolicy 指 定 可 以 传 送 请 求 或 其 相 应 的 回 答 的 相 对 时 限 。如 果 在 该 时 限 之 后 没 有 传 送 回 答 , 则 请 求 被 取 消 。 另 外 , 如 果 请 求 已 被 传 送 而 且 有一 个 回 答 从 目 标 返 回 , 则 在 该 时 限 之 后 , 回 答 会 被 丢 弃 。 该 策 略 对 同 步 和 异 步 调 用均 适 用 。 如 果 请 求 在 指 定 的 时 限 内 完 成 , 则 回 答 绝 不 会 因 为 时 限 的 原 因 而 被 丢 弃 。时 限 值 是 以 10^7 纳 秒 为 单 位 来 指 定 的 。以 下 的 代 码 示 范 如 何 创 建 RelativeRoundTripTimeoutPolicy:// 以 10^7 纳 秒 为 单 位 来 输 入// 要 设 定 一 个 90 s 的 时 限 时 , 设 定 为 90 * 10^7 nsint rttTimeout = 20;RelativeRoundtripTimeoutPolicyImpl relRtt = newRelativeRoundtripTimeoutPolicyImpl(rttTimeout * 10000000);Any policyValue = orb.create_any();RelativeRoundtripTimeoutPolicyHelper.insert(policyValue,(RelativeRoundtripTimeoutPolicy)relRtt);// 设 定 RelativeRoundtripTimeoutPolicyorg.omg.CORBA.Policy rttPolicy = orb.create_policy(RELATIVE_RT_TIMEOUT_POLICY_TYPE.value, policyValue);PolicyManager orbManager = PolicyManagerHelper.narrow(orb.resolve_initial_references("ORBPolicyManager"));orbManager.set_policy_overrides(new Policy[]SetOverrideType.SET_OVERRIDE);C++ Messaging::SyncScopePolicy, 或Java org.omg.CORBA.Messaging.SyncScopePolicy注 :SyncScopePolicy 为 请 求 定 义 与 目 标 相 关 的 同 步 级 。 SyncScope 类 型 的 值 和SyncScopePolicy 一 起 使 用 控 制 单 向 操 作 的 行 为 。默 认 的 SyncScopePolicy 是 SYNC_WITH_TRANSPORT。应 用 必 须 显 式 设 定 <strong>VisiBroker</strong> ORB 级 SyncScopePolicy 以 确 保 在 <strong>VisiBroker</strong>ORB 实 现 上 的 可 移 植 性 。 当 SyncScopePolicy 的 实 例 被 创 建 后 , 一 个Messaging::SyncScope 类 型 值 会 传 递 到 CORBA::ORB::create_policy。 该 策 略 仅 可以 用 作 客 户 端 门 限 。QoS 违 例● 当 Policy 之 间 出 现 不 兼 容 时 , 会 引 发 CORBA::INV_POLICY (C++) 或org.omg.CORBA.INV_POLICY (Java)。● 当 RebindPolicy 具 有 NO_REBIND、NO_RECONNECT、 或 VB_NOTIFY_REBIND 值 , 而对 限 制 的 对 象 的 调 用 引 发 对 象 前 转 或 位 置 前 转 消 息 时 , 会 掷 出 CORBA::REBIND(C++) 或 org.omg.CORBA.REBIND (Java) 违 例 。客 户 基 础 10-15


使 用 服 务 质 量● 当 所 请 求 的 Policy 不 受 支 持 时 , 会 掷 出 CORBA::PolicyError (C++) 或org.omg.CORBA.PolicyError (Java) 违 例 。● 当 一 个 操 作 作 为 PolicyList 序 列 传 递 时 , 会 此 引 发 CORBA::InvalidPolicies(C++) 或 org.omg.CORBA.InvalidPolicies (Java) 违 例 。 违 例 体 包 含 从 无效 序 列 中 而 来 的 策 略 , 或 者 因 为 策 略 在 当 前 的 作 用 域 内 已 被 覆 盖 , 或 者 因 为 其 对其 它 请 求 的 策 略 无 效 。10-16 <strong>VisiBroker</strong> 开 发 者 指 南


第章使 用 IDL第 11 章本 章 介 绍 如 何 使 用 CORBA 接 口 描 述 语 言 (IDL)。IDL 简 介注接 口 定 义 语 言 (IDL) 是 一 种 描 述 语 言 ( 不 是 编 程 语 言 ), 它 描 述 由 远 端 对 象 实 现的 接 口 。 在 IDL 中 , 您 可 以 定 义 接 口 的 名 称 , 每 种 属 性 和 方 法 的 名 称 等 。 一 旦 创建 了 IDL 文 件 , 您 就 可 以 在 C++ 或 Java 编 程 语 言 下 , 使 用 IDL 编 译 器 来 生 成 客户 存 根 文 件 和 服 务 器 框 架 文 件 。 有 关 详 情 , 请 参 阅 程 序 员 参 考 。OMG 已 为 该 类 语 言 映 射 定 义 了 规 范 。 由 于 <strong>VisiBroker</strong> <strong>Edition</strong> 遵 守 由 OMG 制订 的 规 范 , 本 手 册 中 不 包 含 关 于 语 言 映 射 的 信 息 。 如 果 您 需 要 了 解 关 于 语 言 映 射 的详 情 , 请 查 看 OMG 网 站 , 其 网 址 为 :http://www.omg.org/。: CORBA 的 正 式 规 范 可 以 在 以 下 网 址 找 到 :http://www.omg.org/corba/corbaiiop.html。有 关 详 情 , 请 参 阅 程 序 员 参 考 。关 于 IDL 的 讨 论 是 一 个 相 当 广 泛 的 话 题 。 由 于 <strong>VisiBroker</strong> <strong>Edition</strong> 遵 守 由 OMG制 订 的 规 范 , 您 可 以 访 问 OMG 网 站 , 以 获 取 关 于 IDL 的 更 详 细 信 息 。IDL 编 译 器 如 何 生 成 代 码您 使 用 接 口 定 义 语 言 (IDL) 来 定 义 客 户 程 序 可 能 要 使 用 的 对 象 接 口 。 idl2cpp 和idl2java 编 译 器 使 用 接 口 定 义 来 生 成 代 码 。有 关 idl2cpp 和 idl2java 编 译 器 的 使 用 语 法 的 详 情 , 请 参 阅 程 序 员 参 考 。使 用 IDL 11-1


查 看 Java 下 生 成 的 代 码实 例 IDL 规 范您 的 接 口 定 义 定 义 对 象 名 称 及 对 象 所 提 供 的 所 有 方 法 的 名 称 。 每 种 方 法 都 指 定 将 要被 传 递 到 本 方 法 的 参 数 、 参 数 的 类 型 、 以 及 参 数 的 输 入 / 输 出 类 型 ( 输 入 类 型 、输 出 类 型 、 或 输 入 输 出 类 型 )。 以 下 的 IDL 示 例 显 示 一 个 命 名 为 example 的 对 象 的IDL 规 范 。 该 example 对 象 仅 有 一 个 方 法 :op1。// 实 例 对 象 的 IDL 规 范interface example {long op1(in char x, out short y);};查 看 Java 下 生 成 的 代 码IDL 编 译 器 从 以 上 的 实 例 中 产 生 了 几 个 文 件 。● _exampleStub.java 是 example 对 象 的 客 户 端 存 根 代 码 。● example.java 是 example 接 口 声 明 。● exampleHelper.java 声 明 exampleHelper 类 , 该 类 为 example 接 口 定 义 有 用 的 实用 工 具 功 能 和 支 持 功 能 。● exampleHolder.java 声 明 exampleHolder 类 , 此 类 提 供 用 于 传 递 out 和 inout 参数 的 Holder。● exampleOperations.java 定 义 实 例 接 口 中 的 方 法 , 它 用 于 客 户 端 和 服 务 器 端 。 它也 可 以 与 提 供 tie 机 制 的 tie 类 一 起 工 作 。● examplePOA.java 包 含 example 对 象 的 服 务 器 端 框 架 代 码 ( 实 现 基 础 )。● examplePOATie.java 包 含 用 于 通 过 Tie 机 制 在 服 务 器 端 实 现 example 对 象 的 类 。Stub.java对 于 用 户 自 定 义 的 类 型 ,idl2java 会 产 生 一 个 存 根 类 。 这 是 一 个 在 服 务 器 端 实 例 化的 类 , 它 实 现 接 口 。Java:public class exampleStub extends com.inprise.vbroker.CORBA.portable.ObjectImplimplements example {final public static java.lang.Class _opsClass = exampleOperations.class;public java.lang.String[] ids () {. . .}public int op1 (char x, org.omg.CORBA.ShortHolder y) {. . .}11-2 <strong>VisiBroker</strong> 开 发 者 指 南


查 看 Java 下 生 成 的 代 码.java.java 文 件 是 为 每 个 IDL 接 口 生 成 的 Java 接 口 。 这 是 一 个 从IDL 接 口 定 义 到 相 应 的 Java 接 口 的 直 接 映 射 。 这 是 一 个 随 后 要 由 客 户 和 服 务 器 框架 两 者 都 要 实 现 的 接 口 。Java:public interface example extends com.inprise.vbroker.CORBA.Object,exampleOperations,org.omg.CORBA.portable.IDLEntity {}Helper.java对 于 用 户 自 定 义 的 类 型 ,idl2java 会 产 生 一 个 helper 类 。 此 helper 类 是 一 个 抽象 类 , 具 有 各 种 用 于 生 成 的 Java 接 口 的 静 态 方 法 。Java:public final class exampleHelper {public static example narrow (final org.omg.CORBA.Object obj) {. . .}public static example unchecked_narrow (org.omg.CORBA.Object obj) {. . .}public static example bind (org.omg.CORBA.ORB orb) {. . .}public static example bind (org.omg.CORBA.ORB orb, java.lang.String name) {. . .}public static example bind (org.omg.CORBA.ORB orb, java.lang.String name,java.lang.String host,com.inprise.vbroker.CORBA.BindOptions _options) {. . .}public static example bind (org.omg.CORBA.ORB orb, java.lang.StringfullPoaName,byte[] oid) {. . .}public static example bind (org.omg.CORBA.ORB orb,java.lang.String fullPoaName, byte[] oid,java.lang.String host,com.inprise.vbroker.CORBA.BindOptions _options) {. . .}public java.lang.Object read_Object (final org.omg.CORBA.portable.InputStream istream) {. . .}public void write_Object (final org.omg.CORBA.portable.OutputStream ostream,使 用 IDL 11-3


查 看 Java 下 生 成 的 代 码}final java.lang.Object obj) {. . .public java.lang.String get_id () { . . . } public org.omg.CORBA.TypeCodeget_type () { . . . } public static example read (finalorg.omg.CORBA.portable.InputStream _input) { . . . } public static voidwrite (final org.omg.CORBA.portable.OutputStream _output, finalexample value) { . . . } public static void insert (final org.omg.CORBA.Anyany, final example value) { . . . } public static example extract (finalorg.omg.CORBA.Any any) { . . . } public static org.omg.CORBA.TypeCodetype () { . . . } public static java.lang.String id () { . . . } }Holder.java对 于 用 户 自 定 义 的 类 型 , idl2java 会 产 生 一 个 holder 类 。 当 作 为 out 和 inout 参数 传 递 时 , 它 为 封 装 支 持 接 口 的 对 象 的 对 象 提 供 了 一 个 类 。Java:public final class exampleHolder implements org.omg.CORBA.portable.Streamable {public foo.example value;public exampleHolder () {}public exampleHolder (final foo.example _vis_value) {. . .}public void _read (final org.omg.CORBA.portable.InputStream input) {. . .}public void _write (final org.omg.CORBA.portable.OutputStream output) {. . .}public org.omg.CORBA.TypeCode _type () {. . .}}Operations.java对 于 用 户 自 定 义 Kind,idl2java 编 译 器 会 创 建 一 个 operations 类 , 它 包 含 IDL声 明 中 所 包 含 的 所 有 方 法 。Java:public interface exampleOperations {public int op1 (char x, org.omg.CORBA.ShortHolder y);}11-4 <strong>VisiBroker</strong> 开 发 者 指 南


查 看 Java 下 生 成 的 代 码POA.javaPOA.java 文 件 接 口 的 服 务 器 端 的 框 架 。 它 解 包 in 参 数 并 在 上 行 调用 中 把 它 们 传 递 给 对 象 实 现 , 然 后 汇 集 返 回 值 和 所 有 的 out 参 数 。Java:public abstract class examplePOA extends org.omg.PortableServer.Servantimplementsorg.omg.CORBA.portable.InvokeHandler, exampleOperations {public example _this () {. . .}public example _this (org.omg.CORBA.ORB orb) {. . .}public java.lang.String[] _all_interfaces (final org.omg.PortableServer.POApoa,. . .}public org.omg.CORBA.portable.OutputStream _invoke (java.lang.String opName,org.omg.CORBA.portable.InputStream _input,org.omg.CORBA.portable.ResponseHandler handler) {. . .}public static org.omg.CORBA.portable.OutputStream _invoke (exampleOperations_self,int _method_id, org.omg.CORBA.portable.InputStream _input,org.omg.CORBA.portable.ResponseHandler _handler) {. . .}}POATie.javaPOATie.java 文 件 是 接 口 的 代 理 实 现 。 每 个 tie类 的 实 例 都 必 须 用 一 个 实 现 类 的 实 例 初 始 化 , 此 实 现 类 实 现 它 为 之 代 理 每 项 操 作 的Operations 类 。Java:public class examplePOATie extends examplePOA {public examplePOATie (final exampleOperations _delegate) {. . .}public examplePOATie (final exampleOperations _delegate,final org.omg.PortableServer.POA _poa) {. . .}public exampleOperations _delegate () {. . .}public void _delegate (final exampleOperations delegate) {. . .}使 用 IDL 11-5


查 看 Java 下 生 成 的 代 码}}public org.omg.PortableServer.POA _default_POA () {. . .public int op1 (char x, org.omg.CORBA.ShortHolder y) {. . .}查 看 为 客 户 所 生 成 的 代 码 ( 在 C++ 下 )以 下 的 代 码 示 例 说 明 IDL 编 译 器 如 何 从 “ 实 例 IDL 规 范 ” 生 成 两 个 文 件 :example_c.hh 和 example_c.cc。 这 两 个 文 件 提 供 客 户 使 用 的 example 类 。 习 惯 上 ,由 IDL 编 译 器 生 成 的 文 件 使 用 一 个 .cc 或 .hh 后 缀 , 以 便 于 区 别 它 们 与 您 自 己 创建 的 文 件 。 当 然 , 如 果 您 乐 意 , 您 也 可 以 改 变 这 一 习 惯 , 以 产 生 带 不 同 后 缀 的 文件 。 请 参 阅 程 序 员 参 考 。小 心 : 不 要 修 改 由 IDL 编 译 器 生 成 的 文 件 的 内 容 。C++: class example : public virtual CORBA_Object {protected:example() {}example(const example&) {}public:virtual ~example() {}static const CORBA::TypeInfo *_desc();virtual const CORBA::TypeInfo *_type_info() const;virtual void *_safe_narrow(const CORBA::TypeInfo& ) const;static CORBA::Object*_factory();example_ptr _this();static example_ptr _duplicate(example_ptr _obj) { /* . . . */ }static example_ptr _nil() { /* . . . */ }static example_ptr _narrow(CORBA::Object* _obj);static example_ptr _clone(example_ptr _obj) { /* . . . */ }static example_ptr _bind(const char *_object_name = NULL,const char *_host_name = NULL,const CORBA::BindOptions* _opt = NULL,CORBA::ORB_ptr _orb = NULL);static example_ptr _bind(const char *_poa_name,const CORBA::OctetSequence& _id,const char *_host_name = NULL,const CORBA::BindOptions* _opt = NULL,CORBA::ORB_ptr _orb = NULL);virtual CORBA::Long op1(CORBA::Char _x, CORBA::Short_out _y);};编 译 器 生 成 的 方 法 ( 存 根 )以 上 的 代 码 示 例 显 示 由 IDL 编 译 器 生 成 的 op1 方 法 及 其 它 一 些 方 法 。op1 方 法 被 称为 stub , 因 为 当 您 的 客 户 程 序 调 用 它 时 , 它 实 际 上 将 接 口 请 求 和 变 量 封 包 在 一 个11-6 <strong>VisiBroker</strong> 开 发 者 指 南


查 看 Java 下 生 成 的 代 码消 息 中 , 将 这 个 消 息 送 到 对 象 实 现 , 等 待 回 答 , 对 回 答 进 行 译 码 , 然 后 将 结 果 返 回您 的 程 序 。由 于 example 类 是 从 CORBA::Object 类 派 生 的 , 所 有 几 种 继 承 的 方 法 可 供 您 使 用 。Pointer type _ptr definitionC++:IDL 编 译 器 始 终 生 成 提 供 一 个 指 针 类 型 定 义 。 以 下 的 代 码 示 例 说 明 example 类 的 类型 定 义 。typedef example *example_ptr;自 动 内 存 管 理 _var 类IDL 编 译 器 也 生 成 命 名 为 example_var 的 类 , 它 可 以 取 代 example_ptr。example_var 类 将 自 动 管 理 与 自 动 分 配 的 对 象 引 用 有 关 的 内 存 。 当 example_var 对象 被 删 除 后 , 与 example_ptr 相 关 的 对 象 被 释 放 。 当 给 example_var 对 象 分 配 一 个新 值 时 , example_ptr 所 指 向 的 旧 对 象 引 用 在 分 配 完 成 之 后 被 释 放 。 另 外 , 也 提 供了 一 个 造 型 操 作 , 它 允 许 您 分 配 一 个 example_var 给 example_ptr 类 型 。C++: class example_var : public CORBA::_var {. . .public:static example_ptr _duplicate(example_ptr);static void _release(example_ptr);example_var();example_var(example_ptr);example_var(const example_var &);~example_var();example_var& operator=(example_ptr);example_var& operator=(const example_var& _var) { /* . . . */ }operator example* () const { return _ptr; }. . .};下 表 描 述 _var 类 中 的 方 法表 11.1方 法_var 类 中 的 方 法说 明example_var() 将 _ptr 初 始 化 为 NULL 的 构 建 器 。example_var(example_ptr ptr)构 建 器 , 创 建 一 个 对 象 并 用 传 递 的 变 量 将 _ptr初 始 化 。 在 销 毁 时 , var 调 用 _ptr 上 的release()。 当 _ptr 的 引 用 数 量 达 到 0 时 , 对象 将 被 删 除 。example_var(const example_var& var) 构 建 器 , 复 制 被 作 为 参 数 var 传 递 的 对 象 , 并让 _ptr 指 向 新 复 制 的 对 象 。~example()解 构 器 , 调 用 _ptr 指 向 的 对 象 上 的_release() 一 次 。operator=(example_ptr p)赋 值 运 算 , 调 用 _ptr 指 向 的 对 象 上 的_release() , 然 后 将 p 存 储 在 _ptr 中 。使 用 IDL 11-7


查 看 为 客 户 所 生 成 的 代 码 服 务 ( 在 C++ 下 )表 11.1_var 类 中 的 方 法方 法operator=(const example_ptr p)example_ptr operator->()说 明赋 值 运 算 , 调 用 _ptr 指 向 的 对 象 上 的_release() , 然 后 将 p 的 _duplicate() 存 储在 _ptr 中 。返 回 本 对 象 上 存 储 的 _ptr。 在 正 确 地 初 始 化 本对 象 之 前 , 不 应 该 调 用 此 运 算 。查 看 为 客 户 所 生 成 的 代 码 服 务 ( 在 C++ 下 )以 下 的 代 码 示 例 说 明 IDL 编 译 器 如 何 生 成 以 下 两 个 文 件 :example_s.hh 和example_s.cc。 这 两 个 文 件 提 供 服 务 器 用 以 派 生 实 现 类 的 POA_example 类 。POA_example 类 是 从 PortableServer_ServantBase 类 派 生 的 。小 心 : 不 要 修 改 由 IDL 编 译 器 生 成 的 文 件 的 内 容 。C++: class POA_example : public virtual PortableServer_ServantBase {protected:POA_example() {}virtual ~POA_example() {}public:static const CORBA::TypeInfo _skel_info;virtual const CORBA::TypeInfo *_type_info() const;example_ptr _this();virtual void *_safe_narrow(const CORBA::TypeInfo& ) const;static POA_example * _narrow(PortableServer_ServantBase *_obj);// 需 要 实 现 以 下 的 操 作virtual CORBA::Long op1(CORBA::Char _x, CORBA::Short_out _y) = 0;// 自 动 实 现 的 框 架 操 作static void _op1(void *_obj, CORBA::MarshalInBuffer &_istrm,const char *_oper, VISReplyHandler& handler);};IDL 编 译 器 生 成 的 方 法 ( 框 架 )注 意 : 在 以 下 的 IDL 规 范 中 所 声 明 的 op1 方 法 是 与 _op1 方 法 一 起 生 成 的 。POA_example 类 声 明 一 个 命 名 为 op1 的 纯 虚 方 法 。 从 POA_example 派 生 的 实 现 类 必须 为 该 方 法 提 供 实 现 。POA_example 类 被 称 为 框 架 , 当 收 到 一 个 客 户 请 求 时 , POA 调 用 该 框 架 的 方 法(_op1)。 框 架 的 内 部 方 法 将 汇 集 请 求 的 所 有 参 数 , 调 用 您 的 op1 方 法 , 然 后 将 所有 返 回 的 参 数 或 违 例 汇 集 到 回 答 消 息 中 。 随 后 , ORB 将 把 回 答 送 到 客 户 程 序 。构 建 器 和 解 构 器 均 受 到 保 护 , 它 们 只 能 由 继 承 的 成 员 来 调 用 。 构 建 器 接 受 对 象 名 称以 便 服 务 器 可 以 将 多 个 不 同 的 对 象 实 例 化 。11-8 <strong>VisiBroker</strong> 开 发 者 指 南


在 IDL 中 定 义 接 口 属 性由 IDL 编 译 器 生 成 的 类 模 板仅 适 用 于 C++:除 了 生 成 POA_example 类 之 外 , IDL 编 译 器 还 生 成 了 一 个 命 名 为 _tie_example 的类 模 板 。 如 果 您 不 愿 意 从 POA_example 派 生 一 个 类 , 则 可 以 使 用 此 模 板 。 模 板 很 有用 , 它 们 可 以 为 不 能 通 过 修 改 来 继 承 一 个 新 类 的 现 有 应 用 提 供 wrapper ( 封 装 )类 。 以 下 的 代 码 示 例 示 范 由 IDL 编 译 器 为 example 类 生 成 的 模 板 类 。:template class POA_example_tie :public POA_example {public:POA_example_tie (T& t):_ptr(&t), _poa(NULL), _rel((CORBA::Boolean)0) {}POA_example_tie (T& t, PortableServer::POA_ptr poa):_ptr(&t),_poa(PortableServer::_duplicate(poa)), _rel((CORBA::Boolean)0) {}POA_example_tie (T *p, CORBA::Boolean release= 1): _ptr(p),_poa(NULL), _rel(release) {}POA_example_tie (T *p, PortableServer::POA_ptr poa, CORBA::Boolean release =1): _ptr(p), _poa(PortableServer::_duplicate(poa)), _rel(release) {}virtual ~POA_example_tie() { /* . . . */ }T* _tied_object() { /* . . . */ }void _tied_object(T& t) { /* . . . */ }void _tied_object(T *p, CORBA::Boolean release=1) { /* . . . */ }CORBA::Boolean _is_owner() { /* . . . */ }void _is_owner(CORBA::Boolean b) { /* . . . */ }CORBA::Long op1(CORBA::Char _x, CORBA::Short_out _y) { /* . . . */ }PortableServer::POA_ptr _default_POA() { /* . . . */ }};有 关 使 用 _tie 模 板 类 的 详 情 , 请 参 阅 “ 使 用 tie 机 制 。”您 也 可 以 生 成 一 个 _ptie 模 板 , 以 便 将 对 象 库 集 成 在 您 的 服 务 器 上 。在 IDL 中 定 义 接 口 属 性除 了 定 义 操 作 之 外 , 接 口 规 范 也 可 以 定 义 属 性 作 为 接 口 的 一 部 分 。 在 默 认 情 况 下 ,所 有 的 属 性 都 是 读 写 型 , IDL 编 译 器 将 生 成 两 种 方 法 : 其 中 一 是 设 定 属 性 的 值 ,另 外 一 个 是 取 得 属 性 的 值 。 您 也 可 以 指 定 只 读 属 性 , 仅 为 此 类 属 性 生 成 reader方 法 。以 下 的 IDL 示 例 说 明 定 义 两 种 属 性 的 IDL 规 范 : 一 种 是 读 写 , 一 种 是 只 读 。interface Test {attribute long count;readonly attribute string name;};以 下 的 代 码 示 例 说 明 为 IDL 中 声 明 的 接 口 所 生 成 的 操 作 类 。C++: class test :public virtual CORBA::Object {...// 读 写 属 性 的 方 法virtual CORBA::Long count();virtual void count(CORBA::Long __count);使 用 IDL 11-9


指 定 无 返 回 值 的 oneway 方 法// 只 读 属 性 的 方 法 。virtual char * name();...};Java: public interface TestOperations {public int count ();public void count (int count);public java.lang.String name ();}指 定 无 返 回 值 的 oneway 方 法IDL 允 许 您 指 定 无 返 回 值 的 操 作 , 称 做 oneway 方 法 。 这 些 操 作 仅 可 以 有 输 入 参数 。 当 调 用 一 个 oneway 方 法 时 , 一 个 请 求 会 被 送 到 服 务 器 , 但 是 , 实 际 接 收 请 求的 对 象 实 现 不 作 任 何 确 认 。 <strong>VisiBroker</strong> <strong>Edition</strong> 使 用 TCP/IP 将 客 户 连 接 到 服 务器 。 这 可 以 确 保 将 所 有 的 数 据 包 可 靠 地 传 递 到 客 户 , 以 便 客 户 可 以 确 定 : 只 要 服 务器 可 用 , 请 求 就 一 定 会 被 传 递 给 客 户 。 不 过 , 客 户 仍 然 无 法 知 道 对 象 实 现 是 否 对 请求 作 了 处 理 。注 : Oneway 操 作 不 可 能 掷 出 违 例 或 返 回 值 。interface oneway_example {oneway void set_value(in long val);};在 IDL 中 指 定 一 个 从 另 一 个 接 口 继 承 而 来 的 接 口IDL 允 许 您 指 定 一 个 从 另 外 一 个 接 口 继 承 而 来 的 接 口 。 由 IDL 编 译 器 生 成 的 类 将反 映 继 承 关 系 。 由 父 接 口 所 声 明 的 所 有 方 法 、 数 据 类 型 定 义 、 常 量 和 枚 举 量 对 派 生的 接 口 都 是 可 见 的 。interface parent {void operation1();};interface child :parent {. . .long operation2(in short s);};以 下 的 代 码 示 例 说 明 从 以 下 所 示 的 接 口 规 范 而 生 成 的 C++ 和 Java 代 码 。...class parent :public virtual CORBA::Object {...void operation1( );...};class child :public virtual parent {11-10 <strong>VisiBroker</strong> 开 发 者 指 南


在 IDL 中 指 定 一 个 从 另 一 个 接 口 继 承 而 来 的 接 口Java:...CORBA::Long operation2(CORBA::Short s);...};public interface parentOperations { public void operation1 (); } publicinterface childOperations extends parentOperations { public intoperation2 (short s); } public interface parent extendscom.inprise.vbroker.CORBA.Object, parentOperations,org.omg.CORBA.portable.IDLEntity { } public interface child extendschildOperations, Baz.parent, org.omg.CORBA.portable.IDLEntity { }使 用 IDL 11-11


11-12 <strong>VisiBroker</strong> 开 发 者 指 南


第章使 用 智 能 代 理第 12 章本 节 介 绍 智 能 代 理 (osagent), 在 寻 找 对 象 实 现 时 客 户 端 程 序 要 向 智 能 代 理 注 册 。本 节 介 绍 如 何 配 置 自 己 的 <strong>VisiBroker</strong> ORB 域 、 如 何 在 不 同 的 局 域 网 上 连 接 智 能 代理 以 及 如 何 将 对 象 从 一 台 主 机 移 植 到 另 一 台 主 机 。什 么 是 智 能 代 理 ?<strong>VisiBroker</strong> <strong>Edition</strong> 的 智 能 代 理 (osagent) 是 动 态 分 布 式 目 录 服 务 , 它 提 供 客 户 端程 序 和 对 象 实 现 所 使 用 的 工 具 。 智 能 代 理 必 须 在 局 域 网 中 的 至 少 一 台 主 机 上 启 动 。客 户 端 程 序 调 用 某 个 对 象 上 的 bind() 时 , 会 自 动 咨 询 智 能 代 理 。 智 能 代 理 定 位 指定 的 实 现 , 这 样 在 客 户 端 和 实 现 之 间 就 可 以 建 立 连 接 。 对 于 客 户 端 程 序 来 说 , 与 智能 代 理 之 间 的 通 讯 是 完 全 透 明 的 。如 果 在 POA 上 设 置 的 是 PERSISTENT 策 略 且 使 用 activate_object_with_id,则 智 能 代 理 会 注 册 对 象 或 实 现 , 这 样 客 户 端 程 序 就 可 以 使 用 该 对 象 或 实 现 。 对 象 实现 被 去 激 活 后 , 智 能 代 理 会 将 其 从 可 用 对 象 清 单 中 删 除 。 同 客 户 端 程 序 一 样 , 对 于对 象 实 现 来 说 , 与 智 能 代 理 之 间 的 通 讯 是 完 全 透 明 的 。定 位 智 能 代 理注 :<strong>VisiBroker</strong> <strong>Edition</strong> 通 过 广 播 消 息 定 位 智 能 代 理 , 供 客 户 端 程 序 或 对 象 程 序 使 用 。第 一 个 响 应 的 智 能 代 理 就 是 要 使 用 的 智 能 代 理 。 定 位 智 能 代 理 后 , 就 使 用 点 对 点UDP 连 接 向 智 能 代 理 发 出 注 册 和 查 找 请 求 。 这 里 使 用 UDP 协 议 , 因 为 它 消 费 的网 络 资 源 比 TCP 连 接 要 少 。 所 有 注 册 和 定 位 请 求 都 是 动 态 的 , 因 此 不 存 在 需 要 维护 的 配 置 文 件 或 映 射 。广 播 消 息 仅 用 于 定 位 智 能 代 理 。 与 智 能 代 理 之 间 的 所 有 其 它 通 讯 都 使 用 点 对 点 通讯 。 有 关 如 何 忽 略 广 播 消 息 的 信 息 , 请 参 阅 第 12-7 页 " 使 用 点 对 点 通 讯 "。使 用 智 能 代 理 12-1


什 么 是 智 能 代 理 ?由 智 能 代 理 协 作 定 位 对 象局 域 网 中 多 台 主 机 都 启 动 智 能 代 理 时 , 每 个 智 能 代 理 识 别 一 个 可 用 对 象 子 集 并 与 其它 智 能 代 理 通 讯 来 定 位 自 己 找 不 到 的 对 象 。 如 果 其 中 一 个 智 能 代 理 过 程 意 外 终 止 ,所 有 注 册 到 该 智 能 代 理 的 实 现 会 发 现 这 一 事 件 并 自 己 自 动 重 新 向 另 一 个 可 用 的 智 能代 理 注 册 。与 OAD 协 作 连 接 对 象对 象 实 现 可 以 在 OAD 注 册 上 , 这 样 就 可 以 根 据 需 要 启 动 。 这 些 对 象 向 智 能 代 理 注册 时 , 就 象 自 己 实 际 上 处 于 激 活 状 态 并 位 于 OAD 内 。 客 户 端 申 请 这 些 对 象 中 的 任一 对 象 时 , 会 被 指 向 OAD。 然 后 OAD 将 客 户 请 求 前 转 到 真 正 的 ( 可 能 是 新 的 )新 建 服 务 器 。 智 能 代 理 不 知 道 OAD 中 真 正 的 对 象 实 现 实 际 上 并 未 激 活 。启 动 智 能 代 理 (osagent)在 局 域 网 中 必 须 至 少 有 一 个 智 能 代 理 在 一 台 主 机 运 行 。 局 域 网 是 指 广 播 消 息 可 以 送达 的 范 围 内 的 子 网 。要 在 Windows 下 启 动 智 能 代 理 , 请 在 <strong>VisiBroker</strong> <strong>Edition</strong> 程 序 组 中 选 择 其 图标 , 或 在 DOS Prompt 下 输 入 以 下 命 令 :WinNT: Prompt> osagent [ 选 项 ]要 在 UNIX 系 统 上 启 动 智 能 代 理 , 请 输 入 以 下 命 令 。UNIX:Prompt> osagent &oasgent 命 令 接 受 以 下 命 令 行 参 数 :选 项说 明-p UDP_port 覆 盖 OSAGENT_PORT 设 置 和 注 册 表 设 置 。-v 打 开 冗 余 模 式 , 该 模 式 在 执 行 期 间 提 供 信 息 和诊 断 消 息 。-help 或 -? 打 印 帮 助 信 息 。-n, -N 禁 用 Windows 系 统 图 标 盒 中 的 图 标 。以 下 osagent 命 令 实 例 指 定 一 个 特 定 UDP 端 口 :实 例 : osagent -p 17000详 细 输 出UNIX:WinNT:在 UNIX 平 台 上 , 详 细 输 出 发 送 到 stdout。在 Windows 系 统 中 , 详 细 输 出 写 入 位 于 < 安 装 _ 位 置 >\log\osagent.log 或VBROKER_ADM 环 境 变 量 所 指 定 的 目 录 内 的 日 志 文 件 中 , 或 者 使 用 OSAGENT_LOG_DIR指 定 一 个 不 同 的 目 录 来 存 放 日 志 。12-2 <strong>VisiBroker</strong> 开 发 者 指 南


<strong>VisiBroker</strong> ORB 域 内 工 作在 Windows NT 下 可 以 将 智 能 代 理 安 装 为 NT 服 务 ( 在 安 装 期 间 选 择 这 种 安 装方 式 ), 这 样 您 就 可 以 使 用 Windows NT 提 供 的 “ 服 务 管 理 ” 对 其 进 行 管 理 。 也可 以 输 入 以 下 命 令 在 DOS Prompt 下 以 控 制 台 模 式 启 动 智 能 代 理 :Prompt> osagent禁 用 代 理 程 序C++:Java:通 过 在 运 行 时 将 属 性 传 递 给 <strong>VisiBroker</strong> ORB 可 以 禁 用 智 能 代 理 :Prompt> Server -Dvbroker.agent.enableLocator=falsePrompt> vbj -Dvbroker.agent.enableLocator=false如 果 使 用 字 符 串 到 对 象 引 用 ( 一 种 命 名 服 务 ), 或 者 传 入 URL 引 用 , 则 不 需 要 智能 代 理 , 可 以 禁 用 。 如 果 将 对 象 名 称 传 入 bind 方 法 , 则 必 须 使 用 智 能 代 理 。保 证 智 能 代 理 的 可 用 性在 局 域 网 中 多 个 台 主 机 上 启 动 智 能 代 理 可 以 使 客 户 端 即 使 在 其 中 一 个 智 能 代 理 意 外终 止 时 也 会 继 续 限 制 对 象 。 如 果 智 能 代 理 不 可 用 , 在 该 智 能 代 理 注 册 的 所 有 对 象 实现 会 自 动 重 新 向 另 一 个 智 能 代 理 注 册 。 如 果 局 域 网 中 没 有 智 能 代 理 运 行 , 则 对 象 实现 会 不 断 地 请 求 注 册 , 直 到 联 系 到 新 的 智 能 代 理 。如 果 某 智 能 代 理 终 止 , 则 在 该 智 能 代 理 终 止 前 建 立 的 任 何 客 户 端 和 对 象 实 现 之 间 的连 接 都 会 继 续 保 持 , 不 会 中 断 。 但 是 , 如 果 某 客 户 端 发 出 任 何 新 bind() 请 求 , 就需 要 联 系 新 的 智 能 代 理 。利 用 这 些 容 错 功 能 不 需 要 任 何 特 殊 的 编 码 技 术 。 只 需 保 证 在 局 域 网 上 的 一 台 或 多 台主 机 上 启 动 智 能 代 理 。检 查 客 户 端 是 否 存 在注 :智 能 代 理 每 隔 两 分 钟 向 其 客 户 端 发 送 一 则 “Are You Alive” 消 息 ( 通 常 称 为“ 心 跳 ” 消 息 ), 以 查 证 客 户 端 是 否 仍 处 于 连 接 状 态 。 如 果 客 户 端 没 有 响 应 , 则 智能 代 理 会 认 为 客 户 端 连 接 已 终 止 。您 可 以 更 改 轮 询 客 户 端 的 时 间 间 隔 。这 里 所 使 用 的 “ 客 户 端 ” 一 词 不 一 定 描 述 对 象 或 进 程 的 功 能 。 连 接 到 智 能 代 理 进 行对 象 引 用 的 任 何 程 序 都 是 客 户 端 。<strong>VisiBroker</strong> ORB 域 内 工 作我 们 通 常 希 望 有 两 个 或 两 个 以 上 单 独 的 <strong>VisiBroker</strong> ORB 域 同 时 运 行 。 一 个 域 可 以用 于 客 户 端 程 序 和 对 象 实 现 的 出 厂 版 本 , 另 一 个 域 可 以 用 于 同 一 客 户 端 和 对 象 的 没有 投 入 正 常 使 用 的 测 试 版 。 如 果 几 个 开 发 者 同 时 在 同 一 局 域 网 上 工 作 , 则 每 名 开 发者 都 希 望 建 立 自 己 的 <strong>VisiBroker</strong> ORB 域 , 这 样 他 们 的 测 试 工 作 就 不 会 相 互 之 间 发生 冲 突 。使 用 智 能 代 理 12-3


在 不 同 局 域 网 中 连 接 智 能 代 理图 12.1同 时 运 行 单 独 的 <strong>VisiBroker</strong> ORB 域Windows:<strong>VisiBroker</strong> <strong>Edition</strong> 允 许 为 每 个 域 中 的 智 能 代 理 指 定 唯 一 的 UDP 端 口 号 , 从 而 区分 同 一 网 络 中 的 多 个 <strong>VisiBroker</strong> ORB 域 。 根 据 默 认 值 , OSAGENT_PORT 变 更 设 置为 14000。 如 果 要 使 用 不 同 的 端 口 号 , 请 向 系 统 管 理 器 咨 询 , 以 确 定 可 用 的 端 口号 。 要 覆 盖 默 认 设 置 , 在 运 行 智 能 代 理 、OAD、 对 象 实 现 或 分 配 到 该 <strong>VisiBroker</strong>ORB 域 的 客 户 程 序 之 前 必 须 相 应 设 置 OSAGENT_PORT。Prompt> setenv OSAGENT_PORT 5678Prompt> osagent &Prompt> oad &智 能 代 理 还 在 内 部 使 用 另 一 个 端 口 号 。 该 端 口 号 可 以 通 过OSAGENT_CLIENT_HANDLER_PORT 环 境 变 量 设 置 。 该 端 口 号 用 于 TCP 和 UDP 协 议 且对 两 者 都 一 样 。设 置 OSAGENT_PORT 环 境 变 量 会 覆 盖 Windows 注 册 表 设 置 或 通 过 vregedit.exe 实用 程 序 ( 位 于 <strong>VisiBroker</strong> <strong>Edition</strong> 的 bin 目 录 下 ) 设 置 的 设 置在 不 同 局 域 网 中 连 接 智 能 代 理如 果 在 局 域 网 上 启 动 多 个 智 能 代 理 , 这 些 智 能 代 理 会 通 过 UDP 广 播 消 息 发 现 对方 。 网 络 管 理 器 可 以 通 过 使 用 IP 子 网 掩 码 指 定 广 播 消 息 的 范 围 来 配 置 局 域 网 。 下图 为 网 络 链 接 连 接 的 两 个 局 域 网 。图 12.2分 别 两 个 局 域 网 上 的 两 个 智 能 代 理要 允 许 一 个 网 络 中 的 智 能 代 理 与 另 一 个 局 域 网 中 的 智 能 代 理 通 讯 , 必 须 在 名 为agentaddr 的 文 件 中 列 出 远 程 智 能 代 理 的 IP 地 址 。 只 有 在 两 个 智 能 代 理 无 法 通 过12-4 <strong>VisiBroker</strong> 开 发 者 指 南


与 多 Home 主 机 配 合 工 作注 :UDP 广 播 消 息 相 互 检 测 到 对 方 时 才 这 样 做 。 以 下 代 码 示 例 显 示 要 允 许 局 域 网 #1 中的 智 能 代 理 连 接 到 另 一 个 网 络 中 的 智 能 代 理 该 文 件 中 应 该 包 含 的 内 容 。 该 文 件 的 路径 由 智 能 代 理 进 程 中 的 VBROKER_ADM 环 境 变 量 指 定 。 您 可 以 通 过 设 置OSAGENT_ADDR_FILE 环 境 变 量 该 文 件 名 称 。101.10.2.6通 过 相 应 的 agentaddr 文 件 , 网 络 #1 中 的 客 户 端 程 序 可 以 定 位 并 使 用 网 络 #2 上 的对 象 实 现 。 有 关 环 境 变 量 的 详 情 , 请 参 阅 第 3 章 " 建 立 您 的 环 境 "。如 果 远 程 网 络 上 有 多 个 智 能 代 理 运 行 , 则 应 该 列 出 远 程 网 络 上 所 有 智 能 代 理 的 IP地 址 。智 能 代 理 如 何 相 互 检 测假 设 两 个 代 理 程 序 Agent 1 和 Agent 2 从 同 一 子 网 中 的 两 台 不 同 计 算 机 监 听 同 一UDP 端 口 。 Agent 1 在 Agent 2 之 前 启 动 , 则 会 发 生 以 下 事 件 :● Agent 2 启 动 时 , 它 通 过 UDP 宣 布 自 己 的 存 在 并 发 出 请 求 信 息 来 定 位 任 何 其 它智 能 代 理 。● Agent 1 记 录 Agent 2 在 网 络 上 可 用 , 并 响 应 请 求 信 息 。● Agent 2 记 录 另 一 个 代 理 程 序 Agent 1 在 网 络 上 可 用 。如 果 Agent 2 正 常 终 止 ( 例 如 通 过 Ctrl+C 终 止 ), Agent 1 会 知 道 Agent 2 不再 可 用 。如 果 Agent 2 异 常 终 止 ( 例 如 通 过 “ 任 务 管 理 器 ” 窗 口 终 止 Agent 2),Agent 1 不 会 知 道 Agent 2 不 再 可 用 ( 代 理 程 序 之 间 没 有 定 期 的 心 跳 信 息 )。Agent 1 会 保 持 现 状 , 直 到 客 户 端 发 出 Agent 1 的 字 典 中 没 有 的 对 象 引 用 请 求 。Agent 1 会 将 请 求 前 转 给 Agent 2。 由 于 Agent 2 不 再 可 用 ,Agent 1 被 迫 清 除 。在 Agent 1 被 迫 清 除 之 前 , osfind 仍 显 示 有 两 个 代 理 程 序 并 捕 获ObjLocation::Fail 违 例 。与 多 Home 主 机 配 合 工 作在 具 有 多 个 IP 地 址 的 主 机 上 启 动 智 能 代 理 时 ( 称 为 “ 多 Home 主 机 ”), 它 可 以为 桥 接 各 个 局 域 网 中 的 对 象 提 供 强 大 的 机 制 。 主 机 连 接 的 所 有 局 域 网 都 可 以 与 一 个智 能 代 理 通 讯 , 从 而 有 效 地 桥 接 局 域 网 。使 用 智 能 代 理 12-5


与 多 Home 主 机 配 合 工 作图 12.3多 Home 主 机 上 的 智 能 代 理UNIX:Windows:在 多 Home UNIX 主 机 上 , 智 能 代 理 动 态 自 我 配 置 对 支 持 点 对 点 连 接 或 广 播 连 接的 所 有 主 机 接 口 监 听 并 广 播 。 您 可 以 使 用 localaddr 文 件 明 确 指 定 接 口 设 置 ( 如 以下 第 12-6 页 " 指 定 智 能 代 理 的 接 口 使 用 " 中 所 述 )。在 多 Home Windows 主 机 上 , 智 能 代 理 无 法 动 态 确 定 正 确 的 子 网 掩 码 并 广 播 地址 值 。 要 突 破 这 一 限 制 , 必 须 使 用 localaddr 文 件 明 确 指 定 希 望 智 能 代 理 使 用 的 接口 设 置 。使 用 -v (verbose [ 冗 余 ]) 选 项 启 动 智 能 代 理 时 , 智 能 代 理 所 使 用 的 每 个 接 口 会列 于 所 产 生 消 息 的 开 始 位 置 。 以 下 代 码 示 例 显 示 从 多 Home 主 机 上 使 用 verbose( 冗 余 ) 选 项 启 动 的 智 能 代 理 的 实 例 输 出 。Bound to the following interfaces:Address:199.10.9.5 Subnet:255.255.255.0 Broadcast:199.10.9.255Address:101.10.2.6 Subnet:255.255.255.0 Broadcast:101.10.2.255...如 上 所 示 , 输 出 显 示 出 计 算 机 上 每 个 接 口 的 地 址 、 子 网 掩 码 和 广 播 地 址 。 对 于UNIX, 该 输 出 应 该 与 从 UNIX 命 令 ifconfig -a 产 生 的 结 果 一 致 。如 果 您 要 覆 盖 这 些 设 置 , 您 可 以 在 localaddr 文 件 中 指 定 该 接 口 信 息 。 有 关 详 情 ,请 参 阅 第 12-6 页 " 指 定 智 能 代 理 的 接 口 使 用 "。指 定 智 能 代 理 的 接 口 使 用注 : 没 有 必 要 指 定 单 Home 主 机 上 的 接 口 信 息 。您 可 以 在 多 Home 主 机 的 localaddr 文 件 中 指 定 希 望 智 能 代 理 使 用 的 每 个 接 口 的接 口 信 息 。 每 个 接 口 在 localaddr 文 件 中 单 独 占 用 一 行 , 每 行 内 包 含 主 机 的 IP 地址 、 子 网 掩 码 和 广 播 地 址 。 根 据 默 认 值 ,<strong>VisiBroker</strong> <strong>Edition</strong> 会 在 VBROKER_ADM 目录 中 搜 索 localaddr 文 件 。 您 可 以 通 过 设 置 OSAGENT_LOCAL_FILE 环 境 变 量 指 向 该文 件 来 覆 盖 该 位 置 。 该 文 件 中 以 “#” 字 符 开 始 的 行 均 视 为 注 释 , 可 以 忽 略 。 以 下代 码 示 例 显 示 以 上 所 列 多 Home 主 机 的 localaddr 文 件 的 内 容 。UNIX:#entries of format 199.10.9.5 255.255.255.0 199.10.9.255101.10.2.6 255.255.255.0 101.10.2.255尽 管 智 能 代 理 可 以 自 动 在 运 行 UNIX 的 多 Home 主 机 上 自 我 配 置 , 但 是 您 可 以 使用 localaddr 文 件 明 确 指 定 自 己 主 机 所 包 含 的 接 口 。 通 过 以 下 命 令 可 以 显 示 自 己UNIX 主 机 所 有 可 用 接 口 的 值 :Prompt> ifconfig -a12-6 <strong>VisiBroker</strong> 开 发 者 指 南


使 用 点 对 点 通 讯Windows:该 命 令 的 输 出 类 似 于 以 下 所 示 内 容 :lo0:flags=849 mtu 8232inet 127.0.0.1 netmask ff000000le0:flags=863 mtu 1500inet 199.10.9.5 netmask ffffff00 broadcast 199.10.9.255le1:flags=863 mtu 1500inet 101.10.2.6 netmask ffffff00 broadcast 101.10.2.255在 运 行 Windows 的 多 Home 主 机 上 需 要 使 用 localaddr 文 件 , 因 为 智 能 代 理 无法 自 动 自 我 配 置 。 从 “ 网 络 控 制 面 板 ” 进 入 TCP/IP 协 议 属 性 可 以 获 得 该 文 件 的相 应 值 。 如 果 主 机 运 行 Windows NT, ipconfig 命 令 可 以 提 供 所 需 的 值 。 该 命 令运 行 方 法 如 下 :Prompt>ipconfig该 命 令 的 输 出 类 似 于 以 下 所 示 内 容 :Ethernet adapter El59x1:IP Address. . . . . . . . . : 199.10.9.5Subnet Mask . . . . . . . . : 255.255.255.0Default Gateway . . . . . . : 199.10.9.1Ethernet adapter Elnk32:IP Address. . . . . . . . . : 101.10.2.6Subnet Mask . . . . . . . . : 255.255.255.0Default Gateway . . . . . . : 101.10.2.1使 用 点 对 点 通 讯<strong>VisiBroker</strong> <strong>Edition</strong> 为 您 提 供 三 种 不 同 的 机 制 , 可 以 用 于 定 位 智 能 代 理 进 程 而 不使 用 UDP 广 播 消 息 。 如 果 某 个 智 能 代 理 是 使 用 这 些 替 代 方 法 中 的 任 何 一 种 定 位的 , 那 么 其 后 所 有 的 互 动 都 将 使 用 该 智 能 代 理 。 如 果 使 用 这 些 替 代 方 法 的 任 何 一 种都 无 法 定 位 某 个 智 能 代 理 , 那 么 <strong>VisiBroker</strong> ORB 会 反 过 来 使 用 广 播 消 息 方 案 定 位智 能 代 理 。指 定 主 机 为 运 行 参 数C++:Java:以 下 代 码 示 例 显 示 如 何 指 定 正 在 运 行 智 能 代 理 的 IP 地 址 为 客 户 端 程 序 或 对 象 实 现的 运 行 参 数 。 由 于 指 定 IP 地 址 后 会 建 立 点 对 点 连 接 , 因 此 , 您 甚 至 可 以 指 定 自 己局 域 网 之 外 的 主 机 的 IP 地 址 。 该 机 制 高 于 任 何 其 它 主 机 规 范 。Prompt > Server -Dvbroker.agent.addr=Prompt > vbj -Dvbroker.agent.addr= Server您 也 可 以 通 过 属 性 文 件 指 定 IP 地 址 。 找 到 vbroker.agent.addr 项 目 。vbroker.agent.addr=根 据 默 认 值 , 属 性 文 件 中 的 vbroker.agent.addr 设 置 为 NULL。也 可 以 列 出 可 能 驻 留 有 代 理 程 序 的 主 机 名 称 , 然 后 使 用 属 性 文 件 中 的vbroker.agent.addrFile 选 项 指 向 该 文 件 。使 用 智 能 代 理 12-7


保 证 对 象 可 用 性通 过 环 境 变 量 指 定 IP 地 址您 可 以 通 过 在 启 动 客 户 端 程 序 或 对 象 实 现 之 前 设 置 OSAGENT_ADDR 环 境 变 量 指 定 智能 代 理 的 IP 地 址 。 如 果 主 机 未 被 指 定 为 运 行 参 数 , 该 环 境 变 量 优 先 。UNIX: Prompt> setenv OSAGENT_ADDR 199.10.9.5Prompt> clientWindows: 要 在 Windows NT 系 统 中 设 置 OSAGENT_ADDR 环 境 变 量 , 您 可 以 进 入 “ 系 统 控 制面 板 ” 并 编 辑 环 境 变 量 :1 在 “ 系 统 变 量 ” 下 , 选 择 任 何 当 前 变 量 。2 在 “ 变 量 ” 编 辑 框 内 键 入 OSAGENT_ADDR。3 在 “ 值 ” 编 辑 框 内 键 入 IP 地 址 。 例 如 199.10.9.5。通 过 agentaddr 文 件 指 定 主 机客 户 端 程 序 或 对 象 实 现 可 以 使 用 agentaddr 文 件 ( 如 第 12-4 页 " 在 不 同 局 域 网 中连 接 智 能 代 理 " 定 位 智 能 代 理 , 而 不 使 用 UDP 广 播 消 息 。 只 需 创 建 一 个 文 件 , 其中 包 含 IP 地 址 或 完 全 符 合 规 范 的 每 个 运 行 智 能 代 理 主 机 的 主 机 名 称 , 然 后 设 置OSAGENT_ADDR_FILE 环 境 变 量 指 向 文 件 的 路 径 。 客 户 端 程 序 或 对 象 实 现 得 到 该 环 境变 量 组 时 , <strong>VisiBroker</strong> ORB 会 尝 试 使 用 文 件 中 的 每 个 地 址 , 直 到 找 到 智 能 代 理 。该 机 制 在 所 有 指 定 主 机 的 机 制 中 优 先 级 最 低 。 如 果 未 指 定 该 文 件 , 则 会 使 用VBROKER_ADM/agentaddr 文 件 。保 证 对 象 可 用 性您 可 以 通 过 在 多 个 主 机 上 启 动 这 些 对 象 的 实 例 为 对 象 提 供 容 错 能 力 。 如 果 实 现 不 可用 , <strong>VisiBroker</strong> ORB 会 检 测 到 客 户 端 程 序 和 对 象 实 现 之 间 的 连 接 中 断 并 自 动 联 系智 能 代 理 , 以 便 与 其 它 对 象 实 现 实 例 建 立 连 接 ( 这 取 决 于 客 户 端 所 建 立 的 再 限 制 策略 的 有 效 性 )。 有 关 建 立 客 户 端 策 略 的 详 细 信 息 , 请 参 阅 第 10-8 页 " 使 用 服 务 质 量 "。注 意 : 如 果 <strong>VisiBroker</strong> ORB 要 尝 试 重 新 连 接 客 户 端 和 复 本 对 象 实 现 , 必 须 启 用 再限 制 选 项 。 这 是 默 认 值 选 项 。调 用 无 状 态 对 象 方 法客 户 端 可 以 调 用 无 状 态 对 象 实 现 上 的 方 法 , 而 无 需 考 虑 对 象 的 新 实 例 是 否 正 在使 用 。为 有 状 态 对 象 实 现 容 错 能 力有 状 态 对 象 实 现 也 可 以 实 现 容 错 能 力 , 但 是 这 种 容 错 对 客 户 端 程 序 是 不 透 明 的 。 在这 些 情 况 下 , 客 户 端 程 序 必 须 使 用 服 务 质 量 (QoS) 策 略 VB_NOTIFY_REBIND 或 为12-8 <strong>VisiBroker</strong> 开 发 者 指 南


在 主 机 之 间 移 植 对 象<strong>VisiBroker</strong> ORB 对 象 注 册 一 个 接 收 器 。 有 关 使 用 QoS 的 信 息 , 请 参 阅 第 10-8 页" 使 用 服 务 质 量 "。与 对 象 实 现 的 连 接 中 断 且 <strong>VisiBroker</strong> ORB 将 客 户 端 重 新 连 接 到 复 本 对 象 实 现 时 ,<strong>VisiBroker</strong> ORB 会 调 用 bind 接 收 器 的 bind 方 法 。 客 户 端 必 须 提 供 该 bind 方 法的 实 现 , 才 能 使 复 本 的 状 态 保 持 在 最 新 状 态 。 接 收 器 在 第 21 章 " 使 用 4.x 接 收 器 "中 介 绍 。复 制 在 OAD 注 册 上 的 对 象注 :OAD 可 保 证 对 象 具 有 更 高 的 可 用 性 , 因 为 如 果 对 象 关 闭 , OAD 会 重 新 启 动 对象 。 如 果 您 要 在 主 机 不 可 用 的 情 况 下 实 现 容 错 能 力 , 则 必 须 在 多 台 主 机 上 启 动OAD, 而 且 对 象 必 须 向 每 个 OAD 实 例 注 册 。<strong>VisiBroker</strong> <strong>Edition</strong> 提 供 的 对 象 复 制 类 型 不 提 供 多 播 和 镜 像 工 具 。 在 任 何 指 定 时刻 客 户 端 和 特 定 对 象 实 现 之 间 始 终 有 一 种 一 一 对 应 关 系 。在 主 机 之 间 移 植 对 象注 :对 象 移 植 是 在 一 台 主 机 上 终 止 对 象 实 现 然 后 在 另 一 台 主 机 上 启 动 对 象 实 现 的 过 程 。对 象 移 植 可 用 于 提 供 负 载 平 衡 , 它 可 以 将 对 象 从 过 载 主 机 移 动 到 资 源 更 多 或 处 理 能力 更 强 的 主 机 ( 向 不 同 osagents 注 册 的 服 务 器 之 间 不 存 在 负 载 平 衡 )。 对 象 移 植也 可 用 于 在 主 机 不 得 不 关 闭 进 行 硬 件 或 软 件 维 护 时 保 持 对 象 的 可 用 性 。无 状 态 对 象 的 移 植 对 客 户 端 程 序 是 透 明 的 。 如 果 客 户 端 连 接 到 已 经 移 植 的 对 象实 现 , 则 智 能 代 理 会 检 测 到 连 接 中 断 , 并 透 明 地 将 客 户 端 重 新 连 接 到 新 主 机 的新 对 象 。移 植 有 状 态 对 象虽 然 有 状 态 对 象 也 可 以 移 植 , 但 是 这 种 移 植 对 在 移 植 进 程 开 始 之 前 连 接 的 客 户 端 程序 是 不 透 明 的 。 在 这 些 情 况 下 , 客 户 端 程 序 必 须 为 对 象 注 册 接 收 器 。C++: 与 原 始 对 象 的 连 接 中 断 且 <strong>VisiBroker</strong> ORB 将 客 户 端 重 新 连 接 到 对 象 时 ,<strong>VisiBroker</strong> ORB 会 调 用 接 收 器 的 rebind_succeeded() 方 法 。 客 户 端 可 以 实 现 该 方法 , 使 对 象 的 状 态 处 于 最 新 状 态 。Java: 与 原 始 对 象 的 连 接 中 断 且 <strong>VisiBroker</strong> ORB 将 客 户 端 重 新 连 接 到 对 象 时 ,<strong>VisiBroker</strong> ORB 会 调 用 接 收 器 的 rebind_succeeded() 成 员 函 数 。 客 户 端 可 以 实 现该 成 员 函 数 , 使 对 象 的 状 态 处 于 最 新 状 态 。有 关 如 何 使 用 接 收 器 的 详 细 信 息 , 请 参 阅 第 20 章 " 使 用 可 移 植 接 收 器 "。移 植 实 例 化 对 象如 果 要 移 植 的 对 象 由 实 例 化 实 现 类 的 服 务 器 进 程 创 建 , 则 只 需 在 新 主 机 上 启 动 该 对象 并 终 止 服 务 器 进 程 。 原 始 实 例 被 终 止 时 , 将 向 智 能 代 理 反 注 册 。 新 实 例 在 新 主 机使 用 智 能 代 理 12-9


报 告 所 有 对 象 和 服 务上 启 动 时 , 该 实 例 将 向 智 能 代 理 注 册 。 从 此 时 起 , 客 户 端 调 用 请 求 即 路 由 到 新 主 机上 的 对 象 实 现 。移 植 在 OAD 注 册 上 的 对 象如 果 要 移 植 的 <strong>VisiBroker</strong> ORB 对 象 已 经 注 册 到 OAD, 必 须 将 其 向 旧 主 机 OAD反 注 册 。 然 后 , 将 其 注 册 到 新 主 机 的 OAD。 具 体 步 骤 如 下 :1 从 旧 主 机 的 OAD 上 反 注 册 对 象 实 现 。2 将 该 对 象 实 现 注 册 到 新 主 机 的 OAD。3 终 止 旧 主 机 上 的 对 象 实 现 。有 关 注 册 和 反 注 册 对 象 实 现 的 详 细 信 息 , 请 参 阅 “ 使 用 对 象 激 活 守 护 进 程 ”。报 告 所 有 对 象 和 服 务智 能 定 位 器 (osfind) 命 令 报 告 与 指 定 网 络 中 当 前 可 用 的 对 象 和 服 务 有 关 的 所 有<strong>VisiBroker</strong> <strong>Edition</strong>。您 可 以 使 用 osfind 了 解 网 络 中 运 行 的 智 能 代 理 进 程 数 量 以 及 正 在 执 行 这 些 进 程 的具 体 主 机 。 osfind 命 令 也 用 于 报 告 网 络 中 激 活 且 已 经 注 册 到 智 能 代 理 的 所 有<strong>VisiBroker</strong> <strong>Edition</strong> 对 象 。 在 调 试 阶 段 , 可 以 利 用 osfind 监 视 网 络 状 态 并 定 位 游离 对 象 。osfind 命 令 的 语 法 如 下 :语 法 : osfind [ 选 项 ]osfind 命 令 具 有 以 下 选 项 。 如 果 未 指 定 选 项 , osfind 会 列 出 域 中 所 有 代 理 程 序 、OAD 和 实 现 。选 项说 明-a 列 出 域 中 所 有 智 能 代 理 。-b 使 用 <strong>VisiBroker</strong> 2.0 的 后 向 兼 容 osfind 机制 。-d 打 印 主 机 名 称 作 为 quad 地 址 。-f < 代 理 程 序 地 址 文 件 名 称 > 查 询 文 件 中 指 定 的 主 机 上 运 行 的 智 能 代 理 。 该文 件 的 每 行 中 包 含 一 个 IP 地 址 或 完 全 符 合 条件 的 主 机 名 称 。 请 注 意 , 报 告 所 有 智 能 代 理 时并 不 使 用 该 文 件 , 只 有 在 报 告 对 象 实 现 和 服 务时 才 能 使 用 。-g 查 证 对 象 是 否 存 在 。 这 会 在 负 载 系 统 上 造 成 相当 长 时 间 的 延 迟 。 只 查 证 通 过BY_INSTANCE 注 册 的 对 象 是 否 存 在 。 不 查证 注 册 到 OAD 或 通 过 BY_POA 策 略 注 册 的对 象 。-h, -help, -usage, -? 打 印 该 选 项 的 帮 助 信 息 。-o 列 出 域 中 所 有 的 对 象 激 活 守 护 进 程 。12-10 <strong>VisiBroker</strong> 开 发 者 指 南


限 制 到 对 象Windows:osfind 是 一 个 控 制 台 应 用 程 序 。 如 果 从 “ 开 始 ” 菜 单 中 启 动 osfind, 它 会 一 直 运行 到 完 成 为 止 并 退 出 , 看 不 到 结 果 。限 制 到 对 象注 :客 户 端 应 用 程 序 调 用 接 口 上 的 方 法 之 前 , 必 须 使 用 bind 方 法 首 先 获 得 对 象 引 用 。客 户 端 应 用 程 序 调 用 bind 方 法 时 , <strong>VisiBroker</strong> ORB 会 代 表 应 用 程 序 执 行 多 种 功能 。● <strong>VisiBroker</strong> ORB 与 osagent 通 讯 以 找 到 正 在 提 供 所 需 接 口 的 对 象 服 务 器 。 如 果已 指 定 对 象 名 称 和 主 机 名 称 ( 或 IP 地 址 ), 则 这 些 名 称 或 地 址 会 用 于 进 一 步 限定 目 录 服 务 搜 索 。● 定 位 对 象 实 现 后 , <strong>VisiBroker</strong> ORB 会 尝 试 在 定 位 的 对 象 实 现 与 您 的 客 户 端 应用 程 序 之 间 建 立 连 接 。● 如 果 成 功 建 立 连 接 , <strong>VisiBroker</strong> ORB 将 创 建 一 个 proxy 对 象 并 返 回 一 个 该 对象 的 引 用 值 。<strong>VisiBroker</strong> ORB 不 是 单 独 的 进 程 。 它 是 支 持 客 户 端 和 服 务 器 之 间 通 讯 的 一 组 类 和其 它 资 源 。使 用 智 能 代 理 12-11


12-12 <strong>VisiBroker</strong> 开 发 者 指 南


第章使 用 定 位 服 务第 13 章<strong>VisiBroker</strong> <strong>Edition</strong> 定 位 服 务 提 供 增 强 型 的 对 象 定 位 功 能 , 允 许 您 根 据 特 定 的 属性 找 到 对 象 实 例 。 定 位 服 务 与 <strong>VisiBroker</strong> <strong>Edition</strong> 智 能 代 理 一 起 工 作 , 它 通 知 您当 前 网 上 哪 些 对 象 可 以 到 达 以 及 它 们 驻 留 在 什 么 地 方 。 定 位 服 务 是 <strong>VisiBroker</strong><strong>Edition</strong> 朝 向 CORBA 规 范 的 扩 展 功 能 , 它 仅 适 用 于 定 位 由 <strong>VisiBroker</strong> <strong>Edition</strong>实 现 的 对 象 。什 么 是 定 位 服 务 ?定 位 服 务 是 朝 向 CORBA 规 范 的 一 项 扩 展 功 能 , 它 提 供 用 以 定 位 对 象 实 例 的 多 用途 实 用 工 具 。 定 位 服 务 直 接 与 一 个 维 护 目 录 的 智 能 代 理 通 信 , 该 目 录 包 含 智 能 代 理所 知 道 的 实 例 的 列 表 。 当 定 位 服 务 查 询 智 能 代 理 时 , 一 个 智 能 代 理 将 查 询 转 发 给 其它 的 智 能 代 理 , 然 后 将 它 们 的 回 答 集 中 在 它 返 回 给 定 位 服 务 的 结 果 中 。定 位 服 务 知 道 所 有 用 BY_INSTANCE 策 略 在 POA 上 注 册 的 实 例 , 生 成 的 实 例 在BOA 注 册 成 为 永 久 对 象 。 包 含 这 些 对 象 的 服 务 器 可 以 由 OAD 手 动 或 自 动 启 动 。下 图 说 明 了 这 一 概 念 。图 13.1 使 用 智 能 代 理 找 到 对 象 的 实 例注 :当 服 务 器 创 建 一 个 实 例 时 , 它 会 指 定 实 例 的 作 用 域 。 仅 具 有 全 局 作 用 域 的 实 例 才 会注 册 在 智 能 代 理 上 。使 用 定 位 服 务 13-1


定 位 服 务 组 件定 位 服 务 可 以 利 用 智 能 代 理 为 每 个 对 象 实 例 保 存 的 信 息 。 定 位 服 务 为 每 个 对 象 实 例维 护 封 装 在 以 下 所 示 的 ObjLocation::Desc 结 构 中 的 信 息 。struct Desc {Object ref;::IIOP::ProfileBodyValue iiop_locator;string repository_id;string instance_name;boolean activable;string agent_hostname;};typedef sequence DescSeq;Desc 结 构 的 IDL 包 含 以 下 信 息 :● 对 象 引 用 ref, 它 是 用 以 调 用 对 象 的 句 柄 。● iiop_locator 接 口 , 它 允 许 访 问 主 机 名 和 实 例 的 服 务 器 的 端 口 。 这 一 信 息 仅 在对 象 与 IIOP 连 接 时 才 有 意 义 , IIOP 是 唯 一 受 支 持 的 协 议 。 主 机 名 字 串 形 式 在实 例 描 述 中 返 回 。● repository_ id, 它 是 可 以 在 接 口 和 “ 实 现 仓 库 ” 中 找 到 的 对 象 实 例 的 接 口 名称 。 如 果 一 个 实 例 可 以 满 足 多 个 接 口 , 则 目 录 为 每 个 接 口 包 含 一 个 条 目 , 就 象 每个 接 口 都 有 一 个 实 例 一 样 。● instance_name, 它 是 对 象 的 服 务 器 给 对 象 指 定 的 名 称 。● activable 标 志 , 用 以 区 分 可 以 由 OAD 激 活 的 实 例 和 手 工 启 动 的 实 例 。● agent_hostname, 注 册 实 例 的 智 能 代 理 的 名 称 。定 位 服 务 对 于 达 成 如 负 载 平 衡 和 监 控 这 样 的 目 的 是 很 有 用 的 。 假 定 一 个 对 象 的 复 制品 位 于 数 个 主 机 上 。 您 可 以 部 署 一 个 绑 定 接 收 器 来 维 护 主 机 名 的 Cache, 这 些 主 机提 供 复 制 品 和 各 主 机 近 期 负 载 的 均 值 。 接 收 器 通 过 向 定 位 服 务 询 问 当 前 正 在 提 供 对象 实 例 的 服 务 器 来 更 新 它 的 Cache, 然 后 查 询 主 机 以 取 得 它 们 的 负 载 平 均 值 。 随 后接 收 器 为 负 载 最 小 的 主 机 上 的 复 制 品 返 回 一 个 引 用 对 象 。 参 阅 第 20 章 " 使 用 可 移植 接 收 器 " 以 取 得 关 于 编 写 接 收 器 应 用 的 详 情 。定 位 服 务 组 件通 过 Agent 接 口 可 以 访 问 定 位 服 务 。 Agent 接 口 的 方 法 可 以 分 为 两 类 : 用 于 向 智 能代 理 查 询 数 据 描 述 对 象 的 方 法 和 用 于 注 册 和 反 注 册 触 发 器 的 方 法 。 触 发 器 提 供 了这 样 一 个 机 制 , 通 过 使 用 这 种 机 制 , 可 以 通 知 定 位 服 务 的 客 户 关 于 实 例 的 可 用 性 的变 化 。什 么 是 定 位 服 务 代 理 ?定 位 服 务 代 理 是 允 许 您 找 到 智 能 代 理 网 络 上 的 对 象 的 方 法 集 。 您 可 以 根 据 接 口 的 仓库 ID 来 查 询 , 也 可 以 根 据 接 口 的 仓 库 ID 和 实 例 名 称 的 组 合 来 查 询 。 查 询 结 果 可以 以 对 象 引 用 的 形 式 或 更 完 整 的 实 例 描 述 的 形 式 来 返 回 。 对 象 引 用 就 是 由 智 能 代理 定 位 的 对 象 的 特 定 实 例 的 句 柄 。 实 例 描 述 包 含 对 象 引 用 , 也 包 含 实 例 的 接 口 名13-2 <strong>VisiBroker</strong> 开 发 者 指 南


定 位 服 务 组 件称 、 实 例 名 称 、 主 机 名 和 端 口 号 、 以 及 实 例 状 态 ( 例 如 , 实 例 是 否 在 运 行 或 者 是 否可 以 被 激 活 ) 的 信 息 。注 : 可 执 行 的 locserv 不 再 存 在 , 因 为 该 服 务 现 在 是 核 心 <strong>VisiBroker</strong> ORB 的 一 部 分 。下 图 说 明 了 以 下 的 实 例 IDL 中 所 给 出 的 接 口 仓 库 ID 和 实 例 名 的 使 用 :module Automobile {interface Car{...};interface Sedan:Car {...};}图 13.2接 口 仓 库 ID 和 实 例 名 的 使 用根 据 以 上 的 实 例 , 下 图 用 Car ( 汽 车 ) 实 例 说 明 了 关 于 汽 车 实 例 的 网 络 上 的 智 能 代理 。 在 本 例 中 有 三 个 实 例 :Kerri's Car ( 科 里 的 车 ) 一 个 实 例 和 Tom's Car ( 汤姆 的 车 ) 的 两 个 复 制 品 。图 13.3具 有 接 口 实 例 的 网 络 上 的 智 能 代 理以 下 的 章 节 说 明 如 何 使 用 由 Agent 类 提 供 的 方 法 来 向 <strong>VisiBroker</strong> <strong>Edition</strong> 智 能 代理 查 询 信 息 。 每 种 查 询 方 法 都 可 以 掷 出 Fail 违 例 , 该 违 例 提 供 失 败 的 原 因 。取 得 所 有 运 行 智 能 代 理 的 主 机 的 名 称通 过 使 用 HostnameSeq in or the String[] in Java all_agent_locations() 方 法 ,您 可 以 找 到 正 在 运 行 <strong>VisiBroker</strong> <strong>Edition</strong> 智 能 代 理 的 服 务 器 。 在 下 图 所 示 的 实 例中 , 该 方 法 将 返 回 两 个 主 机 的 名 称 :Athena 和 Zeus。找 出 所 有 可 访 问 的 接 口注 :您 可 以 询 问 一 个 网 络 上 的 <strong>VisiBroker</strong> <strong>Edition</strong> 智 能 代 理 , 以 找 出 所 有 可 访 问 的 接口 的 信 息 。 要 达 成 此 目 的 , 您 可 以 使 用 RepositoryIDSeq in C++ or the String[]in Java all_repository_ids() 方 法 。 在 下 图 所 示 的 实 例 中 , 该 方 法 将 返 回 两 个 接口 的 仓 库 ID:Car 和 Sedan。<strong>VisiBroker</strong> ORB 的 早 期 版 本 使 用 IDL 接 口 名 称 来 识 别 接 口 , 但 是 定 位 服 务 使 用仓 库 ID。 举 个 例 子 来 说 明 其 中 的 不 同 , 如 果 一 个 实 例 名 称 是::module1::module2::interface, 则 相 应 的 仓 库 ID 是 IDL:module1/module2/interface:1.0。 在 上 图 所 示 的 实 例 中 , Car ( 小 汽 车 ) 的 仓 库 ID 为IDL:Automobile/Car:1.0, 而 Sedan ( 轿 车 ) 的 库 ID 为 IDL:Automobile/Sedan:1.0。使 用 定 位 服 务 13-3


定 位 服 务 组 件取 得 接 口 实 例 的 引 用您 可 以 查 询 网 络 上 的 <strong>VisiBroker</strong> <strong>Edition</strong> 智 能 代 理 以 找 到 一 个 特 定 接 口 的 所 有 可用 实 例 。 在 执 行 查 询 时 , 您 可 以 使 用 以 下 方 法 之 下 :表 13.1C++ 下 取 得 实 现 一 个 给 定 接 口 的 对 象 的 引 用方 法CORBA::ObjectSeq* all_instances(constchar* _repository_id)DescSeq* all_instances_descs(const char*_repository_id)说 明使 用 该 方 法 将 对 象 引 用 返 回 给 接 口 的 实 例 。使 用 该 方 法 返 回 接 口 的 实 例 的 一 个 实 例 描 述 。表 13.2在 Java 下 取 得 实 现 一 个 给 定 接 口 的 对 象 的 引 用方 法org.omg.CORBA.Object[]all_instances(String repository_id)Desc[]all_instance_descs(Stringrepository_id)说 明使 用 该 方 法 将 对 象 引 用 返 回 给 接 口 的 实 例 。使 用 该 方 法 返 回 接 口 的 实 例 的 一 个 实 例 描 述 。在 上 图 所 示 的 实 例 中 , 用 IDL:Automobile/Car:1.0 请 求 对 任 一 方 面 的 调 用 都 会 返 回车 接 口 的 三 个 实 例 : 在 Athena 上 的 汤 姆 的 车 、 Zeus 上 的 汤 姆 的 车 、 和 科 里 的车 。 汤 姆 的 车 实 例 被 返 回 两 次 , 这 是 因 为 两 个 不 同 的 智 能 代 理 都 返 回 了 实 例 。取 得 接 口 的 同 名 实 例 的 引 用通 过 使 用 以 下 方 法 之 一 , 您 可 以 查 询 网 络 上 的 智 能 代 理 以 返 回 具 有 一 个 特 定 名 称 的所 有 实 例 。表 13.3C++ 下 接 口 的 同 名 实 例 的 引 用方 法CORBA::ObjectSeq* all_replica(const char*_repository_id, constchar*_instance_name)DescSeq all_replica_descs(constchar*_repository_id, const char*_instance_name)说 明使 用 该 方 法 返 回 接 口 的 同 名 实 例 的 对 象 引 用 。使 用 该 方 法 返 回 接 口 的 同 名 实 例 的 一 个 实 例 描述 。表 13.4Java 下 接 口 的 同 名 实 例 的 引 用方 法org.omg.CORBA.Object[] all_replica Stringrepository_id, String instance_nameDesc[] all_replica_descs(Stringrepository_id, String instance_name)说 明使 用 该 方 法 返 回 接 口 的 同 名 实 例 的 对 象 引 用 。使 用 该 方 法 返 回 接 口 的 同 名 实 例 的 一 个 实 例 描述 。在 上 图 所 示 的 实 例 中 , 指 定 仓 库 ID IDL:Automobile/Sedan:1.0 和 实 例 名 汤 姆 的 车将 会 返 回 两 个 实 例 , 这 是 因 为 两 个 不 同 的 智 能 代 理 上 都 返 回 了 实 例 。13-4 <strong>VisiBroker</strong> 开 发 者 指 南


定 位 服 务 组 件什 么 是 触 发 器 ?触 发 器 实 际 上 是 一 种 回 调 机 制 , 它 允 许 您 确 定 一 个 指 定 的 实 例 的 可 用 性 的 变 化 。 这是 检 测 Agent 的 异 步 替 代 方 案 。 通 常 , 在 对 一 个 对 象 的 连 接 丢 失 之 后 , 使 用 触 发 器对 其 进 行 恢 复 。 虽 然 有 多 种 方 法 可 以 进 行 查 询 , 但 触 发 器 是 专 用 的 。查 看 触 发 器 方 法下 表 描 述 的 是 Agent 类 中 的 触 发 器 方 法 :表 13.5C++ 下 的 触 发 器 方 法方 法void reg_trigger(const TriggerDesc&_desc,TriggerHandler_ptr _handler)void unreg_trigger(const TriggerDesc&_desc,TriggerHandler_ptr _handler)说 明使 用 该 方 法 注 册 一 个 触 发 器 处 理 器 。使 用 该 方 法 反 注 册 触 发 器 处 理 器 。表 13.6Java 下 的 触 发 器 方 法方 法void reg_trigger(com.inprise.vbroker.ObjLocation.TriggerDescdesc,com.inprise.vbroker.ObjLocation.TriggerHandler handler)void unreg_trigger(com.inprise.vbroker.ObjLocation.TriggerDescdesc,com.inprise.vbroker.ObjLocation.TriggerHanler handler)说 明使 用 该 方 法 注 册 触 发 器 处 理 器 。使 用 该 方 法 反 注 册 触 发 器 处 理 器 。两 种 Agent 触 发 器 方 法 都 可 能 掷 出 Fail 违 例 , 该 违 例 提 供 失 败 的 原 因 。TriggerHandler 接 口 包 含 下 表 中 所 描 述 的 方 法 :表 13.7C++ 下 的 TriggerHandler 接 口 方 法方 法void impl_is_ready(const Desc& _desc)void impl_is_down(const Desc& _desc)说 明当 一 个 与 desc 匹 配 的 实 例 变 为 可 访 问 时 , 定位 服 务 调 用 该 方 法 。当 一 个 实 例 变 为 不 可 用 时 , 定 位 服 务 调 用 该 方法 。表 13.8Java 下 的 TriggerHandler 接 口 方 法方 法voidimpl_is_ready(com.inprise.vbroker.ObjLocation.TriggerDescdesc)voidimpl_is_down(com.inprise.vbroker.ObjLocation.TriggerDescdesc)说 明当 一 个 与 desc 匹 配 的 实 例 变 为 可 访 问 时 , 定位 服 务 调 用 该 方 法 。当 一 个 实 例 变 为 不 可 用 时 , 定 位 服 务 调 用 该 方法 。使 用 定 位 服 务 13-5


查 询 代 理注 :创 建 触 发 器TriggerHandler 是 一 个 回 调 对 象 。 您 可 以 通 过 从 TriggerHandlerPOA 类 ( 或 BOA的 TriggerHandlerImpl 类 ) 派 生 的 方 式 实 现 TriggerHandler, You implement aTriggerHandler, 并 实 现 其 impl_is_ready() 和 impl_is_down() 方 法 。 要 在 定 位 服务 上 注 册 触 发 器 , 您 可 以 使 用 Agent 接 口 上 的 reg_trigger() 方 法 。 这 种 方 法 需 要您 提 供 您 想 要 监 视 的 实 例 的 描 述 , 以 及 当 实 例 的 可 用 性 发 生 了 变 化 时 您 所 要 调 用 的TriggerHandler 对 象 。 实 例 描 述 (TriggerDesc) 可 以 包 含 下 列 的 实 例 信 息 的 组合 : 仓 库 ID、 实 例 名 、 主 机 名 。 您 所 提 供 的 信 息 越 多 , 您 的 实 例 规 范 就 越 具 体 。struct TriggerDesc {string repository_id;string instance_name;string host_name;};如 果 TriggerDesc 中 的 一 个 字 段 设 定 为 空 字 串 (""), 则 该 字 段 被 忽 略 。 各 字 段 的默 认 值 为 空 字 串 。例 如 , 一 个 仅 包 含 仓 库 ID 的 TriggerDesc 可 以 与 接 口 的 任 何 实 例 匹 配 。 回 头 再 看一 下 上 图 中 的 实 例 , 当 以 下 实 例 之 一 变 为 可 用 或 不 可 用 时 , IDL:Automobile/Car:1.0 的 任 何 实 例 的 一 个 触 发 器 将 会 出 现 :Athena 上 的 汤 姆 的 车 、 Zeus 上 的 汤姆 的 车 、 或 科 里 的 车 。 给 TriggerDesc 增 加 一 个 实 例 名 称 “ 汤 姆 的 车 ”, 将 会 使 规范 更 具 体 , 因 此 , 当 两 个 “ 汤 姆 的 车 ” 实 例 之 一 的 可 用 性 发 生 了 变 化 时 , 仅 出 现 唯一 的 触 发 器 。 最 后 , 增 加 一 个 主 机 名 Athena 进 一 步 细 化 了 触 发 器 , 使 其 仅 在Athena 服 务 器 上 的 实 例 汤 姆 的 车 变 成 可 用 或 不 可 用 时 出 现 。仅 查 看 由 触 发 器 发 现 的 第 一 个 实 例触 发 器 是 很 “ 执 着 ” 的 每 当 一 个 满 足 触 发 器 描 述 的 对 象 变 为 可 访 问 时 , 就 会 调 用TriggerHandler。 也 许 您 只 想 知 道 什 么 时 候 第 一 个 实 例 会 变 成 可 访 问 。 如 果 是 这 种情 况 下 , 则 在 找 出 第 一 个 实 例 后 , 调 用 Agent 的 unreg_trigger() 方 法 来 反 注 册 触发 器 。查 询 代 理本 节 包 含 两 上 关 于 使 用 定 位 服 务 找 出 接 口 的 实 例 的 两 个 实 例 。 第 一 个 实 例 使 用 在 以下 IDL 片 段 中 所 示 的 Account 接 口 :// Bank.idlmodule Bank {interface Account {float balance();};interface AccountManager {Account open (in string name);};};13-6 <strong>VisiBroker</strong> 开 发 者 指 南


查 询 代 理找 出 接 口 的 所 有 实 例C++:以 下 的 两 个 代 码 实 例 均 使 用 all_instances() 方 法 来 定 位 帐 户 接 口 的 所 有 实 例 。 注意 : 查 询 智 能 代 理 时 , 先 将 “LocationService” 传 递 给 C++ORB::resolve_initial_references() 方 法 或 JavaORB.resolve_initial_references(), 然 后 将 该 方 法 返 回 的 对 象 窄 转 换 成 C++ 下 的ObjLocation::Agent 或 C++ Java 下 ObjLocation.Agent。 另 请 注 意 帐 户 库 ID 的 格式 :IDL:Bank/Account:1.0。在 C++ 下 找 出 所 有 满 足 AccountManager 接 口 的 实 例 :#include "corba.h"#include "locate_c.hh"// USE_STD_NS 是 由 <strong>VisiBroker</strong> 建 立 的 使 用 std namespace USE_STD_NS 的 定 义int main(int argc, char** argv){try {// ORB 初 始 化CORBA::ORB_var the_orb = CORBA::ORB_init(argc, argv);// 取 得 定 位 服 务 的 一 个 引 用CORBA::Object_var obj = the_orb->resolve_initial_references("LocationService");if ( CORBA::is_nil(obj) ) {cout


查 询 代 理public class AccountFinder {public static void main(String[] args) {try {// 初 始 化 ORB。org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);com.inprise.vbroker.ObjLocation.Agent the_agent = null;try {the_agent =com.inprise.vbroker.ObjLocation.AgentHelper.narrow(orb.resolve_initial_references("LocationService"));} catch (org.omg.CORBA.ORBPackage.InvalidName e) {System.out.println("Not able to resolve references " +"for LocationService");System.exit(1);} catch (Exception e) {System.out.println("Unable to locate LocationService!");System.out.println("Caught exception: " + e);System.exit(1);}org.omg.CORBA.Object[] accountRefs =the_agent.all_instances("IDL:Bank/AccountManager:1.0");System.out.println("Agent returned " + accountRefs.length +" object references");for (int i=0; i < accountRefs.length; i++) {System.out.println("Stringified IOR for account #" + (i+1) + ":");System.out.println(orb.object_to_string(accountRefs[i]));System.out.println();}} catch (Exception e) {System.out.println("Caught exception: " + e);System.exit(1);}}}找 出 智 能 代 理 已 知 的 接 口 和 实 例C++:以 下 的 代 码 示 例 说 明 如 何 找 到 智 能 代 理 已 知 的 所 有 接 口 和 实 例 。 该 示 例 先 通 过 调 用all_repository_ids() 方 法 来 取 得 所 有 已 知 的 接 口 。 然 后 , 它 调 用all_instances_descs() 方 法 使 每 个 接 口 取 得 实 例 描 述 。在 C++ 找 出 智 能 代 理 已 知 的 所 有 接 口 和 实 例 :#include "corba.h"#include "locate_c.hh"// USE_STD_NS 是 由 <strong>VisiBroker</strong> 建 立 的 使 用 std namespace 的 定 义// 如 其 存 在USE_STD_NSint DisplaybyRepID(CORBA::ORB_ptr the_orb,ObjLocation::Agent_var the_agent,char * myRepId) {13-8 <strong>VisiBroker</strong> 开 发 者 指 南


查 询 代 理ObjLocation::ObjSeq_var accountRefs;accountRefs = the_agent->all_instances(myRepId);cout


查 询 代 理Agents"


查 询 代 理orb.resolve_initial_references("LocationService"));} catch (org.omg.CORBA.ORBPackage.InvalidName e) {System.out.println("Not able to resolve references " + "forLocationService");System.exit(1);} catch (Exception e) {System.out.println("Not able to resolve references " + "forLocationService");System.out.println("Caught exception: " + e);System.exit(1);}boolean done=false;java.io.BufferedReader in =new java.io.BufferedReader(newjava.io.InputStreamReader(System.in));while (! done) {System.out.print("-> ");System.out.flush();String line = in.readLine();if(line.startsWith("agents")) {java.lang.String[] agentList = agent.all_agent_locations();System.out.println("Located " + agentList.length + " agents");for (int i=0; i < agentList.length; i++) {System.out.println("\t" + "Agent #" + (i+1) + ": " +agentList[i]);}} else if(line.startsWith("rep")) {java.lang.String[] repIds = agent.all_repository_ids();System.out.println("Located " + repIds.length + " repository Ids");for (int i=0; i < repIds.length; i++) {System.out.println("\t" + "Repository Id #" + (i+1) + ": " +repIds[i]);}} else if(line.startsWith("objects ")) {String names = line.substring("objects ".length(), line.length());PrintObjects(names,agent,orb);} else if(line.startsWith("quit")) {done = true;} else {System.out.println("Commands: agents\n" +" repository_ids\n" +" objects \n" +" objects \n" +" quit\n");}}} catch (com.inprise.vbroker.ObjLocation.Fail err) {System.out.println("Location call failed with reason " + err.reason);} catch (java.lang.Exception err) {System.out.println("Caught error " + err);err.printStackTrace();}}public static void PrintObjects(String names,使 用 定 位 服 务 13-11


编 写 和 注 册 触 发 器 处 理 器}}com.inprise.vbroker.ObjLocation.Agent agent,org.omg.CORBA.ORB orb)throws com.inprise.vbroker.ObjLocation.Fail {int space_pos = names.indexOf(' ');String repository_id;String object_name;if (space_pos == -1) {repository_id = names;object_name = null;} else {repository_id = names.substring(0,names.indexOf(' '));object_name = names.substring(names.indexOf(' ')+1);}org.omg.CORBA.Object[] objects;com.inprise.vbroker.ObjLocation.Desc[] descriptors;if (object_name == null) {objects = agent.all_instances(repository_id);descriptors = agent.all_instances_descs(repository_id);} else {objects = agent.all_replica(repository_id,object_name);descriptors = agent.all_replica_descs(repository_id,object_name);}System.out.println("Returned " + objects.length + " objects");for (int i=0; i


C++:编 写 和 注 册 触 发 器 处 理 器如 果 触 发 器 反 注 册 自 身 , 则 该 方 法 调 用 CORBA::ORB::shutdown() 方 法 , 该 方 法 将 引导 BOA 退 出 主 程 序 的 impl_is_ready() 方 法 , 以 便 程 序 可 以 结 止 。Java: 如 果 要 反 注 册 触 发 器 , 则 该 方 法 System.exit() 以 终 止 程 序 。注 意 :TriggerHandlerImpl 类 保 存 desc 和 创 建 它 时 所 用 的 Agent 参 数 的 副 本 。unreg_trigger() 方 法 需 要 desc 参 数 。 对 Agent 参 数 进 行 了 复 制 , 以 防 主 程 序 中 而来 的 引 用 被 释 放 。在 C++ 下 实 现 触 发 器 处 理 器 :C++: // AccountTrigger.c#include "locate_s.hh"// USE_STD_NS 是 由 <strong>VisiBroker</strong> 建 立 的 使 用 std namespace 的 定 义USE_STD_NS// 如 果 该 类 为 之 而 注 册 的 事 件 发 生 , 则// 代 理 将 回 调 该 类 的 实 例 。class TriggerHandlerImpl : public _sk_ObjLocation::_sk_TriggerHandler{public:TriggerHandlerImpl(ObjLocation::Agent_var agent,const ObjLocation::TriggerDesc& initial_desc): _agent(ObjLocation::Agent::_duplicate(agent)),_initial_desc(initial_desc) {}{endl;void impl_is_ready(const ObjLocation::Desc& desc) {notification(desc, 1);}void impl_is_down(const ObjLocation::Desc& desc) {notification(desc, 0);}private:void notification(const ObjLocation::Desc& desc, CORBA::Boolean isReady)if (isReady) {cout


编 写 和 注 册 触 发 器 处 理 器}}try {_agent->unreg_trigger(_initial_desc, this);}catch (const ObjLocation::Fail& e) {cout


编 写 和 注 册 触 发 器 处 理 器class TriggerHandlerImpl extendscom.inprise.vbroker.ObjLocation.TriggerHandlerPOA {public TriggerHandlerImpl(com.inprise.vbroker.ObjLocation.Agent agent,com.inprise.vbroker.ObjLocation.TriggerDesc initial_desc) {agent = agent;initial_desc = initial_desc;}public void impl_is_ready(com.inprise.vbroker.ObjLocation.Desc desc) {notification(desc, true);}public void impl_is_down(com.inprise.vbroker.ObjLocation.Desc desc) {notification(desc, false);}private void notification(com.inprise.vbroker.ObjLocation.Desc desc,boolean isReady) {if (isReady) {System.out.println("Implementation is ready:");} else {System.out.println("Implementation is down:");}System.out.println("\tRepository Id = " + desc.repository_id + "\n" +"\tInstance Name = " + desc.instance_name + "\n" +"\tHost Name = " + desc.iiop_locator.host + "\n" +"\tBOA Port = " + desc.iiop_locator.port + "\n" +"\tActivable = " + desc.activable + "\n" + "\n");System.out.println("Unregister this handler and exit (yes/no)?");try {BufferedReader in = new BufferedReader(new InputStreamReader(System.in));String line = in.readLine();if(line.startsWith("y") || line.startsWith("Y")) {try {agent.unreg_trigger(_initial_desc, _this());} catch (com.inprise.vbroker.ObjLocation.Fail e) {System.out.println("Failed to unregister trigger with reason=["+e.reason + "]");}System.out.println("exiting...");System.exit(0);}} catch (java.io.IOException e) {System.out.println("Unexpected exception caught: " + e);System.exit(1);}}private com.inprise.vbroker.ObjLocation.Agent _agent;private com.inprise.vbroker.ObjLocation.TriggerDesc _initial_desc;}public class AccountTrigger {public static void main(String args[]) {try {// 初 始 化 ORB。org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);使 用 定 位 服 务 13-15


编 写 和 注 册 触 发 器 处 理 器POA rootPoa =POAHelper.narrow(orb.resolve_initial_references("RootPOA"));rootPoa.the_POAManager().activate();com.inprise.vbroker.ObjLocation.Agent the_agent =com.inprise.vbroker.ObjLocation.AgentHelper.narrow(orb.resolve_initial_references("LocationService"));// 创 建 触 发 器 描 述 和 相 应 的 TriggerHandler。// 当 osagent 得 知// 以 下 接 口 的 任 何 新 实 现 时 , 将 调 用 TriggerHandler"Bank::AccountManger"com.inprise.vbroker.ObjLocation.TriggerDesc desc =new com.inprise.vbroker.ObjLocation.TriggerDesc("IDL:Bank/AccountManager:1.0", "", "");TriggerHandlerImpl trig = new TriggerHandlerImpl(the_agent, desc);rootPoa.activate_object(trig);the_agent.reg_trigger(desc, trig._this());orb.run();} catch (Exception e) {e.printStackTrace();System.exit(1);}}}13-16 <strong>VisiBroker</strong> 开 发 者 指 南


第章使 用 命 名 服 务第 14 章本 章 描 述 如 何 使 用 <strong>VisiBroker</strong> <strong>Edition</strong> 命 名 服 务 , 该 服 务 是 OMG 的 可 互 操 作 的命 名 规 范 文 件 (orbos/98-10-11) 的 一 个 完 整 实 现 。概 述命 名 服 务 允 许 您 将 一 个 或 多 个 逻 辑 名 与 一 个 对 象 引 用 联 结 起 来 , 并 将 这 些 名 称 存 储在 一 个 命 名 空 间 (namespace) 中 。 它 也 允 许 您 的 客 户 应 用 使 用 命 名 服 务 , 以 便 通过 使 用 分 配 给 对 象 的 逻 辑 名 称 来 取 得 该 对 象 的 引 用 。下 图 包 含 命 名 服 务 的 一 个 简 化 视 图 , 该 视 图 说 明 :1 一 个 对 象 实 现 怎 样 将 一 个 名 称 限 制 到 其 在 命 名 空 间 中 的 对 象 之 一 。2 客 户 端 应 用 随 后 又 如 何 使 用 相 同 的 命 名 空 间 来 解 析 将 对 象 引 用 返 回 到 命 名 上 下 文或 对 象 的 名 称 。使 用 命 名 服 务 14-1


理 解 命 名 空 间图 14.1限 制 、 解 析 和 使 用 从 命 名 空 间 内 的 命 名 上 下 文 而 来 的 对 象 名 称在 使 用 <strong>VisiBroker</strong> <strong>Edition</strong> 命 名 服 务 和 使 用 智 能 代 理 来 定 位 一 个 对 象 实 现 之 间 存在 一 些 值 得 考 虑 的 重 要 差 别 。C++:C++:Java:Java:● 智 能 代 理 使 用 平 面 型 命 名 空 间 , 而 命 名 服 务 使 用 层 次 型 的 命 名 空 间 。● 如 果 您 使 用 智 能 代 理 , 则 在 您 编 译 您 的 客 户 和 服 务 器 应 用 的 过 程 中 , 将 会 定 义 一个 对 象 的 接 口 名 称 。 这 意 味 着 , 如 果 您 改 变 了 一 个 接 口 的 名 称 , 您 必 须 重 新 编 译您 的 应 用 。 与 此 相 反 , 命 名 服 务 允 许 对 象 实 现 在 运 行 期 内 将 逻 辑 名 称 限 制 到 它 的对 象 上 。● 使 用 智 能 代 理 时 , 一 个 对 象 仅 可 以 实 现 一 个 接 口 名 称 , 但 是 , 接 口 服 务 允 许 您 限制 一 个 以 上 的 逻 辑 名 称 到 一 个 对 象 。● 对 象 的 接 口 名 称 是 在 您 编 译 客 户 和 服 务 器 应 用 的 过 程 中 定 义 的 。 要 变 更 接 口 名称 , 您 需 要 重 新 编 译 应 用 。 与 此 相 反 , 命 名 服 务 允 许 对 象 实 现 在 运 行 期 内 将 逻 辑名 称 限 制 到 它 的 对 象 上 。● 对 象 仅 可 以 实 现 一 个 接 口 名 称 , 但 是 , 命 名 服 务 允 许 您 限 制 一 个 以 上 的 逻 辑 名 称到 一 个 对 象 。理 解 命 名 空 间下 图 说 明 如 何 使 用 命 名 服 务 来 给 组 成 一 个 订 单 登 录 系 统 的 对 象 命 名 。 这 个 虚 构 的 订单 登 录 系 统 先 按 照 地 理 区 域 来 组 织 其 命 令 空 间 , 然 后 再 按 部 门 等 来 组 织 。 命 名 服 务允 许 您 将 命 名 空 间 组 织 成 为 一 个 NamingContext 对 象 的 层 次 结 构 , 您 可 以 在 该 结 构中 来 回 穿 行 以 定 位 一 个 特 定 的 名 称 。 例 如 , 逻 辑 名 称 NorthAmerica/ShippingDepartment/Orders 可 用 于 定 位 Order 对 象 。14-2 <strong>VisiBroker</strong> 开 发 者 指 南


理 解 命 名 空 间图 14.2订 单 登 录 系 统 的 命 名 方 案命 名 上 下 文要 用 <strong>VisiBroker</strong> <strong>Edition</strong> 命 名 服 务 实 现 如 上 所 示 的 命 名 空 间 , 每 个 有 阴 影 的 方 块都 要 由 NamingContext 对 象 来 实 现 。 NamingContext 对 象 包 含 已 被 限 制 到 对 象 实 现或 其 它 NamingContext 对 象 的 名 称 结 构 的 一 个 列 表 。 虽 然 一 个 逻 辑 名 称 可 以 被 限 制到 NamingContext, 但 重 要 的 一 点 是 要 明 白 , 在 默 认 情 况 下 ,NamingContext 没 有 与其 联 结 的 逻 辑 名 , 而 这 样 的 一 个 名 称 也 不 是 必 需 的 。对 象 实 现 使 用 NamingContext 对 象 以 将 名 称 限 制 到 它 们 所 提 供 的 对 象 。 客 户 应 用 使用 NamingContext 来 解 析 限 制 到 对 象 引 用 的 名 称 。另 外 , 还 有 一 个 可 用 的 NamingContextExt 接 口 , 该 接 口 为 使 用 字 串 化 的 名 称 提 供 所必 需 的 方 法 。命 名 上 下 文 工 厂命 名 上 下 文 工 厂 提 供 用 于 启 动 命 名 服 务 的 接 口 。 它 具 有 关 闭 命 名 服 务 的 操 作 , 以及 在 没 有 上 下 文 时 , 创 建 新 的 上 下 文 的 操 作 。 工 厂 也 具 有 返 回 根 上 下 文 的 一 个 额 外的 API。 根 上 下 文 作 为 一 个 参 考 点 , 扮 演 很 重 要 的 角 色 。 这 是 一 个 存 储 所 有 要 公 用的 数 据 的 公 共 起 点 。<strong>VisiBroker</strong> <strong>Edition</strong> 命 名 服 务 提 供 两 个 类 , 它 们 允 许 您 创 建 命 名 空 间 : 默 认 的 命名 上 下 文 工 厂 和 扩 展 的 命 名 上 下 文 工 厂 。 默 认 的 命 名 上 下 文 工 厂 创 建 没 有 根NamingContext 的 空 命 名 空 间 。 您 可 能 会 发 现 使 用 护 展 的 命 名 上 下 文 工 厂 更 方 便 ,因 为 它 可 以 创 建 包 含 根 NamingContext 的 命 名 空 间 。在 您 的 对 象 实 现 可 以 将 名 称 限 制 到 它 们 的 对 象 之 前 , 以 及 客 户 应 用 可 以 解 析 一 个 对象 引 用 的 名 称 之 前 , 您 至 少 必 须 取 得 这 些 NamingContext 对 象 之 一 。上 图 中 所 示 的 每 个 NamingContext 对 象 都 可 以 在 单 个 的 命 名 服 务 进 程 中 实 现 。 它们 也 可 以 在 多 达 5 个 不 同 的 命 名 服 务 器 进 程 中 实 现 。使 用 命 名 服 务 14-3


理 解 命 名 空 间名 称 和 NameComponentCosNaming::Name 表 示 可 以 限 制 到 对 象 实 现 或 CosNaming::NamingContext 的 标 识符 。 Name 不 是 仅 由 字 母 组 成 的 字 串 ; 它 是 一 个 或 多 个 NameComponent 结 构 的 序 列 。每 个 NameComponent 包 含 两 个 属 性 字 串 :id 和 kind。 命 名 服 务 不 解 译 或 管 理 这 些 字串 , 只 是 确 保 每 个 id 和 kind 在 给 定 的 NamingContext 内 是 唯 一 的 。id 和 kind 属 性 字 串 是 可 以 唯 一 地 识 别 名 称 所 限 制 的 对 象 的 字 串 。 kind 成 员 给 名 称中 增 加 一 个 描 述 语 。 例 如 , 名 称 “Inventory.RDBMS” 具 有 一 个 “Inventory”id 成 员 , 而 kind 具 有 一 个 “RDBMS” 成 员 。module CosNamingtypedef string Istring;struct NameComponent {Istring id;Istring kind;};typedef sequence Name;};NameComponent 的 id 和 kind 属 性 必 须 使 用 ISO 8859-1 (Latin-1) 字 符 集 中 的 字符 , 其 中 不 包 括 空 字 符 (0x00) 和 其 它 非 打 印 字 符 。 NameComponent 中 的 任 何 一 个字 串 都 不 可 以 超 过 255 个 字 符 。 另 外 , 命 名 服 务 不 支 持 使 用 宽 字 符 的NameComponent。注 : 名 称 的 id 属 性 不 能 为 空 , 但 kind 属 性 可 以 为 空 。名 称 解 析您 的 客 户 应 用 使 用 NamingContext 的 resolve 方 法 来 取 得 在 逻 辑 Name 中 给 定 的 对 象引 用 。 因 为 一 个 Name 包 含 一 个 或 多 个 NameComponent 对 象 , 所 以 解 析 进 程 要 求 可 以在 所 有 组 成 Name 的 NameComponent 结 构 中 来 回 移 动 。字 串 化 的 名 称因 为 CosNaming::Name 的 表 示 方 式 不 可 读 或 不 便 于 交 换 , 所 以 定 义 了 一 个 字 串 化 的名 称 来 解 决 这 一 问 题 。 字 串 化 的 名 称 是 字 串 和 CosNaming::Name 之 间 的 一 对 一 映射 。 如 果 两 个 CosNaming::Name 对 象 是 相 同 的 , 则 它 们 的 字 串 化 表 示 法 也 相 同 , 反之 亦 然 。 在 字 串 化 的 名 称 中 , 用 右 斜 杠 (/) 来 分 隔 名 称 组 件 ; 用 句 点 (.) 来 分隔 id 和 kind 属 性 ; 用 反 斜 杠 (\) 来 作 转 义 字 符 。 通 常 , 具 有 空 kind 属 性 的NameComponent 不 使 用 句 点 ( 例 如 , 订 单 )。"Borland.Company/Engineering.Department/Printer.Resource"注 : 在 以 下 的 实 例 中 , NameComponent 的 结 构 是 在 其 字 串 化 的 表 示 法 中 给 出 的 。简 单 名 和 复 杂 名简 单 名 , 例 如 Billing ( 开 帐 单 ), 只 有 个 单 一 的 NameComponent, 它 总 是 根 据 目 标命 名 上 下 文 来 解 析 。 简 单 名 可 以 被 限 制 到 对 象 实 现 或 NamingContext。14-4 <strong>VisiBroker</strong> 开 发 者 指 南


运 行 命 名 服 务复 杂 名 , 例 如 NorthAmerican/ShippingDepartment/Inventory, 包 含 一 个 由 三 个NameComponent 结 构 组 成 的 序 列 。 如 果 一 个 由 n 个 NameComponent 对 象 组 成 的 复 杂名 已 被 限 制 到 一 个 对 象 实 现 , 则 序 列 中 的 前 (n-1) 个 NameComponent 对 象 各 自 都必 须 解 析 到 NamingContext, 而 最 后 一 个 NameComponent 对 象 必 须 解 析 到 一 个 对 象实 现 。如 果 一 个 Name 被 限 制 到 NamingContext, 则 序 列 中 的 每 个 NameComponent 结 构 都 必须 引 用 NamingContext。以 下 的 代 码 示 例 说 明 一 个 复 杂 名 , 它 包 含 3 个 组 件 , 被 限 制 到 一 个 CORBA 对 象 。该 名 称 对 应 字 串 的 名 称 NorthAmerica/SalesDepartment/Order。 在 顶 层 命 名 上 下 文中 解 析 后 , 该 复 杂 名 的 前 两 个 组 件 解 析 到 NamingContext 对 象 , 而 最 后 一 个 对 象 解析 到 具 有 逻 辑 名 “Order” 的 对 象 实 现 。C++: . . .// 名 称 字 串 化 为 "NorthAmerica/SalesDepartment/Order"CosNaming::Name_var continentName = rootNamingContext->to_name("NorthAmerica");CosNaming::NamingContext_var continentContext =rootNamingContext->bind_new_context(continentName);CosNaming::Name_var departmentName = continentContext->to_name("SalesDepartment");CosNaming::NamingContext_var departmentContext =rootNamingContext->bind_new_context(departmentName);CosNaming::Name_var objectName = departmentContext->to_name("Order");departmentContext->rebind(objectName,myPOA->servant_to_reference(managerServant));. . .Java: . . .// 名 称 字 串 化 为 "NorthAmerica/SalesDepartment/Order"NameComponent[] continentName = { new NameComponent("NorthAmerica", "") };NamingContext continentContext =rootNamingContext.bind_new_context(continentName);NameComponent[] departmentName = { new NameComponent("SalesDepartment", "") };NamingContext departmentContext =continentContext.bind_new_context(departmentName);NameComponent[] objectName = { new NameComponent("Order", "") };departmentContext.rebind(objectName,myPOA.servant_to_reference(managerServant));. . .运 行 命 名 服 务可 以 用 以 下 命 令 来 启 动 命 名 服 务 。 一 旦 您 启 动 命 名 服 务 之 后 , 您 就 可 以 使 用<strong>VisiBroker</strong> <strong>Edition</strong> 控 制 台 来 浏 览 它 的 内 容 。使 用 命 名 服 务 14-5


运 行 命 名 服 务安 装 命 名 服 务在 您 安 装 <strong>VisiBroker</strong> <strong>Edition</strong> 5.0 的 过 程 中 , 会 自 动 安 装 命 名 服 务 。 它 包 含 一 个nameserv 文 件 ( 该 文 件 对 于 Windows NT 而 言 是 一 个 二 进 制 可 执 行 文 件 , 对 于UNIX 是 一 个 脚 本 ) 和 存 储 于 vbjorb.jar 文 件 下 的 Java 类 文 件 。配 置 命 名 服 务注 :在 <strong>VisiBroker</strong> <strong>Edition</strong> 的 早 期 版 本 中 , 命 名 服 务 通 过 将 修 改 操 作 以 日 志 的 形 式 存入 一 个 平 面 文 件 来 保 持 永 久 性 。 从 4.0 版 以 后 , 命 名 服 务 与 备 份 存 储 适 配 器 配 合 工作 。 特 别 注 意 : 不 是 所 有 的 备 份 存 储 适 配 器 都 可 以 支 持 永 久 性 。 默 认 的 InMemory适 配 器 是 非 永 久 型 的 , 而 其 它 的 适 配 器 是 永 久 型 的 。 有 关 适 配 器 的 详 情 , 请 参 阅 第14-14 页 " 可 插 入 的 备 份 存 储 "。在 命 名 服 务 的 启 动 过 程 中 , 它 需 要 将 自 身 注 册 在 智 能 代 理 上 。 所 以 , 您 需 要 运 行 智能 代 理 以 启 动 命 名 服 务 。 这 样 一 来 , 客 户 就 通 过 调 用 resolve_initial_references方 法 来 检 索 初 始 根 上 下 文 。 解 析 功 能 通 过 智 能 代 理 来 检 索 所 需 要 的 引 用 。 与 此 类似 , 加 入 该 联 合 的 命 名 服 务 也 使 用 同 样 的 机 制 来 建 立 联 合 。启 动 命 名 服 务UNIX:Windows:您 可 以 通 过 使 用 bin 目 录 下 的 nameserv 登 录 器 程 序 来 启 动 您 的 命 名 服 务 。 在 默 认情 况 下 , nameserv 登 录 器 使 用 com.inprise.vbroker.naming.ExtFactory 工 厂 类 。nameserv [driver_options] [nameserv_options] root_context_name &start nameserv [driver_options] [nameserv_options] root_context_name选 项用 vbj 启 动 命 名 服 务仅 适 用 于 Java: 命 名 服 务 仍 可 以 使 用 vbj 来 启 动 。描 述driver_options ( 必 须 出 现 在 工 厂 名 称 之 前 )-J将 指 定 的 选 项 直 接 传 递 给 JVM。-VBJversion 打 印 VBJ 的 版 本 号 。-VBJdebug 打 印 VBJ 的 调 试 信 息 。nameserv_options-?, -h, -help, -usage 打 印 使 用 信 息 。-config=在 启 动 命 名 服 务 时 , 用 来 作配 置 文 件 。 要 用 于 该 命 名 服 务 的 名 称 。 这 是 一 个 可 选 项 ;默 认 名 称 为 NameService。prompt>vbj com.inprise.vbroker.naming.ExtFactory 14-6 <strong>VisiBroker</strong> 开 发 者 指 南


从 命 令 行 调 用 命 名 服 务从 命 令 行 调 用 命 名 服 务命 名 服 务 实 用 工 具 (nsutil) 提 供 从 命 令 行 存 储 和 检 索 限 制 的 能 力 。配 置 nsutil要 使 用 nsutil, 首 先 要 使 用 下 列 命 令 之 一 配 置 命 名 服 务 实 例 :prompt>nameserve 或prompt>nsutil -VBJprop [args]选 项ns_configSVCnameroot=ORBInitRef=NameService=cmd说 明定 义 工 厂 名 称注 : 使 用 SVCnameroot 之 前 , 您 必 须 先 运 行OSAgent。文 件 名 或 URL, 使 用 其 类 型 作 前 缀 , 该 类 型可 能 是 corbaloc:、 corbaname:、 file:、ftp:、 http:、 或 ior:。 例 如 , 要 将 一 个 文 件分 配 到 一 个 本 地 目 录 , ns_config 字 串 可 能 会是 :-VBJpropORBInitRef=NameService=任 何 CosNaming 操 作 , 也 包 括 ping 和shutdown ( 关 闭 )。运 行 nsutil命 名 服 务 实 用 工 具 支 持 所 有 的 CosNaming 操 作 和 两 个 额 外 的 命 令 。 支 持 的CosNaming 操 作 为 :cmdbindbind_contextbind_new_contextdestroylistnew_contextrebindrebind_contextresolveunbind参 数name objRefname objRefname ctxRefnamename*No parametername objRefname ctxRefnamename使 用 命 名 服 务 14-7


启 动 命 名 服 务额 外 的 nsutil 命 令 为 :cmd 参 数 说 明ping name 解 析 字 串 化 的 name 并 与 对 象联 络 以 检 查 它 是 否 是 活 动 的 。shutdown factory_name 从 命 令 行 正 确 地 关 闭 命 名 服务 。factory_name 是 启 动 命 名服 务 时 指 定 的 名 称 。 注 : 调 用该 命 令 前 , 不 必 设 定 初 始 上 下文 。要 使 用 nsutil 命 令 来 执 行 一 个 操 作 , 将 操 作 的 名 称 及 其 参 数 设 置 成 参 数 。例 如 :prompt>nsutil -VBJprop ORBInitRef=NameService=file://ns.ior resolve myName关 闭 nsutil要 关 闭 nsutil 时 , 使 用 shutdown 命 令 :prompt>nsutil -VBJprop ORBInitRef=NameService=file://ns.ior shutdown启 动 命 名 服 务有 三 种 方 法 可 以 用 来 启 动 一 个 客 户 端 应 用 , 以 取 得 指 定 的 命 名 服 务 的 初 始 对 象 引用 。 在 启 动 命 名 服 务 时 , 您 可 用 使 用 以 下 的 命 名 行 选 项 :● ORBInitRef● ORBDefaultInitRef● SVCnameroot调 用 resolve_initial_references新 的 命 名 服 务 提 供 了 一 种 简 单 的 机 制 , 通 过 这 种 机 制 , 可 以 配 置resolve_initial_references 方 法 以 返 回 公 共 命 名 上 下 文 。 您 可 以 使 用resolve_initial_references 方 法 , 该 方 法 可 以 返 回 客 户 端 程 序 所 连 接 的 命 名 服 务的 根 上 下 文 。 以 下 的 三 个 简 单 实 例 将 要 说 明 如 何 使 用 这 三 个 选 项 。 假 定 有 主 机TestHost 上 有 三 个 <strong>VisiBroker</strong> <strong>Edition</strong> 命 名 服 务 在 运 行 :ns1、 ns2 和 ns3。 有 三个 服 务 器 应 用 :sr1、 sr2、 sr3。 每 个 应 用 运 行 于 主 机 TestHost 的 不 同 端 口 上(20001、 20002、 和 20003)。 服 务 器 sr1 限 制 在 ns1 ; 服 务 器 sr2 限 制 在 ns2 ; 服务 器 sr3 限 制 在 ns3。C++: . . .CORBA::ORB_ptr orb = CORBA::ORB_init(argv, argc, NULL);CORBA::Object_var rootObj = orb->resolve_initial_references("NameService");. . .14-8 <strong>VisiBroker</strong> 开 发 者 指 南


启 动 命 名 服 务Java: . . .org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null);org.omg.CORBA.Object rootObj =orb.resolve_initial_references("NameService");. . .使 用 -DSVCnamerootJava:C++:您 使 用 -DSVCnameroot 选 项 来 指 定 您 所 要 启 动 的 <strong>VisiBroker</strong> <strong>Edition</strong> 命 名 服 务 实例 ( 如 果 有 几 个 相 关 的 命 名 服 务 在 运 行 , 则 这 一 操 作 特 别 重 要 )。例 如 , 如 果 您 要 启 动 ns1, 则 您 要 用 以 下 命 令 来 启 动 您 的 客 户 端 应 用 程 序 : -DSVCnameroot=ns1vbj -DSVCnameroot=ns1 然 后 , 您 可 以 通 过 调 用 的 您 的 客 户 端 程 序 中 的 一 个 ORB 引 用 上 的resolve_initial_references 方 法 来 取 得 ns1 的 根 上 下 文 ( 如 以 上 程 序 所 示 )。仅 适 用 于 C++: 要 使 用 该 选 项 , OSAgent 必 须 正 在 运 行 。仅 适 用 于 C++:请 注 意 :-DSVCnameroot 启 动 机 制 基 于 <strong>VisiBroker</strong> OSAgent 提 供 的 专 有 功能 , 它 不 能 与 其 它 的 CORBA 实 现 进 行 互 操 作 。使 用 C++ -ORBInitRef 或 Java -DORBInitRef您 可 以 使 用 corbaloc 或 corbaname URL 命 名 方 案 来 指 定 您 所 要 启 动 的 <strong>VisiBroker</strong><strong>Edition</strong> 命 名 服 务 。使 用 corbaloc URLC++:Java:注 :注 :如 果 您 要 使 用 命 名 服 务 ns2 来 启 动 , 则 您 应 该 用 以 下 的 命 令 来 启 动 您 的 客 户 端应 用 : -ORBInitRef NameService=iioploc://TestHost:20002/NameServicevbj -DORBInitRef NameService=corbaloc::TestHost:20002/NameService然 后 , 您 可 以 通 过 调 用 的 您 的 客 户 端 程 序 中 的 <strong>VisiBroker</strong> ORB 引 用 上 的resolve_initial_references 方 法 来 取 得 ns2 的 根 上 下 文 ( 如 以 上 实 例 所 示 )。仅 当 您 要 访 问 的 命 名 服 务 所 限 制 的 服 务 器 运 行 于 端 口 20002 上 时 , 本 实 例 才 可 以 执行 。iiploc 和 iiopname URL 方 案 是 由 corbaloc 和 corbaname 分 别 实 现 的 。 由 于 提 供 了后 向 兼 容 , 所 以 仍 然 支 持 原 来 的 方 案 。使 用 命 名 服 务 14-9


启 动 命 名 服 务使 用 corbaname URLC++:Java:如 果 您 要 通 过 使 用 corbaname 来 启 动 ns3, 则 您 应 该 用 以 下 方 式 来 启 动 您 的 客 户 端程 序 : -ORBInitRef NameService=iiopname://TestHost:20003/vbj -DORBInitRef NameService=corbaname::TestHost:20003/ 然 后 , 您 可 以 通 过 调 用 的 您 的 客 户 端 程 序 中 的 <strong>VisiBroker</strong> ORB 引 用 上 的resolve_initial_references 方 法 来 取 得 ns3 的 根 上 下 文 ( 如 以 上 实 例 所 示 )。-ORBDefaultInitRef (C++) 或 -DORBDefaultInitRef(Java)您 可 以 使 用 corbaloc 或 corbaname URL 来 指 定 您 想 要 启 动 的 <strong>VisiBroker</strong> <strong>Edition</strong>命 名 服 务 。C++:Java:用 corbaloc URL 使 用 -ORBDefaultInitRef (C++) 或 -DORBDefaultInitRef (Java)如 果 您 想 启 动 ns2, 则 您 应 该 用 以 下 方 式 来 启 动 您 的 客 户 端 应 用 程 序 : -ORBDefaultInitRef iioploc://TestHost:20002vbj -DORBDefaultInitRef corbaloc::TestHost:20002 然 后 , 您 可 以 通 过 调 用 的 您 的 客 户 端 程 序 中 的 <strong>VisiBroker</strong> ORB 引 用 上 的resolve_initial_references 方 法 来 取 得 ns2 的 根 上 下 文 ( 如 以 上 实 例 所 示 )。用 corbaname 使 用 -ORBDefaultInitRef (C++) 或 -DORBDefaultInitRef (Java)C++:Java:C++ -ORBDefaultInitRef 或 Java -DORBDefaultInitRef 与 corbaname 组 合 的 工 作方 式 与 想 象 的 不 同 。 如 果 指 定 了 C++ -ORBDefaultInitRef 或 Java -DORBDefaultInitRef , 则 一 个 斜 杠 和 字 串 化 的 对 象 key 会 始 终 连 接 到 corbaname。例 如 , 如 果 URL corbaname::TestHost:20002, 则 通 过 指 定 -ORBDefaultInitRef,C++ resolve_initial_references 将 会 产 生 一 个 新 的 URL:corbaname::TestHost:20003/NameService。或 者 :如 果 URL corbaname::TestHost:20002, 则 通 过 指 定 -DORBDefaultInitRef, Javaresolve_initial_references 将 产 生 一 个 新 的 URL:corbaname::TestHost:20003/NameService。14-10 <strong>VisiBroker</strong> 开 发 者 指 南


NamingContextNamingContextNamingContextExt该 对 象 用 于 保 存 和 管 理 限 制 到 <strong>VisiBroker</strong> ORB 对 象 或 其 它 NamingContext 对 象 的名 称 的 列 表 。 客 户 端 应 用 使 用 该 接 口 来 resolve ( 解 析 ) 或 list ( 列 出 ) 上 下 文中 的 所 有 名 称 。 对 象 实 现 使 用 该 对 象 将 名 称 bind ( 限 制 ) 到 对 象 实 现 或 将 名 称 限制 到 NamingContext 对 象 。 以 下 的 示 例 说 明 NamingContext 的 IDL 规 范 。module CosNaming {interface NamingContext {void bind(in Name n, in Object obj)raises(NotFound, CannotProceed, InvalidName, AlreadyBound);void rebind(in Name n, in Object obj)raises(NotFound, CannotProceed, InvalidName);void bind_context(in Name n, in NamingContext nc)raises(NotFound, CannotProceed, InvalidName, AlreadyBound);void rebind_context(in Name n, in NamingContext nc)raises(NotFound, CannotProceed, InvalidName);Object resolve(in Name n)raises(NotFound, CannotProceed, InvalidName);void unbind(in Name n)raises(NotFound, CannotProceed, InvalidName);NamingContext new_context();NamingContext bind_new_context(in Name n)raises(NotFound, CannotProceed, InvalidName, AlreadyBound);void destroy()raises(NotEmpty);void list(in unsigned long how_many,out BindingList bl,out BindingIterator bi);};};The NamingContextExt 接 口 扩 展 了 NamingContext, 它 提 供 使 用 字 串 化 的 名 称 和URL 所 需 的 操 作 。module CosNaming {interface NamingContextExt : NamingContext {typedef string StringName;typedef string Address;typedef string URLString;StringName to_string(in Name n)raises(InvalidName);Name to_name(in StringName sn)raises(InvalidName);exception InvalidAddress {};URLString to_url(in Address addr, in StringName sn)raises(InvalidAddress, InvalidName);Object resolve_str(in StringName n)raises(NotFound, CannotProceed, InvalidName);使 用 命 名 服 务 14-11


默 认 的 命 名 上 下 文};};默 认 的 命 名 上 下 文客 户 端 应 用 可 以 指 定 一 个 默 认 的 命 名 上 下 文 , 应 用 将 要 考 虑 用 该 上 下 文 来 作 其 根上 下 文 。 注 意 默 认 的 命 名 上 下 文 是 仅 与 该 客 户 应 用 相 关 的 root ( 根 ), 实 际 上 , 它可 以 包 含 于 另 外 一 个 上 下 文 中 。在 C++ 下 取 得 默 认 的 上 下 文C++:<strong>VisiBroker</strong> ORB 方 法 resolve_initial_references 可 以 由 客 户 端 应 用 使 用 以 取 得默 认 的 命 名 上 下 文 。 默 认 的 命 名 上 下 文 必 须 已 在 客 户 端 应 用 的 启 动 过 程 中 通 过 传 递ORBInitRef 命 令 行 变 量 作 了 指 定 。 以 下 的 示 例 说 明 C++ 客 户 应 用 应 该 如 何 调 用 该方 法 。#include "CosNaming_c.hh". . .int main(int argc, char* const* argv) {try {CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);. . .CORBA::Object_var ref = orb->resolve_initial_references("NameService");CosNaming::NamingContext_var rootContext =CosNaming::NamingContext::_narrow(ref);. . .} catch(const CORBA::Exception& e) {cout


命 名 服 务 属 性命 名 服 务 属 性命 名 服 务 的 属 性 为 :表 14.1命 名 服 务 属 性属 性 默 认 说 明vbroker.naming.adminPwd inprise 管 理 性 Visibroker 命 名 服 务操 作 所 需 要 的 密 码 。truevbroker.naming.enableClusterFailOver当 设 置 为 true 时 , 它 指 定 安装 一 个 接 收 器 来 处 理 从 命 名 服务 检 索 到 的 对 象 的 失 效 恢 复 功能 。 当 对 象 失 效 时 , 尝 试 透 明地 从 与 原 来 的 集 群 相 同 的 集 群中 重 新 连 接 到 另 外 一 个 对 象 。vbroker.naming.enableSlave 0 当 设 置 为 true 时 , 允 许 主 /从 命 名 服 务 配 置 。 参 阅 “ 失效 恢 复 ” 以 取 得 关 于 配 置 主 /从 命 名 服 务 的 详 情 。vbroker.naming.iorFile ns.ior 指 定 存 储 命 名 服 务 IOR 的 完整 路 径 。 如 果 您 不 设 定 该 属性 , 则 命 名 服 务 将 尝 试 将 其IOR 输 入 到 当 前 目 录 下 一 个命 名 为 ns.ior 的 文 件 。 当 文件 尝 试 输 出 其 IOR 时 , 它 会隐 式 地 忽 略 文 件 访 问 许 可 违例 。vbroker.naming.LogLevel emerg 指 定 要 从 命 名 服 务 输 出 的 日 志信 息 的 级 别 。vbroker.naming.propBindOn 0 如 果 设 置 为 true, 则 允 许 隐式 集 群 特 性 。vbroker.naming.smrr.pruneStaleRef1 该 属 性 在 命 名 服 务 集 群 使 用 智能 循 环 标 准 时 起 作 用 。 当 该 属性 被 设 置 为 1 时 , 如 果 命 名 服务 发 现 一 个 以 前 限 制 到 使 用 智能 循 环 标 准 的 旧 对 象 引 用 , 则将 其 删 除 。 如 果 该 属 性 设 置 为0, 则 不 删 除 该 集 群 下 的 旧 的对 象 引 用 限 制 。 但 是 , 不 论vbroker.naming.smrr.pruneStaleRef 属 性 设 为 何 值 , 使 用智 能 循 环 标 准 的 集 群 始 终 会 在resolve() 或 select() 调 用 之后 返 回 一 个 活 动 的 对 象 引 用( 如 果 存 在 这 样 对 象 限 制 )。在 默 认 情 况 下 , 该 属 性 的 值 被设 定 为 1, 4.5 命 名 服 务 中 的隐 式 集 群 使 用 智 能 循 环 标 准 。使 用 命 名 服 务 14-13


可 插 入 的 备 份 存 储可 插 入 的 备 份 存 储以 前 版 本 的 命 名 服 务 将 其 命 名 空 间 ( 即 , 命 名 上 下 文 和 对 象 / 名 称 限 制 集 ) 保 留在 内 存 中 。 但 是 , 它 将 所 有 可 修 改 的 操 作 从 其 命 名 空 间 中 导 入 一 个 日 志 文 件 。 此后 , 当 要 启 动 命 名 服 务 以 重 建 以 前 的 命 名 空 间 时 , 可 以 使 用 这 个 平 面 文 件 。现 行 的 命 名 服 务 通 过 使 用 可 插 入 的 备 份 存 储 来 保 存 其 命 名 空 间 。 命 名 空 间 是 永 久 性与 否 取 决 于 您 配 置 备 份 存 储 的 方 式 : 是 要 使 用 JDBC 适 配 器 , 即 Java 命 名 和 目 录接 口 (JNDI, 已 通 过 LDAP 认 证 ); 还 是 要 使 用 默 认 配 置 , 即 内 置 适 配 器 。备 份 存 储 的 类 型支 持 的 备 份 存 储 适 配 器 的 类 型 为 :● 内 置 适 配 器● 适 用 于 关 系 型 数 据 库 的 JDBC 适 配 器● DataExpress 适 配 器● JNDI ( 仅 适 用 于 LDAP)注 : 有 关 使 用 可 插 入 式 适 配 器 的 实 例 的 详 情 , 请 查 看 以 下 目 录 下 的 代 码 :/examples/ins/pluggable_adaptors内 置 适 配 器内 置 适 配 器 将 命 名 空 间 保 留 信 息 在 内 存 中 , 该 适 配 器 是 非 永 久 性 的 。 在 默 认 情 况下 , 命 名 服 务 使 用 该 适 配 器 。JDBC 适 配 器关 系 型 数 据 库 通 过 JDBC 来 支 持 。 以 下 的 数 据 库 已 通 过 认 证 , 它 们 可 以 与 命 名 服 务JDBC 适 配 器 一 起 工 作 :● JDataStore● Oracle● Sybase● Microsoft SQLServer● DB2● InterbaseDataExpress 适 配 器除 了 JDBC 适 配 器 之 外 , 还 有 一 个 允 许 您 从 本 地 访 问 JDataStore 数 据 库 的DataExpress 适 配 器 。 通 过 该 适 配 器 访 问 JDataStore 要 比 通 过 JDBC 来 访 问 快 得多 , 但 是 DataExpress 适 配 器 有 一 些 限 制 条 件 。 它 仅 支 持 在 命 名 服 务 所 处 的 机 器14-14 <strong>VisiBroker</strong> 开 发 者 指 南


可 插 入 的 备 份 存 储上 运 行 的 本 地 数 据 库 。 要 访 问 远 端 JDataStore 数 据 库 , 您 必 须 使 用 JDBC 适 配器 。JNDI 适 配 器JNDI 适 配 器 也 受 支 持 。 Sun 的 JNDI (Java 命 名 和 目 录 接 口 ) 提 供 到 整 个 企 业内 的 多 个 命 名 和 目 录 服 务 的 标 准 和 接 口 。 JNDI 具 有 一 个 必 须 由 不 同 的 命 名 和 服 务销 售 商 确 认 的 服 务 供 应 商 接 口 (SPI)。 有 不 同 的 SPI 模 块 可 用 于 NetscapeLDAP 服 务 器 、 Novell NDS、 WebLogic Tengah 等 。 通 过 支 持 JNDI,<strong>VisiBroker</strong> <strong>Edition</strong> 命 名 服 务 , 您 可 以 方 便 地 利 用 这 些 命 名 和 目 录 服 务 及 其 它 未来 的 SPI 供 应 商 。 但 是 , JNDI 适 配 器 仅 通 过 了 Netscape LDAP Server 4.0 认证 。配 置 和 使 用注 :备 份 存 储 适 配 器 是 可 插 入 的 , 这 意 味 着 , 当 启 动 命 名 服 务 时 , 所 使 用 的 这 类 适 配 器可 以 由 用 户 自 定 义 的 存 储 在 所 使 用 的 配 置 ( 属 性 ) 文 件 中 的 信 息 来 指 定 。 除 内 置适 配 器 外 , 所 有 的 适 配 器 均 提 供 永 久 支 持 。 当 您 想 要 使 用 轻 量 级 命 名 服 务 ( 其 命 名空 间 整 个 保 存 于 内 存 中 ) 时 , 您 应 该 使 用 内 置 适 配 器 。在 现 行 命 名 服 务 版 本 下 , 当 命 名 服 务 正 在 运 行 时 , 您 不 能 改 变 设 置 。 要 改 变 设 置时 , 您 必 须 关 闭 服 务 , 修 改 配 置 文 件 , 然 后 再 重 新 启 动 命 名 服 务 。属 性 文 件大 体 上 说 , 与 在 命 名 服 务 中 一 样 , 使 用 哪 一 个 适 配 器 及 其 特 定 的 配 置 要 在 命 名 服 务属 性 文 件 中 来 处 理 。 所 有 适 配 器 的 公 共 默 认 属 性 为 :表 14.2所 有 适 配 器 的 公 共 默 认 属 性属 性 默 认 说 明vbroker.naming.backingStoreTypeJDBC 适 配 器 属 性InMemory以 下 几 节 描 述 JDBC 适 配 器 属 性 。● vbroker.naming.backingStoreType指 定 要 使 用 的 命 名 适 配 器 的 类型 。 该 属 性 指 定 您 想 要 命 名 服务 使 用 哪 一 类 备 份 存 储 。 合 法的 选 项 为 :InMemory、 JDBC、Dx、 JNDI。 默 认 类 型 为InMemory。vbroker.naming.cacheOn 0 指 定 是 否 要 使 用 命 名 服 务cache。vbroker.naming.cacheSize 5 在 命 名 服 务 cache 开 启 时 ,指 定 该 cache 的 大 小 。该 属 性 应 该 设 置 为 JDBC。 另 外 , 也 必 须 为 JDBC 适 配 器 设 置 poolSize 、jdbcDriver 、url 、 loginName 和 loginPwd 属 性 。使 用 命 名 服 务 14-15


可 插 入 的 备 份 存 储● vbroker.naming.jdbcDriver该 属 性 指 定 访 问 用 作 备 份 存 储 的 数 据 库 所 需 要 的 JDBC 驱 动 程 序 。 命 名 服 务 装载 所 指 定 的 适 用 的 JDBC 驱 动 程 序 。 默 认 驱 动 程 序 为 Java DataStore JDBC 驱动 程 序 。JDBC 驱 动 程 序 值com.borland.datastore.jdbc.DataStoreDrivercom.sybase.jdbc.SybDriveroracle.jdbc.driver.OracleDriverinterbase.interclient.Driverweblogic.jdbc.mssqlserver4.DriverCOM.ibm.db2.jdbc.app.DB2Driver说 明JDataStore 驱 动 程 序Sybase 驱 动 程 序Oracle 驱 动 程 序Interbase 驱 动 程 序WebLogic MS SQLServer 驱 动 程 序IBM DB2 驱 动 程 序● vbroker.naming.loginName该 属 性 是 与 数 据 库 相 关 连 的 登 录 名 。 默 认 值 为 VisiNaming。● vbroker.naming.loginPwd该 属 性 是 与 数 据 库 相 关 连 的 登 录 密 码 。 默 认 值 为 VisiNaming。● vbroker.naming.poolSize该 属 性 指 定 在 使 用 JDBC 适 配 器 作 为 备 份 存 储 时 您 的 连 接 池 中 的 数 据 库 连 接 数量 。 默 认 值 是 5, 但 是 该 值 可 以 调 升 成 任 何 数 据 库 可 以 处 理 的 值 。 如 果 您 希 望 可以 向 命 名 服 务 发 出 多 个 请 求 , 则 您 可 以 加 大 该 值 。● vbroker.naming.url该 属 性 指 定 您 要 访 问 的 数 据 库 的 位 置 。 设 置 取 决 于 正 在 使 用 的 数 据 库 。 默 认 值 是JDataStore, 数 据 库 的 位 置 是 当 前 的 目 录 , 命 名 为 rootDB.jds。 您 可 以 使 用 任何 您 喜 欢 的 名 称 , 不 一 定 要 用 rootDB.jds。 配 置 文 件 需 要 作 相 应 的 更 新 。URL 名 称jdbc:borland:dslocal:jdbc:sybase:Tds::/jdbc:oracle:thin:@::jdbc:interbase:///jdbc:weblogic:mssqlserver4:@:jdbc:db2:说 明JDataStore URLSybase URLOracle URLInterbase 1 URLWebLogic MS SQLServer URLIBM DB2 2 URL本 地 驱 动 程 序 的 DataExpress 3 URL14-16 <strong>VisiBroker</strong> 开 发 者 指 南


可 插 入 的 备 份 存 储1在 通 过 JDBC 访 问 InterBase 时 , 您 应 该 先 启 动 InterServer。 如 果 InterBase 服 务 器 驻 留 在 本 地主 机 上 , 则 指 定 作 为 localhost ; 否 定 指 定 其 作 主 机 名 。 如 果 InterBase 数 据 库 驻 留 在Windows NT, 则 指 定 作 为 driver:\\dir1\dir2\\db.gdb ( 第 一 个 反 斜 杠 [\]的 作 用 是 让 第 二 个 反 斜 杠 [\] 逃 脱 )。 如 果 InterBase 数 据 库 驻 留 在 UNIX 上 , 则 指 定 作 为 \dir1\dir2\db.gdb。 您 可 以 从 http://www.interbase.com/ 取 得 更 多 的信 息 。2在 您 访 问 DB2 via JDBC 之 前 , 您 必 须 通 过 客 户 配 置 助 手 用 数 据 库 的 别 名 来 注 册数 据 库 。 在 注 册 了 数 据 库 之 后 , 您 不 必 为 vbroker.naming.url 属 性 指 定 和 。3如 果 JDataStore 数 据 库 驻 留 在 Windows NT 上 , 则 应 该 是 Driver:\\dir1\\dir2\\db.jds ( 第 一 个 反 斜 杠 [\] 的 作 用 是 让 第 二 个 反 斜 杠 [\] 逃 脱 。) 如 果 JDataStore 数 据 库 驻 留 在 UNIX 上 , 则 应 该 是 /dir1/dir2/db.jds。DataExpress 适 配 器 属 性以 下 几 小 节 说 明 DataExpress 适 配 器 的 属 性 。● vbroker.naming.backingStoreType该 属 性 应 该 设 置 为 Dx。● vbroker.naming.loginName该 属 性 是 与 数 据 库 相 关 边 的 登 录 名 。 默 认 值 为 VisiNaming。● vbroker.naming.loginPwd该 属 性 是 与 数 据 库 相 关 连 的 登 录 密 码 。 默 认 值 为 VisiNaming。● vbroker.naming.url该 属 性 指 定 数 据 库 的 位 置 。JNDI 适 配 器 属 性以 下 的 实 例 说 明 可 能 会 出 现 在 JNDI 适 配 器 配 置 文 件 中 的 设 置 :表 14.3设 置JNDI 适 配 器 配 置 文 件 的 实 例vbroker.naming.backingStoreType=JNDIvbroker.naming.loginName=说 明指 定 备 份 存 储 库 的 类 型 , 对 JNDA 适 配 器 而言 , 该 类 型 为 JNDI 。JNDI 备 份 服 务 器 上 的 用 户 登 录 名 。vbroker.naming.loginPwd= JNDI 备 份 服 务 器 用 户 的 密 码 。vbroker.naming.jndiInitialFactory=com.s 指 定 JNDI 初 始 工 厂 。un.jndi.ldap.LdapCtxFactoryvbroker.naming.jndiProviderURL=ldap: 指 定 JNDI 提 供 者 URL//:389/vbroker.naming.jndiAuthentication=simple指 定 JNDI 备 份 服 务 器 所 支 持 的 JNDI 验 证 类型 。注 : 要 将 模 式 / 属 性 增 加 到 目 录 服 务 器 , 用 户 必 须 有 必 要 的 权 利 。使 用 命 名 服 务 14-17


集 群高 速 缓 存 实 用 工 具注 :开 启 高 速 缓 存 实 用 工 具 后 , 您 可 以 改 进 备 份 存 储 的 性 能 。 例 如 , 就 JDBC 适 配 器 而言 , 每 当 有 解 析 或 限 制 操 作 时 , 直 接 访 问 数 据 库 相 对 较 慢 。 如 果 您 可 以 将 结 果 存 入高 速 缓 存 , 您 就 可 以 减 少 访 问 数 据 库 的 次 数 。 在 开 启 高 速 缓 实 用 工 具 前 , 要 留 意 许多 注 意 事 项 。 首 先 , 要 确 定 使 用 高 速 缓 存 (cache) 的 命 名 服 务 是 唯 一 一 个 访 问 基本 数 据 的 命 名 服 务 , 否 则 , 使 用 命 名 服 务 的 客 户 可 能 会 得 到 错 误 的 数 据 , 这 是 因 为cache 中 可 能 会 包 含 过 时 的 数 据 。 仅 当 同 一 数 据 单 元 被 访 问 一 次 以 上 时 , 您 才 可 以看 到 性 能 的 改 善 。除 非 您 可 以 绝 对 确 定 高 速 缓 存 可 以 改 进 您 的 环 境 中 的 性 能 , 否 则 , 不 要 将 它 设 置 为开 启 。高 速 缓 存 实 用 工 具 实 现 一 个 上 下 文 一 个 cache。 每 个 上 下 文 中 都 安 装 一 个 cache,它 用 于 存 储 上 下 文 和 对 象 。 该 cache 的 大 小 是 可 调 的 。 在 默 认 情 况 下 , 该 cache的 大 小 是 5。要 使 用 高 速 缓 存 实 用 工 具 , 请 将 下 列 属 性 加 入 到 您 的 配 置 文 件 中 :vbroker.naming.cacheOn=1vbroker.naming.CacheSize=5集 群<strong>VisiBroker</strong> <strong>Edition</strong> 支 持 集 群 功 能 , 该 功 能 允 许 多 个 对 象 限 制 与 单 个 名 称 相 关 联 。这 样 一 来 , 命 名 服 务 就 可 以 在 集 群 中 的 不 同 限 制 之 间 执 行 负 载 平 衡 。 您 可 以 在 创 建集 群 时 确 定 一 个 负 载 平 衡 标 准 。 随 后 , 要 在 集 群 上 解 析 “ 名 称 - 对 象 ” 限 制 的 客户 , 就 可 以 在 不 同 的 集 群 服 务 器 成 员 之 间 实 现 负 载 平 衡 。集 群 是 一 种 将 一 个 Name 与 一 组 对 象 引 用 联 结 在 一 起 的 多 限 制 机 制 。 集 群 的 创 建 是通 过 ClusterManager 引 用 完 成 的 。 在 创 建 过 程 中 , ClusterManager 的create_cluster 方 法 使 用 一 个 指 定 要 使 用 的 标 准 的 String ( 字 串 ) 参 数 。 这 种 方法 返 回 集 群 的 一 个 引 用 , 通 过 使 用 这 个 引 用 , 您 可 以 增 加 、 删 除 集 群 的 成 员 , 并 可以 在 成 员 之 间 切 换 。 在 确 定 了 集 群 的 组 成 之 后 , 您 可 以 将 它 的 具 有 特 定 名 称 的 引 用限 制 到 命 名 服 务 中 的 任 何 上 下 文 。 这 样 一 来 , 随 后 对 于 Name 的 解 析 操 作 将 返 回 集群 中 一 个 特 定 的 对 象 引 用 。集 群 标 准注 :在 默 认 情 况 下 , 命 名 服 务 在 集 群 上 使 用 RoundRobin ( 循 环 标 准 ) 集 群 创 建 之后 , 它 的 标 准 不 能 改 变 。 不 支 持 用 户 自 定 义 标 准 , 但 支 持 的 标 准 会 与 日 俱 增 。 除 了默 认 的 RoundRobin 标 准 外 , 另 一 个 当 前 可 用 的 标 准 是 SmartRoundRobin。SmartRoundRobin 和 RoundRobin 之 间 的 区 别 是 SmartRoundRobin 执 行 一些 确 认 操 作 以 确 定 CORBA 对 象 引 用 是 活 动 的 ; 对 象 引 用 所 引 用 的 是 处 于 准 备 就绪 状 态 的 CORBA 服 务 器 。我 们 不 建 议 您 使 用 SmartRoundRobin, 因 为 当 前 的 实 现 将 激 活 所 有 被 确 认 为 活动 的 对 象 。 另 外 , 集 群 失 效 恢 复 功 能 仅 可 以 在 RoundRobin 标 准 下 使 用 。14-18 <strong>VisiBroker</strong> 开 发 者 指 南


集 群 标 准集 群 和 ClusterManager 接 口虽 然 集 群 与 命 名 上 下 文 非 常 相 似 , 但 是 上 下 文 中 找 到 的 一 些 标 准 方 法 是 与 集 群 无 关的 。 例 如 , 将 命 名 上 下 文 限 制 到 集 群 没 有 意 义 , 因 为 集 群 应 该 包 含 一 组 对 象 引 用 ,而 不 是 命 名 上 下 文 。 但 是 , 集 群 接 口 与 NamingContext 接 口 共 享 许 多 方 法 , 如bind、 rebind、 resolve、 unbind 和 list。 该 公 共 操 作 组 主 要 与 组 中 的 操 作 有 关 。唯 一 与 集 群 有 关 的 操 作 是 pick。 两 者 之 间 的 另 外 一 个 重 大 差 别 是 集 群 不 支 持 混 合名 。 它 仅 可 以 使 用 单 一 成 分 的 名 称 , 这 是 因 为 集 群 没 有 层 次 型 的 目 录 结 构 , 而 它 将其 对 象 引 用 存 储 在 一 个 平 面 结 构 中 。集 群 接 口 的 IDL 规 范CosNamingExt module {typedef sequence ClusterList;enum ClusterNotFoundReason {missing_node,not_context,not_cluster_context};exception ClusterNotFound {ClusterNotFoundReason why;CosNaming::Name rest_of_name;};exception Empty {};interface Cluster {Object select() raises(Empty);void bind(in CosNaming::NameComponent n, in Object obj)raises(CosNaming::NamingContext::CannotProceed,CosNaming::NamingContext::InvalidName,CosNaming::NamingContext::AlreadyBound);void rebind(in CosNaming::NameComponent n, in Object obj)raises(CosNaming::NamingContext::CannotProceed,CosNaming::NamingContext::InvalidName);Object resolve(in CosNaming::NameComponent n)raises(CosNaming::NamingContext::NotFound,CosNaming::NamingContext::CannotProceed,CosNaming::NamingContext::InvalidName);void unbind(in CosNaming::NameComponent n)raises(CosNaming::NamingContext::NotFound,CosNaming::NamingContext::CannotProceed,CosNaming::NamingContext::InvalidName);void destroy()raises(CosNaming::NamingContext::NotEmpty);void list(in unsigned long how_many,out CosNaming::BindingList bl,out CosNaming::BindingIterator bi);};ClusterManager 接 口 的 IDL 规 范CosNamingExt module {interface ClusterManager使 用 命 名 服 务 14-19


集 群 标 准Cluster create_cluster(in string algo);Cluster find_cluster(in CosNaming::NamingContext ctx, in CosNaming::Namen)raises(ClusterNotFound, CosNaming::NamingContext::CannotProceed,CosNaming::NamingContext::InvalidName);Cluster find_cluster_str(in CosNaming::NamingContext ctx, in string n)raises(ClusterNotFound, CosNaming::NamingContext::CannotProceed,CosNaming::NamingContext::InvalidName);ClusterList clusters();};};创 建 集 群要 创 建 一 个 集 群 , 您 可 以 使 用 集 群 管 理 器 接 口 。 启 动 命 名 服 务 时 , 会 自 动 创 建 单 一的 ClusterManager 对 象 。 每 个 命 名 服 务 中 仅 有 一 个 ClusterManager。ClusterManager 功 能 是 创 建 、 检 索 和 追 踪 命 名 服 务 中 的 集 群 。1 限 制 到 您 要 用 以 创 建 集 群 对 象 的 命 名 服 务 器 。2 调 用 工 厂 引 用 上 的 get_cluster_manager 方 法 , 以 取 得 集 群 管 理 器 的 引 用 。3 使 用 指 定 的 集 群 标 准 来 创 建 集 群 。4 将 对 象 限 制 到 使 用 集 群 的 名 称 上 。5 将 Cluster 对 象 本 身 限 制 到 一 个 名 称 。6 通 过 指 定 的 集 群 标 准 的 集 群 引 用 来 解 析 。C++: . . .ExtendedNamingContextFactory_var myFactory =ExtendedNamingContextFactory::_bind(orb, "NamingService");ClusterManager_var clusterMgr = myFactory->get_cluster_manager();Cluster_var clusterObj = clusterMgr->create_cluster("RoundRobin");clusterObj->bind(new NameComponent("member1", "aCluster"), obj1);clusterObj->bind(new NameComponent("member2", "aCluster"), obj2);clusterObj->bind(new NameComponent("member3", "aCluster"), obj3);NameComponent_var myClusterName = new NameComponent("ClusterName", "");root->bind(myClusterName, clusterObj);root->resolve(myClusterName); // 返 回 集 群 的 一 个 成 员root->resolve(myClusterName); // 返 回 集 群 的 下 一 个 成 员root->resolve(myClusterName); // 返 回 集 群 的 最 后 一 个 成 员. . .Java: . . .ExtendedNamingContextFactory myFactory =ExtendedNamingContextFactoryHelper.bind(orb, "NamingService");ClusterManager clusterMgr = myFactory.get_cluster_manager();Cluster clusterObj = clusterMgr.create_cluster("RoundRobin");clusterObj.bind(new NameComponent("member1", "aCluster"), obj1);clusterObj.bind(new NameComponent("member2", "aCluster"), obj2);clusterObj.bind(new NameComponent("member3", "aCluster"), obj3);NameComponent myClusterName = new NameComponent("ClusterName", "");root.bind(myClusterName, clusterObj);14-20 <strong>VisiBroker</strong> 开 发 者 指 南


失 效 恢 复root.resolve(myClusterName) // 返 回 集 群 的 一 个 成 员root.resolve(myClusterName) // 返 回 集 群 的 下 一 个 成 员 。root.resolve(myClusterName) // 返 回 集 群 的 最 后 一 个 成 员 。. . .显 式 和 隐 式 集 群集 群 功 能 可 以 为 一 个 命 名 服 务 自 动 开 启 。 要 注 意 的 是 , 一 旦 开 启 了 该 实 现 工 具 , 将会 自 动 透 明 地 创 建 一 个 集 群 以 限 制 对 象 。 所 使 用 的 标 准 固 定 为 循 环 。 其 含 义 是 , 将数 个 对 象 限 制 到 命 名 服 务 器 中 的 同 一 名 称 是 可 能 的 。 反 过 来 , 解 析 该 名 将 会 返 回 这些 对 象 之 一 , 而 一 个 unbind 操 作 将 销 毁 与 该 名 称 相 关 联 的 集 群 。 这 意 味 着 命 名 服务 不 再 遵 守 CORBA 规 范 。 互 操 作 命 名 规 范 明 确 地 禁 止 将 数 个 对 象 限 制 到 同 一 名称 。 这 是 因 为 , 在 一 个 遵 守 规 范 的 命 名 服 务 中 , 如 果 一 个 客 户 尝 试 使 用 将 同 一 名 称限 制 到 不 同 的 对 象 , 将 会 掷 出 AlreadyBound 违 例 。 从 一 开 始 , 用 户 就 要 决 定 是 否要 将 这 一 特 性 用 于 特 定 的 服 务 器 并 应 该 一 直 坚 持 这 一 决 策 。注 : 不 要 从 隐 式 集 群 模 式 切 换 到 显 式 集 群 模 式 , 因 为 这 样 会 破 坏 备 份 存 储 。一 旦 将 隐 式 集 群 特 性 用 于 一 个 命 名 服 务 器 , 则 应 该 在 该 特 性 开 启 的 情 况 下 , 继 续 激活 该 服 务 器 。 要 开 启 该 特 性 , 您 需 要 在 配 置 文 件 中 定 义 以 下 属 性 值 :vbroker.naming.propBindOn=1注 : 有 关 同 时 具 有 显 式 和 隐 式 集 群 的 实 例 , 请 查 看 以 下 目 录 下 的 代 码 :/examples/ins/implicit_clustering/examples/ins/explicit_clustering负 载 平 衡ClusterManager 和 智 能 代 理 都 可 以 提 供 循 环 负 载 平 衡 实 用 工 具 , 但 它 们 的 性 质 差别 很 大 。 您 可 以 自 由 地 从 智 能 代 理 上 得 到 负 载 平 衡 。 当 一 个 服 务 器 启 动 时 , 它 自 动将 自 己 注 册 在 智 能 代 理 上 , 而 这 反 过 来 又 允 许 <strong>VisiBroker</strong> <strong>Edition</strong> 提 供 一 个 方 便而 专 用 的 方 法 让 客 户 取 得 服 务 器 的 一 个 引 用 。 但 是 , 所 有 这 些 自 动 操 作 都 是 要 付 出代 价 的 。 您 无 权 决 定 用 什 么 来 组 建 群 组 及 群 组 成 员 。 智 能 代 理 会 为 您 作 所 有 的 决定 。 正 因 为 如 此 , 才 诞 生 了 集 群 以 提 供 替 代 方 案 。 集 群 提 供 了 一 个 编 程 的 方 法 以 定义 各 创 建 集 群 的 属 性 。 它 允 许 您 定 义 标 准 用 于 集 群 , 并 在 选 择 集 群 成 员 时 享 有 充 分的 灵 活 性 。 虽 然 标 准 在 创 建 时 是 固 定 的 , 但 客 户 可 以 在 集 群 的 生 命 周 期 内 从 集 群 上增 加 或 删 除 成 员 。失 效 恢 复命 名 服 务 实 现 使 用 主 / 备 模 式 的 失 效 恢 复 功 能 。 两 个 命 名 服 务 器 必 须 同 时 运 行 , 主服 务 器 处 于 活 动 模 式 而 备 用 服 务 器 处 于 备 用 模 式 。 主 备 命 名 服 务 器 都 必 须 支 持 永 久存 储 库 中 的 基 础 数 据 , 两 个 服 务 器 的 高 速 缓 存 实 用 工 具 都 必 须 关 闭 , 这 会 迫 使 用 每个 服 务 器 直 接 处 理 备 份 存 储 库 , 以 确 保 其 数 据 保 持 不 变 。如 果 两 个 服 务 器 都 是 活 动 的 , 则 使 用 命 名 服 务 的 客 户 总 是 优 先 使 用 主 服 务 器 。 如 果主 服 务 器 意 外 停 机 , 则 备 用 服 务 器 接 管 其 职 。 主 备 倒 换 是 无 缝 的 、 对 客 户 透 明 的 。使 用 命 名 服 务 14-21


C++ 编 译 和 链 接 程 序注 :但 是 , 备 用 命 名 服 务 器 不 会 变 成 主 用 服 务 器 。 当 主 用 服 务 器 不 可 用 时 , 它 提 供 临 时支 持 。 同 进 , 用 户 应 该 采 取 必 要 的 矫 正 行 动 以 恢 复 主 服 务 器 。 当 主 服 务 器 恢 复 之后 , 仅 由 新 客 户 发 起 的 请 求 才 会 送 到 主 服 务 器 。 已 限 制 到 备 用 服 务 器 的 客 户 不 会 自动 切 换 回 主 服 务 器 。当 失 效 恢 复 出 现 时 , 它 对 于 客 户 是 透 明 的 , 但 可 能 会 有 所 延 迟 , 这 是 因 为 备 用 命 名服 务 器 上 的 服 务 器 对 象 可 能 由 于 进 入 的 请 求 的 要 求 而 必 须 激 活 。 另 外 , 临 时 对 象 引用 ( 如 继 续 器 ) 不 再 有 效 。 这 是 正 常 的 , 因 为 使 用 临 时 继 续 器 引 用 的 客 户 必 须 为 那些 失 效 的 引 用 作 准 备 。 通 常 , 一 个 命 名 服 务 器 从 不 保 留 太 多 的 资 源 密 集 型 继 续 器 对象 , 它 可 以 在 任 何 时 候 使 一 个 客 户 的 继 续 器 对 象 失 效 。 与 这 些 临 时 引 用 不 同 , 其 它使 用 永 久 引 用 的 客 户 请 求 将 被 重 新 发 送 到 备 用 命 名 服 务 器 。已 经 限 制 到 备 用 服 务 器 的 客 户 将 不 会 自 动 切 换 到 主 服 务 器 , 仅 提 供 一 个 级 别 的 失 效恢 复 支 持 。 所 以 , 如 果 备 用 命 名 服 务 器 也 停 机 , 则 命 名 服 务 不 可 用 。命 名 服 务 的 容 错 配 置必 须 有 两 个 服 务 器 正 运 行 。 您 必 须 指 定 其 中 一 个 为 个 主 服 务 器 而 另 一 个 为 备 用 服 务器 。 同 样 的 属 性 文 件 可 用 于 两 个 服 务 器 。 属 性 文 件 中 的 相 关 属 性 值 如 下 :vbroker.naming.enableSlave=1vbroker.naming.masterServerName=vbroker.naming.masterHost=vbroker.naming.masterPort=vbroker.naming.slaveServerName=vbroker.naming.slaveHost=vbroker.naming.slavePort=要 强 制 命 名 服 务 在 一 个 特 定 的 端 口 上 启 动 , 应 该 用 以 下 的 命 令 行 选 项 来 启 动 命 名 服务 器prompt> nameserv -J-Dvbroker.se.iiop_tp.scm.iiop_tp.listener.port=\com.inprise.vbroker.naming.ExtFactory 注 : 对 主 备 服 务 器 的 启 动 顺 序 没 有 限 制 。C++ 编 译 和 链 接 程 序C++: 使 用 命 名 服 务 的 C++ 应 用 需 要 包 含 以 下 生 成 的 文 件 :#include "CosNaming_c.hh"#include "CosNamingExt_c.hh"UNIX: UNIX 应 用 需 要 链 接 到 存 储 库 。● cosnm.so● cosnm_r.so ( 多 线 程 )Windows: Windows 应 用 需 要 链 接 到 以 下 存 储 库 :● cosnm.dll14-22 <strong>VisiBroker</strong> 开 发 者 指 南


Java 导 入 声 明● cosnm_r.dll (multithreaded)Java 导 入 声 明Java:使 用 <strong>VisiBroker</strong> <strong>Edition</strong> 朝 向 命 名 服 务 扩 展 功 能 的 Java 类 应 该 使 用 以 下 的 导 入 声明import com.inprise.vbroker.CosNamingExt.*;. . .如 果 您 有 兴 趣 访 问 命 名 服 务 所 遵 守 的 OMG 特 性 , 则 需 要 以 下 的 包 :import org.omg.CosNaming.*import org.omg.CosNaming.NamingContextPackage.*import org.omg.CosNaming.NamingContextExtPackage.*实 例 程 序警 告 :<strong>VisiBroker</strong> <strong>Edition</strong> 提 供 了 数 个 示 范 命 名 服 务 使 用 的 实 例 程 序 。 它 们 示 范 了 当 前命 名 服 务 可 用 的 所 有 新 特 性 , 它 们 可 以 在 examples/ins 目 录 下 找 到 。 在 examples/basic/bank_naming 目 录 下 , 可 以 找 到 一 个 示 范 命 名 服 务 基 本 用 法 的 银 行 命 名 实 例 。在 运 行 实 例 程 序 前 , 您 必 须 先 启 动 命 名 服 务 , 请 参 阅 第 14-5 页 " 运 行 命 名 服 务 "中 所 述 。 此 外 , 您 必 须 通 过 执 行 以 下 操 作 之 一 确 保 至 少 已 创 建 了 一 个 命 名 服 务 :● 启 动 命 名 服 务 ,( 参 阅 第 14-5 页 " 运 行 命 名 服 务 " 中 所 述 ), 这 样 会 自 动 创 建 一个 初 始 上 下 文 。● 使 用 <strong>VisiBroker</strong> <strong>Edition</strong> 控 制 台 ( 如 “ 用 户 指 南 ” 中 所 述 )。● 将 您 的 客 户 限 制 到 NamingContextFactory, 并 使 用 create_context 方 法 。● 让 您 的 客 户 使 用 ExtendedNamingContextFactory。如 果 未 创 建 上 下 文 , 则 当 客 户 尝 试 在 C++ 下 发 起CosNaming::NamingContext::bind 时 , 会 掷 出 一 个 CORBA::NO_IMPLEMENT 违 例 。如 果 未 创 建 上 下 文 , 则 当 客 户 尝 试 在 Java 下 发 起 bind 时 , 会 掷 出 一 个CORBA.NO_IMPLEMENT 违 例 。在 Java 下 限 制 名 称仅 适 用 于 Java: 银 行 命 名 实 例 使 用 AccountManager 接 口 打 开 一 个 帐 户 并 查 询 该 帐 户 中 的 余 额 。以 下 的 服 务 器 类 示 范 将 一 个 名 称 限 制 到 一 个 对 象 引 用 的 命 名 服 务 。 服 务 器 将 它 的IOR 传 递 到 命 名 服 务 的 根 上 下 文 中 , 随 后 客 户 将 对 其 进 行 检 索 。从 这 个 实 例 中 , 您 将 学 到 :1 如 何 使 用 <strong>VisiBroker</strong> ORB 实 例 上 的 resolve_initial_references 方 法 来 取 得命 名 服 务 的 根 上 下 文 的 引 用 。( 在 本 实 例 中 , 您 需 要 使 用 默 认 名 NameService来 启 动 命 名 服 务 。使 用 命 名 服 务 14-23


实 例 程 序2 如 何 通 过 使 用 NamingContextExtHelper 类 的 窄 转 化 方 法 , 对 根 上 下 文 的 引用 进 行 造 型 。3 如 何 为 您 的 AccountManagerImpl 对 象 创 建 POA 和 服 务 对 象 。4 最 后 , 如 何 使 用 NamingContext 接 口 的 bind 方 法 将 名 称“BankManager” 限 制 到 AccountManagerImpl 对 象 的 对 象 引 用 。import org.omg.PortableServer.*;import org.omg.CosNaming.*;public class Server {public static void main(String[] args) {try {// 初 始 化 ORB。org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);// 取 得 根 POA 的 引 用POA rootPOA =POAHelper.narrow(orb.resolve_initial_references("RootPOA"));// 取 得 命 名 服 务 根 上 下 文 的 引 用org.omg.CORBA.Object rootObj =orb.resolve_initial_references("NameService");NamingContextExt root = NamingContextExtHelper.narrow(rootObj);// 为 我 们 永 久 的 POA 创 建 方 针org.omg.CORBA.Policy[] policies = {rootPOA.create_lifespan_policy(LifespanPolicyValue.PERSISTENT)};// 用 正 确 的 方 针 创 建 myPOAPOA myPOA = rootPOA.create_POA( "bank_agent_poa",rootPOA.the_POAManager(),policies );// 创 建 服 务 对 象AccountManagerImpl managerServant = new AccountManagerImpl();// 确 定 服 务 对 象 IDbyte[] managerId = "BankManager".getBytes();// Activate the servant with the ID on myPOAmyPOA.activate_object_with_id(managerId, managerServant);// 激 活 POA 管 理 器rootPOA.the_POAManager().activate();// 将 银 行 管 理 器 与 根 上 下 文 中 的 名 称 联 结 起 来// 注 意 为 避 免 JDK 1.1.x 问 题 , 造 型 是 必 要 的 。((NamingContext)root).bind(root.to_name("BankManager"),myPOA.servant_to_reference(managerServant));System.out.println(myPOA.servant_to_reference(managerServant)+ " is ready.");// 等 待 进 入 的 请 求 。orb.run();} catch (Exception e) {e.printStackTrace();}}}14-24 <strong>VisiBroker</strong> 开 发 者 指 南


第章使 用 事 件 服 务第 15 章注 :本 章 介 绍 <strong>VisiBroker</strong> <strong>Edition</strong> 事 件 服 务 。对 象 管 理 组 (OMG) 事 件 服 务 被 OMG 通 知 服 务 取 代 。 我 们 强 烈 建 议 需 要 使 用 该功 能 的 <strong>VisiBroker</strong> <strong>Edition</strong> 用 户 使 用 单 独 的 OpenFusion 通 知 服 务 。概 述事 件 服 务 包 提 供 了 一 个 分 离 对 象 间 通 信 的 实 用 工 具 。 它 提 供 了 一 个 提 供 者 - 接 收 者通 信 模 型 , 该 模 型 允 许 多 个 提 供 者 对 象 通 过 一 个 事 件 通 道 同 时 发 送 数 据 给 多 个 接收 者 对 象 。 提 供 者 - 接 收 者 通 信 模 型 允 许 对 象 将 状 态 的 重 要 变 化 ( 例 如 , 磁 盘 空间 不 足 ) 传 达 给 其 它 任 何 可 能 对 此 事 件 感 兴 趣 的 对 象 。图 15.1提 供 者 - 接 收 者 通 信 模 型上 图 显 示 的 是 3 个 提 供 者 通 过 事 件 通 道 与 2 个 接 收 者 对 象 进 行 的 通 信 。 进 入 事 件 通道 的 数 据 流 由 提 供 者 对 象 处 理 , 流 出 事 件 通 道 的 数 据 流 由 接 收 者 对 象 处 理 。 如 果 上使 用 事 件 服 务 15-1


概 述图 中 所 示 的 3 个 提 供 者 每 秒 钟 各 发 送 1 条 消 息 , 则 每 个 接 收 者 每 秒 钟 将 收 到 3 条 消息 , 而 事 件 通 道 每 秒 钟 内 总 共 前 传 6 条 消 息 。事 件 通 道 既 是 事 件 的 接 收 者 又 是 事 件 的 提 供 者 。 在 提 供 者 和 接 收 者 之 间 传 递 的 数 据由 Any 表 示 , 允 许 任 何 CORBA 类 型 以 类 型 安 全 的 方 式 传 递 。 提 供 者 对 象 与 接 收者 对 象 通 过 事 件 通 道 使 用 标 准 CORBA 请 求 进 行 通 信 。代 理 接 收 者 和 提 供 者通 过 使 用 代 理 对 象 , 接 收 者 和 提 供 者 被 完 全 分 离 。 不 用 相 互 直 接 接 触 , 它 们 从EventChannel 得 到 一 个 代 理 对 象 并 与 该 对 象 沟 通 。 提 供 者 对 象 得 到 一 个 接 收 者 代理 , 而 接 收 者 对 象 得 到 一 个 提 供 者 代 理 。 EventChannel 为 接 收 者 和 提 供 者 代 理对 象 之 间 的 数 据 传 递 提 供 了 方 便 。 下 图 显 示 一 个 提 供 者 如 何 将 数 据 分 发 给 多 个 接收 者 。图 15.2接 收 者 和 提 供 者 代 理 对 象注 :上 图 所 示 的 事 件 通 道 是 一 个 单 独 的 进 程 , 但 它 也 可 以 作 为 提 供 者 对 象 的 进 程 的 一 部分 来 实 现 。 参 阅 第 15-21 页 " 启 动 事 件 服 务 " 以 取 得 更 详 细 信 息 。OMG 公 共 对 象 服 务 规 范<strong>VisiBroker</strong> <strong>Edition</strong> 事 件 服 务 实 现 遵 守 OMG 公 共 对 象 服 务 规 范 , 但 在 以 下 方 面例 外 :● <strong>VisiBroker</strong> <strong>Edition</strong> 事 件 服 务 仅 支 持 普 通 事 件 。 当 前 , <strong>VisiBroker</strong> <strong>Edition</strong> 事件 服 务 不 支 持 创 建 的 事 件 。15-2 <strong>VisiBroker</strong> 开 发 者 指 南


通 信 模 型● <strong>VisiBroker</strong> <strong>Edition</strong> 事 件 服 务 对 事 件 通 道 或 接 收 者 应 用 的 数 据 传 递 不 作 任 何 确认 。 TCP/IP 用 于 实 现 接 收 者 、 提 供 者 和 事 件 通 道 之 间 的 通 信 , 这 提 供 了 可 靠的 到 通 道 和 接 收 者 的 数 据 传 递 。 但 是 , 这 并 不 能 保 证 传 递 的 所 有 数 据 确 实 由 接 收者 处 理 。通 信 模 型事 件 服 务 为 提 供 者 和 接 收 者 提 供 了 拉 和 推 两 种 通 信 模 型 。 在 推 式 模 型 中 , 提 供 者 对象 通 过 将 数 据 流 推 向 接 收 者 来 控 制 数 据 流 。 在 拉 式 模 型 中 , 接 收 者 对 象 从 提 供 者 拉数 据 来 控 制 数 据 流 。EventChannel 使 提 供 者 和 接 收 者 不 必 知 道 另 一 方 对 象 在 通 道 上 所 使 用 的 模 型 。 这 意味 着 一 个 拉 型 提 供 者 可 以 为 一 个 推 型 接 收 者 提 供 数 据 , 而 一 个 推 型 提 供 者 可 以 为 一个 拉 型 接 收 者 提 供 数 据 。图 15.3推 式 模 型注 :上 图 所 示 的 事 件 通 道 是 一 个 单 独 的 进 程 , 但 它 也 可 以 作 为 提 供 者 对 象 的 进 程 的 一 部分 来 实 现 。 参 阅 第 15-21 页 " 启 动 事 件 服 务 " 以 取 得 更 详 细 信 息 。推 式 模 型在 两 种 通 信 模 型 中 , 推 式 模 型 更 为 普 遍 。 使 用 推 式 模 型 的 一 个 实 例 是 这 样 的 一 个 提供 者 : 它 监 视 磁 盘 可 用 空 间 , 并 在 磁 盘 空 间 占 满 时 给 有 关 的 接 收 者 发 出 通 知 。 推 型提 供 者 发 数 据 给 其 ProxyPushConsumer, 以 回 应 其 正 在 监 视 的 事 件 。使 用 事 件 服 务 15-3


通 信 模 型推 型 接 收 者 将 其 大 多 数 时 间 花 费 在 事 件 回 路 中 , 等 待 从 ProxyPushSupplier 而 来 的数 据 。 EventChannel 为 从 ProxyPushSupplier 到 ProxyPushConsumer 的 数 据 传 递 提供 了 方 便 。下 图 显 示 的 是 一 个 推 型 提 供 者 及 其 相 应 的 ProxyPushConsumer 对 象 。 该 图 也 显 示 了3 个 推 型 接 收 者 及 其 各 自 的 ProxyPushSupplier 对 象 。拉 式 模 型在 拉 式 模 型 中 , 事 件 通 道 定 期 从 提 供 者 拉 出 数 据 , 将 数 据 置 入 一 个 队 列 , 并 让 一 个接 收 者 可 以 将 它 拉 走 。 拉 型 接 收 者 的 一 个 实 例 是 一 个 或 多 个 定 期 检 测 网 络 路 由 以 作统 计 工 作 的 网 络 监 视 器 。拉 型 提 供 者 将 其 大 部 分 的 时 间 花 费 在 网 络 事 件 回 路 中 , 等 待 接 收 从ProxyPullConsumer 发 出 的 数 据 请 求 。 当 拉 型 接 收 者 准 备 好 处 理 更 多 的 数 据 时 , 它向 ProxyPullSupplier 请 求 数 据 。 EventChannel 从 提 供 者 拉 出 数 据 , 将 它 置 入 一 个队 列 并 让 ProxyPullSupplier 可 以 使 用 该 数 据 。下 图 显 示 的 是 一 个 拉 型 提 供 者 及 其 相 应 的 ProxyPullConsumer 对 象 。 图 中 同 时 也 显示 了 3 个 拉 型 接 收 者 及 其 相 应 的 ProxyPullSupplier 对 象 。图 15.4拉 式 模 型注 :上 图 所 示 的 事 件 通 道 为 一 个 单 独 的 进 程 , 它 也 可 以 作 为 提 供 者 对 象 的 进 程 的 一 部 分来 实 现 。 另 请 参 阅 第 15-22 页 " 进 程 内 事 件 通 道 (Java) ", 以 取 得 关 于 如 何 启 动Java 事 件 服 务 的 更 详 细 信 息 。15-4 <strong>VisiBroker</strong> 开 发 者 指 南


使 用 事 件 通 道使 用 事 件 通 道Windows:C++:Windows:Java:UNIX:要 创 建 一 个 EventChannel, 将 一 个 提 供 者 或 接 收 者 连 接 它 并 使 用 它 :1 创 建 并 启 动 EventChannel。创 建 并 启 动 事 件 通 道 :prompt> start vbj com.inprise.vbroker.CosEvent.EventServer -ior prompt> start vbj com.inprise.vbroker.CosEvent.EventServer -ior prompt> vbj com.inprise.vbroker.CosEvent.EventServer -ior &其 中 , 是 事 件 通 道 的 用 户 自 定 义 的 对 象 名 称 , 是 将要 写 入 该 对 象 的 ior 的 文 件 的 用 户 自 定 义 文 件 名 。仅 适 用 于 Java: 另 外 一 个 创 建 EventChannel 以 执 行 PushModelChannel 的 方 法 是 :注 :prompt> vbj PushModelChannel PushModelChannel 首 先 创 建 一 个 EventChannel 并 将 其 ior 传 递 到 用 户 指 定 的 文 件 。 此 后 , 其 它 用 户 ( 例 如 , PushModel) 就 可 以 使 用 最 初 引用 限 制 到 EventChannel。要 执 行 此 操 作 :prompt> vbj -DORBInitRef=EventService=file: PushModel不 管 用 何 种 方 式 创 建 事 件 通 道 , 务 必 确 定 将 中 所 指 定 的 名 称 创 建 到指 定 的 目 录 下 。仅 可 以 支 持 EventChannel 的 一 个 实 例 。 到 EventChannel 的 所 有 限 制 都 是 通 过调 用 orb.resolve_initial_references("EventService") 来 实 现 的 , 其 中"EventService" 是 硬 编 码 的 EventChannel 名 称 。1 连 接 到 EventChannel。2 从 通 道 取 得 一 个 管 理 对 象 , 然 后 用 它 来 取 得 一 个 代 理 对 象 。3 连 接 到 代 理 对 象 。4 开 始 传 递 或 接 收 数 据 。使 用 事 件 服 务 15-5


推 型 提 供 者 和 接 收 者 的 实 例表 15.1连 接 提 供 者 到 EventChannel随 着 所 连 接 的 对 象 是 提 供 者 或 者 是 接 收 者 以 及 所 使 用 的 通 信 模 型 的 不 同 , 执 行 这 些步 骤 的 方 法 会 有 所 不 同 。 下 表 显 示 的 是 适 用 于 提 供 者 的 方 法 。步 骤 推 型 提 供 者 拉 型 提 供 者限 制 到 EventChannel (C++) CosEventChannelAdmin::EventChannel::_narrow(orb::resolve_initial_references("EventService"))CosEventChannelAdmin::EventChannel::_narrow(orb::resolve_initial_references("EventService"))限 制 到 EventChannel (C++)EventChannelHelper.narrow(orb.resolve_initial_references("EventService"))下 表 显 示 的 是 适 用 于 接 收 者 的 方 法 。EventChannelHelper.narrow(orb.resolve_initial_references("EventService"))取 得 提 供 者 Admin EventChannel::for_suppliers() EventChannel::for_suppliers()取 得 接 收 者 代 理SupplierAdmin::obtain_push_consumer SupplierAdmin::obtain_pull_consumer()()添 加 提 供 者 到 EventChannelProxyPushConsumer::connect_push_supplier()ProxyPullConsumer::connect_pull_supplier()数 据 传 递 ProxyPushConsumer::push() Implements pull() and try_pull()表 15.2连 接 接 收 者 到 EventChannel步 骤 推 型 接 收 者 拉 型 接 收 者限 制 到 EventChannel (C++) CosEventChannelAdmin::EventChannel::_narrow(orb::resolve_initial_references("EventService"))CosEventChannelAdmin::EventChannel::_narrow(orb::resolve_initial_references("EventService"))限 制 到 EventChannel (Java)EventChannelHelper.narrow(orb.resolve_initial_references("EventService"))EventChannelHelper.narrow(orb.resolve_initial_references("EventService"))取 得 ConsumerAdmin EventChannel::for_consumers() EventChannel::for_consumers()取 得 提 供 者 代 理ConsumerAdmin::obtain_push_supplier ConsumerAdmin::obtain_pull_supplier()()添 加 接 收 者 到 EventChannelProxyPushSupplier::connect_push_consumer()ProxyPushSupplier::connect_pull_consumer()数 据 传 递 Implements push() ProxyPushSupplier::pull() andtry_pull()推 型 提 供 者 和 接 收 者 的 实 例本 节 包 括 两 个 小 节 。 第 一 小 节 描 述 C++ 下 的 推 型 提 供 者 和 接 收 者 应 用 实 例 。 第 二小 节 描 述 Java 下 的 推 型 提 供 者 和 接 收 者 应 用 实 例 。C++ 下 的 推 型 提 供 者 和 接 收 者本 节 描 述 推 型 提 供 者 和 接 收 者 应 用 实 例 。 在 执 行 过 程 中 , 提 供 者 应 用 提 示 用 户 输 入数 据 , 然 后 将 数 据 推 向 接 收 者 应 用 。 接 收 者 应 用 接 收 数 据 并 将 数 据 写 到 屏 幕 上 。15-6 <strong>VisiBroker</strong> 开 发 者 指 南


推 型 提 供 者 和 接 收 者 的 实 例推 型 提 供 者 应 用 在 PushModel.C 文 件 中 实 现 , 而 推 型 接 收 者 在 PushView.C 文件 中 实 现 。 这 些 文 件 可 以 在 您 的 系 统 中 安 装 C++ <strong>VisiBroker</strong> <strong>Edition</strong> 的 目 录 下 的examples/CosEvent 子 目 录 中 找 到 。派 生 PushSupplier 类C++:实 现 提 供 者 的 第 一 个 步 骤 是 从 如 下 所 示 的 PushSupplier 接 口 派 生 我 们 自 己 的PushModel 类 。module CosEventComm {interface PushSupplier {void disconnect_push_supplier();};};以 下 的 代 码 示 例 显 示 的 是 在 C++ 下 实 现 的 PushModel 类 。 当 通 道 遭 受 破 坏 时 ,EventChannel 将 调 用 disconnect_push_supplier 方 法 以 断 开 提 供 者 。 该 实 现 仅 打 印一 条 消 息 , 然 后 退 出 。 如 果 PushModel 对 象 是 永 久 型 的 , 该 方 法 也 可 以 调 用deactivate_obj 以 去 激 活 对 象 。// PushModel.C#include "CosEventComm_s.hh"#include "CosEventChannelAdmin_c.hh"class PushModel :public POA_CosEventComm::PushSupplier, public VISThread {public:void disconnect_push_supplier() {cout


推 型 提 供 者 和 接 收 者 的 实 例}CPushModel* model = NULL;CosEventChannelAdmin::ProxyPushConsumer_var pushConsumer = NULL;model = new PushModel(orb, pushConsumer, serverPOA);CORBA::String_var supplier_name(CORBA::string_dup("PushModel"));PortableServer::ObjectId_var objId =PortableServer::string_to_ObjectId(supplier_name);serverPOA->activate_object_with_id(objId, model);// 激 活 POA 管 理 器serverPOA->the_POAManager()->activate();CORBA::Object_var reference = serverPOA->servant_to_reference(model);cout


推 型 提 供 者 和 接 收 者 的 实 例提 供 者 应 用 的 一 个 不 同 的 线 程 提 示 用 户 输 入 字 串 , 等 待 输 入 字 串 , 然 后 将 字 串 转 换到 Any 对 象 。 最 后 , 数 据 被 “ 推 ” 到 接 收 者 代 理 对 象 。. . .while(true) {VISPortable::vsleep(_delay);try {char buf[81];std::string str;sprintf(buf, "%s%d", "Hello #", ++_counter);str = buf;CORBA::Any_var message = new CORBA::Any();*message


推 型 提 供 者 和 接 收 者 的 实 例{}void delay(int time) { delay = time; }void start() {// 启 动 线 程run();}void disconnect_push_supplier() {cout


推 型 提 供 者 和 接 收 者 的 实 例};intCORBA::ORB_varPortableServer::POA_varCosEventComm::PushConsumer_var_counter;_orb;_pushConsumer;_myPOA;int main(int argc, char* const* argv){try {// 初 始 化 ORB。CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);// 取 得 根 POA 的 引 用CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");PortableServer::POA_var rootPOA = PortableServer::POA::_narrow(obj);/ / 为 永 久 POA 创 建 策 略CORBA::PolicyList policies;policies.length(1);policies[(CORBA::ULong)0] =rootPOA->create_lifespan_policy(PortableServer::PERSISTENT);PortableServer::POAManager_var poa_manager = rootPOA->the_POAManager();// 用 正 确 的 策 略 创 建 serverPOAPortableServer::POA_var serverPOA =rootPOA->create_POA("event_service_poa", poa_manager, policies);CosEventChannelAdmin::EventChannel_var channel = NULL;PushModel* model = NULL;CosEventChannelAdmin::ProxyPushConsumer_var pushConsumer = NULL;while(true) {try {cout > cmd ) {if (cmd == 'e') {obj = orb->resolve_initial_references("EventService");channel = CosEventChannelAdmin::EventChannel::_narrow(obj);cout


推 型 提 供 者 和 接 收 者 的 实 例}}else if (cmd == 'm') {if (pushConsumer == NULL) {cout the_POAManager()->activate();CORBA::Object_var reference = serverPOA->servant_to_reference(model);cout


cout


推 型 提 供 者 和 接 收 者 的 实 例{public:void push(const CORBA::Any& data) {cout > cmd) {if (cmd == 'e') {obj = orb->resolve_initial_references("EventService");15-14 <strong>VisiBroker</strong> 开 发 者 指 南


推 型 提 供 者 和 接 收 者 的 实 例channel = CosEventChannelAdmin::EventChannel::_narrow(obj);cout activate();CORBA::Object_var reference = serverPOA->servant_to_reference(view);cout


推 型 提 供 者 和 接 收 者 的 实 例}cout


推 型 提 供 者 和 接 收 者 的 实 例上 运 行 , 并 不 断 地 将 数 据 送 到 同 一 事 件 通 道 , 以 便 PushView 接 收 数 据 。 提 供 者和 接 收 者 可 以 按 任 何 顺 序 来 启 动 。运 行 推 式 模 型 实 例Java: 要 运 行 PullModel 实 例 , 在 提 示 符 下 输 入 :prompt> vbj -DORBInitRef=EventService=file: PullModel选 择 e 以 限 制 到 事 件 通 道 ; 选 择 p 以 从 事 件 通 道 取 得 推 型 接 收 者 的 一 个 代 理 ; 选择 m 以 将 PullModel 实 例 化 ; 选 择 c 以 连 接 事 件 通 道 ; 选 择 d 以 断 开 ; 选 择 q 以退 出 。要 运 行 PullView, 在 提 示 符 下 输 入 :prompt>vbj -DORBInitRef=EventService=file: PullView选 择 e 以 限 制 到 事 件 通 道 ; 选 择 p 以 从 事 件 通 道 取 得 推 型 提 供 者 的 一 个 代 理 ; 选 择m 以 将 PushView 实 例 化 ; 选 择 c 以 连 接 事 件 通 道 。 然 后 选 择 a 以 异 步 拉 数 据 或 选择 s 以 同 时 拉 数 据 。 要 退 出 时 , 选 择 d 以 断 开 , 再 选 择 q 以 退 出 。要 运 行 这 个 实 例 , 一 个 “ 推 ” 或 “ 拉 ” 类 型 的 提 供 者 必 须 正 在 另 外 一 个 终 端 上 运行 , 并 不 断 地 将 数 据 送 到 同 一 事 件 通 道 , 以 便 PullView 接 收 数 据 。 提 供 者 和 接 收者 可 以 按 任 何 顺 序 来 启 动 。PullSupplyJava:PullSupply 类 是 从 PullSupplierPOA 类 派 生 的 , 它 可 以 为 main、 pull 和 try_pull方 法 提 供 实 现 。 如 以 下 所 示 的 pull 方 法 返 回 编 号 的 “hello” 消 息 。 try_pull 方 法始 终 将 hasEvent 标 志 设 置 为 true, 并 调 用 pull 方 法 以 提 供 消 息 。 一 旦 PullSupply对 象 连 接 到 EventChannel, 这 些 方 法 将 被 通 道 用 以 从 提 供 者 拉 数 据 。如 下 所 示 的 main 方 法 执 行 常 规 的 <strong>VisiBroker</strong> ORB 和 POA 创 建 , 连 接 指 定 的EventChannel, 从 EventChannel 取 得 ProxyPullConsumer , 实 例 化 PullSupply 对象 , 激 活 POA 上 的 PullSupply 对 象 , 然 后 将 该 拉 型 提 供 者 连 接 到 代 理 拉 型 接收 者 。执 行 PullSupply在 编 译 PullSupply.java 和 启 动 事 件 服 务 之 后 ( 参 见 第 15-22 页 " 进 程 内 事 件 通 道(Java) ", 您 可 以 用 以 下 命 令 来 执 行 提 供 者 :vbj -DORBInitRef = = file: PullSupplyPull 和 try_pull 方 法 的 实 现 :// PullSupply.javaimport org.omg.CosEventComm.*;import org.omg.CosEventChannelAdmin.*;import org.omg.PortableServer.*;public class PullSupply extends PullSupplierPOA {private POA _myPOA;private PullConsumer _pullConsumer;private int _counter;PullSupply(PullConsumer pullConsumer, POA myPOA) {使 用 事 件 服 务 15-17


推 型 提 供 者 和 接 收 者 的 实 例_pullConsumer = pullConsumer;_myPOA = myPOA;}public void disconnect_pull_supplier() {System.out.println("Model::disconnect_pull_supplier()");try {_myPOA.deactivate_object("PullSupply".getBytes());} catch(Exception e) {e.printStackTrace();}}public org.omg.CORBA.Any pull() throws Disconnected {if(_pullConsumer == null) {throw new Disconnected();try {Thread.currentThread().sleep(1000);} catch(Exception e) {}//org.omg.CORBA.Any message =new org.omg.CORBA.Any().from_string("Hello #" + ++_counter);org.omg.CORBA.Any message = _orb().create_any();message.insert_string("Hello #" + ++_counter);System.out.println("Supplier being pulled:" + message);return message;}public org.omg.CORBA.Any try_pull(org.omg.CORBA.BooleanHolder hasEvent)throwsorg.omg.CORBA.SystemException, Disconnected {hasEvent.value = true;return pull();}. . .PullSupply 的 主 要 方 法 :// PullSupply.javaimport org.omg.CosEventComm.*;import org.omg.CosEventChannelAdmin.*;import org.omg.PortableServer.*;public class PullSupply extends PullSupplierPOA {. . .public static void main(String[] args) {try {org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null);// 取 得 根 POA 的 引 用POA rootPOA =POAHelper.narrow(orb.resolve_initial_references("RootPOA"));// 为 永 久 POA 创 建 策 略org.omg.CORBA.Policy[] policies = {rootPOA.create_lifespan_policy(LifespanPolicyValue.PERSISTENT)};// 用 正 确 的 策 略 创 建 myPOAPOA myPOA = rootPOA.create_POA("event_service_poa",rootPOA.the_POAManager(), policies);EventChannel channel = null;15-18 <strong>VisiBroker</strong> 开 发 者 指 南


推 型 提 供 者 和 接 收 者 的 实 例}PullSupply model = null; ProxyPullConsumer pullConsumer = null;channel =EventChannelHelper.narrow(orb.resolve_initial_references("EventService"));System.out.println("Located event channel:" + channel);pullConsumer = channel.for_suppliers().obtain_pull_consumer();System.out.println("Obtained pull consumer:" + pullConsumer);model = new PullSupply(pullConsumer, myPOA);myPOA.activate_object_with_id("PullSupply".getBytes(), model);myPOA.the_POAManager().activate();System.out.println("Created model:" + model);System.out.println("Connecting ...");pullConsumer.connect_pull_supplier(model._this());} catch(Exception e) {e.printStackTrace();}}PullConsumePullConsume 类 是 从 PullConsumerPOA 类 派 生 的 , 它 为 从 PullSupply 类 拉 出 数 据 提供 命 令 行 界 面 。 以 下 的 代 码 示 例 说 明 应 用 如 何 连 接 到 任 何 可 用 的 EventChannel,取 得 ProxyPullSupplier, 连 接 到 通 道 , 并 显 示 命 令 提 示 符 。 下 表 总 结 出 了 可 以输 入 的 命 令 。表 15.3描 述PullConsume 命 令使 用 try_pull 方 法 , 从 事 件 通 道 异 步 拉 出 数据 。 如 果 当 前 没 有 可 用 的 数 据 , 则 该 命 令 返 回一 个 “ 无 数 据 ” 消 息 。使 用 pull 方 法 , 从 事 件 通 道 同 步 拉 出 数 据 。如 果 当 前 没 有 可 用 的 数 据 , 则 该 命 令 保 持 阻 塞直 到 数 据 可 用 。从 通 道 断 开 并 退 出 工 具 。命 令asq执 行 PullConsume在 编 译 PullConsume.java 和 启 动 事 件 服 务 之 后 ( 参 见 第 15-22 页 " 进 程 内 事 件通 道 (Java) ", 您 可 以 用 以 下 命 令 来 执 行 接 收 者 :vbj -DORBInitRef = = file: PullConsume// PullConsume.javaimport org.omg.CosEventComm.*;import org.omg.CosEventChannelAdmin.*;import org.omg.PortableServer.*;import java.io.*;public class PullConsume extends PullConsumerPOA {public void disconnect_pull_consumer() {System.out.println("View.disconnect_pull_consumer");}public static void main(String[] args) {使 用 事 件 服 务 15-19


推 型 提 供 者 和 接 收 者 的 实 例try {org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null);// 取 得 根 POA 的 引 用POA rootPOA =POAHelper.narrow(orb.resolve_initial_references("RootPOA"));// 为 永 久 POA 创 建 策 略org.omg.CORBA.Policy[] policies = {rootPOA.create_lifespan_policy(LifespanPolicyValue.PERSISTENT)};// 用 正 确 的 策 略 创 建 myPOAPOA myPOA = rootPOA.create_POA("event_service_poa",rootPOA.the_POAManager(), policies );EventChannel channel = null;PullConsume view = null;ProxyPullSupplier pullSupplier = null;BufferedReader in = new BufferedReader(newInputStreamReader(System.in));channel =EventChannelHelper.narrow(orb.resolve_initial_references("EventService"));System.out.println("Located event channel: " + channel);view = new PullConsume();myPOA.activate_object_with_id("PullConsume".getBytes(), view);myPOA.the_POAManager().activate();System.out.println("Created view: " + view);pullSupplier = channel.for_consumers().obtain_pull_supplier();System.out.println("Obtained pull supplier: " + pullSupplier);System.out.println("Connecting...");System.out.flush();pullSupplier.connect_pull_consumer(view._this());while(true) {System.out.print("-> ");System.out.flush();if (System.getProperty("VM_THREAD_BUG") != null) {while(!in.ready()) {try {Thread.currentThread().sleep(100);} catch(InterruptedException e) {}}}String line = in.readLine();if(line.startsWith("a")) {org.omg.CORBA.BooleanHolder hasEvent = neworg.omg.CORBA.BooleanHolder();org.omg.CORBA.Any result = pullSupplier.try_pull(hasEvent);System.out.println("try_pull: " +(hasEvent.value ? result.toString() : "NO DATA"));continue;} else if(line.startsWith("s")) {org.omg.CORBA.Any result = pullSupplier.pull();System.out.println("pull: " + result);continue;} else if(line.startsWith("q")) {15-20 <strong>VisiBroker</strong> 开 发 者 指 南


}}System.out.println("Disconnecting...");pullSupplier.disconnect_pull_supplier();System.out.println("Quitting...");break;}System.out.println("Commands: a [a]synchronous pull\n" +" s [s]ynchronous pull\n" +" q [q]uit\n");}} catch(Exception e) {e.printStackTrace();}启 动 事 件 服 务启 动 事 件 服 务Java: 在 使 用 <strong>VisiBroker</strong> for Java 时 , 可 以 用 以 下 命 令 来 启 动 事 件 服 务 。vbj [-Dvbroker.events.debug] [-Dvbroker.events.interactive] [-Dvbroker.events.max_queue_length=] [-Dvbroker.events.debug.factory] \[-Dvbroker.events.vm_thread_bug] com.inprise.vbroker.CosEvent.EventServer -ior 选 项说 明-Dvbroker.events.debug可 选 参 数 , 允 许 调 试 消 息 输 出 到 stdout。-Dvbroker.events.interactive 指 定 事 件 通 道 以 控 制 台 驱 动 的 交 互 方 式 执 行 。-Dvbroker.events.maxQueueLength指 定 为 缓 慢 的 接 收 者 排 入 队 列 中 的 消 息 的 数量 。 默 认 的 最 大 队 列 长 度 是 每 个 接 收 者 100 条消 息 。-Dvbroker.events.factory指 定 要 实 例 化 事 件 通 道 工 厂 而 不 是 的 事 件 通道 。channel_name 通 道 或 通 道 工 厂 的 名 称 。注 :Java 虚 拟 机 ( 包 括 Solaris) 的 一 些 实 现 存 在 一 个 已 知 的 问 题 , 它 可 能 会 导 致 此 命令 中 止 。 如 果 您 在 启 动 事 件 服 务 时 遇 到 困 难 , 尝 试 指 定 -Dvbroker.events.vm_thread_bug 参 数 。设 置 队 列 长 度在 一 些 环 境 下 , 接 收 者 应 用 运 行 起 来 可 能 会 比 提 供 者 应 用 缓 慢 。 maxQueueLength 参数 通 过 限 制 为 每 个 跟 不 上 提 供 者 消 息 发 送 速 率 的 接 收 者 保 留 的 待 处 理 消 息 的 数 量 来防 止 出 现 “ 内 存 不 足 ” 现 象 的 发 生 。如 果 一 个 提 供 者 每 秒 产 生 10 条 消 息 , 而 一 个 接 收 者 每 秒 只 能 处 理 1 条 消 息 , 则 队列 很 快 就 排 满 。 队 列 中 的 消 息 具 有 一 个 最 大 长 度 , 如 果 尝 试 将 一 条 消 息 加 入 一 个 已排 满 的 队 列 , 通 道 将 会 删 除 最 “ 旧 ” 的 消 息 以 为 新 消 息 留 出 空 间 。使 用 事 件 服 务 15-21


进 程 内 事 件 通 道 (Java)C++:Java:每 个 接 收 者 均 具 有 单 独 的 队 列 , 因 此 一 个 缓 慢 的 接 收 者 可 能 会 错 过 消 息 , 而 另 一 个较 快 的 接 收 者 可 能 不 会 丢 失 任 何 消 息 。 以 下 的 代 码 示 例 说 明 如 何 限 制 每 个 接 收 者 只能 拥 有 15 条 未 处 理 消 息 。CosEventChannel -maxQueueLength=15 MyChannelvbj -Dvbroker.events.maxQueueLength=15 CosEvent.EventServer -ior myChannel.iorMyChannel注 : 如 果 未 指 定 maxQueueLength 或 指 定 了 一 个 非 法 的 数 值 , 则 使 用 默 认 队 列 长 度 100。进 程 内 事 件 通 道 (Java)Java:除 了 将 EventChannel 作 为 单 独 的 独 立 服 务 器 运 行 之 外 , 事 件 服 务 也 允 许 您 在 您 的服 务 器 或 客 户 应 用 中 创 建 EventChannel 。 这 使 您 不 必 启 动 一 个 单 独 的 进 程 来 为 您的 提 供 者 或 接 收 者 应 用 提 供 EventChannel。对 于 Java 应 用 , 提 供 有 一 个 EventLibrary 类 , 它 提 供 用 于 创 建 EventChannel 对 象的 方 法 , 反 过 来 , 该 对 象 又 处 理 必 要 的 类 的 装 载 。 要 在 提 供 者 / 接 收 者 应 用 中 创 建进 程 内 EventChannel 对 象 , 执 行 下 列 调 用 :EventLibrary.create_Channel("MyChannel",whetherToDebug,maxQueueLength);因 此 , 要 创 建 一 个 命 名 为 MyChannel 的 通 道 , 关 闭 调 试 , 最 大 队 列 长 度 为 100, 则您 应 该 编 写 :EventLibrary.create_Channel("MyChannel",false,100);完 成 该 调 用 后 , 得 到 的 客 户 端 应 用 程 序 可 以 限 制 到 EventChannel, 因 为 它 将 限 制 到其 它 任 何 CORBA 对 象 。例 如 , 您 可 能 想 让 一 个 提 供 者 应 用 在 进 程 中 创 建 通 道 , 并 想 让 接 收 者 程 序 连 接 到 同一 通 道 。 要 达 成 此 目 的 , 您 需 要 将 通 道 对 象 从 提 供 者 应 用 传 递 到 接 收 者 应 用 。 要 完成 此 任 务 , 将 EventChannel 对 象 转 换 成 ior 字 串 并 将 该 字 串 写 入 一 个 文 件 :try {EventChannel channel = EventLibrary.create_Channel("MyChannel",false,100);PrintWriter pw = new PrintWriter(new FileWriter(ior_filename));pw.println(orb.object_to_string(channel));pw.close();}catch(IOException e) {System.out.println("Error writing the IOR to file " ior_filename);}ior_filename 指 定 要 写 入 通 道 的 ior 的 文 件 的 名 称 。要 运 行 PushModelChannel:vbj PushModelChannel PushModelChannel 是 一 个 推 型 提 供 者 。 您 可 以 将 推 型 接 收 者 或 拉 型 接 收 者 连 接到 PushModelChannel 中 创 建 的 通 道 。vbj -DORBInitRef=EventService=file: PushView15-22 <strong>VisiBroker</strong> 开 发 者 指 南


编 译 和 链 接 程 序 ( 仅 限 于 C++)其 中 , 是 传 递 到 PushModelChannel 的 ior_filename的 完 整 路 径 , 而 EventService 是 限 制 到 ior_filename 中 所 包 含 的 ior 的 名 称 ( 或标 识 符 )。 从 PushView 内 部 , 您 可 以 用 以 下 命 令 限 制 到 事 件 通 道 :EventChannel channel =EventChannelHelper.narrow(orb.resolve_initial_references("EventService"));Java 用 法仅 适 用 于 Java: 如 果 您 的 应 用 使 用 进 程 内 事 件 通 道 特 性 , 您 必 须 加 入 以 下 的 import 声 明 :import com.inprise.vbroker.CosEvent.*;Java EventLibrary 类The EventLibrary 类 提 供 几 种 在 应 用 内 创 建 EventChannel 的 方 法 。 参 阅 第 15-24页 "EventLibrary (Java) " 以 查 看 关 于 这 些 方 法 的 完 整 描 述 。Java 实 例PushModelChannel.java 文 件 实 现 使 用 进 程 内 事 件 通 道 的 推 型 提 供 者 。 该 应 用 显示 一 个 命 令 提 示 符 , 允 许 您 输 入 以 下 所 示 的 命 令 之 一 。命 令说 明e 创 建 一 个 事 件 通 道 。s 将 对 事 件 通 道 的 延 迟 设 置 为 指 定 的 秒 数 , 该 数值 必 须 是 一 个 非 负 数 。p 取 得 一 个 推 型 接 收 者 代 理 对 象 。m创 建 一 个 PushModelChannel 并 在 POA 上将 它 激 活 。c 连 接 推 型 提 供 者 。d 断 开 推 型 接 收 者 。q 退 出 应 用 。以 下 的 代 码 示 例 包 含 从 PushModelChannel.java 摘 录 的 一 个 片 段 , 它 说 明 如 何 使 用ChannelLib.create_channel 方 法 。public static void main(String[] args) {. . .channel = EventLibrary.create_channel("channel_server", false, 100);. . .编 译 和 链 接 程 序 ( 仅 限 于 C++)使 用 事 件 服 务 的 C++ 应 用 需 要 包 含 下 列 生 成 的 文 件 :#include "CosEventComm_s.hh"#include "CosEventChannelAdmin_c.hh"使 用 事 件 服 务 15-23


Java 导 入 声 明UNIX: UNIX 应 用 需 要 链 接 到 程 序 库 之 一 :● libcosev.a● libcosev.soWindows: Windows 应 用 需 要 链 接 到 以 下 程 序 库 :● cosev.libJava 导 入 声 明要 使 用 事 件 服 务 的 Java 应 用 应 该 使 用 以 下 的 导 入 (Import) 声 明 :import org.omg.CosEventComm.*;import org.omg.CosEventChannelAdmin.*;. . .接 口 引 用本 节 的 后 续 部 分 介 绍 关 于 所 有 事 件 服 务 接 口 的 引 用 信 息 。EventChannelEventChannel 为 增 加 提 供 者 和 接 收 者 和 销 毁 通 道 提 供 管 理 操 作 。ConsumerAdmin for_consumers();这 个 方 法 返 回 一 个 可 以 用 来 取 得 代 理 提 供 者 的 ConsumerAdmin 对 象 。SupplierAdmin for_suppliers();这 个 方 法 返 回 一 个 可 以 用 来 取 得 代 理 提 供 者 的 SupplierAdmin 对 象 。void destroy();这 个 方 法 销 毁 此 EventChannel。EventLibrary (Java)仅 适 用 于 Java:EventLibrary 类 提 供 几 种 在 应 用 进 程 内 创 建 EventChannel 的 方 法 。 使 用 进 程 内 事件 通 道 可 以 使 您 不 必 启 动 单 独 的 事 件 通 道 或 事 件 通 道 工 厂 进 程 。EventLibrary 方 法仅 适 用 于 Java:static org.omg.CosEventChannelAdmin.EventChannel create_channel(String name, boolean debug, int maxQueueLength);15-24 <strong>VisiBroker</strong> 开 发 者 指 南


接 口 引 用这 个 方 法 用 指 定 的 name、 debug 和 队 列 长 度 设 置 来 创 建 EventChannel。参 数static org.omg.CosEventChannelAdmin.EventChannel create_channel(String name, boolean debug);此 方 法 用 指 定 的 name 和 debug 设 置 创 建 EventChannel。 每 个 接 收 者 的 队 列 长 度 设定 为 100。static org.omg.CosEventChannelAdmin.EventChannel create_channel( String name);此 方 法 用 指 定 的 name 创 建 EventChannel。EventChannel 对 象 的 debug 标 志 设 定 为false 而 队 列 长 度 设 定 为 100。static org.omg.CosEventChannelAdmin.EventChannel create_channel( );此 方 法 创 建 EventChannel。 没 有 给 定 EventChannel 对 象 的 名 称 , debug 标 志 设定 为 false, 队 列 长 度 设 定 为 100。ConsumerAdmin说 明名 称 用 于 此 通 道 的 名 称 。debug如 果 设 定 为 true, 则 允 许 调 试 输 出 。 如 果 设 定为 false, 则 禁 止 调 试 输 出 。maxQueueLength可 以 为 每 个 接 收 者 加 入 队 列 的 消 息 的 最 大 数量 。参 数说 明名 称 用 于 此 通 道 的 名 称 。debug如 果 设 定 为 true, 则 允 许 调 试 输 出 。 如 果 设 定为 false, 则 禁 止 调 试 输 出 。参 数说 明名 称 用 于 此 通 道 的 名 称 。此 接 口 被 接 收 者 应 用 用 来 取 得 代 理 提 供 者 对 象 的 引 用 。 这 是 将 接 收 者 应 用 连 接 到EventChannel 的 第 二 个 步 骤 。module CosEventChannelAdmin {interface ConsumerAdmin {ProxyPushSupplier obtain_push_supplier();ProxyPullSupplier obtain_pull_supplier();};};如 果 发 起 调 用 的 接 收 者 应 用 是 用 推 式 模 型 实 现 的 , 则 调 用 obtain_push_supplier 方法 。 如 果 应 用 是 用 拉 式 模 型 实 现 的 , 则 应 该 调 用 obtain_pull_supplier 方 法 。使 用 事 件 服 务 15-25


接 口 引 用返 回 的 引 用 被 用 于 调 用 connect_push_consumer ( 参 见 第 15-26 页"ProxyPushConsumer") 或 onnect_pull_consumer 方 法 ( 参 见 第 15-24 页"EventLibrary (Java) "。SupplierAdmin这 个 接 口 被 提 供 者 应 用 用 来 取 得 代 理 接 收 者 对 象 。 这 是 连 接 提 供 者 应 用 到EventChannel 的 第 二 个 步 骤 。module CosEventChannelAdmin {interface SupplierAdmin {ProxyPushConsumer obtain_push_consumer();ProxyPullConsumer obtain_pull_consumer();};};如 果 提 供 者 应 用 是 使 用 推 式 模 型 实 现 的 , 则 调 用 obtain_push_consumer 方 法 。 如 果应 用 是 用 拉 式 模 型 实 现 的 , 则 调 用 obtain_pull_consumer 方 法 。返 回 的 引 用 用 于 调 用 connect_push_supplier ( 参 见 以 下 第 15-27 页"ProxyPushSupplier", 或 connect_pull_supplier 方 法 ,( 参 见 以 下 第 15-27 页"ProxyPullSupplier")。ProxyPullConsumer这 个 接 口 由 拉 型 提 供 者 应 用 使 用 , 它 提 供 connect_pull_supplier 方 法 , 此 方 法 用于 将 提 供 者 的 PullSupplier 派 生 的 对 象 连 接 到 EventChannel。 如 果ProxyConsumer 已 连 接 到 PullSupplier, 则 掷 出 AlreadyConnected 违 例 。module CosEventChannelAdmin {exception AlreadyConnected();interface ProxyPullConsumer :CosEventComm::PullConsumer {void connect_pull_supplier(in CosEventComm::PullSupplier pull_supplier)raises(AlreadyConnected);};};ProxyPushConsumer这 个 接 口 由 推 型 提 供 者 应 用 使 用 , 它 提 供 connect_push_supplier 方 法 , 此 方 法 用于 将 提 供 者 的 PushSupplier 派 生 的 对 象 连 接 到 EventChannel。 如 果ProxyConsumer 已 连 接 到 PullSupplier, 则 掷 出 AlreadyConnected 违 例 。module CosEventChannelAdmin {exception AlreadyConnected();interface ProxyPushConsumer :CosEventComm::PushConsumer {void connect_push_supplier(in CosEventComm::PushSupplier push_supplier)raises(AlreadyConnected);15-26 <strong>VisiBroker</strong> 开 发 者 指 南


接 口 引 用};};ProxyPullSupplier这 个 接 口 由 拉 型 接 收 者 应 用 使 用 , 它 提 供 connect_pull_consumer 方 法 , 此 方 法 用于 将 接 收 者 的 PullConsumer 派 生 的 对 象 连 接 到 EventChannel。 如 果ProxyConsumer 已 连 接 到 PullSupplier, 则 掷 出 AlreadyConnected 违 例 。module CosEventChannelAdmin {exception AlreadyConnected();interface ProxyPullSupplier :CosEventComm::PullSupplier {void connect_pull_consumer(in CosEventComm::PullConsumer pull_consumer)raises(AlreadyConnected);};};ProxyPushSupplier这 个 接 口 由 推 型 接 收 者 应 用 使 用 , 它 提 供 connect_push_consumer 方 法 , 此 方 法 用于 将 接 收 者 的 PushConsumer 派 生 的 对 象 连 接 到 EventChannel. 如 果ProxyConsumer 已 连 接 到 PullSupplier, 则 掷 出 AlreadyConnected 违 例module CosEventChannelAdmin {exception AlreadyConnected();interface ProxyPushSupplier :CosEventComm::PushSupplier {void connect_push_consumer(in CosEventComm::PushConsumer push_consumer)raises(AlreadyConnected);};};PullConsumer此 接 口 用 于 派 生 使 用 通 信 的 拉 式 模 型 的 接 收 者 对 象 。 每 当 接 收 者 向 提 供 者 索 取 数 据的 时 候 , 它 就 调 用 pull 方 法 。 如 果 提 供 者 已 被 断 开 , 则 会 掷 出 一 个 Disconnected违 例 。如 果 通 道 已 销 毁 , 则 用 disconnect_push_consumer 方 法 对 接 收 者 去 激 活 。module CosEventComm {exception Disconnected {};interface PullConsumer {void disconnect_pull_consumer();};};在 派 生 的 PullConsumer 类 中 必 须 使 用 的 唯 一 方 法 是 disconnect_pull_consumer ,它 用 于 将 PullConsumer 从 EventChannel 断 开 。 例 如 , 在 PullModel 实 例中 , PullSupplier 使 用 此 方 法 断 开 拉 型 接 收 者 。使 用 事 件 服 务 15-27


接 口 引 用PushConsumer这 个 接 口 用 于 使 用 通 信 的 推 式 模 型 的 接 收 者 对 象 。 每 当 一 个 提 供 者 要 给 接 收 者 提 供数 据 时 , 它 就 调 用 push 方 法 。 如 果 接 收 者 已 被 断 开 , 则 会 掷 出 一 个 Disconnected违 例 。module CosEventComm {exception Disconnected();interface PushConsumer {void push(in any data) raises(Disconnected);void disconnect_push_consumer();};};PushConsumer 实 现 push(in any data) 方 法 。 此 方 法 由 推 型 提 供 者 调 用 以 连 续接 收 数 据 直 到 通 过 调 用 ProxyPushSupplier 上 的 disconnect_push_supplier 将 推型 提 供 者 从 PushConsumer 透 明 地 断 开 。PullSupplier这 个 方 法 用 于 派 生 使 用 通 信 的 拉 式 模 型 的 提 供 者 对 象 。module CosEventComm {exception Disconnected{};interface PullSupplier {any pull() raises(Disconnected);any try_pull() raises(Disconnected);void disconnect_pull_supplier();};};PullConsumer 从 PullSupplier 拉 出 数 据 。 一 旦 连 接 到 ProxyPullSupplier,PllConsumer 就 可 以 使 用 ProxyPullSupplier 对 象 上 的 code>pull() 或try_pull() 方 法 。 try_pull() 方 法 用 于 异 步 拉 数 据 ( 即 使 数 据 不 可 用 , 也 会 立 即返 回 ); pull() 方 法 用 于 同 步 拉 数 据 ( 当 数 据 可 用 时 返 回 )。当 接 收 者 想 要 从 ProxyPullSupplier 断 开 时 , PullConsumer 调 用ProxyPullServer 上 的 disconnect_pull_supplier() 方 法 。 pull() 和 try_pull()方 法 返 回 CORBA::Any 对 象 。 在 本 实 例 中 , 返 回 的 Any 对 象 包 含 一 个 带 编 号 的 字 串 ,字 串 值 为 “Hello”。PullSupplier 方 法any pull();此 方 法 保 持 阻 塞 , 直 到 提 供 者 提 供 可 用 的 数 据 。 返 回 的 数 据 是 Any 类 型 。 如 果 接 收者 已 断 开 , 则 此 方 法 掷 出 一 个 Disconnected 违 例 。any try_pull(out boolean has_event);这 个 非 阻 塞 方 法 尝 试 从 提 供 者 检 索 数 据 。 当 此 方 法 返 回 时 , has_event 被 设 定 为CORBA::TRUE ; 如 果 有 可 用 的 数 据 , 则 数 据 以 Any 类 型 返 回 。 如 果 has_event 设 定为 CORBA::FALSE, 则 没 有 可 有 数 据 , 而 返 回 值 为 NULL。15-28 <strong>VisiBroker</strong> 开 发 者 指 南


接 口 引 用void disconnect_pull_supplier();如 果 通 道 已 销 毁 , 则 此 方 法 将 去 激 活 拉 型 服 务 器 。PushSupplier此 接 口 用 于 派 生 使 用 通 信 的 推 式 模 型 的 提 供 者 对 象 。 当 通 道 已 被 销 毁 时 ,EventChannel 使 用 disconnect_push_supplier 来 断 开 提 供 者 。module CosEventComm {exception Disconnected();interface PushSupplier {void disconnect_push_supplier();};};应 该 实 现 PushSupplier 以 便 它 可 以 不 断 地 将 数 据 “ 推 ” 给 接 收 者 。 在PushModel 实 例 中 , 一 旦 创 建 了 一 个 PushModel 对 象 ( 一 个 PushSupplier派 生 的 对 象 ), 它 就 启 动 一 个 新 的 线 程 , 此 线 程 将 不 时 调 用ProxyPushConsumer 上 的 push(CORBA.Any) 。 推 出 的 数 据 是 Any 类 型 , 其 中 插入 了 一 个 消 息 字 串 ( 带 编 号 的 Hello 字 串 )。在 推 型 提 供 者 的 派 生 类 中 所 必 须 使 用 的 唯 一 方 法 是 disconnect_pull_consumer, 此方 法 用 于 将 PullConsumer 从 EventChannel 上 断 开 。 例 如 , 在 PushView 实例 中 ,Push 接 收 者 PushConsumer 使 用 此 方 法 来 断 开 ProxyPushSupplier。使 用 事 件 服 务 15-29


15-30 <strong>VisiBroker</strong> 开 发 者 指 南


第章使 用 对 象 激 活 守 护 进 程第 16 章(Daemon)本 章 描 述 如 何 使 用 对 象 激 活 守 护 进 程 。对 象 和 服 务 器 的 自 动 激 活对 象 激 活 守 护 进 程 (OAD) 是 实 现 库 的 <strong>VisiBroker</strong> <strong>Edition</strong> 的 实 现 。 该 实 现 库提 供 有 关 服 务 器 支 持 的 类 、 实 例 化 对 象 及 其 ID 的 信 息 的 运 行 期 存 储 库 。 除 了 由 一个 典 型 的 实 现 库 提 供 的 服 务 之 外 , OAD 用 于 在 客 户 引 用 对 象 时 自 动 激 活 实 现 。 您可 以 在 OAD 上 注 册 对 象 实 现 以 给 您 的 对 象 提 供 该 自 动 激 活 行 为 。可 以 使 用 命 令 行 界 面 (oadutil) 来 注 册 对 象 实 现 。 ODA 也 有 一 个 <strong>VisiBroker</strong>ORB 接 口 , 请 参 阅 第 16-13 页 " 面 向 OAD 的 IDL 接 口 "。 在 各 种 情 况 下 , 必 须指 定 表 示 实 现 的 仓 库 id、 对 象 名 、 激 活 策 略 、 和 可 执 行 程 序 。注 : 您 可 以 使 用 <strong>VisiBroker</strong> <strong>Edition</strong> OAD 将 由 <strong>VisiBroker</strong> for Java ( 任 何 版 本 )和 <strong>VisiBroker</strong> for C++ 3.0 生 成 的 服 务 器 实 例 化 。OAD 是 一 个 单 独 的 进 程 , 它 仅 需 要 在 要 求 激 活 对 象 服 务 器 的 主 机 上 启 动 。定 位 实 现 库 数 据在 OAD 上 注 册 的 所 有 对 象 实 现 的 激 活 信 息 存 储 在 实 现 库 中 。 在 默 认 情 况 下 , 实 现库 数 据 存 储 在 命 名 为 impl_rep 的 文 件 中 。 该 文 件 的 路 径 名 取 决 于 VBROKER_ADM 变 量的 值 。 如 果 <strong>VisiBroker</strong> <strong>Edition</strong> 安 装 于 /usr/local/vbroker/, 则 该 文 件 的 路 径 为/usr/local/vbroker/adm/impl_dir/impl_rep。 可 以 使 用 OAD 环 境 变 量 来 将 这 些默 认 值 覆 盖 。 请 参 阅 第 3 章 " 建 立 您 的 环 境 "。使 用 对 象 激 活 守 护 进 程 (Daemon) 16-1


启 动 对 象 激 活 守 护 进 程激 活 服 务 器OAD 应 客 户 的 请 求 来 激 活 服 务 器 。 以 下 的 客 户 类 型 可 以 通 过 OAD 来 激 活 服务 器 :● <strong>VisiBroker</strong> for C++ 4.x 客 户 。● <strong>VisiBroker</strong> for C++ 3.x 客 户 。● <strong>VisiBroker</strong> for Java 4.x 客 户 。● <strong>VisiBroker</strong> for Java 3.x 客 户 。● 非 <strong>VisiBroker</strong> <strong>Edition</strong> IIOP 兼 容 客 户 。 当 使 用 了 服 务 器 的 引 用 之 后 , 使 用IIOP 协 议 的 任 何 客 户 都 可 以 激 活 该 <strong>VisiBroker</strong> <strong>Edition</strong> 服 务 器 。 服 务 器 的 开放 出 的 对 象 引 用 指 向 OAD, 根 据 IIOP 规 则 , 客 户 被 前 转 到 新 产 生 的 服 务 器 。要 允 许 服 务 器 对 象 的 真 正 永 久 化 ( 例 如 , 通 过 使 用 命 名 服 务 ), OAD 必 须 始 终在 同 一 端 口 上 启 动 。 例 如 , 要 在 端 口 16050 上 启 动 OAD, 可 输 入 以 下 命 令 :prompt> oad -VBJprop vbroker.se.iiop_tp.scm.iiop_tp.listener.port=16050注 : 端 口 16000 是 默 认 的 端 口 , 但 可 以 通 过 设 置 listener.port 属 性 来 改 变 默 认 端 口 。启 动 对 象 激 活 守 护 进 程对 象 激 活 守 护 进 程 是 一 个 可 选 的 功 能 , 它 允 许 您 注 册 在 客 户 尝 试 访 问 时 可 以 自 动 启动 的 对 象 。 在 启 动 OAD 前 , 您 首 先 应 该 启 动 智 能 代 理 。在 Windows 平 台 上 启 动 对 象 激 活 守 护 进 程要 在 Windows 下 要 启 动 OAD , 在 <strong>VisiBroker</strong> <strong>Edition</strong> 程 序 组 中 选 择 其 图 标 或在 DOS 提 示 符 下 输 入 以 下 命 令 :prompt> oadoad 命 令 接 受 以 下 命 令 行 变 量 :选 项说 明-verbose 开 启 详 细 模 式 。-version 打 印 该 工 具 的 版 本 。-path 指 定 用 于 存 储 实 现 库 的 与 平 台 有 关 的 目 录 。 该操 作 将 覆 盖 任 何 通 过 使 用 环 境 变 量 提 供 的 设置 。-filename 指 定 实 现 库 的 名 称 。 如 果 您 不 作 设 定 , 使 用 默认 值 impl_rep。 该 操 作 将 覆 盖 任 何 用 户 环 境 变量 设 置 。16-2 <strong>VisiBroker</strong> 开 发 者 指 南


使 用 对 象 激 活 守 护 进 程 实 用 工 具选 项-t 指 定 OAD 用 于 等 待 新 产 生 的 服 务 器 进 程 激 活所 请 求 的 <strong>VisiBroker</strong> ORB 对 象 的 时 间 。 默认 的 时 限 是 20s。 如 果 您 要 无 限 地 等 待 , 则 将该 值 设 为 0。 如 果 新 产 生 的 服 务 器 进 程 在 设 定的 时 限 内 没 有 激 活 所 要 求 的 对 象 , OAD 将 销毁 该 新 生 进 程 , 而 客 户 端 将 会 看 到 一 个CORBA::NO IMPLEMENT 违 例 。 开 启 verbose 选项 以 查 看 更 详 细 的 信 息 。-ior 指 定 要 存 储 OAD 的 字 串 化 的 IOR 的 文 件名 。-kill规 定 如 果 一 个 对 象 的 子 进 程 的 所 有 对 象 都 在OAD 反 注 册 , 则 销 毁 该 子 进 程 。-no_verify 开 启 注 册 有 效 性 检 查 。-? 显 示 命 令 用 法 。-readonly当 使 用 -readonly 选 项 启 动 OAD 之 后 , 不 能对 已 注 册 的 对 象 进 行 任 何 更 改 。 如 果 尝 试 注 册或 反 注 册 对 象 , 则 会 出 错 。 在 您 对 实 现 库 作 了变 更 并 已 在 readonly 模 式 下 启 动 OAD 以 防止 额 外 的 变 更 之 后 , 通 常 要 使 用 -readonly 选项 。在 Windows NT 下 OAD 以 NT 服 务 的 形 式 安 装 , 它 允 许 您 用 Windows NT提 供 的 服 务 管 理 器 来 控 制 OAD。 您 也 可 以 在 DOS 提 示 符 下 输 入 以 下 命 令 , 以 便在 控 制 台 模 式 下 启 动 OAD:prompt> oad -C在 UNIX 平 台 上 启 动 对 象 激 活 守 护 进 程要 在 UNIX 系 统 上 启 动 OAD, 请 输 入 以 下 命 令 :prompt> oad &说 明使 用 对 象 激 活 守 护 进 程 实 用 工 具注 :oadutil 命 令 提 供 一 个 让 您 手 动 注 册 、 反 注 册 和 列 出 您 的 <strong>VisiBroker</strong> <strong>Edition</strong> 系 统中 可 用 的 对 象 实 现 的 方 法 。 oadutil 命 令 在 Java 中 实 现 , 它 使 用 一 个 命 令 行 界 面 。访 问 每 个 命 令 的 方 式 都 是 : 调 用 oadutil 命 令 并 将 要 执 行 的 操 作 类 型 作 为 第 一 个 变量 来 传 递 。在 您 使 用 oadutil 命 令 之 前 , 您 至 少 必 须 在 网 络 上 的 一 台 主 机 上 启 动 对 象 激 活 守 护进 程 (oad)。oadutil 命 令 的 语 法 如 下 :语 法 :oadutil {list|reg|unreg} [options]根 据 您 是 否 指 定 list、 reg 或 unreg, 该 工 具 的 选 项 会 有 所 不 同 。使 用 对 象 激 活 守 护 进 程 (Daemon) 16-3


使 用 对 象 激 活 守 护 进 程 实 用 工 具将 接 口 名 称 转 化 为 仓 库 IDC++:Java:接 口 名 称 和 库 ID 都 是 用 以 表 示 被 激 活 的 对 象 应 该 实 现 的 接 口 类 型 的 方 法 。 IDL 中定 义 的 所 有 接 口 都 分 配 到 了 一 个 唯 一 的 库 标 识 符 。 在 与 接 口 仓 库 、 OAD 和 对<strong>VisiBroker</strong> ORB 自 身 的 大 多 数 调 用 的 通 信 过 程 中 , 该 字 串 用 以 识 别 类 型 。当 在 OAD 上 注 册 和 反 注 册 对 象 时 ,oadutil 命 令 允 许 您 指 定 对 象 的 IDL 接 口 名 称或 其 仓 库 ID。接 口 名 称 可 以 通 过 以 下 方 法 转 换 成 仓 库 ID:1 将 “IDL:” 前 连 到 接 口 名 称 。2 用 斜 杠 (/) 字 符 取 代 所 有 非 先 行 实 例 的 作 用 域 解 析 操 作 符 (::)。3 将 “:1.0” 后 连 到 接 口 名 称 。例 如 , IDL 接 口 名 称::Module1::Module2::IntfName将 会 被 转 换 成 以 下 的 仓 库 I DIDL:Module1/Module2/IntfName:1.0#pragma ID 和 #pragma 前 缀 机 制 可 以 用 于 覆 盖 从 接 口 名 生 成 的 默 认 仓 库 ID。 如 果在 用 户 自 定 义 的 IDL 文 件 中 使 用 #pragma ID 机 制 来 指 定 非 标 准 仓 库 ID, 则 上 述 的转 换 进 程 不 能 运 行 。 在 这 种 情 况 下 , 您 必 须 使 用 -r 库 ID 变 量 来 指 定 对 象 的 仓 库ID。要 在 C++ 下 取 得 对 象 实 现 的 大 多 数 派 生 接 口 的 仓 库 ID, 可 以 使 用 为 所 有 CORBA对 象 所 定 义 的 ._repository_id() 方 法 。要 在 Java 下 取 得 对 象 实 现 的 大 多 数 派 生 接 口 的 仓 库 ID, 可 以 使 用 为 所 为 有CORBA 对 象 所 定 义 的 java:Helper.id() in Java 方 法 。用 oadutil list 列 出 对 象注 :oadutil list 命 令 返 回 在 对 象 激 活 守 护 进 程 中 注 册 的 所 有 <strong>VisiBroker</strong> ORB 对 象 实现 。 每 个 OAD 都 具 有 自 己 的 实 现 库 数 据 库 , 注 册 信 息 就 在 该 库 中 。在 您 使 用 oadutil list 命 令 之 前 , 您 至 少 必 须 在 网 络 上 的 一 台 主 机 上 启 动 对 象 激 活守 护 进 程 (oad)。oadutil list 命 令 的 语 法 如 下 :语 法 :oadutil list [ 选 项 ]16-4 <strong>VisiBroker</strong> 开 发 者 指 南


使 用 对 象 激 活 守 护 进 程 实 用 工 具oadutil list 命 令 接 受 以 下 命 令 行 变 量 :选 项说 明-i 列 出 具 有 特 定 的 IDL 接 口 名 的 对 象 的 实 现 信息 。 每 次 仅 可 以 指 定 下 列 选 项 之 一 :-i、 -r、-s 或 -poa。注 : 与 <strong>VisiBroker</strong> ORB 的 所 有 通 信 均 引 用对 象 的 仓 库 ID 而 不 是 接 口 名 。 有 关 指 定 接 口名 时 所 要 执 行 的 转 换 的 详 情 , 请 参 阅 “ 将 接口 名 转 换 为 仓 库 ID”。-r 列 出 特 定 仓 库 ID 的 实 现 信 息 。 有 关 指 定 库 ID的 详 情 , 请 参 阅 “ 将 接 口 名 转 换 成 库 ID” 。每 次 仅 可 以 指 定 下 列 选 项 之 一 :-i、-r、-s 或-poa。-s 列 出 一 个 特 定 服 务 名 称 的 实 现 信 息 。 每 次 仅 可以 指 定 下 列 选 项 之 一 :-i、 -r、 -s 或 -poa。-poa 列 出 一 个 特 定 POA 名 称 的 实 现 信 息 。 每 次 仅可 以 指 定 下 列 选 项 之 一 :-i、-r、-s 或 -poa。-o 列 出 一 个 特 定 对 象 名 称 的 实 现 信 息 。 仅 当 在 命令 声 明 中 指 定 了 接 口 或 仓 库 ID 时 , 才 可 以 使用 该 命 令 。 当 使 用 了 -s 或 -poa 变 量 时 , 该 选项 不 可 用 。-h 列 出 在 特 定 远 端 主 机 上 运 行 的 ODA 上 注 册 的对 象 的 实 现 信 息 。-verbose如 果 将 详 细 模 式 设 置 为 on ( 开 启 ), 则 将 消息 输 出 到 stdout。-version 打 印 该 工 具 的 版 本 。-full 列 出 在 OAD 上 注 册 的 所 有 实 现 的 状 态 。实 例 :描 述oadutil list 实 用 工 具 允 许 您 列 出 在 OAD 注 册 的 所 有 <strong>VisiBroker</strong> ORB 对 象 实现 。 每 个 对 象 的 信 息 包 括 :● <strong>VisiBroker</strong> ORB 对 象 的 接 口 名 。● 由 该 实 现 提 供 的 对 象 的 实 例 名 。● 服 务 器 实 现 的 可 执 行 程 序 的 完 整 路 径 名 。● <strong>VisiBroker</strong> ORB 对 象 的 激 活 策 略 ( 共 享 的 或 非 共 享 的 )。● 实 现 在 OAD 上 注 册 时 所 指 定 的 引 用 数 据 。● 在 激 活 过 程 中 要 传 递 给 服 务 器 的 变 量 的 列 表 。● 在 激 活 过 程 中 要 传 递 给 服 务 器 的 环 境 变 量 的 列 表 。以 下 是 关 于 本 地 列 表 请 求 的 一 个 实 例 , 其 中 指 定 了 接 口 名 和 对 象 名 :oadutil list -i Bank::AccountManager -o InpriseBank以 下 是 关 于 远 端 列 表 请 求 的 一 个 实 例 , 其 中 指 定 了 一 个 主 机 IP 地 址 :实 例 : oadutil list -h 206.64.15.198使 用 对 象 激 活 守 护 进 程 (Daemon) 16-5


使 用 对 象 激 活 守 护 进 程 实 用 工 具用 oadutil 注 册 对 象oadutil 对 象 可 用 于 从 命 令 行 或 在 脚 本 中 注 册 对 象 实 现 。 参 数 是 接 口 名 和 对 象 名 、服 务 名 , 以 及 启 动 实 现 的 可 执 行 程 序 的 路 径 名 ; 或 者 POA 名 与 该 路 径 名 。 如 果 未指 定 激 活 策 略 , 则 使 用 默 认 的 共 享 服 务 器 指 针 。 在 开 发 和 测 试 阶 段 , 您 可 以 编 写 实现 并 以 人 工 方 式 进 行 启 动 。 当 您 的 实 现 已 为 部 署 作 好 了 准 备 时 , 您 就 可 以 直 接 使 用oadutil 在 OAD 上 注 册 您 的 实 现 。注 : 在 注 册 对 象 实 现 时 , 所 使 用 的 对 象 名 称 要 与 实 现 对 象 在 构 建 时 所 使 用 的 名 称 相 同 。只 有 命 名 的 对 象 ( 具 有 全 局 作 用 域 ) 才 可 以 在 OAD 上 注 册 。oadutil reg 命 令 的 语 法 如 下 :语 法 : oadutil reg [ 选 项 ]注 :在 您 使 用 oadutil reg 命 令 之 前 , 您 至 少 必 须 在 网 络 上 的 一 台 主 机 上 启 动 oad进 程 。oadutil reg 命 令 的 选 项 接 受 以 下 命 令 行 变 量 :说 明选 项必 选 项-i 指 定 特 定 IDL 接 口 名 称 。 每 次 仅 可 以 指 定 下 列 选 项 之 一 :-i、-r、-s 或 -poa。 有 关 指 定 仓 库 ID 的 详 情 , 请 参 阅 第16-4 页 " 将 接 口 名 称 转 化 为 仓 库 ID"。-r 指 定 特 定 的 仓 库 ID。 每 次 仅 可 以 指 定 下 列 选 项 之 一 :-i、-r、 -s 或 -poa。-s 指 定 特 定 的 服 务 名 称 。 每 次 仅 可 以 指 定 下 列 选 项 之 一 :-i、 -r、 -s 或 -poa。-poa 使 用 该 选 项 会 注 册 POA, 而 不 是 注 册 对 象 实 现 。 每 次 仅可 以 指 定 下 列 选 项 之 一 :-i、 -r、 -s 或 -poa。-o 指 定 特 定 的 对 象 。 仅 当 在 命 令 声 明 中 指 定 了 接 口 名 或 仓 库ID 时 , 才 可 以 使 用 该 选 项 。 当 使 用 -s 或 -poa 变 量 时 , 该选 项 不 可 用 。-cpp 为 必 须 创 建 和 注 册 对 象 的 可 执 行 文 件 指 定 完 整 的 路 径 , 该对 象 与 -o/-r/-s/-poa 变 量 相 匹 配 。 使 用 -cpp 变 量 注 册的 应 用 程 序 必 须 是 独 立 可 执 行 文 件 。-java 指 定 包 含 主 例 程 的 Java 类 的 全 名 。 该 应 用 程 序 必 须 创 建和 注 册 与 -o/-r/-s/-poa 变 量 匹 配 的 对 象 。 使 用 -java 变量 注 册 的 类 将 通 过 vbj 命 令 执 行 。可 选-host 指 定 运 行 OAD 的 具 体 远 程 主 机 。-verbose如 果 将 详 细 模 式 设 置 为 on ( 开 启 ), 则 将 消 息 输 出 到stdout。-version 打 印 该 工 具 的 版 本 。-d 指 定 在 激 活 时 要 传 递 到 服 务 器 的 引 用 数 据 。-a arg1-a arg2 指 定 要 作 为 命 令 行 变 量 传 递 到 新 生 的 可 执 行 文 件 的 变 量 。变 量 可 以 通 过 多 个 -a (arg) 参 数 传 递 。 要 创 建 新 生 可 执 行文 件 , 必 须 广 播 这 些 变 量 。16-6 <strong>VisiBroker</strong> 开 发 者 指 南


使 用 对 象 激 活 守 护 进 程 实 用 工 具说 明选 项-e env1-e env2 指 定 要 传 递 到 新 生 可 执 行 文 件 的 环 境 变 量 。 变 量 可 以 通 过多 个 -e (env) 参 数 传 递 。 要 创 建 新 生 可 执 行 文 件 , 必 须 广播 这 些 变 量 。-p {shared|unshared} 指 定 新 生 对 象 的 激 活 策 略 。 默 认 策 略 是 SHARED_SERVER。共 享 : 给 定 对 象 的 多 个 客 户 共 享 同 一 实 现 。 OAD 每 次 仅激 活 一 个 服 务 器 。 不 共 享 : 只 有 给 定 实 现 的 一 个 客 户 会 绑定 到 激 活 的 服 务 器 。 如 果 多 个 客 户 要 绑 定 到 同 一 对 象 实现 , 要 为 每 个 客 户 端 应 用 程 序 激 活 一 个 单 独 的 服 务 器 。 在服 务 器 客 户 端 应 用 程 序 断 开 连 接 或 退 出 时 , 服 务 器 会 退出 。实 例 1: 指 定 仓 库 ID以 下 命 令 将 在 OAD 上 注 册 <strong>VisiBroker</strong> <strong>Edition</strong> 程 序 factory。 它 将 在 请 求 具 有仓 库 ID IDL:ehTest/Factory:1.0 ( 它 与 接 口 名 ehTest::Factory 相 对 应 ) 的 对 象时 被 激 活 。 要 激 活 的 对 象 实 例 名 是 ReentrantServer, 且 该 名 称 也 作 为 命 令 行 变 量传 递 到 新 生 的 可 执 行 文 件 。 该 服 务 器 具 有 不 共 享 策 略 , 在 该 策 略 下 , 在 发 出 请 求 的客 户 中 断 自 己 与 新 生 服 务 器 之 间 的 连 接 时 服 务 器 会 被 终 止 。C++ 实 例 : prompt> oadutil reg -r IDL:ehTest/Factory:1.0 -o ReentrantServer \-cpp /home/developer/Project1/factory_r -a ReentrantServer \-p unsharedJava 实 例 : prompt> oadutil reg -r IDL:ehTest/Factory:1.0 -o ReentrantServer \-java factory_r -a ReentrantServer -p unshared注 : 在 以 上 实 例 中 , 指 定 的 Java 类 必 须 能 够 在 CLASSPATH 中 找 到 。实 例 2: 指 定 IDL 接 口 名以 下 命 令 将 在 OAD 上 注 册 <strong>VisiBroker</strong> <strong>Edition</strong> 类 Server。 在 本 实 例 中 , 指 定 的类 必 须 激 活 仓 库 ID IDL:Bank/AccountManager:1.0 ( 与 接 口 名 IDL 名 称Bank::AccountManager 相 对 应 ) 的 对 象 和 实 例 名 CreditUnion。 服 务 器 将 在 不 共 享策 略 下 启 动 , 以 确 保 在 发 出 请 求 的 客 户 中 断 自 己 的 连 接 时 , 服 务 器 会 被 中 止 。Java 实 例 : prompt> oadutil reg -i Bank::AccountManager -o CreditUnion \-java Server -a CreditUnion -p unshared -e DEBUG=1注 : 在 以 上 的 实 例 中 , 指 定 的 Java 类 必 须 能 够 在 CLASSPATH 中 找 到 。以 上 的 注 册 让 OAD 在 产 生 所 请 求 的 服 务 器 的 过 程 中 执 行 以 下 命 令 :vbj -DDEBUG=1 Server CreditUnion从 远 端 在 OAD 上 注 册要 将 实 现 注 册 到 远 端 主 机 上 的 OAD, 可 使 用 -h 变 量 来 执 行 oadutil reg。以 下 的 实 例 说 明 如 何 从 UNIX shell 下 的 Windows NT 上 的 OAD 上 执 行 远 端 注册 。 双 反 斜 线 是 必 要 的 , 这 样 可 以 避 免 让 shell 在 斜 线 传 递 到 oadutil 之 前 对 斜 线进 行 翻 译 。使 用 对 象 激 活 守 护 进 程 (Daemon) 16-7


使 用 对 象 激 活 守 护 进 程 实 用 工 具实 例 : prompt> oadutil reg -r IDL:Library:1.0 Harvard \-cpp c:\\vbroker\\examples\\library\\libsrv.exe -p shared -h 100.64.15.198不 借 助 智 能 代 理 来 访 问 服 务 器当 客 户 需 要 通 过 OAD 访 问 服 务 器 , 而 它 不 使 用 智 能 代 理 时 , 可 以 使 用 oadutil 来将 vbroker.orb.activationIOR 属 性 设 置 到 IOR 或 .ior 文 件 的 位 置 。 例 如 , 如 果server.ior 文 件 位 于 /home/username 目 录 下 , 则 命 令 如 下 :oadutil -VBJprop vbroker.orb.activationIOR = file:///home/username/server.ior有 关 详 情 , 请 参 阅 第 14 章 " 使 用 命 名 服 务 "。区 分 一 个 对 象 的 多 个 实 例C++:您 的 实 现 可 以 使 用 ReferenceData 来 区 分 同 一 对 象 的 多 个 实 例 。 引 用 数 据 的 值 由 实现 在 对 象 创 建 过 程 中 选 择 , 在 对 象 的 生 命 周 期 内 保 持 不 变 。 ReferenceDatatypedef 可 以 在 平 台 和 <strong>VisiBroker</strong> ORB 上 移 植 。<strong>VisiBroker</strong> <strong>Edition</strong> 不 使 用 inf_ptr, inf_ptr 是 由 CORBA 规 范 定 义 的 , 它 用 以识 别 被 创 建 的 对 象 的 接 口 。 由 <strong>VisiBroker</strong> <strong>Edition</strong> 创 建 的 应 用 应 该 始 终 为 该 参 数指 定 一 个 NULL 值 。用 CreationImplDef 类 设 置 激 活 属 性CreationImplDef 类 包 含 OAD 所 需 要 的 用 以 激 活 <strong>VisiBroker</strong> ORB 对 象(path_name、 activation_policy、 args、 env) 的 属 性 。 以 下 的 示 例 说 明CreationImplDef 结 构 。path_name 属 性 指 定 实 现 对 象 的 可 执 行 程 序 的 确 切 路 径 名 。activation_policy 属 性表 示 服 务 器 的 激 活 策 略 , 请 参 阅 “CreationImplDef 接 口 ”。 args 和 env 属 性 表示 命 令 行 变 量 和 服 务 器 的 环 境 设 置 。module extension {...enum Policy {SHARED_SERVER,UNSHARED_SERVER};struct CreationImplDef {CORBA::RepositoryId repository_id;stringobject_name;CORBA::ReferenceData id;stringpath_name;Policyactivation_policy;CORBA::StringSequence args;};...};CORBA::StringSequenceenv;16-8 <strong>VisiBroker</strong> 开 发 者 指 南


使 用 对 象 激 活 守 护 进 程 实 用 工 具动 态 变 更 <strong>VisiBroker</strong> ORB 实 现小 心 :以 下 的 示 例 说 明 change_implementation() 成 员 函 数 , 该 函 数 可 用 于 动 态 变 更 对 象的 注 册 。 您 可 以 使 用 该 函 数 变 更 对 象 的 激 活 政 策 、 路 径 名 、 变 量 、 和 环 境 变 量 。module Activation{...void change_implementation(in extension::CreationImplDef old_info,in extension::CreationImplDef new_info)raises ( NotRegistered, InvalidPath, IsActive );...};虽 然 您 可 以 使 用 change_implementation() 成 员 函 数 来 变 更 对 象 的 实 现 名 和 对 象名 , 但 您 得 小 心 行 事 , 这 样 的 操 作 会 禁 止 客 户 程 序 用 旧 名 称 来 定 位 对 象 。使 用 OAD::reg_implementation 的 OAD 注 册<strong>VisiBroker</strong> <strong>Edition</strong> 不 使 用 手 工 方 式 的 或 在 脚 本 中 的 oadutil reg 命 令 , 它 允 许 客户 应 用 使 用 OAD::reg_implementation 操 作 来 注 册 一 个 或 多 个 具 有 激 活 守 护 进 程 的对 象 。 使 用 该 操 作 的 结 果 是 , 对 象 实 现 在 OAD 和 osagent 上 注 册 。 OAD 将 把 信息 存 储 在 实 现 库 中 , 以 便 在 客 户 尝 试 绑 定 到 对 象 时 , 允 许 定 位 和 激 活 对 象 实 现 。module Activation {...typedef sequence ObjectStatus List;...typedef sequence ImplStatusList;...interface OAD {// 注 册 实 现 。Object reg_implementation(in extension::CreationImplDef impl)raises (DuplicateEntry, InvalidPath);}}CreationImplDef 结 构 包 含 OAD 所 要 求 的 属 性 。 属 性 为 repository_id、object_name、id、path_name、activation_policy、args 和 env。 另 外 , 也 提 供 了设 定 和 查 询 它 们 的 值 的 操 作 。 OAD 可 以 使 用 这 些 额 外 的 属 性 来 激 活 <strong>VisiBroker</strong>ORB 对 象 。struct CreationImplDef {CORBA::RepositoryId repository_id;string object_name;CORBA::ReferenceData id;string path_name;Policy activation_policy;CORBA::StringSequence args;CORBA::StringSequence env;};使 用 对 象 激 活 守 护 进 程 (Daemon) 16-9


使 用 对 象 激 活 守 护 进 程 实 用 工 具path_name 属 性 指 定 实 现 对 象 的 可 执 行 程 序 的 确 切 路 径 名 。activation_policy 属 性表 示 服 务 器 的 激 活 策 略 。 args 和 env 属 性 表 示 要 传 递 给 服 务 器 的 可 选 变 量 和 环 境变 量 。对 象 创 建 和 注 册 的 实 例以 下 的 代 码 示 例 说 明 如 何 使 用 CreationImplDef 类 和 OAD.reg_implementation() 成员 函 数 在 OAD 上 注 册 服 务 器 。 这 一 机 制 可 用 于 单 独 的 管 理 程 序 , 不 一 定 要 用 在 对象 实 现 中 。 如 果 用 在 对 象 实 现 中 , 这 些 任 务 必 须 在 激 活 对 象 实 现 之 前 执 行 。int main(int argc, char* const* argv){try {// 初 始 化 ORB。CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);// 取 得 管 理 器 IdPortableServer::ObjectId_var managerId =PortableServer::string_to_ObjectId("BankManager");// 找 到 一 个 帐 户 管 理 器 。 Give the full POA name and the servant ID.Bank::AccountManager_var manager =Bank::AccountManager::_bind("/bank_agent_poa", managerId);// 使 用 argv[1] 作 account 名 称 , 或 使 用 默 认 值 。const char* name = argc > 1 ? argv[1] :"Jack B. Quick";// 要 求 帐 户 管 理 器 打 开 一 个 命 名 的 帐 户 。Bank::Account_var account = manager->open(name);// 得 到 帐 户 的 余 额 。CORBA::Float balance = account->balance();// 打 印 余 额 。cout


}}com.inprise.vbroker.extension.CreationImplDef();_implDef.repository_id = "IDL:Bank/AccountManager:1.0";_implDef.object_name = "BankManager";_implDef.path_name = "vbj";_implDef.id = new byte[0];_implDef.activation_policy =com.inprise.vbroker.extension.Policy.SHARED_SERVER;_implDef.env = new String[0];String[] str = new String[1];str[0] = "Server";_implDef.args = str;try {anOAD.reg_implementation(_implDef);} catch (Exception e) {System.out.println("Caught " + e);}}catch (org.omg.CORBA.NO_IMPLEMENT e) {}反 注 册 对 象由 OAD 传 递 的 变 量当 OAD 启 动 一 个 对 象 实 现 时 , 它 将 传 递 实 现 在 OAD 注 册 时 所 指 定 的 所 有 变 量 。反 注 册 对 象当 由 对 象 提 供 的 服 务 不 再 可 用 或 需 要 暂 停 时 , 该 对 象 应 该 在 OAD 上 反 注 册 。 当 反注 册 <strong>VisiBroker</strong> ORB 对 象 时 , 将 会 从 实 现 库 上 删 除 该 对 象 。 同 时 , 该 对 象 同 时 也被 从 智 能 代 理 的 词 典 上 删 除 。 一 旦 反 注 册 一 个 对 象 后 , 客 户 端 程 序 将 不 能 找 到 或 使用 它 。 另 外 , 您 将 不 能 使 用 OAD.change_implementation() 成 员 函 数 来 变 更 对 象 的实 现 。 与 注 册 过 程 一 样 , 反 注 册 过 程 可 以 在 命 令 行 完 成 , 也 可 以 编 程 来 完 成 。 另外 , 还 有 一 个 到 OAD 的 <strong>VisiBroker</strong> ORB 对 象 接 口 , 请 参 阅 第 16-11 页 " 反 注册 对 象 "。使 用 oadutil 工 具 反 注 册 对 象注 :oadutil unreg 命 令 允 许 您 反 注 册 一 个 或 多 个 在 ODA 上 注 册 的 对 象 实 现 。 一 旦 反注 册 了 一 个 对 象 后 , 如 果 客 户 请 求 该 对 象 , 则 OAD 将 不 能 再 自 动 激 活 它 。 只 有 以前 使 用 oadutil reg 命 令 注 册 的 对 象 才 可 以 通 过 oadutil unreg 命 令 反 注 册 。如 果 您 仅 指 定 了 一 个 接 口 名 称 , 则 所 有 与 该 接 口 相 关 联 的 <strong>VisiBroker</strong> ORB 对 象 都将 被 反 注 册 。 另 外 , 您 可 以 通 过 接 口 名 和 对 象 名 来 识 别 一 个 特 定 的 <strong>VisiBroker</strong>ORB 对 象 。 当 您 反 注 册 了 一 个 对 象 后 , 与 该 对 象 相 关 联 的 一 切 进 程 都 将 终 止 。在 您 使 用 oadutil reg 命 令 之 前 , 您 至 少 必 须 在 网 络 上 的 一 台 主 机 上 启 动 oad进 程 。使 用 对 象 激 活 守 护 进 程 (Daemon) 16-11


反 注 册 对 象oadutil unreg 命 令 的 语 法 如 下 :语 法 :oadutil unreg [ 选 项 ]oadutil unreg 命 令 的 选 项 接 受 以 下 的 命 令 行 变 量 :选 项说 明必 选 项-i 指 定 特 定 IDL 接 口 名 称 。 每 次 仅 可 以 指 定 下列 选 项 之 一 :-i、 -r、 -s 或 -poa。 有 关 指 定仓 库 ID 的 详 情 , 请 参 阅 “ 将 接 口 名 转 换 为 库ID" 。-r 指 定 特 定 的 仓 库 ID。 每 次 仅 可 以 指 定 下 列 选项 之 一 :-i、 -r、 -s 或 -poa。-s 指 定 特 定 的 服 务 名 称 。 每 次 仅 可 以 指 定 下 列 选项 之 一 :-i、 -r、 -s 或 -poa。-o 指 定 特 定 的 对 象 名 称 。 仅 当 接 口 名 或 仓 库 ID包 含 于 命 令 声 明 中 时 , 您 才 可 以 使 用 该 选 项 。当 使 用 了 -s 或 -poa 变 量 后 , 该 选 项 不 可 用 。-poa 用 oadutil reg -poa 反 注 册POA。可 选-host 指 定 运 行 OAD 的 主 机 名 。-verbose允 许 详 细 模 式 , 使 用 消 息 输 出 到 stdout。-version 打 印 该 工 具 的 版 本 。反 注 册 实 例oadutil unreg 实 用 工 具 可 以 从 以 下 三 个 位 置 反 注 册 一 个 或 多 个 <strong>VisiBroker</strong> ORB对 象 :● OAD● 实 现 库● 智 能 代 理以 下 的 实 例 说 明 如 何 使 用 oadutil unreg 命 令 。 该 实 例 从 本 地 OAD 上 反 注 册 命 名为 InpriseBank 的 Bank::AccountManager 的 实 现 。oadutil unreg -i Bank::AccountManager -o InpriseBank用 OAD 操 作 反 注 册对 象 实 现 可 以 使 用 OAD 接 口 上 的 任 何 一 个 操 作 或 属 性 来 反 注 册 一 个 <strong>VisiBroker</strong>ORB 对 象 。● unreg_implementation(in CORBA::RepositoryId repId, in stringobject_name)● unreg_interface(in CORBA::RepositoryId repId)16-12 <strong>VisiBroker</strong> 开 发 者 指 南


面 向 OAD 的 IDL 接 口● unregister_all()● attribute boolean destroy_on_unregisterunreg_implementation()unreg_interface()unregister_all()destroy_on_unregister当 您 想 要 使 用 特 定 的 仓 库 ID 或 对 象 名 来反 注 册 实 现 时 , 您 可 以 使 用 该 操 作 。 该 操作 终 止 当 前 正 在 实 现 指 定 的 仓 库 ID 和 对象 名 的 所 有 进 程 。当 您 想 只 使 用 特 定 的 仓 库 ID 来 反 注 册 实现 时 , 您 可 以 使 用 该 操 作 。 该 操 作 将 终 止当 前 所 有 正 在 实 现 指 定 的 仓 库 ID 的 进程 。该 操 作 可 用 于 反 注 册 所 有 实 现 。 除 非 将destroyActive 设 置 为 true, 否 则 所 有 活动 的 实 现 将 继 续 执 行 。 由 于 提 供 了 后 向 兼容 , unregister_all() 不 是 破 坏 性 的 ;它 相 当 于 调 用unregister_all_destroy(false)。使 用 该 属 性 销 毁 所 有 在 反 注 册 有 关 实 现 时新 生 成 的 进 程 。 默 认 值 是 false。module Activation {...interface OAD {...void unreg_implementation(in CORBA::RepositoryId repId, in stringobject_name)raises(NotRegistered);...}}显 示 实 现 库 的 内 容您 可 以 使 用 oadutil 工 具 来 列 出 特 定 实 现 库 的 内 容 。 对 于 库 中 的 每 个 实 现 ,oadutil工 具 将 列 出 所 有 的 对 象 实 例 名 、 可 执 行 程 序 的 路 径 名 、 激 活 方 式 和 引 用 数 据 。 另外 , 所 有 要 传 递 到 可 执 行 程 序 的 变 量 或 环 境 变 量 也 会 被 列 出 。面 向 OAD 的 IDL 接 口OAD 是 作 为 <strong>VisiBroker</strong> ORB 对 象 来 实 现 的 , 它 允 许 您 创 建 绑 定 到 OAD 的 客 户端 程 序 , 并 使 用 其 接 口 来 查 询 已 经 注 册 的 对 象 的 状 态 。 以 下 的 代 码 示 例 说 明 ODA的 IDL 接 口 规 范 。module Activation{enum state {使 用 对 象 激 活 守 护 进 程 (Daemon) 16-13


面 向 OAD 的 IDL 接 口ACTIVE,INACTIVE,WAITING_FOR_ACTIVATION};struct ObjectStatus {long unique_id;State activation_state;Object objRef;};typedef sequence ObjectStatusList;struct ImplementationStatus {extension::CreationImplDef impl;ObjectStatusList status;};typedef sequence ImplStatusList;exception DuplicateEntry {};exception InvalidPath {};exception NotRegistered {};exception FailedToExecute {};exception NotResponding {};exception IsActive {};exception Busy {};interface OAD {Object reg_implementation( in extension::CreationImplDef impl)raises (DuplicateEntry, InvalidPath);extension::CreationImplDef get_implementation(in CORBA::RepositoryId repId,in string object_name)raises ( NotRegistered);void change_implementation(in extension::CreationImplDef old_info,in extension::CreationImplDef new_info)raises (NotRegistered,InvalidPath,IsActive);attribute boolean destroy_on_unregister;void unreg_implementation(in CORBA::RepositoryId repId,in string object_name)raises ( NotRegistered );void unreg_interface(in CORBA::RepositoryId repId)raises ( NotRegistered );void unregister_all();ImplementationStatus get_status(in CORBA::RepositoryId repId,in string object_name)raises ( NotRegistered);ImplStatusList get_status_interface(in CORBA::RepositoryId repId)raises (NotRegistered);ImplStatusList get_status_all();};16-14 <strong>VisiBroker</strong> 开 发 者 指 南


第章使 用 接 口 仓 库第 17 章接 口 仓 库 (IR) 中 包 含 关 于 CORBA 对 象 接 口 的 描 述 。 IR 中 的 数 据 与 IDL 文 件中 的 数 据 是 相 同 的 , 其 中 包 括 关 于 模 块 、 接 口 、 操 作 、 和 参 数 的 描 述 , 但 是 , IR中 的 数 据 是 有 组 织 的 , 有 助 于 客 户 在 运 行 期 内 存 取 。 客 户 可 以 浏 览 接 口 仓 库 ( 可 能是 作 为 开 发 者 的 在 线 参 考 库 ), 或 者 可 以 查 询 它 具 有 其 引 用 的 任 何 对 象 的 接 口 ( 可能 准 备 好 用 DII 来 调 用 对 象 )。阅 读 本 章 后 , 您 将 可 以 创 建 一 个 接 口 仓 库 并 用 <strong>VisiBroker</strong> <strong>Edition</strong> 实 用 工 具 或 您自 己 的 代 码 来 访 问 它 。什 么 是 接 口 仓 库 ?一 个 接 口 仓 库 (IR) 就 象 CORBA 对 象 接 口 信 息 的 一 个 数 据 库 , 它 允 许 客 户 在 运行 期 内 了 解 或 更 新 接 口 描 述 。 IR 与 第 13 章 " 使 用 定 位 服 务 " 所 描 述 的<strong>VisiBroker</strong> <strong>Edition</strong> 定 位 服 务 不 同 , 定 位 服 务 保 存 描 写 对 象 实 例 的 数 据 , 但 IR的 数 据 描 写 接 口 ( 类 型 )。 可 能 存 在 也 可 能 不 存 在 可 以 满 足 存 储 在 IR 中 的 接 口 的可 用 实 例 。IR 中 信 息 相 当 于 存 储 在 IDL 文 件 中 的 信 息 , 但 是 ,IR 中 的 信 息 的 表 示方 法 让 用 户 在 运 行 期 内 使 用 起 来 更 容 易 。使 用 接 口 仓 库 的 用 户 也 可 以 使 用 第 18 章 " 使 用 动 态 调 用 接 口 " 中 所 描 述 的 动 态 调用 接 口 (DII)。 这 样 的 客 户 使 用 接 口 仓 库 来 了 解 未 知 对 象 的 接 口 , 它 们 使 用 DII来 调 用 对 象 上 的 方 法 。 但 是 , IR 和 DII 之 间 不 存 在 必 然 的 联 系 。 例 如 , 有 些 人 可能 使 用 IR 为 开 发 者 编 写 “IDL 浏 览 器 ” 工 具 , 在 这 样 的 一 个 工 具 中 , 要 从 浏 览 器中 将 方 法 描 述 拖 动 到 编 辑 器 , 开 发 者 的 源 代 码 中 需 要 插 入 一 个 模 板 方 法 调 用 。 在 该实 例 中 , IR 是 在 没 有 DII 的 情 况 下 使 用 的 。您 可 以 用 <strong>VisiBroker</strong> <strong>Edition</strong> irep 程 序 创 建 一 个 接 口 仓 库 , 该 程 序 是 IR 服 务 器( 实 现 )。 您 可 以 用 <strong>VisiBroker</strong> <strong>Edition</strong> idl2ir 程 序 更 新 或 配 置 接 口 仓 库 , 您 也 可以 编 写 IR 客 户 , 用 它 来 检 查 接 口 仓 库 , 更 新 接 口 仓 库 或 者 两 者 兼 有 。使 用 接 口 仓 库 17-1


用 irep 创 建 和 查 看 接 口 仓 库接 口 仓 库 中 包 含 的 是 什 么 ?接 口 仓 库 中 包 含 的 是 对 象 的 结 构 , 这 些 对 象 的 方 法 “ 暴 露 ” 有 关 接 口 信 息 。 虽 然 接口 通 常 被 认 为 是 用 来 描 述 对 象 的 , 但 是 使 用 一 套 对 象 来 描 述 接 口 在 CORBA 环 境下 是 很 有 意 义 的 , 因 为 这 不 需 要 象 数 据 库 这 样 的 新 机 制 。举 个 例 子 来 看 一 下 IR 中 所 包 含 的 对 象 的 种 类 , 设 想 IDL 文 件 可 以 容 纳 IDL 模 块定 义 , 模 块 可 以 容 纳 接 口 定 义 , 而 接 口 可 以 容 纳 操 作 ( 方 法 ) 定 义 。 相 应 地 , 一 个接 口 仓 库 可 以 容 纳 ModuleDef 对 象 , ModuleDef 对 象 可 以 容 纳 InterfaceDef 对 象 ,而 InterfaceDef 对 象 可 以 容 纳 OperationDef 对 象 。 因 此 , 给 定 一 个 IRModuleDef, 您 就 可 以 知 道 它 所 包 含 的 是 什 么 InterfaceDef。 反 过 来 也 成 立 。 给 定一 个 InterfaceDef, 您 就 可 以 知 道 它 包 含 于 什 么 ModuleDef 中 。 所 有 其 它 IDL 构造 ( 包 括 违 例 、 属 性 、 和 值 类 型 ) 都 可 以 在 接 口 仓 库 中 表 示 。接 口 仓 库 中 也 可 以 容 纳 typecode。Typecode 不 是 被 显 式 地 列 在 IDL 文 件 中 , 但是 , 它 们 可 以 从 IDL 文 件 中 所 定 义 的 或 涉 及 的 类 型 (long、 string、 struct 等 )自 动 派 生 。 Typecode 用 于 对 CORBA 的 any 类 型 的 实 例 进 行 编 码 和 解 码 。CORBA any 类 型 表 示 任 何 类 型 , 可 用 于 动 态 调 用 接 口 。您 可 以 创 建 多 少 个 接 口 仓 库 ?注 :接 口 仓 库 就 象 其 它 对 象 一 样 , 您 想 创 建 多 少 就 可 以 创 建 多 少 。<strong>VisiBroker</strong> <strong>Edition</strong>没 有 制 订 任 何 约 束 创 建 和 使 用 IR 的 策 略 。 您 可 以 自 行 决 定 如 何 部 署 和 命 名 您 自 己的 接 口 仓 库 。 例 如 , 您 可 以 采 用 这 样 的 惯 例 , 即 一 个 中 心 接 口 仓 库 容 纳 所 有 “ 产品 ” 对 象 的 接 口 , 而 开 发 者 创 建 他 们 自 己 的 IR 来 作 测 试 。接 口 仓 库 是 可 写 的 , 不 受 存 取 控 制 的 保 护 。 一 个 错 误 或 恶 意 的 客 户 可 以 毁 坏 IR 或从 其 上 得 到 敏 感 的 信 息 。如 果 您 想 使 用 为 所 有 对 象 定 义 的 _get_interface_def 方 法 , 您 至 少 必 须 有 一 个 接 口仓 库 服 务 器 正 在 运 行 , 以 便 <strong>VisiBroker</strong> ORB 可 以 在 IR 查 询 接 口 。 如 果 没 有 接 口仓 库 可 用 , 或 <strong>VisiBroker</strong> ORB 所 限 制 到 的 IR 尚 未 载 入 对 象 的 接 口 定 义 , 则_get_interface_def 会 掷 出 一 个 NO_IMPLEMENT 违 例 。用 irep 创 建 和 查 看 接 口 仓 库<strong>VisiBroker</strong> <strong>Edition</strong> 接 口 仓 库 服 务 器 被 称 为 irep, 它 位 于 bin 目 录 下 。 irep 程 序是 以 daemon ( 守 护 进 程 ) 方 式 运 行 的 。 您 可 以 在 对 象 激 活 守 护 进 程 (OAD)中 注 册 irep , 就 象 注 册 任 何 对 象 实 现 一 样 。 oadutil 工 具 需 要 对 象 ID, 例 如 ,IDL:org.omg/CORBA/Repository:2.3 ( 与 接 口 名 称 相 对 , 例 如 ,CORBA::Repository)。用 irep 创 建 接 口 仓 库使 用 irep 程 序 来 创 建 一 个 接 口 仓 库 , 并 检 查 它 的 内 容 。 irep 程 序 的 使 用 语 法 如下 :17-2 <strong>VisiBroker</strong> 开 发 者 指 南


用 irep 创 建 和 查 看 接 口 仓 库语 法 :irep IRepName [file.idl]下 表 描 述 用 于 在 irep 中 创 建 接 口 仓 库 的 语 法 :语 法IRep Namefile.idl说 明指 定 接 口 仓 库 的 实 例 名 称 。 客 户 可 以 通 过 指 定该 名 称 来 限 制 到 这 个 接 口 仓 库 。指 定 一 个 IDL 文 件 , irep 将 要 把 该 文 件 的 内容 载 入 它 所 创 建 的 接 口 仓 库 , 并 在 它 退 出 时 ,将 IR 内 容 存 入 该 文 件 。 如 果 未 指 定 文 件 , 则irep 创 建 一 个 空 的 接 口 仓 库 。下 表 中 定 义 了 irep 的 变 量 。变 量说 明驱 动 程 序 选 项-J将 该 选 项 直 接 传 递 给 JVM。-VBJversion打 印 VBJ 版 本-VBJdebug 打 印 VBJ 调 试 信 息 。-VBJclasspath 指 定 classpath, 在 CLASSPATH env 变 量 前 。-VBJprop [=传 递 名 / 值 对 到 JVM。-VBJjavavm 指 定 JVM 路 径 。-VBJaddJar 在 执 行 JVM 前 , 将 jarfile 连 接 到CLASSPATH。其 它 选 项-D, -define foo[=bar] 定 义 预 处 理 器 宏 , 有 可 选 值 。-I, -include 为 #include 搜 索 指 定 额 外 的 目 录 。-P, -no_line_directives不 从 预 处 理 器 发 出 #line directives。 默 认 值 是off ( 关 闭 )。-H, -list_includes显 示 所 包 含 的 文 件 名 称 ( 当 遇 到 它 们 时 )。 默 认值 是 off ( 关 闭 )。-C, -retain_comments将 注 释 保 留 在 预 处 理 的 输 出 中 。 . 默 认 值 是 off( 关 闭 )。-U, -undefine foo Undefine 一 个 预 处 理 器 宏 。-[no_]idl_strict对 IDL 源 进 行 严 格 的 OMG 标 准 翻 译 。 默 认 值 是off ( 关 闭 )。-[no_]warn_unrecognized_pragmas 如 果 不 认 可 #pragma, 则 发 出 警 告 。 默 认 值 是on ( 打 开 )。-[no_]back_compat_mapping 使 用 与 <strong>VisiBroker</strong> <strong>Edition</strong> 3.x 兼 容 的 映 射 。-h, -help, -usage, -? 打 印 使 用 信 息 。-version 显 示 软 件 版 本 号 。-install 安 装 为 NT 服 务 。-remove 对 该 NT 服 务 解 除 安 装 。实 例 :以 下 的 实 例 说 明 如 何 从 一 个 命 名 Bank.idl 的 文 件 创 建 一 个 命 名 为 TestIR 接 口 仓库 。irep TestIR Bank.idl使 用 接 口 仓 库 17-3


用 idl2ir 更 新 接 口 仓 库查 看 接 口 仓 库 的 内 容您 可 以 使 用 <strong>VisiBroker</strong> <strong>Edition</strong> ir2idl 实 用 工 具 或 <strong>VisiBroker</strong> <strong>Edition</strong>Console 应 用 来 查 看 接 口 仓 库 的 内 容 。 ir2idl 实 用 工 具 的 语 法 是 :语 法 :ir2idl [-irep IRname]下 表 中 给 出 了 有 关 在 irep 中 查 看 接 口 仓 库 的 内 容 的 语 法 :语 法-irep IRname说 明指 示 程 序 限 制 到 命 名 为 IRname 的 接 口 仓 库 实例 。 如 果 未 指 点 定 选 项 , 则 它 限 制 到 由 智 能 代理 返 回 的 任 意 一 个 接 口 仓 库 。有 关 ir2idl 实 用 工 具 变 量 的 详 情 , 请 参 阅 程 序 员 参 考 。用 idl2ir 更 新 接 口 仓 库您 可 以 使 用 <strong>VisiBroker</strong> <strong>Edition</strong> idl2ir 实 用 工 具 来 更 新 一 个 接 口 仓 库 , 这 是 IR客 户 。 idl2ir 实 用 工 具 的 语 法 是 :语 法 :idl2ir [arguments] idl_file_list有 关 idl2ir 实 用 工 具 变 量 的 详 情 , 请 参 阅 程 序 员 参 考 。以 下 的 代 码 示 例 说 明 如 何 用 Bank.idl 文 件 中 的 定 义 来 更 新 TestIR 接 口 仓 库 。实 例 :idl2ir -irep TestIR -replace Bank.idl不 能 使 用 idl2ir 或 irep 实 用 工 具 来 删 除 接 口 仓 库 中 的 项 目 。 要 删 除 一 个 项 目 ,● 退 出 irep 程 序 。● 退 出 在 irep 命 令 行 中 命 名 的 IDL 文 件 。● 用 更 新 过 的 文 件 重 新 启 动 irep 。接 口 仓 库 具 有 一 个 简 单 的 事 务 服 务 。 如 果 指 定 的 IDL 文 件 载 入 失 败 , 则 接 口 仓 库将 其 内 容 恢 复 为 以 前 的 状 态 。 在 载 入 IDL 之 后 , 接 口 仓 库 提 交 要 在 随 后 的 事 务 中使 用 的 状 态 。 对 于 任 何 接 口 仓 库 , 在 主 目 录 下 都 有 一 个 IRname.rollback, 其 中 包含 最 后 一 个 未 完 成 的 事 务 。注 : 如 果 您 想 删 除 接 口 仓 库 中 的 所 有 项 目 , 您 可 以 用 新 的 空 IDL 文 件 来 取 代 其 内 容 。例 如 , 您 可 以 使 用 命 名 为 Empty.idl 的 IDL 文 件 来 执 行 以 下 命 令 :idl2ir -irep TestIR -replace Empty.idl了 解 接 口 仓 库 的 结 构接 口 将 其 所 包 含 的 对 象 组 织 成 与 接 口 在 IDL 规 范 中 的 定 义 方 式 相 对 应 的 层 次 结 构 。接 口 仓 库 中 的 一 些 对 象 包 含 另 外 一 些 对 象 , 就 象 IDL 模 块 定 义 可 以 包 含 几 个 接 口17-4 <strong>VisiBroker</strong> 开 发 者 指 南


了 解 接 口 仓 库 的 结 构定 义 一 样 。 想 想 以 下 显 示 的 实 例 IDL 文 件 如 何 被 转 换 成 接 口 仓 库 中 的 对 象 的 层 次结 构 。// Bank.idlmodule Bank {interface Account {float balance();};interface AccountManager {Account open(in string name);};};图 17.1Bank.idl 的 接 口 仓 库 对 象 层 次 结 构OperationDef 对 象 包 含 额 外 的 含 有 参 数 和 返 回 值 的 数 据 结 构 ( 不 是 接 口 ) 的引 用 。识 别 接 口 仓 库 中 的 对 象下 表 显 示 的 是 用 以 识 别 接 口 仓 库 中 的 对 象 并 给 它 们 分 类 的 对 象 。表 17.1项 目用 于 识 别 接 口 仓 库 中 的 对 象 并 给 它 们 分 类 的 对 象说 明名 称对 应 于 在 IDL 规 范 中 所 分 配 给 模 块 、 接 口 、 操 作 等 的 标 识 符 的 字 串 。 标 识符 不 一 定 是 唯 一 的 。id唯 一 地 标 识 一 个 IRObject 的 字 串 。 一 个 RepositoryID 包 含 三 个 组 件 , 由冒 号 (:) 分 隔 符 分 开 。 第 一 个 组 件 是 “IDL:”, 最 后 一 个 组 件 是 版 本 号 ,例 如 “:1.0”。 第 二 个 组 件 是 由 斜 杠 (/) 分 隔 开 的 标 识 符 的 序 列 。 第 一个 标 识 符 通 常 是 唯 一 的 前 缀 。def_kind 枚 举 型 数 据 值 , 定 义 用 以 表 示 接 口 仓 库 中 的 对 象 的 所 有 可 能 类 型 的 值 。可 以 存 储 在 接 口 仓 库 中 的 对 象 的 类 型下 表 总 结 出 了 可 以 包 含 在 接 口 仓 库 中 的 对 象 。 大 多 数 这 些 对 象 与 IDL 语 法 元 素 对应 。 例 如 ,StructDef 包 含 与 IDL struct 声 明 相 同 的 信 息 , InterfaceDef 包 含 与使 用 接 口 仓 库 17-5


了 解 接 口 仓 库 的 结 构IDL 接 口 声 明 相 同 的 信 息 , 以 此 类 推 , PrimitiveDef 包 含 与 IDL 基 元(boolean、 long 等 ) 声 明 相 同 的 信 息 。表 17.2对 象 类 型可 以 存 储 于 接 口 仓 库 中 的 对 象说 明仓 库 表 示 包 含 其 它 所 有 对 象 的 顶 层 模 块 。ModuleDef表 示 包 含 ModuleDefs、 InterfaceDefs、 ConstantDefs、 AliasDefs、ExceptionDefs 以 及 其 它 可 以 在 IDL 模 块 中 定 义 的 IDL 结 构 的 IR 对 等物 的 IDL 模 块 声 明 。InterfaceDef 表 示 IDL 接 口 声 明 , 包 含 OperationDefs、 ExceptionDefs、AliasDefs、 ConstantDefs 和 AttributeDefs。AttributeDef 表 示 IDL 属 性 声 明 。OperationDef 表 示 IDL 操 作 ( 方 法 ) 声 明 。 定 义 接 口 上 的 一 个 操 作 。 它 包 括 该 操 作所 需 要 的 参 数 列 表 、 返 回 值 、 该 操 作 可 能 会 掷 出 的 违 例 的 列 表 、 上 下 文列 表 。ConstantDef 表 示 IDL 常 量 声 明 。ExceptionDef 表 示 IDL 违 例 声 明 。ValueDef表 示 包 含 常 数 、 类 型 、 值 元 、 违 例 、 操 作 和 属 性 的 列 表 的 valuetype( 值 型 )。ValueBoxDef表 示 另 外 一 个 IDL 类 型 的 简 单 封 包 valuetype。ValueMemberDef 表 示 valuetype 的 一 个 成 员 。NativeDef 表 示 一 个 本 地 定 义 。 用 户 不 可 以 定 义 他 们 自 己 的 本 地 定 义 。StructDef 表 示 一 个 IDL 结 构 声 明 。UnionDef 表 示 一 个 IDL union 声 明 。EnumDef 表 示 一 个 IDL 枚 举 声 明 。AliasDef表 示 一 个 IDL typedef 声 明 。 注 意 :IR TypedefDef 接 口 是 一 个 基 础 接口 , 它 为 StructDefs、 UnionDefs 等 定 义 公 共 操 作 。StringDef 表 示 一 个 IDL 限 制 的 字 串 声 明 。SequenceDef 表 示 一 个 IDL 序 列 声 明 。ArrayDef 表 示 一 个 IDL 数 组 声 明 。PrimitiveDef 表 示 一 个 IDL primitive ( 基 元 ) 声 明 :null、void、long、 ushort、ulong、 float、 double、 boolean、 char、octet、 any、 TypeCode、Principal、 string、objref、 longlong、 ulonglong、longdouble、wchar、 wstring。17-6 <strong>VisiBroker</strong> 开 发 者 指 南


访 问 接 口 仓 库继 承 的 接 口三 个 非 可 实 例 化 ( 即 抽 象 ) 的 IDL 接 口 定 义 由 IR ( 参 见 上 表 ) 中 包 含 的 许 多 对 象继 承 的 公 共 方 法 。 下 表 总 结 出 了 这 些 被 广 泛 继 承 的 接 口 。 有 关 这 些 接 口 的 其 它 方 法的 详 情 , 请 参 阅 程 序 员 参 考 。表 17.3由 许 多 IR 对 象 继 承 的 接 口接 口 继 承 者 主 要 查 询 方 法IRObject 包 含 Repository 所 有 IR def_kind(): 返 回 IR 对 象 的 定 义类 型 , 例 如 , 模 块 或 接 口 ;destroy(): 销 毁 一 个 IR 对 象ContainerContained包 含 其 它 IR 对 象 ( 例 如 模 块 或 接口 ) 的 IR 对 象 。可 被 包 含 于 其 它 对 象 中 ( 即Containers) 中 的 IR 对 象 。lookup(): 根 据 名 称 查 询 一 个 包 含的 对 象 ; contents(): 列 出Container 中 所 包 含 的 对 象 ;describe_contents()/code> ; 描述 Container 中 的 对 象 。name(): 该 对 象 的 名 称 ;defined_in(): 包 含 一 个 对 象 的Container ; describe(): 描 述 一个 对 象 ; move (): 将 一 个 对 象 移到 另 一 个 container。访 问 接 口 仓 库您 的 客 户 端 程 序 可 以 使 用 一 个 接 口 仓 库 的 IDL 接 口 来 取 得 关 于 它 所 包 含 的 对 象 的信 息 。 您 的 客 户 端 程 序 可 以 限 制 到 Repository , 然 后 调 用 以 下 所 示 的 方 法 。 关 于该 接 口 的 完 整 描 述 , 请 参 阅 程 序 员 参 考C++: class CORBA {class Repository : public Container {. . .CORBA::Contained_ptr lookup_id(const char * search_id);CORBA::PrimitiveDef_ptr get_primitive(CORBA::PrimitiveKind kind);CORBA::StringDef_ptr create_string(CORBA::ULong bound);CORBA::SequenceDef_ptr create_sequence(CORBA::ULong bound,CORBA::IDLType_ptr element_type);CORBA::ArrayDef_ptr create_array(CORBA::ULong length,CORBA::IDLType_ptr element_type);. . .};. . .};注 : 使 用 接 口 仓 库 的 程 序 必 须 用 -D_VIS_INCLUDE_IR 标 志 来 编 译 。Java:package org.omg.CORBA;public interface Repository extends Container {. . .org.omg.CORBA.Contained lookup_id(string id);org.omg.CORBA.PrimitiveDef get_primitive(org.omg.CORBA.PrimitiveKind kind);org.omg.CORBA.StringDef create_string(long bound);使 用 接 口 仓 库 17-7


实 例 程 序}org.omg.CORBA.SequenceDef create_sequence(long bound,org.omg.CORBA.IDLType element_type);org.omg.CORBA.ArrayDef create_array(long length,org.omg.CORBA.IDLType element_type);. . .实 例 程 序本 节 描 述 了 一 个 简 单 的 接 口 仓 库 实 例 , 其 中 包 含 一 个 创 建 帐 户 和 ( 重 ) 开 帐 户 的 简单 的 AccountManager 接 口 。 实 例 的 代 码 在 examples\ir 目 录 下 。 在 初 始 化 时 ,AccountManager 实 现 对 管 理 的 Account ( 帐 户 ) 接 口 的 接 口 仓 库 定 义 进 行 解 包 。这 将 给 客 户 揭 示 已 由 该 特 定 的 Account 实 现 所 实 现 的 额 外 操 作 。 客 户 随 之 就 可 以 访问 所 有 已 知 的 操 作 ( 描 述 在 IDL 中 ), 另 外 , 它 们 也 可 以 验 证 接 口 仓 库 对 其 它 操作 的 支 持 并 调 用 这 些 操 作 。 本 实 例 说 明 我 们 如 何 管 理 接 口 仓 库 定 义 对 象 , 如 何 在C++ 和 Java 下 用 接 口 仓 库 来 观 察 远 端 对 象 。要 测 试 该 程 序 , 必 须 具 备 下 列 条 件 :● OSAgent 应 该 正 在 运 行 。● 应 该 已 使 用 irep 启 动 了 接 口 仓 库 。● 接 口 仓 库 中 应 该 载 入 IDL 文 件 , 文 件 可 以 在 您 启 动 接 口 仓 库 时 用 命 令 行 载 入 ,也 可 以 用 idl2ir 载 入 。● 启 动 客 户 端 程 序 。在 C++ 下 查 看 IR 中 的 接 口 的 操 作 和 属 性 :C++: /* PrintIR.C */#ifndef _VIS_INCLUDE_IR#define _VIS_INCLUDE_IR#endif#include "corba.h"#include "strvar.h"int main(int argc, char *argv[]) {try {if (argc != 2) {cout describe_interface();cout


实 例 程 序Java:}for(i = 0; i < fullDesc->attributes.length(); i++)cout


实 例 程 序InterfaceDefHelper.narrow(account._get_interface_def());// 检 查 这 个 * 特 别 * 实 现 是 否 支 持 “describe” 操 作if (accountDef.lookup("describe") != null) {// 这 里 我 们 不 可 以 用 静 态 框 架 的 方 法 , 因 为 在 其// 创 建 时 , 该 方 法 在 IDL 的 帐 户 接 口 版 本// 中 尚 不 存 在 。 使 用 的 是 DII。Request request = account._request("describe");request.result().value().insert_string("");request.invoke();return request.result().value().extract_string();} else {return "";}}}17-10 <strong>VisiBroker</strong> 开 发 者 指 南


第章使 用 动 态 调 用 接 口第 18 章大 多 数 客 户 程 序 的 开 发 员 知 道 其 代 码 将 要 调 用 的 CORBA 对 象 的 类 型 , 他 们 在 其代 码 中 包 含 有 这 些 类 型 的 编 译 器 生 成 的 存 根 。 相 形 之 下 , 普 通 客 户 的 开 发 者 不 可 能知 道 其 用 户 将 要 调 用 什 么 类 型 的 对 象 。 这 样 的 开 发 者 , 根 据 从 运 行 期 内 得 到 的 知识 , 使 用 动 态 调 用 接 口 (DII) 来 编 写 可 以 调 用 任 何 CORBA 对 象 上 的 任 何 方 法 的客 户 。什 么 是 动 态 调 用 接 口 ?动 态 调 用 接 口 (DII) 允 许 客 户 程 序 在 编 写 CORBA 对 象 时 对 该 对 象 的 类 型 未 知 的情 况 下 调 用 该 对 象 上 的 方 法 。 DII 不 同 于 缺 省 的 静 态 调 用 , 静 态 调 用 要 求 客 户 源 代码 中 为 客 户 要 调 用 的 每 一 类 CORBA 对 象 包 括 一 个 编 译 器 生 成 的 存 根 。 换 句 话 说 ,使 用 静 态 调 用 的 客 户 要 提 前 声 明 它 将 调 用 的 对 象 类 型 。 使 用 DII 的 用 户 无 须 作 这 样的 声 明 , 因 为 它 的 编 程 员 不 知 道 将 会 调 用 什 么 类 型 的 对 象 。 DII 的 优 点 是 其 灵 活性 : 它 可 以 被 用 来 编 写 可 以 调 用 任 何 对 象 的 普 通 客 户 , 其 中 包 括 在 编 译 客 户 时 接 口不 存 在 的 那 些 对 象 。 DII 有 两 个 缺 点 :● 它 的 编 程 更 难 ( 实 际 上 , 您 的 代 码 必 须 做 存 根 的 工 作 )。● 调 用 耗 时 更 长 , 这 是 因 为 运 行 期 内 要 做 更 多 的 工 作 。DII 是 一 个 纯 粹 的 客 户 接 口 - 从 对 象 实 现 的 角 度 来 看 , 静 态 调 用 和 动 态 调 用 是 没 有分 别 的 。您 可 以 用 DII 构 建 象 这 样 的 客 户 :● 脚 本 环 境 与 CORBA 对 象 之 间 的 桥 接 器 或 适 配 器 。 例 如 , 一 个 脚 本 调 用 您 的 桥接 器 , 传 递 对 象 和 方 法 标 识 和 参 数 值 。 您 的 桥 接 器 构 建 并 发 送 一 个 动 态 请 求 , 接收 结 果 , 并 将 其 返 回 给 脚 本 环 境 。 这 样 的 桥 接 器 不 能 使 用 静 态 调 用 , 因 为 它 的 开发 者 不 可 能 提 前 知 道 将 要 调 用 什 么 类 型 的 脚 本 环 境 。使 用 动 态 调 用 接 口 18-1


什 么 是 动 态 调 用 接 口 ?注 :● 普 通 对 象 测 试 器 。 例 如 , 一 个 客 户 取 出 一 个 任 意 的 对 象 标 识 , 在 接 口 仓 库 中 查 询它 的 接 口 ( 参 阅 第 17 章 " 使 用 接 口 仓 库 "), 然 后 用 人 工 变 量 值 调 用 其 每 种 方法 。 同 样 的 道 理 , 这 种 普 通 测 试 器 不 可 能 用 静 态 调 用 来 构 建 。客 户 必 须 在 DII 请 求 中 传 递 合 法 的 变 量 。 如 果 不 这 样 做 , 可 能 会 产 生 无 法 预 料 的结 果 , 其 中 包 括 服 务 器 出 现 事 故 。 虽 然 动 态 地 检 查 接 口 仓 库 中 的 参 数 值 是 可 能 的 ,但 这 样 做 成 本 很 高 。 为 了 得 到 最 佳 性 能 , 确 保 调 用 使 用 DII 客 户 的 代 码 ( 如 脚 本 )可 令 人 信 赖 地 传 递 合 法 的 变 量 。主 要 DII 概 念 介 绍动 态 调 用 接 口 实 际 上 分 布 于 数 个 CORBA 接 口 中 。 而 且 ,DII 经 常 提 供 一 个 以 上 的方 法 来 完 成 一 项 任 务 - 平 衡 点 是 编 程 的 简 单 性 与 特 殊 情 况 下 的 性 能 。 因 此 , DII 是更 难 掌 难 的 CORBA 实 用 工 具 之 一 。 本 节 是 起 点 , 即 主 要 概 念 的 高 级 描 述 。 详 情( 包 括 代 码 实 例 ) 在 后 续 章 节 中 讨 论 。要 使 用 DII, 您 需 要 理 解 这 些 概 念 , 从 最 普 通 之 处 起 步 :● Request 对 象● Any 和 Typecode 对 象● Request 发 送 选 项● Reply 接 收 选 项使 用 request 对 象Request 对 象 表 示 对 一 个 CORBA 对 象 上 的 一 个 方 法 的 一 个 调 用 。 如 果 您 想 要 调 用同 一 CORBA 对 象 上 的 两 个 方 法 , 或 者 两 个 不 同 对 象 上 的 同 一 方 法 , 则 您 需 要 两个 Request 对 象 。 要 调 用 方 法 , 您 首 先 需 要 一 个 代 表 CORBA 对 象 的 对 象 引 用 ,即 目 标 引 用 。 通 过 使 用 目 标 引 用 , 您 创 建 一 个 Request, 为 其 配 置 变 量 , 发 送Request, 等 待 回 答 , 然 后 从 Request 得 到 结 果 。有 两 种 方 法 可 以 创 建 一 个 Request。 比 较 简 单 的 方 法 是 调 用 目 标 对 象 的 _request 方法 , 所 有 的 CORBA 对 象 都 继 承 了 这 一 方 法 。 实 际 上 , 这 并 不 调 用 目 标 对 象 。 您传 递 _request - 您 要 在 Request 调 用 的 方 法 的 IDL 名 称 , 例 如 “get_balance”。要 给 用 _request 创 建 的 Request 加 上 变 量 值 , 您 得 为 您 想 调 用 的 方 法 所 需 要 的 每 个变 量 调 用 Request 的 add_value 方 法 。 要 将 一 个 或 多 个 Context 对 象 传 递 到 目 标 ,您 必 须 使 用 Request 的 ctx 方 法 , 将 其 添 加 到 code>Request 上 。虽 然 感 觉 起 来 不 明 显 , 但 您 也 必 须 使 用 Request 的 result 方 法 来 指 定 Request 结 果的 类 型 。 由 于 性 能 方 面 的 原 因 , <strong>VisiBroker</strong> ORB 之 间 交 换 的 信 息 不 包 含 类 型 信息 。 通 过 在 Request 中 指 定 一 个 空 间 容 器 (place holder) 结 果 类 型 , 您 给 它 提 供了 所 需 要 的 <strong>VisiBroker</strong> ORB 信 息 , 使 它 能 够 以 适 当 的 方 式 从 目 标 对 象 发 送 的 回 答消 息 中 提 取 结 果 。 同 样 , 如 果 您 调 用 的 方 法 可 以 掷 出 用 户 违 例 , 则 您 在 使 用Request 前 , 必 须 给 它 添 加 place holder 违 例 。比 较 复 杂 的 创 建 Request 对 象 的 方 法 是 调 用 目 标 对 象 的 _create_request 方 法 , 所有 的 CORBA 对 象 也 都 继 承 了 这 一 方 法 。 这 一 方 法 使 用 数 个 变 量 , 它 们 为 新 的Request 配 置 变 量 并 指 定 它 可 能 会 返 回 的 结 果 类 型 和 用 户 违 例 ( 如 果 有 )。 要 使 用_create_request 方 法 , 您 必 须 先 构 建 它 要 用 作 变 量 的 组 件 。 _create_request 方 法18-2 <strong>VisiBroker</strong> 开 发 者 指 南


什 么 是 动 态 调 用 接 口 ?注 :的 潜 在 优 点 是 在 性 能 方 面 。 如 果 在 多 个 目 标 对 象 上 调 用 同 一 方 法 , 则 您 可 以 在 多 个_create_request 调 用 中 重 新 使 用 变 量 组 件 。有 两 种 _create_request 方 法 的 过 载 形 式 , 其 中 一 种 包 括 ContextList 和ExceptionList 参 数 , 而 另 外 一 种 则 不 包 括 。 如 果 您 要 在 调 用 中 传 递 一 个 或 多 个Context 对 象 , 而 且 ( 或 者 ) 您 想 要 调 用 的 方 法 可 能 会 掷 出 一 个 或 多 个 和 户 违 例 ,则 您 必 须 使 用 具 有 特 别 参 数 的 _create_request 方 法 。用 Any 类 型 封 装 变 量目 标 方 法 的 变 量 、 结 果 和 违 例 分 别 指 定 在 被 称 为 Any 的 特 殊 对 象 中 。 一 个 Any 是 一个 可 以 封 装 一 个 任 何 类 型 的 变 量 的 普 通 对 象 。 Any 可 以 容 纳 IDL 中 描 述 的 任 何 类型 。 将 一 个 变 量 作 为 Any 指 定 给 Request 可 以 使 Request 接 受 任 意 的 变 量 类 型 和值 , 而 不 会 使 编 译 器 “ 抱 怨 ” 类 型 不 匹 配 。( 结 果 和 违 例 也 是 如 此 。)一 个 Any 包 含 一 个 TypeCode 和 一 个 值 。 一 个 值 不 过 就 是 一 个 值 , 而 TypeCode 是 一个 描 述 如 何 解 析 该 值 中 的 比 特 的 对 象 ( 即 值 的 类 型 )。 用 于 简 单 IDL 类 型 的 简 单TypeCode 常 量 , 如 long 和 Object, 被 建 入 由 idl2cpp 或 idl2java 编 译 器 产 生 的报 头 文 件 中 。 用 于 IDL 结 构 化 类 型 的 TypeCode, 如 structs、 unions 和 typedefs,必 须 构 建 。 这 样 TypeCode 可 以 递 归 , 因 为 它 所 描 述 的 类 型 可 以 递 归 。 考 虑 一 下 一个 由 long 和 string 组 成 的 struct 。 struct 的 TypeCode 包 含 一 个 long 的TypeCode 和 一 个 string 的 TypeCode 。 如 果 使 用 -type_code_info 选 项 来 调 用 编 译器 , 则 idl2cpp 编 译 器 将 会 为 IDL 文 件 中 结 构 化 类 型 生 成 TypeCodes。 但 是 , 如 果您 在 使 用 DII, 则 您 需 要 在 运 行 期 内 得 到 TypeCodes 。 您 可 以 在 运 行 期 内 从 接 口 仓库 ( 参 阅 第 17 章 " 使 用 接 口 仓 库 ") 中 得 到 TypeCode, 或 者 通 过 调 用ORB::create_struct_tc 或 ORB::create_exception_tc 让 <strong>VisiBroker</strong> ORB 创 建 一个 TypeCode。如 果 您 使 用 _create_request 方 法 , 则 您 需 要 将 Any 封 装 的 目 标 方 法 变 量 置 入 被 称为 NVList 的 另 外 一 个 特 殊 对 象 中 。 不 管 您 怎 样 创 建 Request, 其 结 果 总 会 编 码 为NVList。 本 段 中 所 讲 述 的 关 于 变 量 的 一 切 内 容 也 适 用 于 结 果 。 NV 表 示 命 名 的 值 ,一 个 NVList 包 含 大 量 的 项 目 , 其 中 每 个 项 目 具 有 一 个 名 称 、 一 个 值 和 一 个 标 志 。名 称 是 变 量 的 名 称 , 值 是 Any 封 装 的 变 量 , 而 标 志 表 示 变 量 的 IDL 方 式 ( 如 in 或out)。 Request 的 结 果 表 示 为 一 个 单 名 值 。用 于 发 送 request 的 选 项一 旦 您 创 建 了 一 个 Request 并 为 其 配 置 了 变 量 、 结 果 类 型 和 违 例 类 型 , 您 就 可 以 将它 发 送 给 目 标 对 象 。 有 数 种 方 法 可 以 发 送 一 个 Request。● 最 简 单 的 方 法 是 调 用 Request 的 invoke 方 法 , 在 收 到 回 答 消 息 之 前 , 它 将 一 直阻 塞 。● 更 为 复 杂 而 无 阻 塞 的 方 法 是 Request 的 send_deferred 方 法 。 这 是 使 用 线 程 平 行的 方 法 的 替 代 方 法 。 对 许 多 操 作 系 统 而 言 , send_deferred 方 法 比 分 散 线 程 更 为经 济 。● 如 果 您 使 用 send_deferred 方 法 的 目 的 是 平 行 地 调 用 多 个 目 标 对 象 , 您 可 以 使 用<strong>VisiBroker</strong> ORB 对 象 的 send_multiple_requests_deferred 方 法 。 它 使 用 一 个Request 对 象 序 列 。使 用 动 态 调 用 接 口 18-3


什 么 是 动 态 调 用 接 口 ?● 当 且 仅 当 目 标 方 法 已 在 IDL 中 被 定 义 为 oneway 时 , 才 可 以 使 用 Request 的send_oneway。● 您 可 以 使 用 <strong>VisiBroker</strong> ORB 的 send_multiple_requests_oneway 方 法 以 平 行 地调 用 多 个 oneway 方 法 。用 于 接 收 回 答 的 选 项如 果 您 通 过 调 用 Request 的 invoke 方 法 来 发 送 Request, 则 只 有 一 种 方 法 可 以 得 到结 果 : 使 用 Request 对 象 的 env 方 法 来 测 试 是 否 有 违 例 ; 如 果 没 有 违 例 , 则 使 用Request 的 result 方 法 从 Request 中 提 取 结 果 。 如 果 您 使 用 的 是 send_oneway 方法 , 则 不 会 有 任 何 结 果 。 如 果 您 使 用 的 是 send_deferred 方 法 , 您 可 以 通 过 调 用Request 的 poll_response 方 法 定 期 检 查 其 完 成 情 况 , 该 方 法 返 回 一 个 指 示 回 答 是否 已 经 收 到 的 代 码 。 如 果 在 检 查 一 段 时 间 之 后 , 您 想 阻 塞 对 一 个 延 迟 发 送 的 等 待 ,则 使 用 Request 的 get_response 方 法 。如 果 您 用 send_multiple_requests_deferred 方 法 发 送 了 Request, 则 您 可 以 通 过 调用 Request 的 get_response 方 法 来 查 实 某 个 Request 是 否 已 完 成 。 想 要 知 道 任 何 未完 成 的 Request 的 完 成 时 间 , 则 使 用 <strong>VisiBroker</strong> ORB get_next_response 方 法 。想 要 做 同 样 的 事 而 不 想 有 产 生 阻 塞 的 风 险 , 则 使 用 <strong>VisiBroker</strong> ORB 的poll_next_response 方 法 。动 态 调 用 对 象 操 作 的 步 骤总 括 起 来 说 , 以 下 是 客 户 在 使 用 DII 时 应 该 执 行 的 步 骤 。C++: 1 确 定 -type_code_info 选 项 被 传 递 到 idl 编 译 器 , 以 便 可 以 为 IDL 接 口 和 类 型生 成 类 型 代 码 。 参 阅 程 序 员 参 考 以 查 看 关 于 idl2cpp 工 具 的 完 整 描 述 。2 取 得 您 要 使 用 的 目 标 对 象 的 普 通 引 用 。3 为 目 标 对 象 创 建 一 个 Request 对 象 。4 初 始 化 要 返 回 的 请 求 参 数 和 结 果 。5 调 用 请 求 并 等 待 结 果 。6 检 索 结 果 。使 用 DII 的 实 例 程 序 的 位 置<strong>VisiBroker</strong> <strong>Edition</strong> 的 examples/bank_dynamic 目 录 下 包 含 数 个 说 明 如 何 使 用 DII的 实 例 。 本 节 中 将 引 用 这 些 实 例 程 序 来 说 明 DII 概 念 。仅 适 用 于 C ++: 用 VIS_INCLUDE_IR 标 志 编 译 这 些 实 例 程 序 , 并 加 入 typecode 生 成 选 项 。18-4 <strong>VisiBroker</strong> 开 发 者 指 南


获 得 普 通 对 象 引 用使 用 idl2java 编 译 器仅 适 用 于 Java:idl2java 编 译 器 具 有 一 个 -dynamic_marshal 标 志 , 当 打 开 该 标 志 时 , 将 使 用 DII生 成 存 根 代 码 。 要 了 解 如 何 作 DII 的 任 何 类 型 : 创 建 一 个 IDL 文 件 , 用 -dynamic_marshal 来 生 成 , 然 后 查 看 存 根 代 码 。获 得 普 通 对 象 引 用在 使 用 DII 时 , 客 户 程 序 不 必 使 用 传 统 的 限 制 机 制 来 取 得 目 标 对 象 的 引 用 , 因 为 在编 译 时 客 户 不 可 能 知 道 目 标 对 象 的 类 定 义 。 以 下 的 代 码 示 例 说 明 您 的 客 户 程 序 如 何使 用 由 <strong>VisiBroker</strong> ORB 对 象 提 供 的 bind 方 法 来 通 过 指 定 对 象 名 称 限 制 到 任 何 对象 。 该 方 法 返 回 一 个 普 通 的 CORBA::Object ( 在 C++ 下 )。C++:. . .CORBA::Object_var account;try {// 初 始 化 ORB。CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);} catch (const CORBA::Exception& e)cout


创 建 与 初 始 化 请 求} catch(const CORBA::Exception& excep) {System.err.println ("Error binding to account" );excep.printStackTrace();}System.out.println ("Bound to account object");. . .创 建 与 初 始 化 请 求注 :当 您 的 客 户 程 序 调 用 一 个 对 象 上 的 方 法 时 , 会 创 建 一 个 Request 对 象 以 表 示 方 法 调用 。 Request 对 象 被 编 写 或 汇 集 入 一 个 缓 冲 器 , 然 后 送 到 对 象 实 现 。 当 您 的 客 户 程序 使 用 客 户 存 根 时 , 这 一 处 理 会 透 明 地 出 现 。 要 使 用 DII 的 客 户 程 序 必 须 自 己 创 建并 发 送 Request 对 象 。没 有 该 类 的 构 建 器 。 Object 的 _request 方 法 或 Object 的 _create_request 方 法 用以 创 建 Request 对 象 。Request 类C++: 以 下 的 代 码 示 例 说 明 Request 类 。 Request 的 target 是 从 用 于 创 建 Request 的 对象 引 用 上 隐 式 设 定 的 。 当 创 建 Request 时 , 必 须 指 定 operation 的 名 称 。C++: class Request {public:CORBA::Object_ptr target() const;const char* operation() const;CORBA::NVList_ptr arguments();CORBA::NamedValue_ptr result();CORBA::Environment_ptr env();void ctx(CORBA::Context_ptr ctx);CORBA::Context_ptr ctx() const;CORBA::Status invoke();CORBA::Status send_oneway();CORBA::Status send_deferred();CORBA::Status get_response();CORBA::Status poll_response();. . .};};Request 接 口Java:以 下 的 代 码 示 例 说 明 Request 接 口 。 Request 的 目 标 是 从 用 于 创 建 Request 的 对 象 引用 上 隐 式 设 定 的 。 当 创 建 Request 时 , 必 须 指 定 操 作 的 名 称 。package org.omg.CORBA;public abstract class Request {public abstract org.omg.CORBA.Object target();public abstract java.lang.String operation();public abstract org.omg.CORBA.NVList arguments();18-6 <strong>VisiBroker</strong> 开 发 者 指 南


创 建 与 初 始 化 请 求}public abstract org.omg.CORBA.NamedValue result();public abstract org.omg.CORBA.Environment env();public abstract org.omg.CORBA.ExceptionList exceptions();public abstract org.omg.CORBA.ContextList contexts();public abstract void ctx(org.omg.CORBA.Context ctx);public abstract org.omg.CORBA.Context ctx();public abstract org.omg.CORBA.Any add_in_arg();public abstract org.omg.CORBA.Any add_named_in_arg(public abstract org.omg.CORBA.Any add_inout_arg();public abstract org.omg.CORBA.Any add_named_inout_arg(public abstract org.omg.CORBA.Any add_out_arg();public abstract org.omg.CORBA.Any add_named_out_arg(public abstract void set_return_type(public abstract org.omg.CORBA.Any return_value();public abstract void invoke();public abstract void send_oneway();public abstract void send_deferred();public abstract void get_response();public abstract boolean poll_response();创 建 和 初 始 化 DII Request 的 方 法一 旦 您 发 送 一 个 限 制 到 一 个 对 象 并 得 到 一 个 对 象 引 用 , 您 就 可 以 使 用 创 建 Request对 象 的 两 个 方 法 之 一 。 以 下 的 代 码 示 例 说 明 由 CORBA::Object 类 提 供 的 方 法 。C++: class Object {. . .CORBA::Request_ptr _request(Identifier operation);CORBA::Status _create_request(CORBA::Context_ptr ctx,const char *operation,CORBA::NVList_ptr arg_list,CORBA::NamedValue_ptr result,CORBA::Request_ptr request,CORBA::Flags req_flags);CORBA::Status _create_request(CORBA::Context_ptr ctx,const char *operation,CORBA::NVList_ptr arg_list,CORBA::NamedValue_ptr result,CORBA::ExceptionList_ptr eList,CORBA::ContextList_ptr ctxList,CORBA::Request_out request,CORBA::Flags req_flags);. . .};Java:以 下 的 代 码 示 例 说 明 了 由 org.omg.CORBA.Object 接 口 提 供 的 方 法 。package org.omg.CORBA;public interface Object {. . .public org.omg.CORBA.Request _request(java.lang.String operation;使 用 动 态 调 用 接 口 18-7


创 建 与 初 始 化 请 求public org.omg.CORBA.Request _create_request(org.omg.CORBA.Context ctx,java.lang.String operation,org.omg.CORBA.NVList arg_list,org.omg.CORBA.NamedValue result)public org.omg.CORBA.Request _create_request(org.omg.CORBA.Context ctx,java.lang.String operation,org.omg.CORBA.NVList arg_list,org.omg.CORBA.NamedValue result,org.omg.CORBA.ExceptionList exceptions,org.omg.CORBA.ContextList contexts). . .}使 用 create_request 方 法您 可 以 使 用 _create_request 方 法 来 创 建 Request 对 象 , 初 始 化 Context、 操 作 名称 、 要 传 递 的 变 量 清 单 、 结 果 。 您 可 以 为 request 设 定 可 选 的 ContextList, 这与 request 的 IDL 中 所 定 义 的 属 性 相 当 。 请 求 参 数 指 向 为 操 作 所 创 建 的 Request对 象 。使 用 _request 方 法以 下 的 代 码 示 例 说 明 如 何 在 仅 指 定 操 作 名 称 的 情 况 下 , 使 用 _request 方 法 来 创 建Request 对 象 。 在 创 建 了 一 个 浮 动 的 请 求 之 后 , 调 用 它 的 add_in_arg 方 法 , 添 加 一个 输 入 参 数 帐 户 名 称 , 其 结 果 类 型 通 过 调 用 set_return_type 方 法 被 初 始 化 为 对 象引 用 类 型 。 调 用 一 次 之 后 , 随 着 结 果 对 result 方 法 的 调 用 , 返 回 值 被 取 出 。 重 复相 同 的 步 骤 可 以 调 用 帐 户 管 理 器 实 例 上 的 另 一 个 方 法 , 其 区 别 仅 在 于 输 入 参 数 和 返回 类 型 。req 是 一 个 Any 对 象 , 它 被 用 所 要 求 的 帐 户 name 初 始 化 并 作 为 输 入 变 量 添 加 到request 的 变 量 列 表 上 。 初 始 化 request 的 最 后 一 个 步 骤 是 设 定 result 值 以 接 收float。关 于 创 建 一 个 Request 对 象 的 实 例Request 对 象 保 持 与 操 作 、 变 量 和 结 果 有 关 的 所 有 存 储 的 所 有 权 , 以 便 使 您 无 法 尝试 释 放 这 些 项 目 。 以 下 的 代 码 示 例 是 在 C++ 和 Java 下 创 建 request 对 象 的 实 例 。在 C++ 下 创 建 一 个 request 对 象 :. . .CORBA::NamedValue_ptr result;CORBA::Any_ptr resultAny;CORBA::Request_var req;CORBA::Any customer;. . .18-8 <strong>VisiBroker</strong> 开 发 者 指 南


创 建 与 初 始 化 请 求try {req = account->_request("balance");// 创 建 request 的 变 量customer add_value("customer", customer, CORBA::ARG_IN);// 设 定 结 果result = req->result();resultAny = result->value();resultAny->replace(CORBA::_tc_float, &result);} catch(CORBA::Exception& excep) {. . .Java:在 Java 下 创 建 一 个 request 对 象 :// Client.javapublic class Client {public static void main(String[] args) {if (args.length ! = 2) {System.out.println("Usage: vbj Client \n");return;}String managerName = args[0];String accountName = args[1];org.omg.CORBA.Object accountManager, account;org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null);accountManager = orb.bind("IDL:Bank/AccountManager:1.0",managerName, null, null);org.omg.CORBA.Request request = accountManager._request("open");request.add_in_arg().insert_string(accountName);request.set_return_type(orb.get_primitive_tc(org.omg.CORBA.TCKind.tk_objref));request.invoke();account = request.result().value().extract_Object();org.omg.CORBA.Request request = account._request("balance");request.set_return_type(orb.get_primitive_tc(org.omg.CORBA.TCKind.tk_float));request.invoke();float balance = request.result().value().extract_float();System.out.println("The balance in " + accountName + "'s account is $" +balance);}}设 定 request 的 上 下 文仅 适 用 于 C++:虽 然 本 实 例 中 没 有 使 用 Context 对 象 , 但 是 它 可 以 用 来 包 含 一 个 属 性 列 表 ( 存 储 为NamedValue 对 象 ), 该 列 表 将 作 为 Request 的 一 部 分 被 传 递 到 对 象 实 现 。 这 些 属 性代 表 自 动 传 达 到 对 象 实 现 的 信 息 。使 用 动 态 调 用 接 口 18-9


创 建 与 初 始 化 请 求class Context {public:const char *context_name() const;CORBA::Context_ptr parent();CORBA::Status create_child(const char *name, CORBA::Context_ptr&);CORBA::Status set_one_value(const char *name, const CORBA::Any&);CORBA::Status set_values(CORBA::NVList_ptr);CORBA::Status delete_values(const char *name);CORBA::Status get_values(const char *start_scope,CORBA::Flags,const char *name,CORBA::NVList_ptr&) const;};设 定 request 的 变 量注 :Request 的 变 量 用 NVList 对 象 表 示 , 其 中 存 储 “ 名 称 - 值 ” 对 作 为 NamedValue 对象 。 您 可 以 使 用 arguments 方 法 来 取 得 到 该 列 表 的 一 个 指 针 。 然 后 , 该 指 针 可 以 被用 来 设 定 每 个 变 量 的 名 称 和 值 。在 发 送 Request 前 , 请 务 必 初 始 化 变 量 。 如 果 不 这 样 做 , 可 能 会 导 致 排 列 错 误 , 甚至 有 可 能 导 致 服 务 器 异 常 中 断 。用 NVList 实 现 变 量 列 表这 个 类 实 现 代 表 一 个 方 法 调 用 的 变 量 的 NamedValue 对 象 。 提 供 有 用 于 增 加 、 删 除 、查 询 列 表 中 的 对 象 的 方 法 。 以 下 的 代 码 示 例 C++ 和 Java 下 的 NVList 类 的 实 例 。C++ 下 的 NVList 类 :C++: class NVList {public:. . .CORBA::Long count() const;CORBA::NamedValue_ptr add(Flags);CORBA::NamedValue_ptr add_item(const char *name, CORBA::Flags flags);CORBA::NamedValue_ptr add_value(const char *name,const CORBA::Any *any,CORBA::Flags flags);CORBA::NamedValue_ptr add_item_consume(char *name, CORBA::Flags flags);CORBA::NamedValue_ptr add_value_consume(char *name,CORBA::Any *any,CORBA::Flags flags);CORBA::NamedValue_ptr item(CORBA::Long index);CORBA::Status remove(CORBA::Long index);. . .};Java 下 的 NVList 类 :18-10 <strong>VisiBroker</strong> 开 发 者 指 南


创 建 与 初 始 化 请 求Java:package org.omg.CORBA;public abstract class NVList {public int count();public void add(int flags);public void add_item(java.lang.String name, int flags);public void add_value(java.lang.String name,org.omg.CORBA.Any value,int flags);public org.omg.CORBA.NamedValue item(int index);public void remove(int index);}用 NamedValue 类 设 定 输 入 和 输 出 变 量这 个 类 实 现 代 表 一 个 方 法 调 用 请 求 的 输 入 和 输 出 变 量 的 名 - 值 对 。 NamedValue 类 也用 于 表 示 一 个 返 回 到 客 户 程 序 的 请 求 的 结 果 。 name 属 性 只 是 一 个 字 串 , 而 value 属性 由 一 个 Any 类 表 示 。 以 下 的 代 码 示 例 是 C++ 和 Java 下 的 NamedValue 类 的实 例 。仅 适 用 于 Java:没 有 该 类 的 构 建 器 。 ORB.create_named_value 方 法 是 用 于 得 取 NamedValue 对 象 的引 用 的 方 法 。NamedValue 类 :C++: class Request {public:const char *name() const;CORBA::Any *value() const;CORBA::Flags flags() const;};Java:NamedValue 接 口 :package org.omg.CORBA;public abstract class NamedValue {public java.lang.String name();public org.omg.CORBA.Any value();public int flags();}下 表 描 述 NamedValue 类 中 的 方 法表 18.1方 法名 称NamedValue 方 法说 明返 回 一 个 到 项 目 的 名 称 的 指 针 , 随 后 您 可 以 用该 名 称 来 初 始 化 名 称 。使 用 动 态 调 用 接 口 18-11


创 建 与 初 始 化 请 求表 18.1方 法值标 志NamedValue 方 法说 明返 回 一 个 到 代 表 项 目 值 的 Any 对 象 的 指 针 , 随后 您 可 以 用 该 值 来 初 始 化 值 。 要 取 得 详 情 , 请参 阅 “ 用 Any 类 安 全 地 传 递 类 型 。”指 示 该 项 目 是 输 入 变 量 、 输 出 变 量 、 或 者 输 入输 出 变 量 。 如 果 该 项 目 是 输 入 输 出 变 量 , 您 可以 指 定 一 个 标 志 来 表 示 <strong>VisiBroker</strong> ORB 应该 复 制 该 变 量 并 让 调 用 者 的 存 储 器 保 持 不 变 。标 志 为 : ARG_IN ARG_OUT ARG_INOUTC++:用 Any 类 安 全 地 传 递 类 型该 类 用 于 保 存 IDL 指 定 的 类 , 以 便 它 能 够 以 类 型 安 全 的 方 式 来 传 递 。该 类 的 对 象 具 有 一 个 到 定 义 包 含 的 对 象 的 类 型 的 TypeCode 的 指 针 和 一 个 到 包 含 的对 象 的 指 针 。 提 供 有 构 建 、 复 制 、 和 释 放 对 象 的 方 法 , 也 提 供 有 初 始 化 和 查 询 对 象的 值 和 类 型 的 方 法 。 另 外 , 也 提 供 有 流 式 操 作 器 方 法 , 以 便 读 写 出 入 流 的 对 象 。 以下 的 代 码 示 例 是 在 C++ 下 定 义 该 类 的 实 例 。C++: class Any {public:. . .CORBA_TypeCode_ptr type();void type(CORBA_TypeCode_ptr tc);const void *value() const;static CORBA::Any_ptr _nil();static CORBA::Any_ptr _duplicate(CORBA::Any *ptr);static void _release(CORBA::Any *ptr);. . .}Java: 该 类 的 对 象 具 有 一 个 到 定 义 包 含 的 对 象 的 类 型 的 TypeCode 的 指 针 和 一 个 到 包 含 的对 象 的 指 针 。 提 供 有 构 建 、 复 制 、 和 释 放 对 象 的 方 法 , 也 提 供 有 初 始 化 和 查 询 对 象的 值 和 类 型 的 方 法 。 另 外 , 也 提 供 有 流 式 操 作 器 方 法 , 以 便 读 写 出 入 流 的 对 象 。 以下 的 代 码 示 例 是 Java 下 的 实 例 。Java:package org.omg.CORBA;public abstract class Any {public abstract TypeCode type();public abstract void type(TypeCode type);public abstract void read_value(InputStream input, TypeCode type);public abstract void write_value(OutputStream output);public abstract boolean equal(Any rhs);. . .}用 TypeCode 类 表 示 变 量 或 属 性 类 型该 类 由 接 口 仓 库 和 IDL 编 译 器 用 于 表 示 变 量 或 属 性 的 类 型 。 TypeCode 对 象 也 用 于Request 对 象 , 以 和 Any 类 一 起 指 定 变 量 的 类 型 。18-12 <strong>VisiBroker</strong> 开 发 者 指 南


创 建 与 初 始 化 请 求C++:Java:仅 适 用 于 Java:在 C++ 中 ,TypeCode 对 象 具 有 一 个 kind 和 参 数 列 表 属 性 。 以 下 的 代 码 示 例 是 一 个TypeCode 类 的 实 例 。在 Java 中 , TypeCode 对 象 具 有 一 个 kind 和 参 数 列 表 属 性 , 由 TCKind 类 所 定 义 的一 个 值 来 表 示 。没 有 该 类 的 构 建 器 。 使 用 ORB.get_primitive_tc 方 法 或 ORB.create_*_tc 方 法 之 一来 创 建 TypeCode 对 象 。 要 取 得 详 情 , 请 参 阅 程 序 员 参 考 。下 表 显 示 了 TypeCode 对 象 的 类 型 (Kind) 和 参 数 。表 18.2KindTypeCode kind 和 参 数参 数 清 单tk_abstract_interfacerepository_id, interface_nametk_aliasrepository_id, alias_name, TypeCodetk_any无tk_arraylength, TypeCodetk_boolean无tk_char无tk_double无tk_enum repository_id, enum-name, enum-id 1 , enum-id 2 ,... enum-id ntk_exceptrepository_id, exception_name,StructMemberstk_fixeddigits, scaletk_float无tk_long无tk_longdouble无tk_longlong无tk_nativeid, nametk_null无tk_objrefrepository_id, interface_idtk_octet无tk_Principal无tk_sequence>TypeCode, maxlentk_short无tk_stringmaxlen-integertk_struct repository_id, struct-name, {member 1 ,TypeCode 1 }, {member n , TypeCode n }tk_TypeCode无tk_ulong无tk_ulonglong无tk_unionrepository_id, union-name, switchTypeCode,{label-value 1 , member-name 1 ,TypeCode 1 }, {label l -value n , member-name n ,TypeCode n }tk_ushort无tk_valuerepository_id, value_name, boxType使 用 动 态 调 用 接 口 18-13


创 建 与 初 始 化 请 求表 18.2 TypeCode kind 和 参 数Kindtk_value_boxtk_voidtk_wchartk_wstring参 数 清 单repository_id, value_name, typeModifier,concreteBase, members无无无C++: class _VISEXPORT CORBA_TypeCode {public:. . .// 适 用 于 所 有 CORBA_TypeCode 类 型CORBA::Boolean equal(CORBA_TypeCode_ptr tc) const;CORBA::Boolean equivalent(CORBA_TypeCode_ptr tc) const;CORBA_TypeCode_ptr get_compact_typecode() const;CORBA::TCKind kind() const // . . .// 适 用 于 tk_objref、 tk_struct、 tk_union、 tk_enum、 tk_alias 和 tk_exceptvirtual const char* id() const; // 掷 出 (BadKind);virtual const char *name() const; // 掷 出 (BadKind);// 适 用 于 tk_struct、 tk_union、 tk_enum 和 tk_exceptvirtual CORBA::ULong member_count() const; // 掷 出 ((BadKind));virtual const char *member_name(CORBA::ULong index) const;// 掷 出 ((BadKind, Bounds));// 适 用 于 tk_struct, tk_union and tk_exceptvirtual CORBA_TypeCode_ptr member_type(CORBA::ULong index) const;// 掷 出 ((BadKind, Bounds));// 适 用 于 tk_unionvirtual CORBA::Any_ptr member_label(CORBA::ULong index) const;// 掷 出 ((BadKind, Bounds));virtual CORBA_TypeCode_ptr discriminator_type() const;// 掷 出 ((BadKind));virtual CORBA::Long default_index() const; // 掷 出 ((BadKind));// 适 用 于 tk_string、 tk_sequence 和 tk_arrayvirtual CORBA::ULong length() const; // 掷 出 ((BadKind));// 适 用 于 tk_sequence、 tk_array 和 tk_aliasvirtual CORBA_TypeCode_ptr content_type() const; // 掷 出 ((BadKind));// 适 用 于 tk_fixedvirtual CORBA::UShort fixed_digits() const; // 掷 出 (BadKind)virtual CORBA::Short fixed_scale() const; // 掷 出 (BadKind)// 适 用 于 tk_valuevirtual CORBA::Visibility member_visibility(CORBA::ULong index) const;// 掷 出 (BadKind, Bounds);virtual CORBA::ValueModifier type_modifier() const; // 掷 出 (BadKind);virtual CORBA::TypeCode_ptr concrete_base_type() const; // 掷 出(BadKind);};TypeCode 类 :Java:public abstract class TypeCode extends java.lang.Objectimplements org.omg.CORBA.portable.IDLEntity {public abstract boolean equal(org.omg.CORBA.TypeCode tc);public boolean equivalent(org.omg.CORBA.TypeCode tc);18-14 <strong>VisiBroker</strong> 开 发 者 指 南


发 送 DII 请 求 与 接 收 结 果}public abstract org.omg.CORBA.TCKind kind();public TypeCode get_compact_typecode()public abstract java.lang.String id()throws org.omg.CORBA.TypeCodePackage.BadKind;public abstract java.lang.String name()throws org.omg.CORBA.TypeCodePackage.BadKind;public abstract int member_count()throws org.omg.CORBA.TypeCodePackage.BadKind;public abstract java.lang.String member_name(int index)throws org.omg.CORBA.TypeCodePackage.BadKind,org.omg.CORBA.TypeCodePackage.Bounds;public abstract org.omg.CORBA.TypeCode member_type(int index)throws org.omg.CORBA.TypeCodePackage.BadKind,org.omg.CORBA.TypeCodePackage.Bounds;public abstract org.omg.CORBA.Any member_label(int index)throws org.omg.CORBA.TypeCodePackage.BadKind,org.omg.CORBA.TypeCodePackage.Bounds;public abstract org.omg.CORBA.TypeCode discriminator_type()throws org.omg.CORBA.TypeCodePackage.BadKind;public abstract int default_index()throws org.omg.CORBA.TypeCodePackage.BadKind;public abstract int length()throws org.omg.CORBA.TypeCodePackage.BadKind;public abstract org.omg.CORBA.TypeCode content_type()throws org.omg.CORBA.TypeCodePackage.BadKind;public short fixed_digits()throws org.omg.CORBA.TypeCodePackage.BadKind;public short fixed_scale()throws org.omg.CORBA.TypeCodePackage.BadKind;public short member_visibility(int index)throws org.omg.CORBA.TypeCodePackage.BadKind,org.omg.CORBA.Bounds;public short type_modifier()throws org.omg.CORBA.TypeCodePackage.BadKind;public TypeCode concrete_base_type()throws org.omg.CORBA.TypeCodePackage.BadKind;发 送 DII 请 求 与 接 收 结 果如 第 18-6 页 " 创 建 与 初 始 化 请 求 " 一 节 中 所 述 , Request 类 提 供 数 种 方 法 可 用 于发 送 经 过 适 当 的 初 始 化 的 请 求 。调 用 请 求最 简 单 的 发 送 请 求 的 方 法 是 调 用 它 的 invoke 方 法 , 该 方 法 发 送 请 求 并 在 返 回 到 您的 客 户 程 序 之 前 等 待 回 答 。return_value 方 法 在 C++ 下 返 回 一 个 指 针 或 者 在 Java下 返 回 一 个 引 用 给 代 表 返 回 值 的 Any 对 象 。 以 下 的 代 码 示 例 说 明 如 何 在 C++ 和Java 下 通 过 调 用 发 送 一 个 请 求 。在 C++ 通 过 调 用 发 送 一 个 request:使 用 动 态 调 用 接 口 18-15


发 送 DII 请 求 与 接 收 结 果try {. . .// 创 建 要 送 到 帐 户 对 象 的 请 求request = account->_request("balance");// 设 定 结 果 类 型request->set_return_type(CORBA::_tc_float);// 对 帐 户 对 象 执 行 请 求request->invoke();// 取 得 返 回 的 余 额CORBA::Float balance;CORBA::Any& balance_result = request->return_value();balance_result >>= balance;// 打 印 余 额cout


C++: . . .try {// 创 建 要 发 送 到 管 理 器 对 象 的 请 求CORBA::Request_var request = manager->_request("open");// 创 建 request 的 变 量CORBA::Any customer;customer add_value( "name" , customer, CORBA::ARG_IN );// 设 定 结 果 类 型request->set_return_type(CORBA::_tc_Object);// 创 建 新 帐 户 的 过 程 要 花 费 一 些 时 间// 对 管 理 器 对 象 执 行 延 迟 的 请 求request->send_deferred();VISPortable::vsleep(1);while (!request->poll_response()) {cout return_value();open_result >>= CORBA::Any::to_object(account.out());. . .}要 在 Java 下 发 送 延 迟 的 DII 请 求 :发 送 DII 请 求 与 接 收 结 果Java: try {. . .// 创 建 要 发 送 到 管 理 器 对 象 的 请 求org.omg.CORBA.Request request = manager._request("open");// 创 建 request 的 变 量org.omg.CORBA.Any customer = orb.create_any();customer.insert_string(name);org.omg.CORBA.NVList arguments = request.arguments();arguments.add_value("name" , customer, org.omg.CORBA.ARG_IN.value);// 设 定 结 果 类 型request.set_return_type(orb.get_primitive_tc(org.omg.CORBA.TCKind.tk_objref));// 创 建 新 帐 户 的 过 程 要 花 费 一 些 时 间// 对 管 理 器 对 象 执 行 延 迟 的 请 求request.send_deferred();Thread.currentThread().sleep(1000);while (!request.poll_response()) {System.out.println(" Waiting for response...");Thread.currentThread().sleep(1000); // 两 次 检 测 之 间 等 待 1s}request.get_response();// 取 得 返 回 值org.omg.CORBA.Object account;org.omg.CORBA.Any open_result = request.return_value();account = open_result.extract_Object();. . .使 用 动 态 调 用 接 口 18-17


发 送 DII 请 求 与 接 收 结 果} catch(Exception e) {e.printStackTrace();}使 用 send_oneway 方 法 发 送 异 步 DII 请 求send_oneway 方 法 可 用 于 发 送 异 步 请 求 。 Oneway 请 求 不 包 括 从 对 象 实 现 返 回 给 客户 的 回 答 。发 送 多 个 请 求C++ :通 过 使 用 Request 对 象 阵 列 , 可 以 创 建 一 个 DII Request 对 象 序 列 。 请 求 序 列 可以 使 用 <strong>VisiBroker</strong> ORB 方 法 send_multiple_requests_oneway 或send_multiple_requests_deferred 来 发 送 。 如 果 请 求 序 列 作 为 oneway 请 求 来 发送 , 则 服 务 器 不 会 给 任 何 请 求 返 回 任 何 回 答 。以 下 的 代 码 示 例 说 明 如 何 创 建 两 个 请 求 并 在 随 后 使 用 它 们 创 建 请 求 序 列 。 然 后 , 使用 send_multiple_requests_deferred 方 法 发 送 该 序 列 。. . .// 创 建 对 余 额 的 请 求try {req1 = account->_request("balance");// 创 建 request 的 变 量customer1 add_value("customer", customer1, CORBA::ARG_IN);// 设 定 结 果. . .} catch(const CORBA::Exception& excep) {cout


try {orb->send_multiple_requests_deferred(reqseq);cout


用 DII 使 用 接 口 仓 库用 DII 使 用 接 口 仓 库仅 适 用 于 C++:关 于 配 置 DII Request 对 象 所 需 要 的 信 息 的 来 源 之 一 是 接 口 仓 库 (IR)( 参 阅 " 使用 接 口 仓 库 ")。 以 下 的 实 例 使 用 接 口 仓 库 来 取 得 一 个 操 作 的 参 数 。 注 意 : 该 实 例是 真 实 DII 应 用 的 一 个 非 典 型 的 实 例 , 它 具 有 远 端 对 象 的 类 型 (Account) 和 其 一个 方 法 (balance) 的 名 称 的 内 置 知 识 。 一 个 实 际 的 DII 应 用 会 从 一 个 外 部 源 ( 例如 , 一 个 用 户 ) 中 得 到 那 些 信 息 。实 例● 限 制 到 任 何 Account 对 象 。● 在 IR 中 查 找 Account 的 balance 方 法 并 从 IR OperationDef 上 建 立 一 个 操 作 列表 。● 创 建 变 量 和 结 果 组 件 并 将 它 们 传 递 到 _create_request 方 法 。 注 意 :balance 方法 不 返 回 违 例 。● 调 用 Request, 取 出 并 打 印 结 果 。// acctdii_ir.C// 本 实 例 说 明 IR 和 DII#include #include "corba.h"int main(int argc, char* const* argv) {CORBA::ORB_ptr orb;CORBA::Object_var account;CORBA::NamedValue_var result;CORBA::Any_ptr resultAny;CORBA::Request_var req;CORBA::NVList_var operation_list;CORBA::Any customer;CORBA::Float acct_balance;try {// 使 用 argv[1] 作 account 名 称 , 或 使 用 默 认 值 。CORBA::String_var name;if (argc == 2)name = (const char *) argv[1];elsename = (const char *) "Default Name";try {// 初 始 化 ORB。orb = CORBA::ORB_init(argc, argv);} catch(const CORBA::Exception& excep) {cout


用 DII 使 用 接 口 仓 库cout


用 DII 使 用 接 口 仓 库if ( env->exception() ) {cout


第章使 用 动 态 框 架 接 口第 19 章本 章 描 述 对 象 服 务 器 如 何 在 运 行 期 内 根 据 服 务 客 户 请 求 动 态 地 创 建 对 象 实 现 。什 么 是 动 态 框 架 接 口 ?注 :动 态 框 架 接 口 (DSI) 提 供 了 一 个 不 需 要 继 承 生 成 的 框 架 接 口 来 创 建 对 象 实 现 的 机制 。 通 常 , 对 象 实 现 是 从 由 C++ idl2cpp 编 译 器 或 Java idl2java 编 译 器 生 成 的 框架 类 衍 生 而 来 的 。 DSI 允 许 对 象 在 <strong>VisiBroker</strong> ORB 注 册 自 身 , 从 客 户 端 接 收 操作 请 求 , 处 理 请 求 , 并 将 结 果 返 回 给 客 户 端 , 无 须 继 承 由 C++ idl2cpp 编 译 器 或Java idl2java 编 译 器 生 成 的 框 架 类 。从 客 户 程 序 的 角 度 来 看 , 用 DSI 实 现 的 对 象 与 其 它 <strong>VisiBroker</strong> ORB 对 象 没 有 区别 。 客 户 无 须 提 供 任 何 特 殊 的 处 理 以 便 与 使 用 DSI 的 对 象 实 现 通 信 。<strong>VisiBroker</strong> ORB 通 过 调 用 DSI 对 象 的 invoke 方 法 并 将 它 传 递 给 一 个ServerRequest 对 象 来 将 客 户 操 作 请 求 提 交 给 该 DSI 对 象 实 现 。 对 象 实 现 负 责 确 定被 请 求 的 操 作 , 解 译 与 请 求 相 关 的 变 量 , 调 用 适 当 的 内 部 方 法 来 实 现 请 求 , 并 返 回适 当 的 值 。用 DSI 实 现 对 象 比 使 用 由 对 象 框 架 提 供 的 常 规 的 语 言 映 射 需 要 更 多 的 人 工 编 程 活动 。 但 是 , 用 DSI 实 现 的 对 象 对 提 供 协 议 桥 接 非 常 有 用 。使 用 idl2java 编 译 器仅 适 用 于 Java:idl2java 编 译 器 具 有 一 个 -dynamic_marshal 标 志 , 当 打 开 该 标 志 时 , 将 使 用 DII生 成 框 架 代 码 。 要 了 解 如 何 作 DSI 类 型 : 创 建 一 个 IDL 文 件 , 用 -dynamic_marshal 来 生 成 , 然 后 查 看 框 架 代 码 。使 用 动 态 框 架 接 口 19-1


动 态 创 建 对 象 实 现 的 步 骤动 态 创 建 对 象 实 现 的 步 骤要 使 用 DSI 动 态 地 创 建 对 象 实 现 , 执 行 以 下 步 骤 :1 当 在 C++ 下 编 译 你 的 IDL 时 , 使 用 -type_code_inf 标 志 ; 或 者在 Java 下 编 译 你 的 IDL 时 , 使 用 -dynamic_marshal 标 志 。2 设 计 你 的 对 象 实 现 使 它 从 C++ PortableServer::DynamicImplementation 抽 象 类或Java org.omg.PortableServer.DynamicImplementation 接 口 派 生 , 而 不 是 从 框架 类 派 生 。3 声 明 并 实 现 invoke 方 法 , <strong>VisiBroker</strong> ORB 将 使 用 该 方 法 将 客 户 请 求 传 送 到 你的 对 象 。4 在 POA 管 理 器 上 将 你 的 对 象 实 现 (POA 服 务 对 象 ) 注 册 为 默 认 的 服 务 对 象 。使 用 DSI 的 实 例 程 序 的 位 置<strong>VisiBroker</strong> <strong>Edition</strong> 的 examples/basic/bank_dynamic 目 录 下 包 含 一 个 说 明 如 何 使用 DSI 的 实 例 。 本 节 中 将 引 用 这 些 实 例 程 序 来 说 明 DSI 概 念 。 以 下 的 Bank.idl 文件 说 明 该 实 例 中 实 现 的 接 口 。// Bank.idlmodule Bank {interface Account {float balance();};interface AccountManager {Account open(in string name);};};扩 展 DynamicImplementation 类C++:Java:要 使 用 DSI, 对 象 实 现 应 该 从 以 下 出 示 的 DynamicImplementation 基 础 类 派 生 。 这个 类 提 供 数 个 构 建 器 和 invoke 方 法 , 你 必 须 实 现 它 们 。class PortableServer::DynamicImplementation : public virtualPortableServer::ServantBase {public:virtual void invoke(PortableServer::ServerRequest_ptr request) = 0;. . .};Java 下 的 DynamicImplementation 抽 象 类 :package org.omg.CORBA;public abstract class DynamicImplementation extends Servant {public abstract void invoke(ServerRequest request);19-2 <strong>VisiBroker</strong> 开 发 者 指 南


扩 展 DynamicImplementation 类. . .}为 动 态 请 求 设 计 对 象 的 实 例以 下 的 代 码 示 例 分 别 说 明 要 在 C++ 和 Java 下 使 用 DSI 实 现 的 AccountImpl 声 明 。它 是 从 DynamicImplementation 类 派 生 的 , 声 明 了 invoke 方 法 。<strong>VisiBroker</strong> ORB将 调 用 invoke 方 法 将 客 户 操 作 请 求 以 ServerRequest 对 象 的 形 式 传 递 到 实 现 。以 下 的 代 码 示 例 说 明 Account 类 构 建 器 和 _primary_interface 功 能 。C++: class AccountImpl : public PortableServer::DynamicImplementation {public:AccountImpl(PortableServer::Current_ptr current,PortableServer::POA_ptr poa): _poa_current(PortableServer::Current::_duplicate(current)),_poa(poa){}CORBA::Object_ptr get(const char *name) {CORBA::Float balance;/ 检 查 帐 户 是 否 存 在if (!_registry.get(name, balance)) {// 在 创 建 新 帐 户 时 模 拟 延 迟VISPortable::vsleep(3);// 整 理 帐 户 余 额 , 在 0 ~1000 元 之 间balance = abs(rand()) % 100000 / 100.0;// 打 印 新 帐 户cout


扩 展 DynamicImplementation 类// 确 保 操 作 名 称 是 正 确 的if (strcmp(request->operation(), "balance") != 0) {throw CORBA::BAD_OPERATION();}// 找 出 余 额 并 填 写 结 果CORBA::NVList_ptr params = new CORBA::NVList(0);request->arguments(params);CORBA::Float balance;if (!_registry.get(name, balance))throw CORBA::OBJECT_NOT_EXIST();CORBA::Any result;result


扩 展 DynamicImplementation 类}public String[] _all_interfaces(POA poa, byte[] objectId) { return null; }public void invoke(org.omg.CORBA.ServerRequest request) {Float balance;// 从 对 象 id 中 取 得 帐 户 名 称String name = new String(_object_id());// 确 保 操 作 名 称 是 正 确 的if (!request.operation().equals("balance")) {throw new org.omg.CORBA.BAD_OPERATION();}// 找 出 余 额 并 填 写 结 果org.omg.CORBA.NVList params = _orb.create_list(0);request.arguments(params);balance = (Float)_registry.get(name);if (balance == null) {throw new org.omg.CORBA.OBJECT_NOT_EXIST();}org.omg.CORBA.Any result = _orb.create_any();result.insert_float(balance.floatValue());request.set_result(result);System.out.println("Checked " + name + "'s balance: " +balance.floatValue());}private Random _random = new Random();static private Hashtable _registry = new Hashtable();private POA _poa;private org.omg.CORBA.ORB _orb;}以 下 的 代 码 示 例 说 明 需 要 用 DSL 实 现 的 AccountManagerImpl 类 的 实 现 。 它 是 从DynamicImplementation 类 派 生 的 , 声 明 了 invoke 方 法 。<strong>VisiBroker</strong> ORB 将 调 用invoke 方 法 将 客 户 操 作 请 求 以 ServerRequest 对 象 的 形 式 传 递 到 实 现 。C++: class AccountManagerImpl : public PortableServer::DynamicImplementation {public:AccountManagerImpl(AccountImpl* accounts) { _accounts = accounts; }CORBA::Object_ptr open(const char* name) {return _accounts->get(name);}private:AccountImpl* _accounts;CORBA::RepositoryId _primary_interface(const PortableServer::ObjectId&oid,PortableServer::POA_ptr poa) {return CORBA::string_dup((const char *)"IDL:Bank/AccountManager:1.0");};void invoke(CORBA::ServerRequest_ptr request) {// 确 定 操 作 名 称 是 正 确 的if (strcmp(request->operation(), "open") != 0)throw CORBA::BAD_OPERATION();// 取 得 输 入 参 数char *name = NULL;try {CORBA::NVList_ptr params = new CORBA::NVList(1);CORBA::Any any;使 用 动 态 框 架 接 口 19-5


扩 展 DynamicImplementation 类any arguments(params);*(params->item(0)->value()) >>= name;} catch (const CORBA::Exception& e) {throw CORBA::BAD_PARAM();}// 调 用 实 际 的 实 现 并 填 写 结 果CORBA::Object_var account = open(name);CORBA::Any result;result private org.omg.CORBA.ORB _orb;}19-6 <strong>VisiBroker</strong> 开 发 者 指 南


查 看 ServerRequest 类指 定 仓 库 ID应 该 实 现 _primary_interface 方 法 以 返 回 支 持 的 仓 库 标 识 符 。 要 确 定 想 要 指 定 的 正确 的 仓 库 标 识 符 , 从 对 象 的 IDL 接 口 名 称 开 始 , 使 用 下 列 步 骤 :1 用 斜 线 (/) 取 代 所 有 具 有 定 界 符 作 用 域 解 析 操 作 符 (::) 的 非 引 领 实 例 。2 将 “IDL:” 加 到 字 串 开 始 。3 将 “:1.0” 加 到 字 串 的 末 尾 。例 如 , 这 个 代 码 示 例 说 明 了 一 个 IDL 接 口 名 称 :Bank::AccountManager最 终 的 仓 库 标 识 符 将 是 :IDL:Bank/AccountManager:1.0查 看 ServerRequest 类一 个 ServerRequest 对 象 被 作 为 参 数 传 递 到 对 象 实 现 的 invoke 方 法 。ServerRequest 对 象 表 示 操 作 请 求 , 并 提 供 取 得 所 请 求 的 操 作 的 名 称 、 参 数 列 表 和上 下 文 的 方 法 。 它 也 提 供 用 于 设 定 要 返 回 到 调 用 者 的 结 果 的 方 法 以 及 反 映 违 例 的 方法 。C++: class CORBA::ServerRequest {public:const char* op_name() const { return _operation; }void params(CORBA::NVList_ptr);void result(CORBA::Any_ptr);void exception(CORBA::Any_ptr exception);...CORBA::Context_ptr ctx() {...}// POA spec 方 法const char *operation() const { return _operation; }void arguments(CORBA::NVList_ptr param) { params(param); }void set_result(const CORBA::Any& a) { result(new CORBA::Any(a)); }void set_exception(const CORBA::Any& a) {exception(new CORBA::Any(a));}};Java:Java 下 的 ServerRequest 抽 象 类 :package org.omg.CORBA;public abstract class ServerRequest {public java.lang.String operation();public void arguments(org.omg.CORBA.NVList args);public void set_result(org.omg.CORBA.Any result);public void set_exception(org.omg.CORBA.Any except);public abstract org.omg.CORBA.Context ctx();使 用 动 态 框 架 接 口 19-7


实 施 Account 对 象// 不 赞 成 以 下 的 方 法public java.lang.String op_name(); // 使 用 operation()public void params(org.omg.CORBA.NVList params); // 使 用 arguments()public void result(org.omg.CORBA.Any result); // 使 用 set_result()public abstract void except(org.omg.CORBA.Any except); // 使 用 set_exception()}传 递 给 arguments、 set_result 或 set_exception 方 法 的 所 有 变 量 在 其 后 均 归<strong>VisiBroker</strong> ORB 所 有 。 这 些 变 量 所 占 内 存 将 由 <strong>VisiBroker</strong> ORB 释 放 - 你 不 应 该释 放 它 们 。注 : 以 下 方 法 已 被 抛 弃 :● op_name● params● result● exception实 施 Account 对 象Account 接 口 只 声 明 一 个 方 法 , 所 以 由 AccountImpl 类 的 invoke 方 法 所 作 的 处 理相 当 简 单 。invoke 方 法 首 先 检 查 是 否 所 请 求 的 操 作 具 有 “balance” 这 个 名 称 。 如 果 名 称 不 匹配 , 则 会 掷 出 一 个 BAD_OPERATION 违 例 。 如 果 Account 对 象 要 提 供 多 个 方 法 , 则invoke 方 法 需 要 检 查 所 有 可 能 的 操 作 名 称 并 使 用 适 当 的 内 部 方 法 来 处 理 操 作 请 求 。由 于 balance 方 法 不 接 受 任 何 参 数 , 所 以 没 有 与 其 操 作 请 求 相 关 联 的 参 数 列 表 。 仅调 用 一 下 balance 方 法 , 则 结 果 被 使 用 ServerRequest 对 象 的 set_result 方 法 封 包在 要 返 回 给 调 用 者 的 Any 对 象 中 。实 现 AccountManager 对 象象 Account 对 象 一 样 , AccountManager 接 口 也 声 明 一 个 方 法 。 但 是 ,AccountManagerImpl 对 象 的 open 方 法 却 可 以 接 受 帐 户 名 参 数 。 这 使 得 由 invoke 方法 所 用 的 处 理 变 得 有 点 复 杂 。这 个 方 法 首 先 检 查 所 请 求 的 操 作 是 否 具 有 “open” 这 个 名 称 。 如 果 名 称 不 匹 配 ,则 会 掷 出 一 个 BAD_OPERATION 违 例 。 如 果 AccountManager 对 象 要 提 供 多 个 方 法 , 则其 invoke 方 法 需 要 检 查 所 有 可 能 的 操 作 名 称 并 使 用 适 当 的 内 部 方 法 来 处 理 操 作 请求 。处 理 输 入 参 数以 下 是 AccountManagerImpl 对 象 的 invoke 方 法 处 理 操 作 请 求 的 输 入 参 数 时 的 步骤 。1 创 建 一 个 保 存 操 作 的 参 数 列 表 的 NVList 。19-8 <strong>VisiBroker</strong> 开 发 者 指 南


服 务 器 实 现2 为 每 个 需 要 的 参 数 创 建 Any 对 象 , 并 将 它 们 加 入 NVList, 设 定 它 们 的 TypeCode和 参 数 类 型 (ARG_IN、 ARG_OUT 或 ARG_INOUT)。注 :3 调 用 ServerRequest 对 象 的 arguments 方 法 , 传 递 NVList, 以 更 新 列 表 上 所 有 参数 的 值 。open 方 法 需 要 一 个 帐 户 名 参 数 , 所 以 要 创 建 一 个 NVList 对 象 来 保 存 ServerRequest所 包 含 的 参 数 。 NVList 对 象 实 现 包 含 一 个 或 多 个 NamedValue 对 象 的 参 数 列 表 。 有关 NVList 和 NamedValue 类 的 描 述 , 请 参 阅 第 18 章 " 使 用 动 态 调 用 接 口 "。创 建 一 个 Any 对 象 来 保 存 帐 户 名 称 。 该 Any 随 后 被 添 加 到 NVList, 变 量 的 名 称 被 设定 为 “name”, 而 参 数 类 型 被 设 定 为 ARG_IN。一 旦 NVList 被 初 始 化 , 则 调 用 ServerRequest 对 象 的 arguments 以 取 得 列 表 上 所 有参 数 的 值 。调 用 arguments 方 法 之 后 , NVList 将 归 <strong>VisiBroker</strong> ORB 所 有 。 这 意 味 着 , 如 果一 个 对 象 实 现 修 改 NVList 中 的 ARG_INOUT 参 数 , 则 该 变 更 会 自 动 对 <strong>VisiBroker</strong>ORB 透 明 。 这 个 NVList 不 应 该 由 调 用 者 来 释 放 。另 外 一 个 可 以 为 输 入 变 量 构 建 NVList 的 方 法 是 使 用 <strong>VisiBroker</strong> ORB 对 象 的create_operation_list 方 法 。 该 方 法 接 受 OperationDef 并 返 回 NVList 对 象 , 它 被用 所 有 必 要 的 Any 对 象 完 全 初 始 化 。 适 用 的 OperationDef 对 象 可 能 要 从 接 口 仓 库 中取 得 , 请 参 阅 第 17 章 " 使 用 接 口 仓 库 "。设 定 返 回 值在 调 用 ServerRequest 对 象 的 arguments 方 法 后 , 可 以 取 出 name 参 数 的 值 并 用 它 来创 建 新 的 Account 对 象 。 创 建 一 个 Any 对 象 来 保 存 新 建 的 Account 对 象 , 通 过 调 用ServerRequest 对 象 的 set_result 方 法 将 该 新 建 对 象 返 回 给 调 用 者 。服 务 器 实 现以 下 代 码 所 示 的 main 例 程 实 现 与 第 4 章 " 使 用 <strong>VisiBroker</strong> <strong>Edition</strong> 开 发 实 例 应 用" 中 介 绍 的 原 来 的 实 例 几 乎 是 完 全 相 同 的 。C++: int main(int argc, char* const* argv) {try {// 初 始 化 ORBCORBA::ORB_var orb = CORBA::ORB_init(argc, argv);// 取 得 根 POA 的 参 考CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");PortableServer::POA_var rootPOA = PortableServer::POA::_narrow(obj);// 得 到 POA 管 理 器PortableServer::POAManager_var poaManager = rootPOA->the_POAManager();// 用 正 确 的 策 略 创 建 account POACORBA::PolicyList accountPolicies;accountPolicies.length(3);accountPolicies[(CORBA::ULong)0] =rootPOA->create_servant_retention_policy(PortableServer::NON_RETAIN);accountPolicies[(CORBA::ULong)1] =使 用 动 态 框 架 接 口 19-9


服 务 器 实 现rootPOA->create_request_processing_policy(PortableServer::USE_DEFAULT_SERVANT);accountPolicies[(CORBA::ULong)2] =rootPOA->create_id_uniqueness_policy(PortableServer::MULTIPLE_ID);PortableServer::POA_var accountPOA =rootPOA->create_POA("bank_account_poa",poaManager,accountPolicies);// 创 建 帐 户 默 认 服 务 对 象PortableServer::Current_var current =PortableServer::Current::_instance();AccountImpl accountServant(current, accountPOA);accountPOA->set_servant(&accountServant);// 用 正 确 的 策 略 创 建 manager POACORBA::PolicyList managerPolicies;managerPolicies.length(3);managerPolicies[(CORBA::ULong)0] = rootPOA->create_lifespan_policy(PortableServer::PERSISTENT);managerPolicies[(CORBA::ULong)1] =rootPOA->create_request_processing_policy(PortableServer::USE_DEFAULT_SERVANT);managerPolicies[(CORBA::ULong)2] =rootPOA->create_id_uniqueness_policy(PortableServer::MULTIPLE_ID);PortableServer::POA_var managerPOA = rootPOA->create_POA("bank_agent_poa",poaManager,managerPolicies);// 创 建 管 理 器 默 认 服 务 对 象AccountManagerImpl managerServant(&accountServant);managerPOA->set_servant(&managerServant);// 激 活 POA 管 理 器poaManager->activate();cout


服 务 器 实 现// 得 到 POA 管 理 器POAManager poaManager = rootPOA.the_POAManager();// 用 正 确 的 策 略 创 建 帐 户 POAorg.omg.CORBA.Policy[] accountPolicies = {rootPOA.create_servant_retention_policy(ServantRetentionPolicyValue.NON_RETAIN),rootPOA.create_request_processing_policy(RequestProcessingPolicyValue.USE_DEFAULT_SERVANT)};POA accountPOA = rootPOA.create_POA("bank_account_poa",poaManager, accountPolicies);// 创 建 帐 户 默 认 的 服 务 对 象AccountImpl accountServant = new AccountImpl(orb, accountPOA);accountPOA.set_servant(accountServant);// 用 正 确 的 策 略 创 建 管 理 器 POAorg.omg.CORBA.Policy[] managerPolicies = {rootPOA.create_lifespan_policy(LifespanPolicyValue.PERSISTENT),rootPOA.create_request_processing_policy(RequestProcessingPolicyValue.USE_DEFAULT_SERVANT)};POA managerPOA = rootPOA.create_POA("bank_agent_poa",poaManager, managerPolicies);// 创 建 管 理 器 默 认 服 务 对 象AccountManagerImpl managerServant = new AccountManagerImpl(orb,accountServant);managerPOA.set_servant(managerServant);// 激 活 POA 管 理 器poaManager.activate();System.out.println("AccountManager is ready");// 等 待 进 入 的 请 求 。orb.run();} catch(Exception e) {e.printStackTrace();}}}DSI 实 现 被 实 例 化 为 一 个 默 认 的 服 务 对 象 , 而 POA 应 该 被 创 建 为 支 持 相 应 的 策略 。 有 关 详 情 , 请 参 阅 第 7 章 " 使 用 POA"。使 用 动 态 框 架 接 口 19-11


19-12 <strong>VisiBroker</strong> 开 发 者 指 南


第章使 用 可 移 植 接 收 器第 20 章本 章 简 要 介 绍 由 OMG 规 范 所 定 义 的 新 型 可 移 植 接 收 器 , 浏 览 了 一 个 可 移 植 接 收 器的 实 例 , 并 描 述 了 一 些 高 级 特 性 , 如 可 移 植 接 收 器 工 厂 等 。 有 关 可 移 植 接 收 器 的 完整 描 述 , 请 参 阅 OMG 最 终 采 用 规 范 , ptc/2001-04-03, 第 21 章 - 可 移 植 接 收器 。概 述<strong>VisiBroker</strong> <strong>Edition</strong> ORB 提 供 了 一 套 被 称 为 接 收 器 的 接 口 , 它 们 为 插 入 额 外 的ORB 行 为 ( 例 如 , 安 全 、 事 务 、 日 志 记 录 ) 提 供 了 框 架 。 这 些 接 收 器 基 于 回 调 机制 。 例 如 , 通 过 使 用 接 收 器 , 您 可 以 了 解 客 户 和 服 务 器 之 间 的 通 信 , 修 改 这 些 通 信( 如 果 您 想 这 么 做 ), 从 而 有 效 地 改 变 <strong>VisiBroker</strong> <strong>Edition</strong> ORB 的 行 为 。接 收 器 最 简 单 的 用 法 是 , 它 对 于 通 过 代 码 来 追 踪 非 常 有 用 。 因 为 您 可 以 看 见 客 户 和服 务 器 之 间 发 送 的 消 息 , 所 以 您 可 以 确 切 地 知 道 ORB 处 理 请 求 的 方 式 。图 20.1接 收 器 如 何 工 作如 果 您 正 在 构 建 更 复 杂 的 应 用 ( 例 如 , 监 视 工 具 或 安 全 层 ), 接 收 器 会 给 您 提 供 必需 的 信 息 和 控 制 , 以 实 现 这 些 低 层 应 用 。 例 如 , 您 可 以 开 发 一 个 监 视 各 种 服 务 器 的活 动 并 执 行 负 载 平 衡 的 应 用 。<strong>VisiBroker</strong> <strong>Edition</strong> ORB 支 持 两 种 接 收 器 : 可 移 植 接 收 器 ( 本 章 中 以 下 简 称“ 接 收 器 ”) 和 <strong>VisiBroker</strong> 接 收 器 。 可 移 植 接 收 器 遵 从 OMG 标 准 , 允 许 为 接 收器 写 入 可 移 植 代 码 并 将 它 用 于 不 同 供 应 商 的 ORB。 <strong>VisiBroker</strong> 接 收 器 是 在使 用 可 移 植 接 收 器 20-1


可 移 植 接 收 器 和 信 息 接 口<strong>VisiBroker</strong> <strong>Edition</strong> 4.x 中 定 义 和 实 现 的 接 收 器 ( 请 参 阅 第 21 章 " 使 用 4.x 接 收器 " 以 查 看 有 关 <strong>VisiBroker</strong> 接 收 器 的 详 情 )。OMG 规 范 定 义 了 两 种 可 移 植 接 收 器 :● 请 求 接 收 器 可 用 于 实 现 在 客 户 和 服 务 器 之 间 传 递 上 下 文 信 息 的 <strong>VisiBroker</strong><strong>Edition</strong> ORB 服 务 。 请 求 接 收 器 可 进 一 步 分 为 客 户 请 求 接 收 器 和 服 务 器 请 求 接收 器 。● IOR 接 收 器 可 用 于 实 现 以 下 <strong>VisiBroker</strong> <strong>Edition</strong> ORB: 在 IOR 中 添 加 描 述 与服 务 器 的 或 对 象 的 ORB 服 务 相 关 的 性 能 。 例 如 , 象 SSL 这 样 的 安 全 服 务 可 以将 它 的 带 标 签 的 组 件 加 入 IOR, 以 便 认 识 该 组 件 的 客 户 可 以 通 过 该 组 件 中 的 信息 建 立 到 服 务 器 的 连 接 。要 取 得 关 于 可 移 植 接 收 器 的 详 情 , 请 参 阅 程 序 员 参 考 。有 关 使 用 可 移 植 接 收 器 和 <strong>VisiBroker</strong> 接 收 器 的 详 情 , 请 参 阅 “ 第 21 章 " 使 用4.x 接 收 器 "。可 移 植 接 收 器 和 信 息 接 口所 有 可 移 植 接 收 器 实 现 以 下 由 <strong>VisiBroker</strong> <strong>Edition</strong> ORB 定 义 和 实 现 的 基 础 接 收 器API 类 之 一 。● RequestInterceptor:● ClientRequestInterceptor● ServerRequestInterceptor● IORInterceptor接 收 器Java:C++:以 上 所 罗 列 的 所 有 接 收 器 类 都 是 从 以 下 的 公 共 类 派 生 的 :Interceptor。 该Interceptor 类 已 定 义 了 其 继 承 类 可 用 的 公 共 方 法 。public interface Interceptorextends org.omg.CORBA.portable.IDLEntity, org.omg.CORBA.LocalInterface{}public java.lang.String name ( );public void destroy ( );Interceptor 类 :class PortableInterceptor::Interceptor{virtual char* name() = 0;virtual void destroy() = 0;}20-2 <strong>VisiBroker</strong> 开 发 者 指 南


可 移 植 接 收 器 和 信 息 接 口请 求 接 收 器 :请 求 接 收 器 用 于 在 特 定 的 拦 截 点 拦 截 请 求 / 回 答 序 列 流 , 以 便 服 务 可 以 在 客 户 和服 务 器 之 间 传 递 上 下 文 信 息 。 <strong>VisiBroker</strong> <strong>Edition</strong> ORB 为 每 个 拦 截 点 提 供 一 个对 象 , 通 过 它 接 收 器 可 以 访 问 请 求 信 息 。 有 两 种 请 求 接 收 器 和 相 应 的 两 种 请 求 信 息接 口 :● ClientRequestInterceptor 和 ClientRequestInfo● ServerRequestInterceptor 和 ServerRequestInfo图 20.2请 求 拦 截 点要 取 得 关 于 请 求 接 收 器 的 详 情 , 请 参 阅 程 序 员 参 考 。ClientRequestInterceptorClientRequestInterceptor 的 拦 截 点 在 客 户 端 实 现 。 OMG 在ClientRequestInterceptor 中 定 义 了 如 下 表 “ClientRequestInterceptor 拦 截点 ” 中 所 示 的 5 个 拦 截 点 。表 20.1ClientRequestInterceptor 拦 截 点拦 截 点send_requestsend_pollreceive_replyreceive_exceptionreceive_other说 明允 许 客 户 端 接 收 器 查 询 一 个 请 求 并 在 请 求 被 送到 服 务 器 之 前 修 改 服 务 上 下 文 。允 许 客 户 端 接 收 器 查 询 时 间 独 立 调 用 (TII) 检测 中 的 请 求 , 以 取 得 回 答 序 列1 。允 许 客 户 端 接 收 器 在 回 答 信 息 从 服 务 器 返 回 之后 而 在 客 户 对 该 回 答 信 息 得 到 控 制 以 前 , 对 其进 行 查 询 。允 许 客 户 端 接 收 器 在 出 现 违 例 但 违 例 尚 未 被 发送 到 客 户 之 前 , 对 其 进 行 查 询 。允 许 客 户 端 接 收 器 在 一 个 请 求 引 发 其 它 非 常 规回 答 或 在 收 到 违 例 时 , 查 询 可 用 的 信 息 。1 TII 未 在 <strong>VisiBroker</strong> <strong>Edition</strong> ORB 中 实 现 。 因 此 , send_poll( ) 拦 截 点 不 会 被 调 用 。要 取 得 关 于 各 拦 截 点 的 详 情 , 请 参 阅 程 序 员 参 考 。使 用 可 移 植 接 收 器 20-3


可 移 植 接 收 器 和 信 息 接 口Java:C++:package org.omg.PortableInterceptor;public interface ClientRequestInterceptorextends Interceptor, org.omg.CORBA.portable.IDLEntity,org.omg.CORBA.LocalInterface{public void send_request(ClientRequestInfo ri) throws ForwardRequest;public void send_poll(ClientRequestInfo ri) throws ForwardRequest;public void receive_reply(ClientRequestInfo ri);public void receive_exception(ClientRequestInfo ri) throws ForwardRequest;public void receive_other(ClientRequestInfo ri) throws ForwardRequest;}ClientRequestInterceptor 类 :class _VISEXPORT ClientRequestInterceptor: public virtual Interceptor{public:virtual void send_request(ClientRequestInfo_ptr _ri) = 0;virtual void send_poll(ClientRequestInfo_ptr _ri) = 0;virtual void receive_reply(ClientRequestInfo_ptr _ri) = 0;virtual void receive_exception(ClientRequestInfo_ptr _ri) = 0;virtual void receive_other(ClientRequestInfo_ptr _ri) = 0;};客 户 端 规 则 如 下 :● 始 发 拦 截 点 为 :send_request 和 send_poll。 在 任 何 给 定 的 请 求 / 回 答 序 列 上 ,有 且 只 有 其 中 一 个 拦 截 点 可 以 被 调 用 ;● 终 止 拦 截 点 为 :receive_reply、receive_exception 和 receive_other。 在 任 何给 定 的 请 求 / 回 答 序 列 上 , 有 且 只 有 其 中 一 个 拦 截 点 可 以 被 调 用 ;● 不 存 在 任 何 中 间 拦 截 点 ;● 当 且 仅 当 send_request 或 send_poll 成 功 执 行 时 , 才 可 以 调 用 一 个 终 止 拦 截 点 。● 如 果 一 个 请 求 因 为 ORB 关 闭 而 被 取 消 , 则 用 具 有 次 要 代 码 (minor code) 4(ORB 已 关 闭 ) 的 系 统 违 例 BAD_INV_ORDER 来 调 用 receive_exception。● 如 果 一 个 请 求 因 为 其 它 原 因 而 被 取 消 , 则 用 具 有 次 要 代 码 (minor code) 3 的系 统 违 例 TRANSIENT 来 调 用 receive_exception。成 功 的 调 用重 试先 调 用 send_request, 再 调 用receive_reply : 始 发 点 后 面 跟 着 终 止 点先 调 用 send_request , 再 调 用receive_other : 始 发 点 后 面 跟 着 终 止 点20-4 <strong>VisiBroker</strong> 开 发 者 指 南


可 移 植 接 收 器 和 信 息 接 口ServerRequestInterceptorServerRequestInterceptor 的 拦 截 点 在 服 务 器 端 实 现 。 OMG 在ClientRequestInterceptor 中 定 义 了 如 下 表 “ServerRequestInterceptor 拦 截点 ” 中 所 示 的 5 个 拦 截 点 。表 20.2ServerRequestInterceptor 拦 截 点拦 截 点receive_request_service_contextsreceive_requestsend_replysend_exceptionsend_other说 明允 许 服 务 器 端 接 收 器 从 进 入 的 请 求 中 取 得 其 服务 上 下 文 信 息 并 将 其 传 递 到PortableInterceptor::Current 的 存 储 槽 。允 许 服 务 器 端 的 接 收 器 在 所 有 的 信 息 ( 包 括 操作 参 数 ) 可 用 时 查 询 请 求 信 息 。允 许 服 务 器 端 接 收 器 在 目 标 操 作 被 调 用 之 后 而在 回 答 返 回 给 客 户 之 前 , 查 询 回 答 信 息 并 修 改回 答 服 务 的 上 下 文 。允 许 客 户 端 接 收 器 在 出 现 违 例 但 违 例 尚 未 被 发送 到 客 户 之 前 , 查 询 违 例 信 息 并 修 改 回 答 服 务的 上 下 文 。允 许 服 务 端 接 收 器 在 一 个 请 求 引 发 其 它 非 常 规回 答 或 在 收 到 违 例 时 , 查 询 可 用 的 信 息 。要 取 得 关 于 各 拦 截 点 的 详 情 , 请 参 阅 程 序 员 参 考 。Java:package org.omg.PortableInterceptor;public interface ServerRequestInterceptorextends Interceptor, org.omg.CORBA.portable.IDLEntity,org.omg.CORBA.LocalInterface{public void receive_request_service_contexts(ServerRequestInfo ri)throws ForwardRequest;public void receive_request(ServerRequestInfo ri) throws ForwardRequest;public void send_reply(ServerRequestInfo ri);public void send_exception(ServerRequestInfo ri) throws ForwardRequest;public void send_other(ServerRequestInfo ri) throws ForwardRequest;}ServerRequestInterceptor 类 :C++:class _VISEXPORT ServerRequestInterceptor: public virtual Interceptor{public:virtual void receive_request_service_contexts(ServerRequestInfo_ptr _ri)= 0;virtual void receive_request(ServerRequestInfo_ptr _ri) = 0;virtual void send_reply(ServerRequestInfo_ptr _ri) = 0;virtual void send_exception(ServerRequestInfo_ptr _ri) = 0;virtual void send_other(ServerRequestInfo_ptr _ri) = 0;};客 户 端 规 则 如 下 :● 始 发 拦 截 点 是 :receive_request_service_contexts。 该 拦 截 点 可 在 任 何 给 定 的请 求 / 回 答 序 列 上 调 用 ;使 用 可 移 植 接 收 器 20-5


可 移 植 接 收 器 和 信 息 接 口● 终 止 拦 截 点 为 :send_reply、 send_exception 和 send_other。 在 任 何 给 定 的 请求 / 回 答 序 列 上 , 有 且 只 有 其 中 一 个 拦 截 点 可 以 被 调 用 ;● 中 间 拦 截 点 是 receive_request。 它 在 receive_request_service_contexts 之后 而 在 终 止 拦 截 点 之 前 被 调 用 ;● 出 现 违 例 时 , 不 可 以 调 用 receive_request ;● 当 且 仅 当 send_request 或 send_poll 成 功 执 行 时 , 才 可 以 调 用 一 个 终 止 拦 截 点 。● 如 果 一 个 请 求 因 为 ORB 关 闭 而 被 取 消 , 则 用 具 有 次 要 代 码 (minor code) 4(ORB 已 关 闭 ) 的 系 统 违 例 BAD_INV_ORDER 来 调 用 send_exception。● 如 果 一 个 请 求 因 为 其 它 原 因 而 被 取 消 , 则 用 具 有 次 要 代 码 (minor code) 3 的系 统 违 例 TRANSIENT 来 调 用 send_exception。成 功 的 调 用拦 截 点 的 顺 序 :receive_request_service_contexts、receive_request、send_reply : 始 发 点 后 面 跟 着 中 间 点 ,中 间 点 后 面 跟 着 终 止 点IOR 接 收 器IORInterceptorC++:IORInterceptor 允 许 应 用 给 对 象 引 用 增 加 与 描 述 服 务 器 或 对 象 的 ORB 服 务 相 关 的功 能 的 信 息 , 以 便 使 客 户 中 的 <strong>VisiBroker</strong> <strong>Edition</strong> ORB 服 务 实 现 正 常 运 行 。 这 是通 过 调 用 拦 截 点 establish_components 来 实 现 的 。 IORInfo 的 一 个 实 例 被 传 递 到 拦截 点 。 要 取 得 关 于 IORInfo 的 详 情 , 请 参 阅 程 序 员 参 考 。package org.omg.PortableInterceptor;public interface IORInterceptorextends Interceptor, org.omg.CORBA.portable.IDLEntity,org.omg.CORBA.LocalInterface{public void establish_components(IORInfo info);public void components_established(IORInfo info);public void adapter_manager_state_changed(int id, short state);public void adapter_state_changed(ObjectReferenceTemplate[] templates, short state);}IORInterceptor 类 :class _VISEXPORT IORInterceptor: public virtual Interceptor{public:virtual void establish_components(IORInfo_ptr _info) = 0;virtual void components_established(IORInfo_ptr _info) = 0;virtual void adapter_manager_state_changed(CORBA::Long _id, CORBA::Short _state) = 0;virtual void adapter_state_changed(const ObjectReferenceTemplateSeq& _templates,20-6 <strong>VisiBroker</strong> 开 发 者 指 南


可 移 植 接 收 器 和 信 息 接 口};CORBA::Short _state) = 0;可 移 植 接 收 器 CurrentPortableInterceptor::Current 对 象 ( 以 下 简 称 PICurrent) 是 一 个 存 储 槽 表 , 可移 植 接 收 器 可 以 用 于 将 线 程 上 下 文 信 息 传 递 给 请 求 上 下 文 。 对 PICurrent 的 使 用 不是 必 需 的 。 但 是 , 如 果 拦 截 点 上 需 要 客 户 的 线 程 上 下 文 信 息 , 则 可 以 用 PICurrent来 传 递 该 信 息 。PICurrent 是 通 过 调 用 以 下 方 法 取 得 的 :ORB.resolve_initial_references("PICurrent");ORB->resolve_initial_references("PICurrent");Java:C++:package org.omg.PortableInterceptor;public interface Currentextends org.omg.CORBA.CurrentOperations, org.omg.CORBA.portable.IDLEntity{public org.omg.CORBA.Any get_slot(int id) throws InvalidSlot;}public void set_slot(int id, org.omg.CORBA.Any data) throws InvalidSlot;PortableInterceptor::Current 类class _VISEXPORT Current: public virtual CORBA::Current, public virtualCORBA_Object{};public:virtual CORBA::Any* get_slot(CORBA::ULong _id);virtual void set_slot(CORBA::ULong _id, const CORBA::Any& _data);CodecJAVA:Codec 提 供 了 一 个 让 接 收 器 可 以 将 组 件 在 其 IDL 数 据 类 型 和 其 CDR 封 装 表 示 之 间转 换 的 机 制 。Codec 是 从 CodecFactory 取 得 的 ( 参 阅 第 20-8 页"CodecFactory")。package org.omg.IOP;public interface Codecextends org.omg.CORBA.portable.IDLEntity, org.omg.CORBA.LocalInterface{public byte[] encode(org.omg.CORBA.Any data) throws InvalidTypeForEncoding;public org.omg.CORBA.Any decode(byte[] data) throws FormatMismatch;public byte[] encode_value(org.omg.CORBA.Any data) throwsInvalidTypeForEncoding;public org.omg.CORBA.Any decode_value(byte[] data, org.omg.CORBA.TypeCodetc)使 用 可 移 植 接 收 器 20-7


可 移 植 接 收 器 和 信 息 接 口C++:}Codec 类 :throws FormatMismatch, TypeMismatch;class _VISEXPORT Codec{public:virtual CORBA::OctetSequence* encode(const CORBA::Any& _data) = 0;virtual CORBA::Any* decode(const CORBA::OctetSequence& _data) = 0;virtual CORBA::OctetSequence* encode_value(const CORBA::Any& _data) = 0;virtual CORBA::Any* decode_value(const CORBA::OctetSequence& _data,CORBA::TypeCode_ptr _tc) = 0;};CodecFactory这 个 类 用 于 创 建 Codec 对 象 , 通 过 指 定 编 码 方 式 ( 主 版 本 和 辅 版 本 )。CodecFactory 可 以 通 过 调 用 以 下 方 法 来 取 得 :ORB.resolve_initial_references("CodecFactory")ORB->resolve_initial_references("CodecFactory")Java:C++:package org.omg.IOP;public interface CodecFactoryextends org.omg.CORBA.portable.IDLEntity, org.omg.CORBA.LocalInterface{public Codec create_codec(Encoding enc) throws UnknownEncoding;}CodecFactory 类 :class _VISEXPORT CodecFactory{public:virtual Codec_ptr create_codec(const Encoding& _enc) = 0;};创 建 可 移 植 接 收 器创 建 可 移 植 接 收 器 的 一 般 步 骤 如 下 :1 接 收 器 必 须 从 以 下 的 接 收 器 接 口 派 生 而 来 :● ClientRequestInterceptor● ServerRequestInterceptor● IORInterceptor2 接 收 器 实 现 它 可 用 的 一 个 或 多 个 拦 截 点 。20-8 <strong>VisiBroker</strong> 开 发 者 指 南


可 移 植 接 收 器 和 信 息 接 口Java:3 接 收 器 可 以 命 名 也 可 以 匿 名 。 所 有 名 称 在 具 有 相 同 类 型 的 接 收 器 中 必 须 是 唯 一的 。 但 是 , 可 以 在 <strong>VisiBroker</strong> <strong>Edition</strong> ORB 上 注 册 任 意 数 量 的 匿 名 接 收 器 。import org.omg.PortableInterceptor.*;public class SampleClientRequestInterceptor extends org.omg.CORBA.LocalObjectimplements ClientRequestInterceptor{public java.lang.String name() {return "SampleClientRequestInterceptor";}public void send_request(ClientRequestInfo ri)throws ForwardRequest {....... // 这 里 是 实 际 的 接 收 器 代 码}public void send_poll(ClientRequestInfo ri)throws ForwardRequest {....... // 这 里 是 实 际 的 接 收 器 代 码}public void receive_reply(ClientRequestInfo ri) {....... // 这 里 是 实 际 的 接 收 器 代 码}public void receive_exception(ClientRequestInfo ri)throws ForwardRequest {....... // 这 里 是 实 际 的 接 收 器 代 码}public void receive_other(ClientRequestInfo ri)throws ForwardRequest {....... // 这 里 是 实 际 的 接 收 器 代 码}}C++:在 C++ 下 创 建 可 移 植 接 收 器 的 实 例 :#include "PortableInterceptor_c.hh"class SampleClientRequestInterceptor: publicPortableInterceptor::ClientRequestInterceptor{char * name() {return "SampleClientRequestInterceptor";}void send_request(ClientRequestInfo_ptr _ri) {....... // 这 里 是 实 际 的 接 收 器 代 码}void send_request(ClientRequestInfo_ptr _ri) {....... // 这 里 是 实 际 的 接 收 器 代 码}使 用 可 移 植 接 收 器 20-9


可 移 植 接 收 器 和 信 息 接 口void receive_reply(ClientRequestInfo_ptr _ri) {....... // 这 里 是 实 际 的 接 收 器 代 码}void receive_exception(ClientRequestInfo_ptr _ri) {....... // 这 里 是 实 际 的 接 收 器 代 码}void receive_other(ClientRequestInfo_ptr _ri) {....... // 这 里 是 实 际 的 接 收 器 代 码}};注 册 可 移 植 接 收 器Java:Java:可 移 植 接 收 器 在 投 入 使 用 之 前 , 必 须 先 在 <strong>VisiBroker</strong> <strong>Edition</strong> ORB 上 注 册 要 注 册可 移 植 接 收 器 , 必 须 实 现 并 注 册 ORBInitializer 对 象 。 可 移 植 接 收 器 在 ORB 初 始化 的 过 程 中 通 过 注 册 相 关 联 的 ORBInitializer 对 象 完 成 实 例 化 和 注 册 , 该 对 象 实 现它 的 pre_init( ) 或 post_init( ) 方 法 , 或 者 两 者 都 实 现 。 <strong>VisiBroker</strong> <strong>Edition</strong>ORB 将 在 初 始 化 过 程 中 使 用 一 个 ORBInitInfo 对 象 来 调 用 每 个 注 册 的ORBInitializer 。package org.omg.PortableInterceptor;public interface ORBInitializerextends org.omg.CORBA.portable.IDLEntity, org.omg.CORBA.LocalInterface{public void pre_init(ORBInitInfo info);public void post_init(ORBInitInfo info);}ORBInitInfo Interface:package org.omg.PortableInterceptor;public interface ORBInitInfoextends org.omg.CORBA.portable.IDLEntity, org.omg.CORBA.LocalInterface{public java.lang.String[] arguments();public java.lang.String orb_id();public CodecFactory codec_factory();public void register_initial_reference(java.lang.String id,org.omg.CORBA.Object obj)throws InvalidName;public void resolve_initial_references(java.lang.String id) throwsInvalidName;public void add_client_request_interceptor(ClientRequestInterceptorinterceptor)throws DuplicateName;public void add_server_request_interceptor(ServerRequestInterceptorinterceptor)throws DuplicateName;public void add_ior_interceptor(IORInterceptor interceptor) throwsDuplicateName;public int allocate_slot_id();20-10 <strong>VisiBroker</strong> 开 发 者 指 南


}可 移 植 接 收 器 和 信 息 接 口public void register_policy_factory(int type, PolicyFactory policy_factory);ORBInitializer 类 :C++:class _VISEXPORT ORBInitializer{public:};virtual void pre_init(ORBInitInfo_ptr _info) = 0;virtual void post_init(ORBInitInfo_ptr _info) = 0;ORBInitInfo 类 :C++:class _VISEXPORT ORBInitInfo{public:virtual CORBA::StringSequence* arguments() = 0;virtual char* orb_id() = 0;virtual IOP::CodecFactory_ptr codec_factory() = 0;virtual void register_initial_reference(const char* _id,CORBA::Object_ptr _obj) = 0;virtual CORBA::Object_ptr resolve_initial_references(const char* _id) = 0;virtual void add_client_request_interceptor(ClientRequestInterceptor_ptr _interceptor) = 0;virtual void add_server_request_interceptor(ServerRequestInterceptor_ptr _interceptor) = 0;virtual void add_ior_interceptor(IORInterceptor_ptr _interceptor) = 0;virtual CORBA::ULong allocate_slot_id() = 0;virtual void register_policy_factory(CORBA::ULong _type,PolicyFactory_ptr _policy_factory) = 0;};注 册 ORBInitializer要 注 册 register_orb_initializer 可 使 用 提 供 的 全 局 方 法 ORBInitializer。 每 个 实现 接 收 器 的 服 务 提 供 一 个 ORBInitializer 的 实 例 。 要 使 用 服 务 , 应 用 需 要 :1 用 服 务 的 ORBInitialier 调 用 register_orb_initializer( ) ; 并 用Java:2 一 个 新 的 ORB 标 识 符 来 执 行 一 个 实 例 化 的 ORB_Init( ) 调 用 , 以 产 生 一 个 新 的ORB。由 于 register_orb_initializer( ) 是 一 个 全 局 方 式 , 它 将 打 破 关 于 ORB 的 程 序片 的 安 全 。 因 此 , ORBInitializers 通 过 使 用 Java ORB 属 性 在 <strong>VisiBroker</strong><strong>Edition</strong> ORB 上 注 册 , 不 使 用 调 用 register_orb_initializer( ) 的 方 式 。新 属 性 集新 属 性 的 名 称 的 形 式 为 :org.omg.PortableInterceptor.ORBInitializerClass.使 用 可 移 植 接 收 器 20-11


可 移 植 接 收 器 和 信 息 接 口其 中 , 是 实 现org.omg.PortableInterceptor.ORBInitializer 的 类 的 字 串 名 称 。在 ORB.init( ) 的 过 程 中 ,1 以 org.omg.PortableInterceptor.ORBInitializerClass 开 头 的 ORB 属 性 被 收集 在 一 起 ;2 每 个 属 性 的 部 分 将 被 收 集 起 来 ;3 一 个 对 象 将 被 实 例 化 , 并 将 字 串 作 为 它 的 类 名 称 ;4 在 该 对 象 上 将 调 用 pre_init( ) 和 post_init( ) 方 法 。5 如 果 发 生 任 何 违 例 , ORB 忽 略 它 们 继 续 运 行 。注 : 为 避 免 名 称 冲 突 , 推 荐 使 用 反 解 DNS 名 称 惯 例 。 例 如 , 如 果 ABC 公 司 有 两 个 初值 设 定 列 (initializer), 则 它 可 以 定 义 以 下 属 性 :org.omg.PortableInterceptor.ORBInitializerClass.com.abc.ORBInit1org.omg.PortableInterceptor.ORBInitializerClass.com.abc.ORBInit2C++: 在 PortableInterceptor 模 块 中 定 义 register_orb_initializer 方 法 的 命 令 如 下 :class _VISEXPORT PortableInterceptor {static void register_orb_initializer(ORBInitializer *init);}实 例Java:由 ABC 公 司 编 写 的 客 户 端 监 视 工 具 可 以 具 有 以 下 的 ORBInitializer 实 现 :package com.abc.Monitoring;import org.omg.PortableInterceptor.Intercepor;import org.omg.PortableInterceptor.ORBInitializer;import org.omg.PortableInterceptor.ORBInitInfo;public class MonitoringService extends org.omg.CORBA.LocalObjectimplements org.omg.PortableInterceptor.ORBInitializer{void pre_init(ORBInitInfo info){// 实 例 化 服 务 的 接 收 器Interceptor interceptor = new MonitoringInterceptor();// 注 册 Monitoring 的 接 收 器 。info.add_client_request_interceptor(interceptor);}void post_init(ORBInitInfo info){// 这 个 init 点 不 是 必 要 的 。}}可 以 用 以 下 的 命 令 来 运 行 命 名 为 MyApp 的 使 用 该 监 视 服 务 的 程 序 :20-12 <strong>VisiBroker</strong> 开 发 者 指 南


可 移 植 接 收 器 和 信 息 接 口java:C++:Dorg.omg.PortableInterceptor.ORBInitializerClass.com.abc.Monitoring.MonitoringService MyApp#include "PortableInterceptor_c.hh"class MonitoringService: public PortableInterceptor::ORBInitializer{void pre_init(ORBInitInfo_ptr _info){// 实 例 化 服 务 的 接 收 器 。Interceptor* interceptor = new MonitoringInterceptor();// 注 册 Monitoring 的 接 收 器 。_info->add_client_request_interceptor(interceptor);}void post_init(ORBInitInfo_ptr _info){// 这 个 init 点 不 是 必 要 的 。}};MonitoringService * monitoring_service = new MonitoringService();PortableInterceptor::register_orb_initializer(monitoring_service);<strong>VisiBroker</strong> <strong>Edition</strong> 朝 向 可 移 植 接 收 器 的 扩 展POA 作 用 域 服 务 器 请 求 接 收 器Java:C++:由 OMG 指 定 的 可 移 植 接 收 器 具 有 全 局 作 用 域 ,<strong>VisiBroker</strong> <strong>Edition</strong> 已 通 过 增 加一 个 新 的 模 块 调 用 PortableInterceptorExt 定 义 了 “POA 作 用 域 服 务 器 请 求 接 收器 ,” 这 是 一 个 公 用 的 到 可 移 植 接 收 器 的 扩 展 模 块 。 这 种 新 的 模 块 具 有 从PortableInterceptor::IORInfo 继 承 而 来 的 一 个 本 地 接 口 IORInfoExt, 该 接 口 提 供额 外 的 安 装 POA 作 用 域 服 务 器 请 求 接 收 器 的 方 法 。package com.inprise.vbroker.PortableInterceptor;public interface IORInfoExt extendsorg.omg.CORBA.LocalInterface,org.omg.PortableInterceptor.IORInfo,com.inprise.vbroker.PortableInterceptor.IORInfoExtOperations,org.omg.CORBA.portable.IDLEntity{public void add_server_request_interceptor(ServerRequestInterceptorinterceptor)throws DuplicateName;public java.lang.String[] full_poa_name();}IORInfoExt 类 :#include "PortableInterceptorExt_c.hh"class IORInfoExt: public PortableInterceptor::IORInfo使 用 可 移 植 接 收 器 20-13


实 例{};public:virtual void add_server_request_interceptor(ServerRequestInterceptor_ptr _interceptor) = 0;virtual char* full_poa_name();实 例在 本 节 中 , 我 们 将 讨 论 如 何 编 写 应 用 以 使 用 可 移 植 接 收 器 以 及 每 个 请 求 接 收 器 是 如何 实 现 的 。 每 个 实 例 包 含 一 组 客 户 端 和 服 务 器 端 应 用 及 其 各 自 的 Java 和 C++ 接 收器 。 要 取 得 关 于 每 个 接 口 的 定 义 的 详 情 , 请 参 阅 程 序 员 参 考 。 另 外 , 我 们 建 议 要 使用 可 移 植 接 收 器 的 开 发 者 阅 读 最 新 的 CORBA 规 范 中 有 关 可 移 植 接 收 器 的 章 节 。实 例 代 码以 下 是 可 以 在 UNIX $VBROKERDIR/examples/vbe/pi 目 录 或 Windows%VBROKERDIR%\examples\vbe\pi 目 录 下 找 到 的 实 例 列 表 。 每 个 实 例 都 与 一 个 目 录 名称 关 联 , 以 便 更 好 地 说 明 该 实 例 的 目 的 。● client_server● chaining在 下 一 小 节 中 我 们 将 详 细 讨 论 client_server 上 的 实 例 , 介 绍 实 例 目 的 , 描 述 实 例中 的 解 释 , 说 明 编 译 步 骤 及 执 行 或 部 署 。实 例 :client_server实 例 的 目 的本 实 例 将 说 明 在 无 需 更 改 任 何 代 码 的 情 况 下 , 如 何 很 方 便 地 将 可 移 植 接 收 器 加 入 现有 的 CORBA 应 用 。 可 移 植 接 收 器 可 以 通 过 重 新 执 行 相 关 的 应 用 并 指 定 可 以 在 运行 期 内 配 置 的 选 项 或 属 性 , 来 加 入 客 户 端 和 服 务 器 端 的 任 何 应 用 。所 使 用 的 客 户 和 服 务 器 程 序 与 UNIX $VBROKERDIR/examples/vbe/basic/bank_agent 目 录 或 Windows %VBROKERDIR%\examples\vbe\basic\bank_agent 目 录中 找 到 的 类 程 序 相 类 似 。 我 们 对 实 例 作 了 完 整 的 引 用 , 并 在 运 行 期 配 置 内 加 入 了 可移 植 接 收 器 。 这 样 做 的 目 的 是 , 为 那 些 熟 悉 <strong>VisiBroker</strong> 接 收 器 的 开 发 者 在<strong>VisiBroker</strong> 的 接 收 器 和 OMG 相 关 的 可 移 植 接 收 器 之 间 提 供 一 个 快 速 的 编 码 途 径 。20-14 <strong>VisiBroker</strong> 开 发 者 指 南


实 例Java:C++:Java:C++ :Java :C++ :代 码 解 释导 入 需 要 的 程 序 包为 使 用 可 移 植 接 收 器 接 口 , 其 中 必 须 包 括 相 关 的 程 序 包 或 头 文 件 。 请 注 意 : 如 果 您正 使 用 任 何 可 移 植 接 收 器 的 违 例 , 例 如 , DuplicateName 和 InvalidName, 则 您 可 以选 用 ORBInitInfoPackage。import org.omg.PortableInterceptor.*;import org.omg.PortableInterceptor.ORBInitInfoPackage.*;在 C++ 下 使 用 可 移 植 拦 截 时 所 需 要 的 头 文 件 :#include "PortableInterceptor_c.hh"#include "IOP_c.hh"现 在 , 我 们 要 从 客 户 端 开 始 , 详 细 解 释 请 求 接 收 器 各 个 部 分 是 如 何 编 写 的 。 要 载 入一 个 客 户 端 请 求 接 收 器 , 必 须 实 现 一 个 实 现 ORBInitilializer 接 口 的 类 。 就 初 始 化而 言 , 这 也 适 用 于 服 务 器 端 的 请 求 接 收 器 。 以 下 是 实 现 该 接 口 的 代 码 。public class SampleClientLoader extends org.omg.CORBA.LocalObjectimplements ORBInitializerclass SampleClientLoader : public PortableInterceptor::ORBInitializer装 载 服 务 器 请 求 接 收 器 时 所 需 要 的 对 ORBInitializer 的 适 当 的 继 承public class SampleServerLoader extends org.omg.CORBA.LocalObjectimplements ORBInitializerclass SampleServerLoader : public PortableInterceptor::ORBInitializer注 意 每 个 实 现 ORBInitializer 接 口 的 对 象 也 要 从 LocalObject 对 象 继 承 而 来 。 这 是必 需 的 , 因 为 ORBInitializer 的 IDL 定 义 使 用 local 关 键 字 。 关 于 IDL 关 键 字local 的 详 情 , 请 参 阅 第 26-1 页 " 使 用 valuetypes" 一 节 。在 ORB 的 初 始 化 过 程 中 , 每 个 请 求 接 收 器 都 是 通 过 实 现 pre_init() 接 口 而 加 入的 。 在 该 接 口 内 部 , 客 户 请 求 接 收 器 是 通 过 add_client_request_interceptor() 方法 加 入 的 。 有 关 的 客 户 请 求 接 收 器 在 加 入 ORB 前 , 必 须 实 例 化 。Java: public void pre_init(ORBInitInfo info) {try {info.add_client_request_interceptor(new SampleClientInterceptor());...C++ : public:void pre_init(PortableInterceptor::ORBInitInfo_ptr _info) {SampleClientInterceptor *interceptor = new SampleClientInterceptor;try {_info->add_client_request_interceptor(interceptor);...根 据 OMG 规 范 , 必 需 的 应 用 将 通 过 register_orb_initializer 方 法 来 注 册 各 自的 接 收 器 。 请 参 阅 第 20-33 页 " 开 发 客 户 和 服 务 器 应 用 " 一 小 节 , 以 取 得 更 详 细 的信 息 。 <strong>VisiBroker</strong> 提 供 了 一 个 可 选 的 注 册 这 些 接 收 器 的 方 法 , 即 通 过 动 态 链 接 库(DLL) 来 注 册 。 使 用 这 一 注 册 方 法 的 优 点 是 , 应 用 不 需 要 改 变 任 何 代 码 , 只 需 要改 变 它 们 的 执 行 方 法 。 在 执 行 过 程 中 , 通 过 选 择 额 外 的 选 项 , 就 可 以 注 册 和 执 行 接使 用 可 移 植 接 收 器 20-15


实 例C++:收 器 。 这 一 选 项 与 4.x 接 收 器 相 似 ; vbroker.orb.dynamicLibs= ,其 中 是 动 态 链 接 库 的 文 件 名 , 扩 展 名 为 “.SO”(UNIX) 或“.DLL”(Windows)。 要 载 入 一 个 以 上 的 DLL 文 件 时 , 用 逗 号 (",") 将 各 文件 名 分 开 , 使 如 ,vbroker.orb.dynamicLibs=a.so,b.so,c.so (UNIX) 或vbroker.orb.dynamicLibs=a.dll,b.dll,c.dll。要 动 态 地 载 入 接 收 器 , 则 需 要 使 用 VISInit。 这 与 在 4.x 接 收 器 中 所 使 用 的 相 似 。有 关 详 情 , 请 参 阅 第 21 章 " 使 用 4.x 接 收 器 "。 在 ORB_init 实 现 内 部 , 每 个 接 收器 装 载 器 的 注 册 是 相 似 的 。void ORB_init(int& argc, char* const* argv, CORBA::ORB_ptr orb){if( _bind_interceptors_installed) return;SampleClientLoader *client = new SampleClientLoader();PortableInterceptor::register_orb_initializer(client);...客 户 端 接 收 器 装 载 器 的 完 整 实 现 如 下 :// SampleClientLoader.javaimport org.omg.PortableInterceptor.*;import org.omg.PortableInterceptor.ORBInitInfoPackage.*;public class SampleClientLoader extends org.omg.CORBA.LocalObjectimplements ORBInitializer{public void pre_init(ORBInitInfo info) {try {System.out.println("=====>SampleClientLoader: Installing ...");info.add_client_request_interceptor(new SampleClientInterceptor());System.out.println("=====>SampleClientLoader: Interceptors loaded.");}catch(DuplicateName dn) {System.out.println("=====>SampleClientLoader: " + dn.name + " alreadyinstalled.");}catch(Exception e) {e.printStackTrace();throw new org.omg.CORBA.INITIALIZE(e.toString());}}public void post_init(ORBInitInfo info) {// 在 这 里 我 们 什 么 也 用 不 着 做 。}}客 户 端 接 收 器 装 载 器 在 C++ 下 的 完 整 实 现 :C++:// SampleClientLoader.C20-16 <strong>VisiBroker</strong> 开 发 者 指 南


实 例#include "PortableInterceptor_c.hh"#include "IOP_c.hh"#include "SampleClientInterceptor.h"#if !defined( DLL_COMPILE )#include "vinit.h"#include "corba.h"#endif// USE_STD_NS 是 由 <strong>VisiBroker</strong> 建 立 的 使 用 std namespace 的 定 义USE_STD_NSclass SampleClientLoader :public PortableInterceptor::ORBInitializer{private:short int _interceptors_installed;#if defined( DLL_COMPILE )static SampleClientLoader _instance;#endifpublic:SampleClientLoader() {_interceptors_installed = 0;}void pre_init(PortableInterceptor::ORBInitInfo_ptr _info) {if(_interceptors_installed) return;cout


实 例};#if defined( DLL_COMPILE )class VisiClientLoader : VISInit{private:static VisiClientLoader _instance;short int _bind_interceptors_installed;public:VisiClientLoader() : VISInit(1) {_bind_interceptors_installed = 0;}void ORB_init(int& argc, char* const* argv, CORBA::ORB_ptr orb) {if( _bind_interceptors_installed) return;try {SampleClientLoader *client = new SampleClientLoader();PortableInterceptor::register_orb_initializer(client);}};_bind_interceptors_installed = 1;}catch(const CORBA::Exception& e){cerr


实 例C++:void ORB_init(int& argc, char* const* argv, CORBA::ORB_ptr orb){if( _poa_interceptors_installed) return;SampleServerLoader *server = new SampleServerLoader();PortableInterceptor::register_orb_initializer(server);...Java:服 务 器 端 接 收 器 装 载 器 的 完 整 实 现 如 下 :// SampleServerLoader.javaimport org.omg.PortableInterceptor.*;import org.omg.PortableInterceptor.ORBInitInfoPackage.*;public class SampleServerLoader extends org.omg.CORBA.LocalObjectimplements ORBInitializer{public void pre_init(ORBInitInfo info) {try {info.add_server_request_interceptor(newSampleServerInterceptor());System.out.println("=====>SampleServerLoader: Interceptors loaded");}catch(DuplicateName dn) {System.out.println("Interceptor: " + dn.name + " already installed.");}catch(Exception e) {e.printStackTrace();throw new org.omg.CORBA.INITIALIZE(e.toString());}}public void post_init(ORBInitInfo info) {// 这 里 我 们 什 么 都 不 用 做 。}}C++:服 务 器 端 接 收 器 装 载 器 在 C++ 下 的 完 整 实 现 :// SampleServerLoader.C#include "PortableInterceptor_c.hh"#include "IOP_c.hh"#if defined( DLL_COMPILE )#include "vinit.h"#include "corba.h"#endif#include "SampleServerInterceptor.h"// USE_STD_NS 是 由 <strong>VisiBroker</strong> 为 使 用 std namespace 而 建 立 的 定 义USE_STD_NS class SampleServerLoader :{public PortableInterceptor::ORBInitializer使 用 可 移 植 接 收 器 20-19


实 例private:short int _interceptors_installed;public:SampleServerLoader() {_interceptors_installed = 0;}void pre_init(PortableInterceptor::ORBInitInfo_ptr _info) {if(_interceptors_installed) return;cout


实 例{cerr


实 例● receive_reply : 提 供 一 个 拦 截 点 , 它 允 许 接 收 器 在 回 答 从 服 务 器 返 回 之 后 而 在控 制 被 返 回 客 户 之 前 , 查 询 关 于 回 答 的 信 息 。Java: public void receive_reply(ClientRequestInfo ri) {...C++: void receive_reply(PortableInterceptor::ClientRequestInfo_ptr ri) {...接 口 void receive_exception(ClientRequestInfo ri) 的 实 现 :● receive_exception : 提 供 一 个 拦 截 点 , 它 允 许 接 收 器 在 违 例 被 提 交 给 客 户 之前 , 查 询 违 例 的 信 息 。Java: public void receive_exception(ClientRequestInfo ri) throws ForwardRequest {...C++: void receive_exception(PortableInterceptor::ClientRequestInfo_ptr ri) {...● receive_other: 提 供 一 个 拦 截 点 , 它 允 许 接 收 器 在 请 求 引 发 非 正 常 回 答 或 违 例时 , 查 询 可 用 的 信 息 。 例 如 , 一 个 请 求 可 能 会 引 发 一 个 重 试 ( 例 如 , 收 到 一 个具 有 LOCATION_FORWARD 状 态 的 GIOP 回 答 ); 或 者 在 异 步 调 用 中 , 回 答 没 有 立即 跟 随 请 求 , 但 是 控 制 返 回 给 了 客 户 , 一 个 终 止 接 收 器 点 将 被 调 用 。Java: public void receive_other(ClientRequestInfo ri) throws ForwardRequest {...C++: void receive_other(PortableInterceptor::ClientRequestInfo_ptr ri) {...Java:客 户 端 请 求 接 收 器 装 载 器 的 完 整 实 现 如 下 :// SampleClientInterceptor.javaimport org.omg.PortableInterceptor.*;import org.omg.Dynamic.*;public class SampleClientInterceptor extends org.omg.CORBA.LocalObjectimplements ClientRequestInterceptor {public SampleClientInterceptor() {this("SampleClientInterceptor");}public SampleClientInterceptor(String name) {_name = name;}private String _name = null;/*** InterceptorOperations 实 现*/public String name() {return _name;20-22 <strong>VisiBroker</strong> 开 发 者 指 南


实 例}public void destroy() {System.out.println("=====>SampleServerLoader: Interceptors unloaded");}/*** ClientRequestInterceptor 实 现*//*** 这 类 似 于 <strong>VisiBroker</strong> 4.x ClientRequestInterceptor** public void preinvoke_premarshal(org.omg.CORBA.Object target,String operation,* ServiceContextListHolder service_contexts_holder, Closureclosure);*/public void send_request(ClientRequestInfo ri) throws ForwardRequest {System.out.println("=====> SampleClientInterceptor id " +ri.request_id() +" send_request => " + ri.operation() +": target = " + ri.target());}/*** 不 存 在 与 <strong>VisiBroker</strong> 4.x* ClientRequestInterceptor 相 当 的 接 口 。*/public void send_poll(ClientRequestInfo ri) {System.out.println("=====> SampleClientInterceptor id " +ri.request_id() +" send_poll => " + ri.operation() +": target = " + ri.target());}/*** 这 类 似 于 <strong>VisiBroker</strong> 4.x ClientRequestInterceptor,** public void postinvoke(org.omg.CORBA.Object target,* ServiceContext[] service_contexts, InputStream payload,* org.omg.CORBA.Environment env, Closure closure);** env 不 包 含 任 何 违 例 值 。*/public void receive_reply(ClientRequestInfo ri) {System.out.println("=====> SampleClientInterceptor id " +ri.request_id() +" receive_reply => " + ri.operation());}/*** 这 类 似 于 <strong>VisiBroker</strong> 4.x ClientRequestInterceptor,使 用 可 移 植 接 收 器 20-23


实 例** public void postinvoke(org.omg.CORBA.Object target,* ServiceContext[] service_contexts, InputStream payload,* org.omg.CORBA.Environment env, Closure closure);** env 包 含 违 例 值 。*/public void receive_exception(ClientRequestInfo ri) throws ForwardRequest {System.out.println("=====> SampleClientInterceptor id " +ri.request_id() +" receive_exception => " + ri.operation() +": exception = " + ri.received_exception());}/*** 这 类 似 于 <strong>VisiBroker</strong> 4.x ClientRequestInterceptor,** public void postinvoke(org.omg.CORBA.Object target,* ServiceContext[] service_contexts, InputStream payload,* org.omg.CORBA.Environment env, Closure closure);** env 包 含 违 例 值 。*/public void receive_other(ClientRequestInfo ri) throws ForwardRequest {System.out.println("=====> SampleClientInterceptor id " +ri.request_id() +" receive_reply => " + ri.operation() +": exception = " + ri.received_exception() +", reply status = "+ getReplyStatus(ri));}protected String getReplyStatus(RequestInfo ri) {switch(ri.reply_status()) {case SUCCESSFUL.value:return "SUCCESSFUL";case SYSTEM_EXCEPTION.value:return "SYSTEM_EXCEPTION";case USER_EXCEPTION.value:return "USER_EXCEPTION";case LOCATION_FORWARD.value:return "LOCATION_FORWARD";case TRANSPORT_RETRY.value:return "TRANSPORT_RETRY";default:return "invalid reply status id";}}}C++:客 户 端 请 求 接 收 器 的 C++ 完 整 实 现// SampleClientInterceptor.h#include "PortableInterceptor_c.hh"#include "IOP_c.hh"20-24 <strong>VisiBroker</strong> 开 发 者 指 南


实 例// USE_STD_NS 是 由 <strong>VisiBroker</strong> 建 立 的 使 用 std namespace 的 定 义USE_STD_NSclass SampleClientInterceptor :public PortableInterceptor::ClientRequestInterceptor{private:char *_name;void init(char *name) {_name = new char[strlen(name)+1];strcpy(_name, name);}public:SampleClientInterceptor(char *name) {init(name);}SampleClientInterceptor() {init("SampleClientInterceptor");}char *name(void) {return _name;}void destroy(void) {// 这 里 什 么 也 不 做cout


实 例void send_poll(PortableInterceptor::ClientRequestInfo_ptr ri) {cout


实 例Java:C++:cout


实 例...C++: void send_reply(PortableInterceptor::ServerRequestInfo_ptr ri) {...● send_exception: 提 供 接 收 器 点 , 它 允 许 接 收 器 在 违 例 被 提 交 给 客 户 之 前 , 查 询违 例 信 息 。Java: public void send_exception(ServerRequestInfo ri) throws ForwardRequest {...C++: void send_exception(PortableInterceptor::ServerRequestInfo_ptr ri) {...● send_other: 提 供 一 个 拦 截 点 , 它 允 许 接 收 器 在 请 求 引 发 非 常 规 回 答 或 违 例 时 ,查 询 可 用 的 信 息 。 例 如 , 一 个 请 求 可 能 会 引 发 了 一 个 重 试 ( 例 如 , 收 到 一 个 具有 LOCATION_FORWARD 状 态 的 GIOP 回 答 ); 或 者 在 异 步 调 用 中 , 回 答 没 有 立 即跟 随 请 求 , 但 是 控 制 返 回 给 客 户 , 一 个 终 止 接 收 器 点 将 要 被 调 用 。Java: public void send_other(ServerRequestInfo ri) throws ForwardRequest {...C++: void send_other(PortableInterceptor::ServerRequestInfo_ptr ri) {...Java:所 有 拦 截 点 都 允 许 客 户 和 服 务 器 在 调 用 的 不 同 点 上 取 得 不 同 种 类 的 信 息 。 在 本 实 例中 , 这 些 信 息 被 显 示 在 屏 幕 上 , 作 为 一 种 调 试 方 式 。服 务 器 端 请 求 接 收 器 的 完 整 实 现 如 下 。// SampleServerInterceptor.javaimport org.omg.PortableInterceptor.*;import org.omg.Dynamic.*;import java.io.PrintStream;public class SampleServerInterceptor extends org.omg.CORBA.LocalObjectimplements ServerRequestInterceptor {private String _name = null;public SampleServerInterceptor() {this("SampleServerInterceptor");}public SampleServerInterceptor(String name) {_name = name;}/*** InterceptorOperations 实 现*/public String name() {return _name;}public void destroy() {System.out.println("=====>SampleServerLoader: Interceptors unloaded");20-28 <strong>VisiBroker</strong> 开 发 者 指 南


实 例}/*** ServerRequestInterceptor 实 现*//*** 这 类 似 于 <strong>VisiBroker</strong> 4.x ServerRequestInterceptor,** public void preinvoke(org.omg.CORBA.Object target, String operation,* ServiceContext[] service_contexts, InputStream payload, Closure closure);*/public void receive_request_service_contexts(ServerRequestInfo ri)throws ForwardRequest {System.out.println("=====> SampleServerInterceptor id " + ri.request_id() +" receive_request_service_contexts => " + ri.operation());}/*** 不 存 在 与 <strong>VisiBroker</strong> 4.x* SeverRequestInterceptor 相 当 的 接 口 。*/public void receive_request(ServerRequestInfo ri)throws ForwardRequest {System.out.println("=====> SampleServerInterceptor id " + ri.request_id() +" receive_request =>" + ri.operation() +": object id = " + ri.object_id() +", adapter_id = " + ri.adapter_id());}/*** 不 存 在 与 <strong>VisiBroker</strong> 4.x* SeverRequestInterceptor 相 当 的 接 口 。*/public void send_reply(ServerRequestInfo ri) {System.out.println("=====> SampleServerInterceptor id " + ri.request_id() +" send_reply =>" + ri.operation());}/*** 这 类 似 于 <strong>VisiBroker</strong> 4.x ServerRequestInterceptor,** public void postinvoke_premarshal(org.omg.CORBA.Object target,* ServiceContextListHolder service_contexts_holder,* org.omg.CORBA.Environment env, Closure closure);** env 包 含 违 例 值 。*/public void send_exception(ServerRequestInfo ri)throws ForwardRequest {System.out.println("=====> SampleServerInterceptor id " + ri.request_id() +" send_exception =>" + ri.operation() +使 用 可 移 植 接 收 器 20-29


实 例}": exception = " + ri.sending_exception() +", reply status = " + getReplyStatus(ri));/*** 这 类 似 于 <strong>VisiBroker</strong> 4.x ServerRequestInterceptor,** public void postinvoke_premarshal(org.omg.CORBA.Object target,* ServiceContextListHolder service_contexts_holder,* org.omg.CORBA.Environment env, Closure closure);** env 包 含 违 例 值 。*/public void send_other(ServerRequestInfo ri) throws ForwardRequest {System.out.print("=====> SampleServerInterceptor id " + ri.request_id() +" send_other =>" + ri.operation() +": exception = " + ri.sending_exception() +", reply status = " + getReplyStatus(ri));}protected String getReplyStatus(RequestInfo ri) {switch(ri.reply_status()) {case SUCCESSFUL.value:return "SUCCESSFUL";case SYSTEM_EXCEPTION.value:return "SYSTEM_EXCEPTION";case USER_EXCEPTION.value:return "USER_EXCEPTION";case LOCATION_FORWARD.value:return "LOCATION_FORWARD";case TRANSPORT_RETRY.value:return "TRANSPORT_RETRY";default:return "invalid reply status id";}}}服 务 器 端 请 求 接 收 器 的 完 整 的 C++ 实 现 :SampleServerInterceptor.c++:C++:// SampleServerInterceptor.h#include "PortableInterceptor_c.hh"#include "IOP_c.hh"// USE_STD_NS 是 由 <strong>VisiBroker</strong> 建 立 的 使 用 namespace 的 定 义USE_STD_NSclass SampleServerInterceptor :public PortableInterceptor::ServerRequestInterceptor{private:char *_name;20-30 <strong>VisiBroker</strong> 开 发 者 指 南


实 例void init(char *name) {_name = new char[strlen(name)+1];strcpy(_name, name);}public:SampleServerInterceptor(char *name) {init(name);}}}SampleServerInterceptor() {init("SampleServerInterceptor");char *name(void) {return _name;void destroy(void) {// 这 里 什 么 也 不 用 做cout


实 例*/void send_reply(PortableInterceptor::ServerRequestInfo_ptr ri) {cout


实 例};}else if(status == PortableInterceptor::TRANSPORT_RETRY)return "TRANSPORT_RETRY";elsereturn "invalid reply status id";开 发 客 户 和 服 务 器 应 用Java:在 编 写 好 接 收 器 类 之 后 , 我 们 需 要 将 这 些 类 注 册 在 各 自 的 客 户 和 服 务 器 应 用 上 。在 Java 下 , 我 们 遵 从 OMG 规 范 , 在 register_orb_initializer 映 射 下 注 册 , 即通 过 Java ORB 属 性 对 它 们 进 行 注 册 。 在 本 实 例 中 , 客 户 和 服 务 器 应 用 实 际 上 读 入了 属 性 文 件 client.properties 和 server.properties, 其 中 包 括 属 性org.omg.PortableInterceptor.ORBInitializerClass.。 其 中 是 实 现 org.omg.PortableInterceptor.ORBInitializer 的 类 的 字 串 名 称 。 在 本 例中 , 两 个 类 是 SampleClientLoader 和 SampleServerLoader。如 果 您 选 择 在 编 写 应 用 时 不 从 文 件 中 读 取 任 何 属 性 , 那 么 您 也 可 以 使 用 命 令 行 选项 。 要 这 样 做 时 , 必 须 用 以 下 命 令 来 运 行 程 序 :vbj -Dorg.omg.PortableInterceptor.ORBInitializerClass.SampleClientLoader=SampleClientLoader Clientvbj -Dorg.omg.PortableInterceptor.ORBInitializerClass.SampleServerLoader=SampleServerLoader Server客 户 应 用 的 完 整 实 现 如 下 。// 客 户 .javaimport org.omg.PortableServer.*;import java.util.Properties;import java.io.FileInputStream;public class Client {private static Properties property = null;public static void main(String[] args) {try {property = new Properties();property.load(new FileInputStream("client.properties"));// 初 始 化 ORB。org.omg.CORBA.ORB orb=org.omg.CORBA.ORB.init(args, property);// 取 得 管 理 器 Idbyte[] AccountManagerId="BankManager".getBytes();// 找 到 一 个 帐 户 管 理 器 。 给 出 POA 全 名 及 服 务 对 象 ID。Bank.AccountManager manager =Bank.AccountManagerHelper.bind(orb, "/bank_client_server_poa",AccountManagerId);// 使 用 args[0] 作 为 帐 户 名 称 , 或 使 用 默 认 值 。String name = null;name = args.length > 0 ? args[0] : "Jack B. Quick";使 用 可 移 植 接 收 器 20-33


实 例// 要 求 帐 户 管 理 器 打 开 一 个 命 名 的 帐 户 。Bank.Account account = manager.open(name);// 取 得 帐 户 余 额 。float balance = account.balance();// 打 印 余 额 。System.out.println("The balance in " + name + "'s account is $" +balance);}catch(Exception e) {e.printStackTrace();}}}服 务 器 应 用 的 完 整 实 现 。// Server.javaimport org.omg.PortableServer.*;import java.util.Properties;import java.io.FileInputStream;public class Server {private static Properties property = null;public static void main(String[] args) {try {property = new Properties();property.load(new FileInputStream("server.properties"));// 初 始 化 ORB。org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, property);// 取 得 根 POA 的 引 用POA rootPOA =POAHelper.narrow(orb.resolve_initial_references("RootPOA"));// 为 我 们 永 久 的 POA 创 建 方 针org.omg.CORBA.Policy[] policies = {rootPOA.create_lifespan_policy(LifespanPolicyValue.PERSISTENT)};// 用 正 确 的 方 针 创 建 myPOAPOA myPOA = rootPOA.create_POA("bank_client_server_poa",rootPOA.the_POAManager(), policies );// 创 建 帐 户 服 务 对 象AccountManagerImpl managerServant = new AccountManagerImpl();byte[] managerId = "BankManager".getBytes();myPOA.activate_object_with_id(managerId, managerServant);rootPOA.the_POAManager().activate();// 通 知 服 务 对 象 已 准 备 好System.out.println(myPOA.servant_to_reference(managerServant) + " isready.");// 等 待 进 入 的 请 求 。20-34 <strong>VisiBroker</strong> 开 发 者 指 南


实 例C++:orb.run();}catch (Exception e) {e.printStackTrace();}}}在 C++ 下 , 客 户 和 服 务 器 将 使 用PortableInterceptor::register_orb_initalizer() 方 法 来 注 册 各 个ORBInitializer 类 。 其 中 是 要 注 册 的 类 的 名 称 。 在 本 实 例 中 , 我 们也 说 明 了 另 外 一 种 方 法 , 即 将 接 收 器 类 注 册 为 动 态 链 接 库 的 (DLL)。 这 种 注 册 方法 的 好 处 是 应 用 不 需 要 改 变 任 何 代 码 , 只 需 要 改 变 执 行 方 式 。 请 参 阅 有 关 应 用 开 发或 执 行 的 小 节 。 请 注 意 这 是 一 个 <strong>VisiBroker</strong> 属 性 方 式 的 注 册 。 如 果 您 想 完 全 遵 从OMG, 请 不 要 使 用 以 下 方 式 。如 果 您 选 择 将 接 收 器 类 作 为 DLL ( 即 使 用 <strong>VisiBroker</strong> 属 性 方 式 ) 来 装 载 , 则 不需 要 给 客 户 和 服 务 器 应 用 加 入 额 外 的 代 码 。 在 本 实 例 中 , 您 将 会 看 到 未 指 定 DLL编 译 和 链 接 , 则 部 分 代 码 被 宏 代 换 掉 。客 户 应 用 的 完 整 实 现 如 下 。// Client.C#include "Bank_c.hh"// USE_STD_NS 是 由 <strong>VisiBroker</strong> 建 立 的 使 用 std namespace 的 定 义USE_STD_NS#if !defined( DLL_COMPILE )#include "SampleClientLoader.C"#endifint main(int argc, char* const* argv){try {// 在 orb 初 始 化 * 前 *, 将 装 载 器 (Loader) 实 例 化// 如 果 选 择 不 使 用 DLL 装 载 方 式#if !defined( DLL_COMPILE )SampleClientLoader* loader = new SampleClientLoader;PortableInterceptor::register_orb_initializer(loader);#endif// 初 始 化 ORB。CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);// 取 得 管 理 器 IdPortableServer::ObjectId_var managerId =PortableServer::string_to_ObjectId("BankManager");// 找 到 一 个 帐 户 管 理 器 。 Give the full POA name and the servant ID.Bank::AccountManager_var manager =Bank::AccountManager::_bind("/bank_agent_poa", managerId);// 使 用 argv[1] 作 account 名 称 , 或 使 用 默 认 值 。const char* name = argc > 1 ? argv[1] : "Jack B. Quick";使 用 可 移 植 接 收 器 20-35


实 例// 要 求 帐 户 管 理 器 打 开 一 个 命 名 的 帐 户 。Bank::Account_var account = manager->open(name);// 得 到 帐 户 的 余 额 。CORBA::Float balance = account->balance();// 打 印 余 额 。cout


用 正 确 的 方 针 创 建 myPOAPortableServer::POA_var myPOA = rootPOA->create_POA("bank_agent_poa",poa_manager,policies);// 创 建 服 务 对 象AccountManagerImpl managerServant;// 确 定 服 务 对 象 IDPortableServer::ObjectId_var managerId =PortableServer::string_to_ObjectId("BankManager");// 用 myPOA 上 的 ID 激 活 服 务 对 象myPOA->activate_object_with_id(managerId, &managerServant);// 激 活 POA 管 理 器poa_manager->activate();CORBA::Object_var reference =myPOA->servant_to_reference(&managerServant);cout nmake -fMakefile.cpp要 使 用 <strong>VisiBroker</strong> 属 性 装 载 方 法 来 编 译 C++ 实 例 , 只 需 执 行 以 下 命 令 :UNIX:$VBROKERDIR/examples/vbe/pi/client_server> make -f Makefile.cppdllWindows:%VBROKERDIR\examples\vbe\pi\client_server> nmake -fMakefile.cpp dll使 用 可 移 植 接 收 器 20-37


实 例客 户 和 服 务 器 应 用 的 执 行 或 部 署Java: 要 执 行 安 装 有 可 移 植 接 收 器 的 Java 实 例 , 用 以 下 方 法 来 启 动 服 务 器 和 客 户 :C++:UNIX ( 打 开 两 个 控 制 台 窗 口 ) $VBROKERDIR/examples/vbe/pi/client_server>vbj Server ( 在 第 一 个 窗 口 中 )$VBROKERDIR/examples/vbe/pi/client_server> vbj Client John ( 在 第 二 个 窗 口中 , 使 用 给 定 的 名 称 )或$VBROKERDIR/examples/vbe/pi/client_server> vbj Client ( 在 第 二 个 窗 口 中 , 使用 默 认 名 称 )Windows:%VBROKERDIR\examples\vbe\pi\client_server> start vbj Server( 在 新 的 命 令 提 示 窗 口 下 )%VBROKERDIR\examples\vbe\pi\client_server> vbj Client John ( 使 用 给 定 的 名称 )或%VBROKERDIR\examples\vbe\pi\client_server> vbj Client ( 使 用 默 认 名 称 )如 果 不 使 用 <strong>VisiBroker</strong> 属 性 装 载 方 式 来 执 行 C++ 实 例 , 则 用 以 下 方 法 来 启 动 服务 器 和 客 户 :UNIX ( 打 开 两 个 控 制 台 窗 口 ) $VBROKERDIR/examples/vbe/pi/client_server>Server ( 在 第 一 个 窗 口 中 )$VBROKERDIR/examples/vbe/pi/client_server> Client John ( 在 第 二 个 窗 口 下 ,使 用 给 定 的 名 称 )或$VBROKERDIR/examples/vbe/pi/client_server> Client ( 在 第 二 个 窗 口 中 , 使 用 给定 的 名 称 )Windows:%VBROKERDIR\examples\vbe\pi\client_server> start Server ( 在 新 的 命 令 提 示 窗口 下 )%VBROKERDIR\examples\vbe\pi\client_server> Client John ( 使 用 给 定 的 名 称 )或%VBROKERDIR\examples\vbe\pi\client_server> Client ( 使 用 默 认 名 称 )要 使 用 <strong>VisiBroker</strong> 属 性 装 载 方 法 来 执 行 C++ 实 例 , 用 下 列 方 法 启 动 服 务 器 和客 户 :UNIX:( 打 开 两 个 控 制 台 窗 口 ):$VBROKERDIR/examples/vbe/pi/client_server> Server-Dvbroker.orb.dynamicLibs=./SampleServerLoader.so ( 在 第 一 个 窗 口 中 )$VBROKERDIR/examples/vbe/pi/client_server> Client20-38 <strong>VisiBroker</strong> 开 发 者 指 南


-Dvbroker.orb.dynamicLibs=./SampleClientLoader.so John ( 在 第 二 个 窗 口 中 ,使 用 给 定 的 名 称 )Windows:%VBROKERDIR\examples\vbe\pi\client_server> start Server-Dvbroker.orb.dynamicLibs= SampleServerLoader.dll 在 新 的 命 令 提 示 窗 口 下 执行 )%VBROKERDIR\examples\vbe\pi\client_server> Client John-Dvbroker.orb.dynamicLibs= SampleClientLoader.dll ( 使 用 给 定 的 名 称 )或%VBROKERDIR\examples\vbe\pi\client_server> Client-Dvbroker.orb.dynamicLibs= SampleClientLoader.dll ( 使 用 默 认 名 称 )实 例使 用 可 移 植 接 收 器 20-39


实 例20-40 <strong>VisiBroker</strong> 开 发 者 指 南


第章使 用 4.x 接 收 器第 21 章本 章 概 述 4.x 接 收 器 结 构 、 讲 解 一 个 4.x 接 收 器 实 例 并 介 绍 一 些 先 进 的 功 能 , 如 接收 器 工 厂 和 链 接 接 收 器 。 最 后 , 本 节 列 出 在 可 移 植 接 收 器 和 4.x 接 收 器 同 时 用 于 一个 服 务 时 预 期 的 行 为 。概 述4.x 接 收 器 是 指 在 <strong>VisiBroker</strong> 4.x 版 中 定 义 和 实 现 的 接 收 器 。 与 可 移 植 接 收 器 相似 , 4.x 接 收 器 可 为 <strong>VisiBroker</strong> <strong>Edition</strong> ORB 服 务 提 供 一 种 拦 截 正 常 ORB 执 行流 的 机 制 。 有 两 种 4.x 接 收 器 :● 客 户 端 接 收 器 是 系 统 级 的 接 收 器 , 在 客 户 端 对 象 上 调 用 方 法 时 会 调 用 此 接 收 器 。注 :● 服 务 器 接 收 器 是 系 统 级 的 接 收 器 , 在 服 务 器 对 象 上 调 用 方 法 时 会 调 用 此 接 收 器 。要 使 用 接 收 器 , 您 可 以 声 明 一 个 实 现 以 下 一 种 接 收 器 接 口 的 类 。 实 例 化 接 收 器 对 象后 , 将 此 对 象 向 其 相 应 的 接 收 器 管 理 器 注 册 。( 例 如 ) 在 某 对 象 的 一 个 方 法 被 调 用或 其 参 数 被 汇 集 或 串 行 化 时 接 收 器 对 象 的 管 理 器 就 会 通 知 它 。如 果 要 在 操 作 请 求 在 客 户 端 被 汇 集 或 在 服 务 器 端 被 处 理 之 前 拦 截 操 作 请 求 , 请 使 用对 象 封 装 器 ( 如 第 22 章 " 使 用 对 象 封 装 器 " 中 所 述 )。4.x 接 收 器 接 口 和 管 理 器4.x 接 收 器 开 发 者 从 以 下 一 种 或 多 种 <strong>VisiBroker</strong> <strong>Edition</strong> 4.x 定 义 和 实 现 的 基 本 接收 器 API 类 导 出 多 种 类 。● 客 户 端 接 收 器 :● BindInterceptor● ClientRequestInterceptor使 用 4.x 接 收 器 21-1


4.x 接 收 器 接 口 和 管 理 器● 服 务 器 接 收 器 :● POALifeCycleInterceptor● ActiveObjectLifeCycleInterceptor● ServerRequestInterceptor● IORCreationInterceptor● ServiceResolver interceptor客 户 端 接 收 器目 前 有 两 种 客 户 端 接 收 器 及 其 相 应 的 管 理 器 :● BindInterceptor 和 BindInterceptorManager● ClientRequestInterceptor 和 ClientRequestInterceptorManager要 取 得 关 于 客 户 端 接 收 器 的 详 情 , 请 参 阅 第 20 章 " 使 用 可 移 植 接 收 器 "。BindInterceptorJava:BindInterceptor 对 象 是 全 局 接 收 器 , 在 限 制 前 或 限 制 后 客 户 端 上 会 调 用 此 对 象 。package com.inprise.vbroker.InterceptorExt;public interface BindInterceptor {public IORValue bind(IORValue ior,org.omg.CORBA.Object target,boolean rebind,Closure closure);public IORValue bind_failed(IORValue ior,org.omg.CORBA.Object target,Closure closure);public void bind_succeeded(IORValue ior,org.omg.CORBA.Object target,int Index,InterceptorManagerControl control,Closure closure);public void exception_occurred(IORValue ior,org.omg.CORBA.Object target,org.omg.CORBA.Environment env,Closure closure);}ClientRequestInterceptorClientRequestInterceptor 对 象 可 在 BindInterceptor 对 象 执 行 bind_succeeded 调用 期 间 注 册 , 且 在 整 个 连 接 期 间 保 持 激 活 状 态 。 其 方 法 中 的 两 个 是 在 从 客 户 端 对 象上 调 用 之 前 调 用 的 , 一 个 是 (preinvoke_premarshal) 在 参 数 被 汇 集 之 前 , 而 另 一 个是 (preinvoke_postmarshal) 在 被 汇 集 之 后 。 第 三 个 方 法 (postinvoke) 在 请 求 完 成之 后 调 用 。21-2 <strong>VisiBroker</strong> 开 发 者 指 南


4.x 接 收 器 接 口 和 管 理 器Java:package com.inprise.vbroker.InterceptorExt;public interface ClientRequestInterceptor {public void preinvoke_premarshal(org.omg.CORBA.Object target,String operation,ServiceContextListHolder service_contexts_holder,Closure closure);public void preinvoke_postmarshal(org.omg.CORBA.Object target,OutputStream payload,Closure closure);public void postinvoke(org.omg.CORBA.Object target,ServiceContext[] service_contexts,InputStream payload,org.omg.CORBA.Environment env,Closure closure);public void exception_occurred(org.omg.CORBA.Object target,org.omg.CORBA.Environment env,Closure closure);}服 务 器 接 收 器目 前 有 四 种 服 务 器 接 收 器 :● POALifeCycleInterceptor 和 POALifeCycleInterceptorManager● ActiveObjectLifeCycleInterceptor 和ActiveObjectLifeCycleInterceptorManager● ServerRequestInterceptor 和 ServerRequestInterceptorManager● IORCreationInterceptor 和 IORCreationInterceptorManager要 取 得 关 于 服 务 器 接 收 器 的 详 情 , 请 参 阅 第 20 章 " 使 用 可 移 植 接 收 器 "。POALifeCycleInterceptorJava:POALifeCycleInterceptor 对 象 是 一 种 全 局 接 收 器 , 每 次 在 创 建 ( 通 过 create 方法 ) 或 销 毁 ( 通 过 destroy 方 法 ) POA 时 会 调 用 此 对 象 。package com.inprise.vbroker.InterceptorExt;public interface POALifeCycleInterceptor {public void create(org.omg.PortableServer.POA poa,org.omg.CORBA.PolicyListHolder policies_holder,IORValueHolder iorTemplate,InterceptorManagerControl control) ;public void destroy(org.omg.PortableServer.POA poa);}ActiveObjectLifeCycleInterceptor无 论 何 时 向 活 动 对 象 映 射 表 中 添 加 对 象 ( 通 过 create 方 法 ) 或 在 去 激 活 和 气 化 对象 ( 通 过 destroy 方 法 ) 之 后 均 会 调 用 ActiveObjectLifeCycleInterceptor 对 象 。使 用 4.x 接 收 器 21-3


4.x 接 收 器 接 口 和 管 理 器Java:该 接 收 器 可 以 通 过 POALifeCycleInterceptor 在 POA 创 建 时 每 个 POA 注 册 一个 。 只 有 在 POA 采 用 RETAIN 方 针 时 才 可 以 注 册 此 接 收 器 。package com.inprise.vbroker.InterceptorExt;public interface ActiveObjectLifeCycleInterceptor {public void create(byte[] oid,org.omg.PortableServer.Servant servant,org.omg.PortableServer.POA adapter);public void destroy (byte[] oid,org.omg.PortableServer.Servant servant,org.omg.PortableServer.POA adapter);}ServerRequestInterceptor在 调 用 之 前 ( 通 过 preinvoke 方 法 ) 和 调 用 之 后 的 答 复 汇 集 之 前 和 之 后 ( 分 别 通过 postinvoke_premarshal 和 postinvoke_premarshal 方 法 ) 调 用 远 端 对 象 的 服 务器 实 现 的 过 程 中 多 个 阶 段 均 会 调 用 ServerRequestInterceptor 对 象 。 此 接 收 器 可 以通 过 POALifeCycleInterceptor 对 象 在 POA 创 建 时 每 个 POA 注 册 一 个 。package com.inprise.vbroker.InterceptorExt;public interface ServerRequestInterceptor {public void preinvoke(org.omg.CORBA.Object target,String operation,ServiceContext[] service_contexts,InputStream payload,Closure closure);public void postinvoke_premarshal(org.omg.CORBA.Object target,ServiceContextListHolder service_contexts_holder,org.omg.CORBA.Environment env,Closure closure);public void postinvoke_postmarshal(org.omg.CORBA.Object target,OutputStream payload,Closure closure);public void exception_occurred(org.omg.CORBA.Object target,org.omg.CORBA.Environment env,Closure closure);}IORCreationInterceptorJava:无 论 何 时 POA 创 建 对 象 引 用 ( 通 过 create 方 法 ) 时 均 会 调 用IORCreationInterceptor 对 象 。 此 接 收 器 可 以 通 过 POALifeCycleInterceptor 在POA 创 建 时 每 个 POA 注 册 一 个 。package com.inprise.vbroker.InterceptorExt;public interface IORCreationInterceptor {public void create(org.omg.PortableServer.POA poa,IORValueHolder ior);}21-4 <strong>VisiBroker</strong> 开 发 者 指 南


4.x 接 收 器 接 口 和 管 理 器服 务 解 析 器 接 收 器此 接 收 器 用 于 安 装 以 后 可 以 动 态 装 载 的 用 户 服 务 。Java: public interface ServiceResolverInterceptor {public org.omg.CORBA.Object resolve (java.lang.Strng name):}public interface ServiceResolverInterceptorManager extendscom.inprise.vbroker.interceptor.InterceptorManager {public void add (java.lang.String name,com.inprise.vbroker.interceptor.ServiceResolverInterceptor \interceeptor) ;pubic void remove (java.lang.String name):}调 用 resolve_initial_references 时 , 所 有 已 安 装 服 务 上 的 解 析 过 程 会 被 调 用 。 解析 过 程 接 着 返 回 适 当 的 对 象 。要 编 写 服 务 初 始 化 程 序 , 必 须 在 通 过 取 得 InterceptorManagerControl 使 自 己 能 够添 加 服 务 之 后 获 得 ServiceResolver。默 认 接 收 器 类Java:<strong>VisiBroker</strong> <strong>Edition</strong> 提 供 可 扩 展 和 实 现 的 默 认 接 收 器 Java 类 。 这 些 默 认 接 收 器 类提 供 的 方 法 与 接 收 器 接 口 相 同 , 但 是 , 在 扩 展 默 认 接 收 器 类 时 , 可 以 选 择 要 实 现 或忽 略 的 方 法 。 使 用 这 些 类 时 , 可 以 接 受 这 这 些 类 提 供 的 默 认 行 为 , 也 可 以 更 改 。● DefaultBindInterceptor 类● DefaultClientInterceptor 类● DefaultServerInterceptor 类向 <strong>VisiBroker</strong> <strong>Edition</strong> ORB 注 册 接 收 器每 个 接 收 器 接 口 都 对 应 一 个 接 收 器 管 理 器 接 口 , 该 接 口 用 于 向 <strong>VisiBroker</strong><strong>Edition</strong> ORB 注 册 自 己 的 接 收 器 对 象 。 以 下 为 注 册 接 收 器 必 须 经 过 的 步 骤 :1 通 过 使 用 “<strong>VisiBroker</strong>InterceptorControl” 参 数 调 用 ORB 对 象 上 的resolve_initial_references 方 法 向 InterceptorManagerControl 对 象 赋 予引 用 。2 使 用 下 表 中 一 个 字 符 串 值 调 用 InterceptorManagerControl 对 象 上 的get_manager 方 法 ( 下 表 所 示 为 要 传 递 给 InterceptorManagerControl 对 象get_manager 方 法 的 字 符 串 值 )。( 一 定 要 将 对 象 引 用 造 型 成 为 相 应 的 接 收 器管 理 器 接 口 。)表 21.1InterceptorManagerControl 对 象 的 字 串 值值ClientRequestBind对 应 的 接 收 器 接 口ClientRequestInterceptorBindInterceptor使 用 4.x 接 收 器 21-5


接 收 器 实 例表 21.1InterceptorManagerControl 对 象 的 字 串 值值POALifeCycleActiveObjectLifeCycleServerRequest>IORCreationServiceResolver对 应 的 接 收 器 接 口POALifeCycleInterceptorActiveObjectLifeCycleInterceptorServerRequestInterceptorIORCreationInterceptorServiceResolverInterceptor3 创 建 自 己 接 收 器 的 实 例 。4 通 过 调 用 add 方 法 向 管 理 器 对 象 注 册 接 收 器 对 象 。5 运 行 客 户 端 和 服 务 器 程 序 时 装 载 接 收 器 对 象 。创 建 接 收 器 对 象最 后 , 需 要 实 现 创 建 接 收 器 实 例 和 向 <strong>VisiBroker</strong> <strong>Edition</strong> ORB 注 册 这 些 实 例 的 工厂 类 。 工 厂 类 必 须 实 现 ServiceLoader 接 口 (Java)。Java:注 :package com.inprise.vbroker.interceptor;public interface ServiceLoader {// 调 用 ORB.init() 时 ORB 会 调 用 此 方 法 。public abstract void init(org.omg.CORBA.ORB orb);// 在 调 用 ORB.init() 之 后 且 控 制 未 返 回 给 用 户 时// 调 用 。 可 用 于 禁 用 某 些 仅 供// 其 它 服 务 单 元 使 用 的 资 源 。public abstract void init_complete(org.omg.CORBA.ORB orb);// orb 正 在 被 关 闭 时 调 用 。public abstract void shutdown(org.omg.CORBA.ORB orb);}也 可 以 创 建 新 的 接 收 器 实 例 , 并 从 其 它 接 收 器 向 <strong>VisiBroker</strong> ORB 注 册 这 些 实 例( 如 下 例 所 示 )。装 载 接 收 器Java:要 装 载 接 收 器 , 必 须 设 置 vbroker.orb.dynamicLibs 属 性 。 此 属 性 可 以 在 属 性 文 件中 设 置 ( 参 见 “ 设 置 属 性 ”), 也 可 以 使 用 -D 选 项 传 递 到 <strong>VisiBroker</strong> <strong>Edition</strong>ORB 中 。接 收 器 实 例以 下 接 收 器 实 例 使 用 了 ( 第 20 章 " 使 用 可 移 植 接 收 器 " 中 所 列 ) 所 有 接 收 器 API方 法 , 目 的 是 让 您 了 解 如 何 使 用 这 些 方 法 以 及 调 用 的 条 件 。21-6 <strong>VisiBroker</strong> 开 发 者 指 南


接 收 器 实 例实 例 代 码在 “ 代 码 列 表 ” 中 , 每 种 接 收 器 API 方 法 的 实 现 只 是 将 信 息 性 信 息 打 印 到 标 准 输出 设 备 。<strong>VisiBroker</strong> <strong>Edition</strong> 的 examples/interceptors 目 录 下 有 四 个 应 用 程 序 实 例 :● active_object_lifecycle● client_server● ior_creationJava:● 加 密客 户 端 服 务 器 接 收 器 实 例要 运 行 实 例 , 请 按 正 常 程 序 编 译 该 文 件 。 然 后 按 如 下 所 示 启 动 服 务 器 和 客 户 端 :Java:prompt>vbj -Dvbroker.orb.dynamicLibs=SampleServerLoader Serverprompt>vbj -Dvbroker.orb.dynamicLibs=SampleClientLoader Client KateJava: 将 实 现 ServiceLoader 接 口 的 两 个 类 指 定 为 <strong>VisiBroker</strong> <strong>Edition</strong> ORB 服 务 。注 : <strong>VisiBroker</strong> <strong>Edition</strong> 3.x 中 使 用 的 ServiceInit 类 变 为 实 现 两 个 接 口 :ServiceLoader 和 ServiceResolverInterceptor。 有 关 具 体 作 法 的 实 例 , 请 参 阅 第21-4 页 "ServerRequestInterceptor" 的 实 例 。接 收 器 实 例 执 行 结 果 如 下 表 所 示 。 客 户 端 和 服 务 器 执 行 结 果 依 次 列 出 。表 21.2接 收 器 实 例 执 行 结 果客 户 端Bind Interceptors loaded============>SampleBindInterceptor bind============>SampleBindInterceptor bind_succeeded============>SampleClientInterceptor id MyClientInterceptorpreinvoke_premarshal=> open============>SampleClientInterceptor id MyClientInterceptorpreinvoke_postmarshal服 务 器============>SampleServerLoader:Interceptorsloaded============>In POA /.Nothing todo.============>In POA bank_agent_poa, 1 ServerRequestinterceptor installedStub[repository_id=IDL:Bank/AccountManager:1.0,key=ServiceId[service=/bank_agent_poa,id={11bytes:[B][a][n][k][M][a][n][a][g][e][r]}]] is ready.============> SampleServerInterceptor idMyServerInterceptor preinvoke => openCreated john'saccount:Stub[repository_id=IDL:Bank/Account:1.0,key=TransientId[poaName=/,id={4bytes:(0)(0)(0)(0)},sec=0,usec=0]]使 用 4.x 接 收 器 21-7


接 收 器 实 例表 21.2接 收 器 实 例 执 行 结 果客 户 端============> SampleClientInterceptor idMyClientInterceptor postinvoke============>SampleBindInterceptor bind============>SampleBindInterceptor bind_succeeded============>SampleClientInterceptor id MyClientInterceptorpreinvoke_premarshal => balance ============>SampleClientInterceptor id MyClientInterceptorpreinvoke_postmarshal============> SampleClientInterceptor idMyClientInterceptor postinvokeThe balance in john'saccount is $245.64服 务 器============> SampleServerInterceptor idMyServerInterceptor postinvoke_premarshal============>SampleServerInterceptor id MyServerInterceptorpostinvoke_postmarshal由 于 OAD 未 运 行 , bind 调 用 失 败 , 服 务 器 继 续 执 行 。 客 户 端 限 制 到 帐 户 对 象 , 然 后 调 用balance 方 法 。 服 务 器 收 到 此 请 求 并 处 理 , 然 后 结 果 返 回 给 客 户 端 。 客 户 端 打 印 结 果 。如 实 例 代 码 和 结 果 所 示 , 在 相 应 进 程 开 始 时 同 时 安 装 客 户 端 和 服 务 器 的 接 收 器 。 有关 注 册 接 收 器 的 信 息 在 第 21-5 页 " 向 <strong>VisiBroker</strong> <strong>Edition</strong> ORB 注 册 接 收 器 " 中有 介 绍 。ServiceResolverInterceptor 实 例Java: 下 列 代 码 为 如 何 实 现 ServiceLoader 接 口 的 实 例 :import com.inprise.vbroker.properties.*;import com.inprise.vbroker.interceptor.*;import com.inprise.vbroker.InterceptorExt.*;public final class UtilityServiceLoader implements ServiceLoader,ServiceResolverInterceptor {private com.inprise.vbroker.orb.ORB _orb = null;private String[] _serviceNames = { "TimeService", "WeatherService"};public void init(org.omg.CORBA.ORB orb) {// 以 防 resolve() 需 要_orb = (com.inprise.vbroker.orb.ORB) orb;PropertyManager pm = _orb.getPropertyManager();// 使 用 PropertyManager 查 询 属 性 设 置// ( 如 有 必 要 , 此 实 例 中 未 使 用 )/**** 安 装 初 始 引 用 *****/InterceptorManagerControl control = _orb.interceptorManager();ServiceResolverInterceptorManager manager =(ServiceResolverInterceptorManager)control.get_manager("ServiceResolver");for (int i = 0; i < _serviceNames.length; i++) {manager.add(_serviceNames[i], this);}21-8 <strong>VisiBroker</strong> 开 发 者 指 南


接 收 器 实 例/**** 安 装 结 束 ***/if (_orb.debug)_orb.println("UtilityServices package has been initialized");}public void init_complete(org.omg.CORBA.ORB orb) {// 可 用 于 后 初 始 化 处 理 ( 如 果 需 要 )}public void shutdown(org.omg.CORBA.ORB orb) {_orb = null;_serviceNames = null;}public org.omg.CORBA.Object resolve(java.lang.String service) {org.omg.CORBA.Object srv = null;byte[] serviceId = service.getBytes();try {if (service == "TimeService") {srv = UtilityServices.TimeServiceHelper.bind(_orb, "/time_service_poa",serviceId);}else if (service == "WeatherService") {srv = UtilityServices.WeatherServiceHelper.bind(_orb,"/weather_service_poa",serviceId);}} catch (org.omg.CORBA.SystemException e) {if (_orb.debug)_orb.println("UtilityServices package resolve error:" + e);srv = null;}return srv;}}代 码 列 表Java:SampleServerLoader 对 象 负 责 装 载 POALifeCycleInterceptor 类 和 实 例 化 对 象 。 此类 由 vbroker.orb.dynamicLibs 动 态 链 接 到 <strong>VisiBroker</strong> <strong>Edition</strong> ORB。SampleServerLoader 类 包 含 由 ORB 在 初 始 化 过 程 中 调 用 的 init 方 法 。 其 唯 一 的 目的 是 通 过 创 建 和 向 InterceptorManager 注 册 安 装 POALifeCycleInterceptor 对 象 。import java.util.*;import com.inprise.vbroker.orb.*;import com.inprise.vbroker.interceptor.*;import com.inprise.vbroker.PortableServerExt.*;public class SampleServerLoader implements ServiceLoader {public void init(org.omg.CORBA.ORB orb) {try {InterceptorManagerControl control =InterceptorManagerControlHelper.narrow(使 用 4.x 接 收 器 21-9


接 收 器 实 例orb.resolve_initial_references("<strong>VisiBroker</strong>InterceptorControl"));// 安 装 一 个 POA 接 收 器POALifeCycleInterceptorManager poa_manager =(POALifeCycleInterceptorManager)control.get_manager("POALifeCycle");poa_manager.add(new SamplePOALifeCycleInterceptor());} catch(Exception e) {e.printStackTrace();throw new org.omg.CORBA.INITIALIZE(e.toString());}System.out.println("============>SampleServerLoader:Interceptors loaded");}public void init_complete(org.omg.CORBA.ORB orb) {}public void shutdown(org.omg.CORBA.ORB orb) {}}Java:每 次 创 建 或 销 毁 POA 时 会 调 用 SamplePOALifeCycleInterceptor 对 象 。 由 于 在client_server 实 例 中 有 两 个 POA, 因 此 此 接 收 器 被 调 用 两 次 , 一 次 是 在 rootPOA创 建 期 间 , 另 一 次 是 在 创 建 myPOA 时 。 我 们 只 在 创 建 myPOA 时 安 装SampleServerInterceptor。import com.inprise.vbroker.interceptor.*;import com.inprise.vbroker.PortableServerExt.*;import com.inprise.vbroker.IOP.*;public class SamplePOALifeCycleInterceptor implements POALifeCycleInterceptor {public void create(org.omg.PortableServer.POA poa,org.omg.CORBA.PolicyListHolder policies_holder,IORValueHolder iorTemplate,InterceptorManagerControl control) {if(poa.the_name().equals("bank_agent_poa")) {// 添 加 请 求 级 接 收 器SampleServerInterceptor interceptor =new SampleServerInterceptor("MyServerInterceptor");// 取 得 IORCreation 接 收 器 管 理 器ServerRequestInterceptorManager manager =(ServerRequestInterceptorManager)control.get_manager("ServerRequest");// 添 加 接 收 器manager.add(interceptor);System.out.println("============>In POA " + poa.the_name() +", 1 ServerRequest interceptor installed");} elseSystem.out.println("============>In POA " + poa.the_name() + ".Nothing todo.");}public void destroy(org.omg.PortableServer.POA poa) {// 作 为 一 跟 踪 手 段 !S ystem.out.println("============> SamplePOALifeCycleInterceptor destroy");}}每 次 服 务 器 收 到 请 求 或 作 出 应 答 时 会 调 用 SampleServerInterceptor 对 象 。21-10 <strong>VisiBroker</strong> 开 发 者 指 南


接 收 器 实 例Java:Java:import com.inprise.vbroker.interceptor.*;import com.inprise.vbroker.IOP.*;import com.inprise.vbroker.CORBA.portable.*;public class SampleServerInterceptor implements ServerRequestInterceptor {private String _id;public SampleServerInterceptor(String id) {_id = id;}public void preinvoke(org.omg.CORBA.Object target,String operation,ServiceContext[] service_contexts,InputStream payload,Closure closure) {// 将 此 ServerRequestInterceptor 的 _id 放 入 封 闭 对 象 中closure.object = new String(_id);System.out.println("============> SampleServerInterceptor id " +closure.object + " preinvoke => " + operation);}public void postinvoke_premarshal(org.omg.CORBA.Object target,ServiceContextListHolder service_contexts_holder,org.omg.CORBA.Environment env,Closure closure) {System.out.println("============> SampleServerInterceptor id " +closure.object + " postinvoke_premarshal");}public void postinvoke_postmarshal(org.omg.CORBA.Object target,OutputStream payload,Closure closure) {System.out.println("============> SampleServerInterceptor id " +closure.object + " postinvoke_postmarshal");}public void exception_occurred(org.omg.CORBA.Object target,org.omg.CORBA.Environment env,Closure closure) {System.out.println("============> SampleServerInterceptor id " +closure.object + " exception_occurred");}}每 次 客 户 端 发 出 请 求 或 收 到 应 答 时 会 调 用 SampleClientInterceptor 对 象 。import com.inprise.vbroker.interceptor.*;import com.inprise.vbroker.IOP.*;import com.inprise.vbroker.CORBA.portable.*;public class SampleClientInterceptor implements ClientRequestInterceptor {private String _id;public SampleClientInterceptor(String id) {_id = id;}public void preinvoke_premarshal(org.omg.CORBA.Object target,String operation,ServiceContextListHolder service_contexts_holder,Closure closure) {// 将 此 ClientRequestInterceptor 的 _id 放 入 封 闭 对 象 中closure.object = new String(_id);使 用 4.x 接 收 器 21-11


接 收 器 实 例Java:Java:System.out.println("============> SampleClientInterceptor id " +closure.object +" preinvoke_premarshal => " + operation);}public void preinvoke_postmarshal(org.omg.CORBA.Object target,OutputStream payload,Closure closure) {System.out.println("============> SampleClientInterceptor id " +closure.object + " preinvoke_postmarshal");}public void postinvoke(org.omg.CORBA.Object target,ServiceContext[] service_contexts,InputStream payload,org.omg.CORBA.Environment env,Closure closure) {System.out.println("============> SampleClientInterceptor id " +closure.object + " postinvoke");}public void exception_occurred(org.omg.CORBA.Object target,org.omg.CORBA.Environment env,Closure closure) {System.out.println("============> SampleClientInterceptor id " +closure.object + " exception_occured");}}装 载 器 负 责 装 载 BindInterceptor 对 象 。 此 类 由 vbroker.orb.dynamicLibs 动 态 链接 到 <strong>VisiBroker</strong> <strong>Edition</strong> ORB。 SampleClientLoader 类 包 含 bind 和bind_succeeded 方 法 。 这 些 方 法 由 ORB 在 对 象 限 制 期 间 调 用 。 限 制 成 功 后 ,ORB将 调 用 bind_succeeded, 同 时 装 载 器 通 过 创 建 并 向 InterceptorManager 注 册 安 装BindInterceptor 对 象 。import java.util.*;import com.inprise.vbroker.orb.*;import com.inprise.vbroker.interceptor.*;import com.inprise.vbroker.PortableServerExt.*;public class SampleClientLoader implements ServiceLoader {public void init(org.omg.CORBA.ORB orb) {try {InterceptorManagerControl control =InterceptorManagerControlHelper.narrow(orb.resolve_initial_references("<strong>VisiBroker</strong>InterceptorControl"));BindInterceptorManager bind_manager =(BindInterceptorManager) control.get_manager("Bind");bind_manager.add(new SampleBindInterceptor());} catch(Exception e) {e.printStackTrace();throw new org.omg.CORBA.INITIALIZE(e.toString());}System.out.println("Bind Interceptors loaded");}public void init_complete(org.omg.CORBA.ORB orb) {}public void shutdown(org.omg.CORBA.ORB orb) {21-12 <strong>VisiBroker</strong> 开 发 者 指 南


在 4.x 接 收 器 之 间 传 递 信 息Java:}}客 户 端 尝 试 限 制 到 对 象 时 会 调 用 SampleBindInterceptor。 ORB 初 始 化 后 客 户 端 上的 第 一 个 步 骤 是 限 制 到 AccountManager 对 象 。 此 限 制 过 程 会 调 用SampleBindInterceptor, 而 且 在 限 制 成 功 后 会 安 装 SampleClientInterceptor。import com.inprise.vbroker.interceptor.*;import com.inprise.vbroker.IOP.*;public class SampleBindInterceptor implements BindInterceptor {public IORValue bind(IORValue ior, org.omg.CORBA.Object target,boolean rebind, Closure closure) {// 作 为 一 跟 踪 手 段 !System.out.println("============> SampleBindInterceptor bind");return null;}public IORValue bind_failed(IORValue ior, org.omg.CORBA.Object target,Closure closure) {// 作 为 一 跟 踪 手 段 !System.out.println("============> SampleBindInterceptor bind_failed");return null;}public void bind_succeeded(IORValue ior, org.omg.CORBA.Object target,int Index, InterceptorManagerControl control,Closure closure) {// 作 为 一 跟 踪 手 段 !System.out.println("============> SampleBindInterceptor bind_succeeded");// 创 建 客 户 端 请 求 接 收 器 :S ampleClientInterceptor interceptor =new SampleClientInterceptor("MyClientInterceptor");// 得 到 管 理 器ClientRequestInterceptorManager manager =(ClientRequestInterceptorManager)control.get_manager("ClientRequest");// 添 加 CRQ 至 列 表 :manager.add(interceptor);}public void exception_occurred(IORValue ior, org.omg.CORBA.Object target,org.omg.CORBA.Environment env,Closure closure) {// 作 为 一 跟 踪 手 段 !System.out.println("============> SampleBindInterceptor exception_occured");}}在 4.x 接 收 器 之 间 传 递 信 息Closure (Java) 对 象 由 ORB 在 某 接 收 器 调 用 序 列 开 始 时 创 建 。 同 一 Closure (Java)对 象 用 于 该 特 定 序 列 中 的 所 有 调 用 。 code>Closure (Java) 对 象 包 含 一 个 公 共数 据 字 段 , 其 类 型 为 java.lang.Object (Java), 可 以 由 接 收 器 设 定 以 保 存 状 态信 息 。 创 建 Closure 对 象 的 序 列 随 接 收 器 类 型 不 同 有 所 不 同 。 在ClientRequestInterceptor 中 , 调 用 preinvoke_premarshal 之 前 会 创 建 一 个 新Closure (Java), 且 同 一 Closure (Java) 会 一 直 用 于 该 请 求 , 直 到 请 求 完 成 , 无 论使 用 4.x 接 收 器 21-13


同 时 使 用 可 移 植 和 4.x 接 收 器成 功 与 否 。 同 样 , 在 ServerInterceptor 中 , 调 用 preinvoke 之 前 也 会 创 建 一 个 新Closure (Java), 而 且 该 Closure (Java) 会 用 于 与 处 理 该 特 定 请 求 相 关 的 所 有 接收 器 。有 关 如 何 使 用 Closure (Java) 的 实 例 , 请 参 见 <strong>VisiBroker</strong> <strong>Edition</strong> 安 装 目 录 下examples 目 录 中 的 interceptors/client_server 目 录 。Closure (Java) 对 象 可 以 被 抛 投 到 ExtendedClosure (Java), 从 而 获 得response_expected 和 request_id, 如 下 所 示 :Java: int my response_expected =((ExtendedClosure)closure).reqInfo.response_expected;int my request_id = ((ExtendedClosure)closure) .reqInfo.request_id;同 时 使 用 可 移 植 和 4.x 接 收 器可 移 植 接 收 器 和 4.x 接 收 器 可 以 随 <strong>VisiBroker</strong> <strong>Edition</strong> ORB 同 时 安 装 。 但 是 , 由于 两 者 的 实 现 不 同 , 因 此 , 在 同 时 使 用 两 种 接 收 器 时 , 开 发 者 需 要 理 解 几 种 流 规 则和 限 制 。拦 截 点 调 用 的 顺 序拦 截 点 调 用 顺 序 遵 循 各 个 版 本 接 收 器 的 拦 截 点 排 序 规 则 , 而 不 管 实 际 上 开 发 者 是 否选 择 安 装 哪 个 版 本客 户 端 接 收 器可 移 植 和 <strong>VisiBroker</strong> 客 户 端 接 收 器 同 时 安 装 时 , 事 件 的 顺 序 ( 假 设 没 有 接 收 器 抛投 违 例 事 件 ) 如 下 :1 send_request ( 可 移 植 接 收 器 ), 其 后 是 preinvoke_premarshal (4.x 接 收 器 )2 构 建 请 求 信 息3 preinvoke_postmarshal (4.x 接 收 器 )4 发 出 请 求 信 息 并 等 待 回 答5 postinvoke (4.x 接 收 器 ), 其 后 是 received_reply/receive_exception/receive_other ( 可 移 植 接 收 器 ), 取 决 于 回 答 的 类 型 。服 务 器 端 接 收 器同 时 安 装 可 移 植 和 <strong>VisiBroker</strong> 服 务 器 端 接 收 器 时 , 收 到 ( 定 位 请 求 不 会 击 发 接 收器 , 这 与 <strong>VisiBroker</strong> 的 行 为 相 同 ) 的 事 件 顺 序 ( 假 设 没 有 接 收 器 抛 投 违 例 事 件 )如 下 :1 received_request_service_contexts ( 可 移 植 接 收 器 ), 其 后 是 preinvoke(4.x 接 收 器 )21-14 <strong>VisiBroker</strong> 开 发 者 指 南


2 servantLocator.preinvoke ( 如 果 使 用 服 务 对 象 定 位 器 的 话 )3 receive_request ( 可 移 植 接 收 器 )4 在 服 务 对 象 上 调 用 操 作5 postinvoke_premarshal (4.x 接 收 器 )6 servantLocator.postinvoke ( 如 果 使 用 服 务 对 象 定 位 器 的 话 )7 send_reply/send_exception/send_other, 取 决 于 请 求 的 结 果8 postinvoke_postmarshal (4.x 接 收 器 )POA 创 建 期 间 ORB 事 件 的 顺 序POA 创 建 期 间 ORB 事 件 的 顺 序 如 下 所 示 :1 根 据 支 持 POA 的 服 务 器 引 擎 的 资 料 创 建 IOR 模 板 。同 时 使 用 可 移 植 和 4.x 接 收 器2 调 用 4.x 接 收 器 POA 的 生 命 周 期 接 收 器 的 create() 方 法 。 此 方 法 可 能 会 添 加新 方 针 或 修 改 上 一 步 骤 创 建 的 IOR 模 板 。3 创 建 可 移 植 接 收 器 的 IORInfo 对 象 , 并 调 用 IORInterceptors 的establish_components() 方 法 。 此 拦 截 点 使 接 收 器 可 以 查 询 传 递 给create_POA() 和 上 一 步 骤 中 添 加 的 方 针 , 并 根 据 这 些 方 针 添 加 组 件 至 IOR 模板 。4 创 建 POA 的 对 象 引 用 工 厂 和 对 象 引 用 模 板 , 并 调 用 可 移 植 接 收 器 的IORInterceptors 的 components_established() 方 法 。 此 拦 截 点 使 接 收 器 可 以更 改 POA 的 将 用 于 生 产 对 象 引 用 的 对 象 引 用 工 厂 。对 象 引 用 创 建 期 间 ORB 事 件 的 顺 序在 对 POA 调 用 创 建 对 象 引 用 期 间 , 发 生 以 下 事 件 , 例 如 create_reference( ) 和create_reference_with_id( )。1 调 用 对 象 引 用 工 厂 的 make_object( ) 方 法 创 建 对 象 引 用 ( 这 一 过 程 不 调 用<strong>VisiBroker</strong> IOR 创 建 接 收 器 , 且 工 厂 可 以 由 用 户 提 供 )。 如 果 未 安 装<strong>VisiBroker</strong> IOR 创 建 接 收 器 , 此 对 象 引 用 应 该 是 返 回 到 应 用 程 序 的 对 象 引 用 ,否 则 , 请 继 续 步 骤 2。2 从 返 回 对 象 引 用 的 委 托 对 象 中 取 出 IOR, 并 调 用 <strong>VisiBroker</strong> IOR 创 建 接 收 器的 create( ) 方 法 。3 步 骤 2 中 取 出 的 IOR 作 为 引 用 对 象 被 返 回 给 create_reference( ) 和create_reference_with_id( ) 的 调 用 者 。使 用 4.x 接 收 器 21-15


21-16 <strong>VisiBroker</strong> 开 发 者 指 南


第章使 用 对 象 封 装 器第 22 章本 章 介 绍 <strong>VisiBroker</strong> <strong>Edition</strong> 对 象 封 装 器 的 功 能 , 该 功 能 可 让 应 用 得 到 通 知 或 为对 象 捕 获 操 作 请 求 。概 述注 :<strong>VisiBroker</strong> <strong>Edition</strong> 的 对 象 封 装 器 功 能 允 许 您 定 义 在 客 户 端 应 用 调 用 限 制 对 象 上的 方 法 或 服 务 器 应 用 收 到 操 作 请 求 时 被 调 用 的 方 法 。 与 接 收 器 功 能 不 同 , 接 收 器 是在 <strong>VisiBroker</strong> ORB 级 被 调 用 的 , 而 对 象 封 装 器 是 在 操 作 请 求 被 汇 集 之 前 被 调 用 。事 实 上 , 可 以 定 义 对 象 封 装 器 直 接 返 回 结 果 , 而 不 汇 集 、 在 网 络 上 发 送 或 真 正 向 对象 实 现 提 交 操 作 请 求 。对 象 封 装 器 可 以 只 在 客 户 端 安 装 、 服 务 器 端 安 装 , 也 可 以 同 时 在 一 个 应 用 的 客 户 和服 务 器 部 分 安 装 。以 下 为 如 何 在 应 用 中 使 用 对 象 封 装 器 的 几 个 实 例 :● 记 录 有 关 客 户 发 出 或 服 务 器 收 到 的 操 作 请 求 的 信 息 。● 计 算 完 成 操 作 请 求 所 需 的 时 间 。● 缓 存 常 用 操 作 请 求 的 结 果 , 以 便 立 即 返 回 结 果 , 而 无 需 每 次 真 正 与 对 象 实 现通 讯 。如 果 接 收 对 象 是 不 同 的 进 程 , 使 用 <strong>VisiBroker</strong> ORB 对 象 的 object_to_string 方 法来 实 例 化 所 安 装 对 象 封 装 器 针 对 的 对 象 的 引 用 并 不 会 将 这 些 封 装 器 传 播 给 字 符 串 化引 用 的 接 收 对 象 。使 用 对 象 封 装 器 22-1


非 型 别 对 象 封 装 器型 别 和 非 型 别 对 象 封 装 器<strong>VisiBroker</strong> <strong>Edition</strong> 提 供 两 种 对 象 封 装 器 : 型 别 和 非 型 别 。 您 可 以 在 一 个 应 用 中混 合 使 用 两 类 封 装 器 。 有 关 型 别 封 装 器 的 信 息 , 请 参 阅 第 22-11 页 " 型 别 对 象 封 装器 "。 下 表 摘 要 介 绍 这 两 类 对 象 封 装 器 的 重 要 区 别 。表 22.1型 别 和 非 型 别 对 象 封 装 器 的 功 能 比 较功 能 型 别 非 型 别接 收 要 传 递 到 存 根 的 所 有 变 是否量 。可 以 向 调 用 者 返 回 控 制 , 而 实际 上 并 不 调 用 下 一 个 封 装 器 、存 根 或 对 象 实 现 。是否对 所 有 对 象 发 出 所 有 操 作 请 求时 均 被 调 用 。否是idl2cpp 特 别 要 求C++:无 论 何 时 要 使 用 型 别 或 非 型 别 对 象 封 装 器 时 , 必 须 保 证 在 生 成 应 用 代 码 时 使 用idl2cpp 编 译 器 的 -obj_wrapper 选 项 。这 样 可 以 为 每 个 接 口 均 生 成 对 象 封 装 器 基 类 。idl2java 特 别 要 求Java:无 论 何 时 要 使 用 型 别 或 非 型 别 对 象 封 装 器 时 , 必 须 保 证 在 生 成 应 用 代 码 时 使 用iidl2java 编 译 器 的 -obj_wrapper 选 项 。 这 样 可 以 生 成● 每 个 接 口 的 对 象 封 装 器 基 类● 用 于 添 加 或 删 除 对 象 封 装 器 的 其 它 Helper 类 方 法实 例 应 用examples/interceptors/objectWrappers 目 录 包 含 三 个 客 户 端 和 服 务 器 应 用 实 例 ,这 些 实 例 将 用 于 在 本 章 中 说 明 型 别 和 非 型 别 对 象 封 装 器 的 概 念 。非 型 别 对 象 封 装 器非 型 别 对 象 封 装 器 允 许 您 定 义 要 在 处 理 操 作 请 求 之 前 、 之 后 或 之 前 和 之 后 调 用 的 方法 。 非 型 别 封 装 器 可 以 安 装 用 于 客 户 端 或 服 务 器 应 用 , 也 可 以 安 装 多 个 版 本 。也 可 以 在 同 一 客 户 端 或 服 务 器 应 用 中 混 合 使 用 型 别 和 非 型 别 对 象 封 装 器 。在 默 认 情 况 下 , 非 型 别 对 象 封 装 器 具 有 全 局 作 用 域 , 发 生 任 何 操 作 请 求 时 均 会 被 调用 。 您 可 以 定 义 非 型 别 封 装 器 , 向 自 己 不 感 兴 趣 的 对 象 类 型 发 出 操 作 请 求 时 , 这 类封 装 器 不 起 作 用 。22-2 <strong>VisiBroker</strong> 开 发 者 指 南


非 型 别 对 象 封 装 器注 : 与 型 别 对 象 封 装 器 不 同 , 非 型 别 封 装 器 方 法 不 接 收 存 根 或 对 象 实 现 会 收 到 的 变 量 ,也 不 能 阻 止 存 根 或 对 象 实 现 的 调 用 。下 图 示 范 在 客 户 端 清 除 方 法 之 前 非 型 别 对 象 封 装 器 的 pre_method 如 何 被 调 用 以 及其 后 post_method 如 何 被 调 用 。 同 时 列 出 了 服 务 器 端 与 对 象 实 现 有 关 的 调 用 顺 序 。图 22.1单 个 非 型 别 对 象 封 装 器使 用 多 个 型 别 和 非 型 别 对 象 封 装 器图 22.2多 个 非 型 别 对 象 封 装 器pre_method 调 用 的 顺 序客 户 端 调 用 某 限 制 对 象 上 的 方 法 时 , 调 用 客 户 端 的 存 根 例 程 之 前 每 个 非 型 别 对 象 封装 器 pre_method 均 会 收 到 控 制 。 服 务 器 收 到 操 作 请 求 后 , 对 象 实 现 收 到 控 制 之 前使 用 对 象 封 装 器 22-3


使 用 非 型 别 对 象 封 装 器每 个 非 型 别 对 象 封 装 器 pre_method 均 会 被 调 用 。 在 两 种 情 况 下 , 第 一 个 收 到 控 制的 pre_method 将 是 第 一 个 注 册 的 对 象 封 装 器 的 pre_method。post_method 调 用 的 顺 序注 :服 务 器 的 对 象 实 现 完 成 其 处 理 后 , 在 回 答 发 送 到 客 户 端 之 前 每 个 post_method 均 会被 调 用 。 客 户 端 收 到 某 操 作 请 求 的 回 答 后 , 在 控 制 返 回 到 客 户 端 之 前 每 个post_method 均 会 被 调 用 。 在 两 种 情 况 下 , 第 一 个 收 到 控 制 的 post_method 将 是最 后 一 个 注 册 的 对 象 封 装 器 的 post_method。如 果 同 时 使 用 型 别 和 非 型 别 对 象 封 装 器 , 请 参 阅 第 22-18 页 " 混 合 使 用 非 型 别 和 型别 对 象 封 装 器 ", 以 取 得 有 关 调 用 顺 序 的 信 息 。使 用 非 型 别 对 象 封 装 器C++:使 用 非 型 别 对 象 封 装 器 时 , 一 定 要 遵 循 下 列 步 骤 。 以 下 说 明 是 按 照 每 个 步 骤 的 先 后顺 序 列 出 的 。1 确 定 您 要 为 其 创 建 非 型 别 对 象 封 装 器 的 接 口 。2 使 用 以 下 编 译 器 从 IDL 规 范 生 成 代 码 :● idl2cpp , 带 -obj_wrapper 选 项Java: ● idl2java , 带 -obj_wrapper 选 项 。C++:Java:C++:Java:3 为 非 型 别 对 象 封 装 器 工 厂 创 建 实 现 , 实 现 从 以 下 类 派 生 :● VISObjectWrapper::UntypedObjectWrapperFactory● UntypedObjectWrapperFactory4 为 非 型 别 对 象 封 装 器 创 建 实 现 , 实 现 从 以 下 类 派 生 :● VISObjectWrapper::UntypedObjectWrapper● UntypedObjectWrapper仅 适 用 于 Java: 5 修 改 客 户 端 或 服 务 器 应 用 以 存 取 相 应 类 型 的ChainUntypedObjectWrapperFactory。6 修 改 应 用 以 创 建 非 型 别 对 象 封 装 器 工 厂 。仅 适 用 于 Java: 7 使 用 ChainUntypedObjectWrapperFactory 的 add 方 法 添 加 工 厂 到 链 。实 现 非 型 别 对 象 封 装 器 工 厂C++:Java:TimeWrap.h 文 件 (ObjectWrappers 应 用 样 本 的 一 部 分 ) 说 明 了 如 何 定 义 从VISObjectWrapper::UntypedObjectWrapperFactory 派 生 的 非 型 别 对 象 封 装 器 工 厂 。TimingUnTypedObjectWrapperFactory 的 实 现 (ObjectWrappers 应 用 样 本 的 一 部分 ) 示 范 了 如 何 定 义 从 TimingUnTypedObjectWrapperFactory 派 生 的 非 型 别 对 象 封装 器 工 厂 。22-4 <strong>VisiBroker</strong> 开 发 者 指 南


使 用 非 型 别 对 象 封 装 器C++:无 论 何 时 客 户 端 限 制 到 对 象 或 服 务 器 调 用 对 象 实 现 上 的 方 法 时 , 工 厂 的 create 方法 均 会 被 调 用 来 创 建 非 型 别 对 象 封 装 器 。 create 方 法 收 到 目 标 对 象 , 这 样 就 可 以定 义 工 厂 , 使 其 不 为 那 些 要 忽 略 的 对 象 类 型 创 建 非 型 别 对 象 封 装 器 。 方 法 还 收 到 一个 enum, 指 定 对 象 封 装 器 是 为 服 务 器 端 对 象 实 现 创 建 的 , 还 是 为 客 户 端 对 象 创建 的 。以 下 代 码 示 例 为 TimingObjectWrapperFactory, 它 用 于 创 建 显 示 方 法 调 用 实 时 信 息的 非 型 别 对 象 封 装 器 。 注 意 :TimingObjectWrapperFactory 构 建 器 增 加 了 key 参数 。 该 参 数 也 被 服 务 初 始 化 器 用 于 识 别 封 装 器 。class TimingObjectWrapperFactory: public VISObjectWrapper::UntypedObjectWrapperFactory{public:TimingObjectWrapperFactory(VISObjectWrapper::Location loc,const char* key): VISObjectWrapper::UntypedObjectWrapperFactory(loc),_key(key) {}// ObjectWrapperFactory 操 作VISObjectWrapper::UntypedObjectWrapper_ptr create(CORBA::Object_ptr target,VISObjectWrapper::Location loc) {if (_owrap == NULL) {_owrap = new TimingObjectWrapper(_key);}return VISObjectWrapper::UntypedObjectWrapper::_duplicate(_owrap);}private:CORBA::String_var _key;VISObjectWrapper::UntypedObjectWrapper_var _owrap;};Java:以 下 代 码 示 例 为 TimingObjectWrapperFactory 的 实 例 , 它 用 于 创 建 显 示 方 法 调 用 实时 信 息 的 非 型 别 对 象 封 装 器 。package UtilityObjectWrappers;import com.inprise.vbroker.interceptor.*;public class TimingUntypedObjectWrapperFactory implementsUntypedObjectWrapperFactory {public UntypedObjectWrapper create(org.omg.CORBA.Object target,com.inprise.vbroker.interceptor.Location loc) {return new TimingUntypedObjectWrapper();}}实 现 非 型 别 对 象 封 装 器C++: 以 下 代 码 示 例 示 范 TimingObjectWrapper 的 实 现 , 在 TimeWrap.h 档 案 中 也 有 定 义 。非 型 别 封 装 器 必 须 从 VISObjectWrapper::UntypedObjectWrapper 类 派 生 , 您 可 以 在非 型 别 对 象 封 装 器 中 同 时 为 pre_method 和 post_method 方 法 提 供 实 现 。通 过 工 厂 的 构 建 器 自 动 安 装 或 通 过 调 用VISObjectWrapper::ChainUntypedObjectWrapper::add 方 法 手 动 安 装 了 工 厂 后 , 无 论使 用 对 象 封 装 器 22-5


使 用 非 型 别 对 象 封 装 器何 时 客 户 限 制 到 对 象 或 服 务 器 调 用 对 象 实 现 上 的 方 法 时 均 会 自 动 创 建 非 型 别 对 象 封装 器 。以 下 代 码 示 例 中 所 示 的 pre_method 调 用 了 TimerBegin 方 法 ( 在 TimeWrap.C 中 定义 ), 该 方 法 使 用 Closure 对 象 以 保 存 当 前 时 间 。 同 样 , post_method 调 用TimerDelta 方 法 以 确 定 自 pre_method 被 调 用 和 打 印 以 来 所 经 过 时 间 。C++: class TimingObjectWrapper :public VISObjectWrapper::UntypedObjectWrapper {public:TimingObjectWrapper(const char* key=NULL) :_key(key) {}void pre_method(const char* operation,CORBA::Object_ptr target,VISClosure& closure) {cout


仅 适 用 于 C++:C++:使 用 非 型 别 对 象 封 装 器Closure closure) {System.out.println("Timing: " +((com.inprise.vbroker.CORBA.Object) target)._object_name() + "->"+ operation + "()");time = System.currentTimeMillis();}public void post_method(String operation,org.omg.CORBA.Object target,org.omg.CORBA.Environment env,Closure closure) {long diff = System.currentTimeMillis() - time;System.out.println("Timing:Time for call \t" +((com.inprise.vbroker.CORBA.Object)target)._object_name() + "->" + operation + "() = " + diff + " ms.");}}pre_method 和 post_method 参 数pre_method 和 post_method 都 会 收 到 下 表 所 示 参 数 。表 22.2参 数pre_method 和 post_method 方 法 的 普 通 变 量说 明operation 目 标 对 象 上 要 求 的 操 作 名 称 。target 目 标 对 象 。closure在 调 用 方 法 期 间 可 以 为 此 封 装 器 保 存 数 据 的 区域 。post_method 也 会 收 到 一 个 Environment 参 数 , 该 参 数 可 用 于 通 知 用 户 在 方 法 调 用的 上 一 步 骤 期 间 可 能 发 生 的 任 何 违 例 现 象 。创 建 和 注 册 非 型 别 对 象 封 装 器 工 厂无 论 何 时 使 用 接 受 定 位 的 基 类 构 建 器 创 建 非 型 别 对 象 封 装 器 工 厂 时 , 该 封 装 器 工 厂均 会 自 动 被 添 加 到 非 型 别 封 装 器 链 上 。在 客 户 端 , 只 有 在 对 象 被 限 制 之 前 创 建 和 注 册 非 型 别 对 象 封 装 器 , 才 会 封 装 对 象 。在 服 务 器 端 , 非 型 别 对 象 封 装 器 工 厂 是 在 对 象 实 现 被 调 用 之 前 创 建 和 注 册 的 。以 下 代 码 示 例 为 样 本 文 件 UntypedClient.C 的 一 部 分 , 其 中 示 范 了 为 某 客 户 端 创 建( 自 动 注 册 ) 两 个 非 型 别 对 象 封 装 器 工 厂 的 过 程 。 这 些 工 厂 是 在 <strong>VisiBroker</strong> ORB被 初 始 化 之 后 、 客 户 端 限 制 到 对 象 之 前 创 建 的 。C++: int main(int argc, char* const* argv) {try {// 初 始 化 ORB。CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);// 安 装 非 型 别 对 象 封 装 器TimingObjectWrapperFactory timingfact(VISObjectWrapper::Client,"timeclient");TraceObjectWrapperFactory tracingfact(VISObjectWrapper::Client,使 用 对 象 封 装 器 22-7


使 用 非 型 别 对 象 封 装 器Java:Java:C++:"traceclient"};// 现 在 找 到 一 个 帐 户 管 理 器 。. . .]以 下 代 码 示 例 为 样 本 文 件 UntypedClient.java 的 一 部 分 , 其 中 示 范 了 为 某 客 户 端创 建 和 安 装 两 个 非 型 别 对 象 封 装 器 工 厂 的 过 程 。 这 些 工 厂 是 在 <strong>VisiBroker</strong> ORB 被初 始 化 之 后 、 客 户 端 限 制 到 对 象 之 前 创 建 的 。// UntypedClient.javaimport com.inprise.vbroker.interceptor.*;public class UntypedClient {public static void main(String[] args) throws Exception {// 初 始 化 ORB。org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);doMain (orb, args);}public static void doMain(org.omg.CORBA.ORB orb, String[] args) throwsException {ChainUntypedObjectWrapperFactory Cfactory =ChainUntypedObjectWrapperFactoryHelper.narrow(orb.resolve_initial_references("ChainUntypedObjectWrapperFactory"));Cfactory.add(new UtilityObjectWrappers.TimingUntypedObjectWrapperFactory(),Location.CLIENT);Cfactory.add(newUtilityObjectWrappers.TracingUntypedObjectWrapperFactory(),Location.CLIENT);// 找 到 一 个 帐 户 管 理 器 。 . . .}}以 下 代 码 示 例 所 示 为 样 本 文 件 UntypedServer.C, 其 中 示 范 了 为 某 服 务 器 创 建 和 注册 非 型 别 对 象 封 装 器 工 厂 的 过 程 。 这 些 工 厂 是 在 <strong>VisiBroker</strong> ORB 被 初 始 化 之 后 、创 建 对 象 实 现 之 前 创 建 的 。C++:// UntypedServer.C#include "Bank_s.hh"#include "BankImpl.h"#include "TimeWrap.h"#include "TraceWrap.h"USE_STD_NSint main(int argc, char* const* argv) {try {// 初 始 化 ORB。CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);// 初 始 化 POA。CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");PortableServer::POA_var rootPoa = PortableServer::POA::_narrow(obj);CORBA::PolicyList policies;policies.length(1);policies[(CORBA::ULong)0] = rootPoa->create_lifespan_policy(PortableServer::PERSISTENT};// 得 到 POA 管 理 器 。PortableServer::POAManager_var poa_manager = rootPoa->the_POAManager();22-8 <strong>VisiBroker</strong> 开 发 者 指 南


使 用 非 型 别 对 象 封 装 器Java:Java:// 用 正 确 的 策 略 创 建 myPOA。PortableServer::POA_var myPOA = rootPoa->create_POA("bank_ow_poa",poa_manager,policies);// 为 帐 户 管 理 器 安 装 非 型 别 对 象 封 装 器 。TimingObjectWrapperFactory timingfact(VISObjectWrapper::Server,"timingserver");TraceObjectWrapperFactory tracingfact(VISObjectWrapper::Server,"traceserver");// 创 建 帐 户 管 理 器 服 务 对 象 。AccountManagerImpl managerServant;// 确 定 服 务 对 象 ID。PortableServer::ObjectId_var managerId =PortableServer::string_to_ObjectId("BankManager");// 用 myPOA 上 的 ID 激 活 服 务 对 象 。myPOA->activate_object_with_id(managerId, &managerServant);// 激 活 POA 管 理 器 。rootPoa->the_POAManager()->activate();cout


使 用 非 型 别 对 象 封 装 器org.omg.CORBA.Policy bsPolicy =orb.create_policy(BIND_SUPPORT_POLICY_TYPE.value, any);// 为 持 久 testPOA 创 建 策 略org.omg.CORBA.Policy[] policies = {rootPOA.create_lifespan_policy(LifespanPolicyValue.PERSISTENT), bsPolicy};// 用 正 确 的 策 略 创 建 myPOAPOA myPOA = rootPOA.create_POA( "bank_agent_poa",rootPOA.the_POAManager(),policies);// 创 建 帐 户 管 理 器 对 象 。AccountManagerImpl managerServant = new AccountManagerImpl();// 确 定 服 务 对 象 IDbyte[] managerId = "BankManager".getBytes();// 用 myPOA 上 的 ID 激 活 服 务 对 象myPOA.activate_object_with_id(managerId, managerServant);// 激 活 POA 管 理 器rootPOA.the_POAManager().activate();System.out.println("AccountManager:BankManager is ready.");for( int i = 0; i < args.length; i++ ) {if( args[i].equalsIgnoreCase("-runCoLocated") ) {if( args[i+1].equalsIgnoreCase("Client") ){Client.doMain(orb, new String[0]);} else if( args[i+1].equalsIgnoreCase("TypedClient") ){TypedClient.doMain(orb, new String[0]);}if( args[i+1].equalsIgnoreCase("UntypedClient") ){UntypedClient.doMain(orb, new String[0]);}System.exit(1);}}// 等 待 进 入 的 请 求orb.run();}}删 除 非 型 别 对 象 封 装 器注 :C++ 中 VISObjectWrapper::ChainUntypedObjectWrapperFactory 类 的 remove 方 法或 Java 中 ChainUntypedObjectWrapperFactory 类 的 remove 方 法 可 用 于 从 客 户 端 或服 务 器 应 用 中 删 除 非 型 别 对 象 封 装 器 。 删 除 工 厂 时 必 须 指 定 位 置 。 也 就 是 说 , 如 果已 经 通 过 C++ 下 的 VISObjectWrapper::Both 或 Java 下 的 Both 定 位 添 加 工 厂 ,则 可 以 有 选 择 地 从 Client 位 置 、 Server 位 置 或 Both 删 除 它 。从 某 客 户 端 删 除 一 个 或 多 个 对 象 封 装 器 工 厂 不 会 影 响 客 户 端 已 经 限 制 的 该 类 的 对象 。 只 有 随 后 限 制 的 对 象 会 受 到 影 响 。 从 某 服 务 器 删 除 对 象 封 装 器 工 厂 不 会 影 响 已经 创 建 的 对 象 实 现 。 只 有 随 后 创 建 的 对 象 实 现 会 受 到 影 响 。22-10 <strong>VisiBroker</strong> 开 发 者 指 南


型 别 对 象 封 装 器型 别 对 象 封 装 器为 某 特 定 类 实 现 型 别 对 象 封 装 器 时 , 可 定 义 在 限 制 对 象 上 方 法 被 调 用 时 要 发 生 的 处理 过 程 。 下 图 示 范 了 客 户 端 上 的 对 象 封 装 器 方 法 是 如 何 在 客 户 端 存 根 类 方 法 之 前 被调 用 的 以 及 服 务 器 端 上 的 对 象 封 装 器 是 如 何 在 服 务 器 的 实 现 方 法 之 前 被 调 用 的 。注 : 实 现 封 装 器 正 在 封 装 的 对 象 所 提 供 的 所 有 方 法 时 不 需 要 型 别 对 象 封 装 器 实 现 。也 可 以 在 同 一 客 户 端 或 服 务 器 应 用 中 混 合 使 用 型 别 和 非 型 别 对 象 封 装 器 。 有 关 详情 , 请 参 阅 第 22-18 页 " 混 合 使 用 非 型 别 和 型 别 对 象 封 装 器 "。图 22.3注 册 单 个 型 别 对 象 封 装 器使 用 多 个 型 别 对 象 封 装 器您 可 以 为 对 象 的 某 一 特 定 类 实 现 并 注 册 多 个 型 别 对 象 封 装 器 , 如 下 图 所 示 。 在 客 户端 , 第 一 个 注 册 的 对 象 封 装 器 是 client_wrapper_1, 因 此 其 方 法 将 第 一 个 收 到 控制 。 执 行 其 处 理 后 , client_wrapper_1 方 法 可 以 将 控 制 传 递 给 链 中 的 下 一 个 对 象 的方 法 , 或 者 也 可 以 将 控 制 返 回 给 客 户 端 。 在 服 务 器 端 , 第 一 个 注 册 的 对 象 封 装 器 是server_wrapper_1, 因 此 其 方 法 将 第 一 个 收 到 控 制 。 执 行 其 处 理 后 ,server_wrapper_1 方 法 可 以 将 控 制 传 递 给 链 中 的 下 一 个 对 象 的 方 法 , 或 者 也 可 以 将控 制 返 回 给 服 务 对 象 。使 用 对 象 封 装 器 22-11


型 别 对 象 封 装 器图 22.4注 册 多 个 型 别 对 象 封 装 器调 用 的 顺 序为 某 特 定 类 注 册 的 型 别 对 象 封 装 器 的 方 法 将 收 到 正 常 情 况 下 传 递 给 客 户 端 上 存 根 方法 或 服 务 器 端 上 框 架 的 所 有 变 量 。 通 过 调 用 父 类 的 方 法 (C++ 中 为ObjectWrapper:: 或 Java 中 为super. ), 每 个 对 象 封 装 器 方 法 可 以 将 控 制 传 递 给 链 中 的 下 一 个 封装 器 方 法 。 如 果 某 对 象 封 装 器 要 返 回 控 制 而 不 调 用 链 中 的 下 一 个 封 装 器 方 法 , 它 可以 通 过 return 返 回 适 当 的 返 回 值 。由 于 型 别 对 象 封 装 器 能 够 将 控 制 返 回 给 上 一 个 方 法 , 因 此 您 可 以 创 建 永 不 调 用 客 户端 存 根 或 对 象 实 现 的 封 装 器 方 法 。 例 如 , 可 以 创 建 一 个 缓 存 常 用 操 作 的 结 果 的 对 象封 装 器 方 法 。 在 这 种 情 况 下 , 第 一 次 调 用 限 制 的 对 象 上 的 方 法 时 , 会 有 操 作 请 求 被发 送 到 对 象 实 现 。 当 控 制 通 过 对 象 封 装 器 方 法 流 回 时 , 结 果 会 被 储 存 起 来 。 随 后 再调 用 同 一 方 法 时 , 对 象 封 装 器 方 法 只 需 返 回 储 存 在 缓 存 内 的 结 果 , 而 无 需 真 正 向 对象 实 现 发 出 操 作 请 求 。如 果 同 时 使 用 型 别 和 非 型 别 对 象 封 装 器 , 请 参 阅 第 22-18 页 " 混 合 使 用 非 型 别 和 型别 对 象 封 装 器 ", 以 取 得 有 关 调 用 顺 序 的 信 息 。客 户 端 和 服 务 器 共 存 时 的 型 别 对 象 封 装 器客 户 端 和 服 务 器 同 时 封 装 在 同 一 进 程 中 时 , 第 一 个 收 到 控 制 的 对 象 封 装 器 方 法 将 属于 所 安 装 的 第 一 个 客 户 端 对 象 封 装 器 。 下 图 所 示 为 调 用 的 顺 序 。22-12 <strong>VisiBroker</strong> 开 发 者 指 南


使 用 型 别 对 象 封 装 器图 22.5型 别 对 象 封 装 器 的 调 用 顺 序使 用 型 别 对 象 封 装 器使 用 型 别 对 象 封 装 器 时 , 一 定 要 遵 循 下 列 步 骤 。 以 下 说 明 是 按 照 每 个 步 骤 的 先 后 顺序 列 出 的 。C++:Java:1 确 定 您 要 为 其 创 建 型 别 对 象 封 装 器 的 接 口 。2 使 用 以 下 编 译 器 ( 带 -obj_wrapper) 从 IDL 规 范 生 成 代 码 :● idl2cpp● idl2java3 从 C++ idl2cpp 编 译 器 或 Java idl2java 编 译 器 生 成 的ObjectWrapper 类 派 生 型 别 对 象 封 装 器 类 , 并 提 供 一 个 那 些 要封 装 的 方 法 的 对 象 实 现 。4 修 改 应 用 以 注 册 型 别 对 象 封 装 器 。实 现 型 别 对 象 封 装 器C++:Java:您 可 以 从 C++ idl2cpp 编 译 器 或 Java idl2java 编 译 器 生 成 的ObjectWrapper 类 派 生 型 别 对 象 封 装 器 。以 下 代 码 示 例 示 范 了 从 C++ 下 的 文 件 BankWrap.h 为 Account 接 口 实 现 型 别 对 象 封装 器 。注 意 , 该 类 是 从 AccountObjectWrapper 接 口 派 生 的 , 它 提 供 一 种 简 单 的 对 balance方 法 的 缓 存 实 现 , 该 实 现 提 供 以 下 处 理 步 骤 :1 请 检 查 以 下 标 志 , 判 断 该 方 法 是 否 曾 被 调 用 :● _inited flag;● _initialized2 如 果 这 是 第 一 次 调 用 , 则 会 调 用 链 中 下 一 个 对 象 上 的 balance 方 法 、 将 结 果 存 储到 _balance 中 、 将 C++ _inited 标 志 或 Java _initialized 标 志 设 置 为 true 并返 回 值 。3 如 果 该 方 法 曾 被 调 用 , 只 需 返 回 保 存 在 缓 存 内 的 值 。使 用 对 象 封 装 器 22-13


使 用 型 别 对 象 封 装 器C++: class CachingAccountObjectWrapper :public Bank::AccountObjectWrapper {public:CachingAccountObjectWrapper() :_inited((CORBA::Boolean)0) {}CORBA::Float balance() {cout


使 用 型 别 对 象 封 装 器// 初 始 化 ORB。CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);// 为 帐 户 安 装 型 别 对 象 封 装 器 。Bank::AccountObjectWrapper::add(orb,CachingAccountObjectWrapper::factory,VISObjectWrapper::Client);Java:Java:// 得 到 管 理 器 ID。PortableServer::ObjectId_var managerId =PortableServer::string_to_ObjectId("BankManager");// 找 到 一 个 帐 户 管 理 器 。Bank::AccountManager_var manager =Bank::AccountManager::_bind("/bank_ow_poa", managerId);. . .客 户 端 上 的 型 别 对 象 封 装 器 是 通 过 调 用 idl2java 编 译 器 为 类 生 成 的 Java 下 的addClientObjectWrapperClass 方 法 注 册 的 。 客 户 端 的 对 象 封 装 器 必 须 在 调 用ORB.init 方 法 之 后 、 限 制 任 何 对 象 之 前 注 册 。 以 下 代 码 示 例 所 示 为 创 建 和 注 册 型 别对 象 封 装 器 的 TypedClient.java 文 件 的 一 部 分 。// TypedClient.javaimport com.inprise.vbroker.interceptor.*;public class TypedClient {public static void main(String[] args) throws Exception {// 初 始 化 ORB。org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);doMain (orb, args);}public static void doMain(org.omg.CORBA.ORB orb, String[] args) {// 为 帐 户 对 象 添 加 型 别 对 象 封 装 器Bank.AccountHelper.addClientObjectWrapperClass(orb,BankWrappers.CachingAccountObjectWrapper.class);// 找 到 一 个 帐 户 管 理 器 。Bank.AccountManager manager =Bank.AccountManagerHelper.bind(orb, "BankManager");. . .}}<strong>VisiBroker</strong> ORB 会 跟 踪 在 客 户 端 为 其 注 册 的 任 何 对 象 封 装 器 。 客 户 端 调 用 _bind方 法 限 制 该 类 型 的 对 象 时 , <strong>VisiBroker</strong> 将 创 建 必 要 的 对 象 封 装 器 。 如 果 客 户 端 限制 到 对 象 的 特 定 类 的 多 个 实 例 , 则 每 个 实 例 将 具 有 自 己 的 一 组 封 装 器 。为 服 务 器 注 册 型 别 对 象 封 装 器C++:C++:正 如 客 户 端 应 用 , 服 务 器 端 上 的 型 别 对 象 封 装 器 是 通 过 调 用::add 方 法 注 册 的 。 服 务 器 端 的 型 别 对 象 封 装 器 必 须 在 调 用ORB_init 方 法 之 后 、 对 象 实 现 处 理 请 求 之 前 注 册 。 以 下 代 码 示 例 所 示 为 安 装 型 别对 象 封 装 器 的 TypedServer.C 文 件 的 一 部 分 。// TypedServer.C#include "Bank_s.hh"使 用 对 象 封 装 器 22-15


使 用 型 别 对 象 封 装 器Java:Java:#include "BankImpl.h"#include "BankWrap.h"USE_STD_NSint main(int argc, char* const* argv) {try {// 初 始 化 ORB。CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);// 初 始 化 POA。CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");PortableServer::POA_var rootPoa = PortableServer::POA::_narrow(obj);CORBA::PolicyList policies;policies.length(1);policies[(CORBA::ULong)0] = rootPoa->create_lifespan_policy(PortableServer::PERSISTENT);// 得 到 POA 管 理 器 。PortableServer::POAManager_var poa_manager = rootPoa->the_POAManager();// 用 正 确 的 策 略 创 建 myPOA。PortableServer::POA_var myPOA = rootPoa->create_POA("bank_ow_poa",poa_manager,policies);// 为 帐 户 管 理 器 安 装 型 别 对 象 封 装 器 。Bank::AccountManagerObjectWrapper::add(orb,SecureAccountManagerObjectWrapper::factory,VISObjectWrapper::Server);Bank::AccountManagerObjectWrapper::add(orb,CachingAccountManagerObjectWrapper::factory,VISObjectWrapper::Server);// 创 建 帐 户 管 理 器 服 务 对 象 。AccountManagerImpl managerServant;// 确 定 服 务 对 象 ID。PortableServer::ObjectId_var managerId =PortableServer::string_to_ObjectId("BankManager");// 用 myPOA 上 的 ID 激 活 服 务 对 象 。myPOA->activate_object_with_id(managerId, &managerServant);// 激 活 POA 管 理 器 。rootPoa->the_POAManager()->activate();cout


使 用 型 别 对 象 封 装 器import com.inprise.vbroker.PortableServerExt.BIND_SUPPORT_POLICY_TYPE;public class TypedServer {public static void main(String[] args) throws Exception {// 初 始 化 ORB。org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);// 为 帐 户 管 理 器 对 象 添 加 两 个 型 别 对 象 封 装 器Bank.AccountManagerHelper.addServerObjectWrapperClass(orb,BankWrappers.SecureAccountManagerObjectWrapper.class);Bank.AccountManagerHelper.addServerObjectWrapperClass(orb,BankWrappers.CachingAccountManagerObjectWrapper.class);// 取 得 根 POA 的 引 用POA rootPOA =POAHelper.narrow(orb.resolve_initial_references("RootPOA"));// 创 建 BindSupport 策 略 , 该 策 略 使 POA 将 每 个 服 务 对 象 注 册// 在 osagent 上org.omg.CORBA.Any any = orb.create_any();BindSupportPolicyValueHelper.insert(any,BindSupportPolicyValue.BY_INSTANCE);org.omg.CORBA.Policy bsPolicy =orb.create_policy(BIND_SUPPORT_POLICY_TYPE.value, any);// 为 持 久 testPOA 创 建 策 略org.omg.CORBA.Policy[] policies = {rootPOA.create_lifespan_policy(LifespanPolicyValue.PERSISTENT),bsPolicy};// 用 正 确 的 策 略 创 建 myPOAPOA myPOA = rootPOA.create_POA( "lilo", rootPOA.the_POAManager(),policies);// 创 建 帐 户 管 理 器 对 象 。AccountManagerImpl managerServant = new AccountManagerImpl();// 确 定 服 务 对 象 IDbyte[] managerId = "BankManager".getBytes();// 用 myPOA 上 的 ID 激 活 服 务 对 象myPOA.activate_object_with_id(managerId, managerServant);// 激 活 POA 管 理 器rootPOA.the_POAManager().activate();System.out.println("AccountManager:BankManager is ready.");for( int i = 0; i < args.length; i++ ) {if ( args[i].equalsIgnoreCase("-runCoLocated") ) {if( args[i+1].equalsIgnoreCase("Client") ){Client.doMain(orb, new String[0]);} else if( args[i+1].equalsIgnoreCase("TypedClient") ){TypedClient.doMain(orb, new String[0]);}if( args[i+1].equalsIgnoreCase("UntypedClient") ){UntypedClient.doMain(orb, new String[0]);}System.exit(1);}}// 等 待 进 入 的 请 求orb.run();使 用 对 象 封 装 器 22-17


混 合 使 用 非 型 别 和 型 别 对 象 封 装 器}}如 果 服 务 器 针 对 对 象 的 某 特 定 类 创 建 多 个 实 例 , 则 <strong>VisiBroker</strong> 会 为 每 个 实 例 创 建一 组 封 装 器 。删 除 型 别 对 象 封 装 器C++:idl2cpp 编 译 器 为 类 生 成 的 ObjectWrapper::remove 方 法 允 许 您 从客 户 端 或 服 务 器 应 用 中 删 除 型 别 对 象 封 装 器 。 删 除 工 厂 时 必 须 指 定 位 置 。 也 就 是说 , 如 果 已 经 通 过 VISObjectWrapper::Both 定 位 添 加 工 厂 , 可 以 有 选 择 地 从Client 位 置 、 Server 位 置 或 Both 删 除 它 。Java: Helper 类 也 提 供 从 客 户 端 或 服 务 器 应 用 中 删 除 型 别 对 象 封 装 器 的 方 法 。 有 关 详 情 ,请 参 阅 程 序 员 参 考 。注 :从 某 客 户 端 删 除 一 个 或 多 个 对 象 封 装 器 不 会 影 响 客 户 端 已 经 限 制 的 该 类 的 对 象 。 只有 随 后 限 制 的 对 象 会 受 到 影 响 。 从 某 服 务 器 删 除 对 象 封 装 器 不 会 影 响 已 经 处 理 请 求的 对 象 实 现 。 只 有 随 后 创 建 的 对 象 实 现 会 受 到 影 响 。混 合 使 用 非 型 别 和 型 别 对 象 封 装 器如 果 选 择 在 自 己 的 应 用 中 同 时 使 用 型 别 和 非 型 别 对 象 封 装 器 , 则 为 非 型 别 封 装 器 定义 的 pre_method 方 法 将 在 为 对 象 定 义 的 任 何 型 别 对 象 封 装 器 方 法 之 前 被 调 用 。 返回 之 前 , 所 有 为 对 象 定 义 的 型 别 对 象 封 装 器 方 法 将 在 为 非 型 别 封 装 器 定 义 的 任 何post_method 方 法 之 前 被 调 用 。C++ 下 的 Client.C 和 Server.C 或 Java 下 的 Client.java 和 Server.java 样 本应 用 设 计 精 巧 , 它 允 许 您 通 过 命 令 行 属 性 指 定 要 使 用 的 型 别 和 非 型 别 对 象 封 装 器( 如 果 有 )。用 于 型 别 封 装 器 的 命 令 行 变 量C++:下 表 所 示 命 令 行 变 量 可 用 于 为 Client.C 和 Server.C 中 实 现 的 样 本 库 应 用 启 用 型 别对 象 封 装 器 。表 22.3用 于 有 控 制 型 别 对 象 封 装 器 的 命 令 行 变 量库 封 装 器 属 性-BANKaccountCacheClnt -BANKaccountCacheSrvr -BANKmanagerCacheClnt -BANKmanagerCacheSrvr 说 明启 用 或 禁 用 为 客 户 端 应 用 缓 存 balance 方 法 结果 的 型 别 对 象 封 装 器 。启 用 或 禁 用 为 服 务 器 应 用 缓 存 balance 方 法 结果 的 型 别 对 象 封 装 器 。启 用 或 禁 用 为 客 户 端 应 用 缓 存 open 方 法 结 果的 型 别 对 象 封 装 器 。启 用 或 禁 用 为 服 务 器 应 用 缓 存 open 方 法 结 果的 型 别 对 象 封 装 器 。22-18 <strong>VisiBroker</strong> 开 发 者 指 南


混 合 使 用 非 型 别 和 型 别 对 象 封 装 器表 22.3用 于 有 控 制 型 别 对 象 封 装 器 的 命 令 行 变 量库 封 装 器 属 性-BANKmanagerSecurityClnt -BANKmanagerSecuritySrvr 说 明启 用 或 禁 用 为 客 户 端 应 用 检 测 通 过 open 方 法的 未 经 授 权 用 户 的 型 别 对 象 封 装 器 。启 用 或 禁 用 为 服 务 器 应 用 检 测 通 过 open 方 法的 未 经 授 权 用 户 的 型 别 对 象 封 装 器 。Java: 型 别 封 装 器 可 以 通 过 在 命 令 行 上 指 定 下 列 内 容 启 用 :1 -Dvbroker.orb.dynamicLibs=BankWrappers.Init2 使 用 一 个 或 多 个 下 述 属 性 。表 22.4用 于 启 用 或 禁 用 库 封 装 器 的 命 令 行 属 性BankWrappers 属 性-DCachingAccount[=]-DCachingAccountManager[=]-DSecureAccountManager[=]说 明安 装 为 客 户 或 服 务 器 缓 存 balance 方 法 结 果 的型 别 对 象 封 装 器 。 如 果 没 有 为 子 属 性 指 定 值 ,则 客 户 端 和 服 务 器 封 装 器 都 安 装 。安 装 为 客 户 或 服 务 器 缓 存 open 方 法 结 果 的 型别 对 象 封 装 器 。 如 果 没 有 为 子 属 性 指 定 值 , 则客 户 端 和 服 务 器 封 装 器 都 安 装 。安 装 为 客 户 和 服 务 器 检 测 通 过 open 方 法 的 未经 授 权 用 户 的 型 别 对 象 封 装 器 。 如 果 没 有 为 子属 性 指 定 值 , 则 客 户 端 和 服 务 器 封 装 器 都 安装 。型 别 封 装 器 的 初 始 化 器C++:型 别 封 装 器 是 在 BankInit::update 初 始 化 器 中 创 建 、 在 objectWrappers/BankWrap.C 中 定 义 的 。 初 始 化 器 将 在 调 用 ORB_init 方 法 时 被 调 用 , 并 且 根 据 您 指定 的 命 令 属 性 组 织 各 种 型 别 对 象 封 装 器 的 安 装 。以 下 代 码 示 例 示 范 了 初 始 化 器 如 何 通 过 一 组 PropStruct 对 象 跟 踪 所 指 定 的 命 令 行选 项 以 及 在 适 当 的 位 置 添 加 或 删 除 AccountObjectWrapper 对 象 。C++: . . .static const CORBA::ULong kNumTypedAccountProps = 2;static PropStruct TypedAccountProps[kNumTypedAccountProps] ={ { "BANKaccountCacheClnt", CachingAccountObjectWrapper::factory,VISObjectWrapper::Client },{ "BANKaccountCacheSrvr", CachingAccountObjectWrapper::factory,VISObjectWrapper::Server }};static const CORBA::ULong kNumTypedAccountManagerProps = 4;static PropStruct TypedAccountManagerProps[kNumTypedAccountManagerProps] ={ { "BANKmanagerCacheClnt", CachingAccountManagerObjectWrapper::factory,VISObjectWrapper::Client },{ "BANKmanagerSecurityClnt", SecureAccountManagerObjectWrapper::factory,VISObjectWrapper::Client },{ "BANKmanagerCacheSrvr", CachingAccountManagerObjectWrapper::factory,VISObjectWrapper::Server },{ "BANKmanagerSecuritySrvr", SecureAccountManagerObjectWrapper::factory,使 用 对 象 封 装 器 22-19


混 合 使 用 非 型 别 和 型 别 对 象 封 装 器Java:Java:VISObjectWrapper::Server },};void BankInit::update(int& argc, char* const* argv) {if (argc > 0) {init(argc, argv, "-BANK");CORBA::ULong i;for (i=0; i < kNumTypedAccountProps; i++) {CORBA::String_var arg(getArgValue(TypedAccountProps[i].propname));if (arg && strlen(arg) > 0) {if (atoi((char*) arg)) {Bank::AccountObjectWrapper::add(_orb,TypedAccountProps[i].fact,TypedAccountProps[i].loc);} else {Bank::AccountObjectWrapper::remove(_orb,TypedAccountProps[i].fact,TypedAccountProps[i].loc);}}}for (i=0; i < kNumTypedAccountManagerProps; i++) {CORBA::String_var arg(getArgValue(TypedAccountManagerProps[i].propname));if (arg && strlen(arg) > 0) {if (atoi((char*) arg)) {Bank::AccountManagerObjectWrapper::add(_orb,TypedAccountManagerProps[i].fact,TypedAccountManagerProps[i].loc);} else {Bank::AccountManagerObjectWrapper::remove(_orb,TypedAccountManagerProps[i].fact,TypedAccountManagerProps[i].loc);}}}}}型 别 封 装 器 在 BankWrappers 封 包 中 定 义 , 封 装 器 包 含 服 务 初 始 化 器 BankWrappers/Init.java ( 如 以 下 代 码 所 示 )。 如 果 在 命 令 行 中 指 定 -Dvbroker.orb.dynamicLibs=BankWrappers.Init 且 带 vbj 选 项 启 动 客 户 或 服 务 器 ,则 会 调 用 该 初 始 化 器 。 根 据 您 指 定 的 命 令 行 属 性 ( 如 上 表 所 示 ), 可 以 安 装 各 种 型别 对 象 封 装 器 。package BankWrappers;import java.util.*;import com.inprise.vbroker.orb.ORB;import com.inprise.vbroker.properties.PropertyManager;import com.inprise.vbroker.interceptor.*;public class Init implements ServiceLoader {com.inprise.vbroker.orb.ORB _orb;public void init(final org.omg.CORBA.ORB orb) {_orb = (ORB) orb;PropertyManager pm = _orb.getPropertyManager();22-20 <strong>VisiBroker</strong> 开 发 者 指 南


混 合 使 用 非 型 别 和 型 别 对 象 封 装 器// 安 装 自 己 的 CachingAccountObjectWrapperString val = pm.getString("CachingAccount", this.toString());Class c = CachingAccountObjectWrapper.class;if( !val.equals(this.toString())) {if( val.equalsIgnoreCase("client") ) {Bank.AccountHelper.addClientObjectWrapperClass(orb, c);} else if( val.equalsIgnoreCase("server") ) {Bank.AccountHelper.addServerObjectWrapperClass(orb, c);} else {Bank.AccountHelper.addClientObjectWrapperClass(orb, c);Bank.AccountHelper.addServerObjectWrapperClass(orb, c);}}// 安 装 自 己 的 CachingAccountManagerObjectWrapperval = pm.getString("CachingAccountManager", this.toString());c = CachingAccountManagerObjectWrapper.class;if( !val.equals(this.toString())) {if( val.equalsIgnoreCase("client") ){Bank.AccountManagerHelper.addClientObjectWrapperClass(orb, c);} else if( val.equalsIgnoreCase("server") ) {Bank.AccountManagerHelper.addServerObjectWrapperClass(orb, c);} else {Bank.AccountManagerHelper.addClientObjectWrapperClass(orb, c);Bank.AccountManagerHelper.addServerObjectWrapperClass(orb, c);}}// 安 装 自 己 的 CachingAccountManagerObjectWrapperval = pm.getString("SecureAccountManager",this.toString());c = SecureAccountManagerObjectWrapper.class;if( !val.equals(this.toString())) {if( val.equalsIgnoreCase("client") ){Bank.AccountManagerHelper.addClientObjectWrapperClass(orb, c);} else if( val.equalsIgnoreCase("server") ) {Bank.AccountManagerHelper.addServerObjectWrapperClass(orb, c);} else {Bank.AccountManagerHelper.addClientObjectWrapperClass(orb, c);Bank.AccountManagerHelper.addServerObjectWrapperClass(orb, c);}}}public void init_complete(org.omg.CORBA.ORB orb) {}public void shutdown(org.omg.CORBA.ORB orb) {}}使 用 对 象 封 装 器 22-21


混 合 使 用 非 型 别 和 型 别 对 象 封 装 器用 于 非 型 别 封 装 器 的 命 令 行 变 量C++:下 表 所 示 命 令 行 变 量 可 用 于 为 Client.C 和 Server.C 中 实 现 的 样 本 库 应 用 启 用 非型 别 对 象 封 装 器 。表 22.5用 于 有 控 制 非 型 别 对 象 封 装 器 的 命 令 行 变 量库 封 装 器 属 性-TRACEWRAPclient -TRACEWRAPserver -TRACEWRAPboth -TIMINGWRAPclient -TIMINGWRAPserver -TIMINGWRAPboth 说 明实 例 化 指 定 数 量 的 非 型 别 对 象 封 装 器 工 厂 , 用于 为 客 户 端 应 用 追 踪 封 装 器 。实 例 化 指 定 数 量 的 非 型 别 对 象 封 装 器 工 厂 , 用于 在 服 务 器 应 用 中 追 踪 封 装 器 。实 例 化 指 定 数 量 的 非 型 别 对 象 封 装 器 工 厂 , 用于 为 客 户 端 和 服 务 器 应 用 追 踪 封 装 器 。实 例 化 指 定 数 量 的 非 型 别 对 象 封 装 器 工 厂 , 用于 在 客 户 端 应 用 上 计 时 。实 例 化 指 定 数 量 的 非 型 别 对 象 封 装 器 工 厂 , 用于 在 服 务 器 应 用 中 计 时 。实 例 化 指 定 数 量 的 非 型 别 对 象 封 装 器 工 厂 , 用于 在 客 户 端 和 服 务 器 应 用 中 计 时 。Java: 非 型 别 封 装 器 可 以 通 过 在 命 令 行 上 指 定 下 列 内 容 启 用 :1 -Dvbroker.orb.dynamicLibs=UtilityObjectWrappers.Init2 使 用 一 个 或 多 个 下 表 中 所 述 属 性 。表 22.6用 于 启 用 或 禁 用 UtilityObjectWrappers 的 命 令 行 属 性UtilityObjectWrappers 属 性-DTiming[=]-DTracing[=]说 明安 装 提 供 客 户 端 或 服 务 器 计 时 信 息 的 型 别 对 象封 装 器 。 如 果 没 有 为 子 属 性 指 定 值 , 则 客 户 端和 服 务 器 封 装 器 都 安 装 。安 装 提 供 客 户 端 或 服 务 器 追 踪 信 息 的 型 别 对 象封 装 器 。 如 果 没 有 为 子 属 性 指 定 值 , 则 客 户 端和 服 务 器 封 装 器 都 安 装 。非 型 别 封 装 器 的 初 始 化 器非 型 别 封 装 器 是 在 TraceWrapInit::update 和 TimingWrapInit::update 方 法 中 创建 、 在 BankWrappers/TraceWrap.C 和 TimeWrap.C 中 定 义 的 。 这 些 初 始 化 器 在 调 用ORB_init 方 法 时 被 调 用 , 并 且 组 织 各 种 非 型 别 对 象 封 装 器 的 安 装 。以 下 代 码 示 例 为 TraceWrap.C 文 件 的 一 部 分 , 它 将 根 据 您 指 定 的 命 令 行 属 性 安 装 适当 的 非 型 别 对 象 封 装 器 工 厂 。C++: TraceWrapInit::update(int& argc, char* const* argv) {if (argc > 0) {init(argc, argv, "-TRACEWRAP");VISObjectWrapper::Location loc;const char* propname;LIST(VISObjectWrapper::UntypedObjectWrapperFactory_ptr) *list;22-22 <strong>VisiBroker</strong> 开 发 者 指 南


混 合 使 用 非 型 别 和 型 别 对 象 封 装 器Java:for (CORBA::ULong i=0; i < 3; i++) {switch (i) {case 0:loc = VISObjectWrapper::Client;propname = "TRACEWRAPclient";list = &_clientfacts;break;case 1:loc = VISObjectWrapper::Server;propname = "TRACEWRAPserver";list = &_serverfacts;break;case 2:loc = VISObjectWrapper::Both;propname = "TRACEWRAPboth";list = &_bothfacts;break;}CORBA::String_var getArgValue(property_value(propname));if (arg && strlen(arg) > 0) {int numNew = atoi((char*) arg);char key_buf[256];for (CORBA::ULong j=0; j < numNew; j++) {sprintf(key_buf, "%s-%d", propname, list->size());list->add(new TraceObjectWrapperFactory(loc,(const char*) key_buf));}}}}}非 型 别 封 装 器 是 在 UtilityObjectWrappers 封 包 中 定 义 的 , 封 装 器 包 含 服 务 初 始 化器 UtilityObjectWrappers/Init.java, 如 下 所 示 。 如 果 在 命 令 行 中 指 定 -Dvbroker.orb.dynamicLibs=UtilityObjectWrappers.Init 且 带 vbj 选 项 启 动 客 户 或服 务 器 , 则 会 调 用 该 初 始 化 器 。 上 表 摘 要 介 绍 了 可 用 于 安 装 各 种 非 型 别 对 象 封 装 器的 命 令 行 变 量 。package UtilityObjectWrappers;import java.util.*;import com.inprise.vbroker.orb.ORB;import com.inprise.vbroker.properties.PropertyManager;import com.inprise.vbroker.interceptor.*;public class Init implements ServiceLoader {com.inprise.vbroker.orb.ORB _orb;public void init(final org.omg.CORBA.ORB orb) {_orb = (ORB) orb;PropertyManager pm= _orb.getPropertyManager();try {ChainUntypedObjectWrapperFactory factory =ChainUntypedObjectWrapperFactoryHelper.narrow(orb.resolve_initial_references("ChainUntypedObjectWrapperFactory"));// 安 装 自 己 的 Timing ObjectWrapper使 用 对 象 封 装 器 22-23


混 合 使 用 非 型 别 和 型 别 对 象 封 装 器C++:Java:String val = pm.getString("Timing", this.toString());if( !val.equals(this.toString())) {UntypedObjectWrapperFactory f= newTimingUntypedObjectWrapperFactory();if( val.equalsIgnoreCase("client") ){factory.add(f, Location.CLIENT);} else if( val.equalsIgnoreCase("server") ) {factory.add(f, Location.SERVER);} else {factory.add(f, Location.BOTH);}}// 安 装 自 己 的 Tracing ObjectWrapperval = pm.getString("Tracing", this.toString());if( !val.equals(this.toString())) {UntypedObjectWrapperFactory f= new TracingUntypedObjectWrapperFactory();if( val.equalsIgnoreCase("client") ){factory.add(f, Location.CLIENT);} else if( val.equalsIgnoreCase("server") ) {factory.add(f, Location.SERVER);} else {factory.add(f, Location.BOTH);}}} catch( org.omg.CORBA.ORBPackage.InvalidName e ) {return;}}public void init_complete(org.omg.CORBA.ORB orb) {}public void shutdown(org.omg.CORBA.ORB orb) {}}执 行 应 用 样 本执 行 应 用 样 本 之 前 , 请 确 保 osagent 正 在 网 络 上 运 行 。 然 后 可 以 使 用 下 列 命 令 执 行服 务 器 应 用 , 无 需 任 何 追 踪 或 计 时 对 象 封 装 器 :prompt> Serverprompt> vbj Server注 : 服 务 器 可 作 为 共 存 应 用 。 它 可 同 时 实 现 服 务 器 和 客 户 。在 另 一 个 窗 口 中 , 可 以 使 用 下 列 命 令 执 行 客 户 端 应 用 查 询 用 户 帐 户 中 的 余 额 , 无 需任 何 追 踪 或 计 时 对 象 封 装 器C++:Java:C++:Java:prompt> Client Johnprompt> vbj Client John如 果 要 使 用 默 认 名 称 , 也 可 以 执 行 下 列 命 令 。prompt> Clientprompt> vbj Client22-24 <strong>VisiBroker</strong> 开 发 者 指 南


混 合 使 用 非 型 别 和 型 别 对 象 封 装 器打 开 计 时 和 追 踪 对 象 封 装 器要 在 启 用 非 型 别 计 时 和 追 踪 对 象 封 装 器 的 情 况 下 执 行 客 户 , 可 使 用 下 列 命 令 :C++: prompt> Client -TRACEWRAPclient 1 -TIMINGWRAPclient 1Java:prompt> vbj -Dvbroker.orb.dynamicLibs=UtilityObjectWrappers.Init-DTiming=client\-DTracing=client Client John要 在 启 用 用 于 计 时 和 追 踪 的 非 型 别 对 象 封 装 器 的 情 况 下 执 行 服 务 器 , 可 使 用 下 列命 令 :C++: prompt> Server -TRACEWRAPserver 1 -TIMINGWRAPserver 1Java:prompt> vbj -Dvbroker.orb.dynamicLibs=UtilityObjectWrappers.Init-DTiming=server\-DTracing=server Server打 开 缓 存 和 安 全 对 象 封 装 器要 在 启 用 用 于 缓 存 和 安 全 的 非 型 别 对 象 封 装 器 的 情 况 下 执 行 客 户 , 可 使 用 下 列命 令 :C++: prompt> Client -BANKaccountCacheClnt 1 _BANKmanagerCacheClnt 1 \-BANKmanagerSecurityClnt 1Java: prompt> vbj -Dvbroker.orb.dynamicLibs=BankWrappers.Init -DCachingAccount=client\-DCachingAccountManager=client\-DSecureAccountManager=clientClient John要 在 启 用 用 于 计 时 和 追 踪 的 非 型 别 对 象 封 装 器 的 情 况 下 执 行 服 务 器 , 可 使 用 下 列命 令 :C++: prompt> Server -BANKaccountCacheSrvr 1 -BANKmanagerCacheSrvr 1 \-BANKmanagerSecuritySrvr 1Java: prompt> vbj -Dvbroker.orb.dynamicLibs=BankWrappers.Init-DCachingAccount=server \-DCachingAccountManager=server \-DSecureAccountManager=server \Server打 开 型 别 和 非 型 别 对 象 封 装 器要 在 启 用 所 型 别 和 非 型 别 对 象 封 装 器 的 情 况 下 执 行 客 户 , 可 使 用 下 列 命 令 :C++: prompt> Client -BANKaccountCacheClnt 1 -BANKmanagerCacheClnt 1 \-BANKmanagerSecurityClnt 1 \-TRACEWRAPclient 1 -TIMINGWRAPclient 1使 用 对 象 封 装 器 22-25


混 合 使 用 非 型 别 和 型 别 对 象 封 装 器Java:prompt> vbj -DOvbroker.orb.dynamicLibs=BankWrappers.Init,UtilityObjectWrappers.Init \-DCachingAccount=client \-DCachingAccountManager=client\-DSecureAccountManager=client \-DTiming=client \-DTracing=client \Client John要 在 启 用 所 有 型 别 和 非 型 别 对 象 封 装 器 的 情 况 下 执 行 服 务 器 , 可 使 用 下 列 命 令 :C++: prompt> Server BANKaccountCacheSrvr 1 BANKmanagerCacheSrvr 1 \-BANKmanagerSecuritySrvr 1 \ -TRACEWRAPserver 1 -TIMINGWRAPserver 1Java:prompt> vbj -Dvbroker.orb.dynamicLibs=BankWrappers.Init,UtilityObjectWrappers.Init \-DCachingAccount=server \-DCachingAccountManager=server\-DSecureAccountManager=server \-DTiming=server \-DTracing=server \Server执 行 共 存 客 户 和 服 务 器下 列 命 令 将 在 启 用 所 有 型 别 封 装 器 、 仅 为 客 户 启 用 非 型 别 封 装 器 和 仅 为 服 务 器 启 用非 型 别 追 踪 封 装 器 的 情 况 下 执 行 共 存 客 户 和 服 务 器 :C++: prompt> Server -BANKaccountCacheClnt 1 -BANKaccountCacheSrvr 1 \-BANKmanagerCacheClnt 1 -BANKmanagerCacheSrvr 1 \-BANKmanagerSecurityClnt 1 \-BANKmanagerSecuritySrvr 1 \-TRACEWRAPboth 1 \-TIMINGWRAPboth 1Java: 指 定 -runCoLocated 命 令 行 选 项 允 许 在 同 一 进 程 中 执 行 客 户 和 服 务 器 。属 性-runCoLocated Client-runCoLocated TypedClient-runCoLocated UntypedClient说 明在 同 一 进 程 上 执 行 Server.java 和Client.java。在 同 一 进 程 上 执 行 Server.java 和TypedClient.java。在 同 一 进 程 上 执 行 Server.java 和UntypedClient.java。下 列 命 令 将 在 启 用 所 有 型 别 封 装 器 、 仅 为 客 户 启 用 非 型 别 计 时 封 装 器 和 仅 为 服 务 器启 用 非 型 别 追 踪 封 装 器 的 情 况 下 执 行 共 存 客 户 和 服 务 器 。仅 适 用 于 Java:prompt> vbj -Dvbroker.orb.dynamicLibs=BankWrappers.Init,UtilityObjectWrappers.Init \-DCachingAccount -DSecureAccountManager \-DTiming=client -DTracing=server \Server -runCoLocated Client22-26 <strong>VisiBroker</strong> 开 发 者 指 南


第章事 件 队 列第 23 章本 章 介 绍 关 于 事 件 队 列 特 性 的 信 息 。 该 特 性 仅 适 用 于 服 务 器 端 。服 务 器 可 以 根 据 其 感 兴 趣 的 事 件 类 型 将 监 听 器 登 记 到 事 件 队 列 中 , 随 后 , 它 可 以 根据 需 要 来 处 理 这 些 事 件 。事 件 类 型当 前 , 连 接 事 件 类 型 是 生 成 的 唯 一 事 件 类 型 。 其 它 事 件 类 型 将 根 据 需 要 在 以 后 的 版本 中 增 加 。连 接 事 件<strong>VisiBroker</strong> ORB 将 产 生 两 种 连 接 类 型 并 推 入 到 登 记 连 接 事 件 , 它 们 是 :● 连 接 建 立 - 这 表 示 一 个 新 的 客 户 已 成 功 连 接 到 服 务 器 。● 连 接 关 闭 - 这 表 示 一 个 现 有 客 户 从 服 务 器 上 断 开 。事 件 监 听 器服 务 器 根 据 其 要 处 理 的 事 件 类 型 实 现 监 听 器 并 将 它 们 注 册 在 <strong>VisiBroker</strong> ORB 上 。在 本 版 本 中 , 连 接 事 件 监 听 器 是 唯 一 支 持 的 事 件 监 听 器 。 其 它 事 件 监 听 器 将 根 据 需要 在 以 后 的 版 本 中 增 加 。IDL 定 义接 口 定 义 如 下 :事 件 队 列 23-1


事 件 监 听 器module EventQueue {// 连 接 事 件 类 型enum EventType {UNDEFINED, CONN_EVENT_TYPE};// 点 ( 客 户 ) 连 接 信 息struct ConnInfo {string ipaddress; // in %d.%d.%d.%d formatlong port;long connID;};// 所 有 类 型 的 事 件 监 听 器 的 标 记 接 口local interface EventListener {};typedef sequence EventListeners;// 连 接 事 件 监 听 器 接 口local interface ConnEventListener :EventListener{void conn_established(in ConnInfo info);void conn_closed(in ConnInfo info);};// EventQueue 管 理 器local interface EventQueueManager :interceptor::InterceptorManager {void register_listener(in EventListener listener, in EventType type);void unregister_listener(in EventListener listener, in EventType type);EventListeners get_listeners(in EventType type);};};接 口 定 义 的 详 情 将 在 后 续 章 节 中 描 述 。ConnInfo 结 构ConnInfo 结 构 包 含 如 下 的 客 户 连 接 信 息 :● ipaddress: 存 储 客 户 IP 地 址 。● port: 存 储 客 户 端 口 号 。● connID: 存 储 服 务 器 分 配 给 每 个 客 户 连 接 的 唯 一 标 识 。EventListener 接 口EventListener 接 口 部 分 是 所 有 类 型 的 监 听 器 的 标 记 接 口 。ConnEventListeners 接 口ConnEventListeners 接 口 定 义 如 下 两 个 操 作 :● void conn_established (in ConnInfo info)本 操 作 由 <strong>VisiBroker</strong> ORB 回 调 以 推 动 连 接 建 立 事 件 。 <strong>VisiBroker</strong> ORB 将 客户 连 接 信 息 填 入 ConnInfo 信 息 参 数 , 并 将 该 值 传 入 回 调 操 作 。● void conn_closed (in ConnInfo info)23-2 <strong>VisiBroker</strong> 开 发 者 指 南


事 件 监 听 器本 操 作 由 <strong>VisiBroker</strong> ORB 回 调 以 推 动 连 接 关 闭 事 件 。 <strong>VisiBroker</strong> ORB 将 客户 连 接 信 息 填 入 ConnInfo 信 息 参 数 , 并 将 该 值 传 入 回 调 操 作 。服 务 器 端 应 用 负 责 实 现 ConnEventListener 接 口 被 推 到 监 听 器 的 事 件 的 处 理 。EventQueueManager 接 口EventQueueManager 接 口 被 服 务 器 端 实 现 用 作 登 记 事 件 监 听 器 的 句 柄 。 该 接 口 定 义如 下 三 个 操 作 :● void register_listener (in EventListener listener, in EventType type)本 操 作 用 于 使 用 指 定 的 事 件 类 型 来 登 记 事 件 监 听 器 。● EventListeners get_listeners (in EventType type)本 操 作 返 回 具 有 指 定 类 型 的 注 册 事 件 监 听 器 的 列 表 。● void unregister_listener (in EventListener listener, in EventType type)本 操 作 删 除 一 个 先 前 注 册 的 具 有 指 定 类 型 的 监 听 器 。如 何 返 回 EventQueueManager?EventQueueManager 对 象 在 ORB 初 始 化 后 创 建 。 服 务 器 端 实 现 通 过 下 列 代 码返 回 EventQueueManager 对 象 引 用 :C++: CORBA::Object *object =orb->resolve_initial_references("<strong>VisiBroker</strong>InterceptorControl");interceptor::InterceptorManagerControl_var control =interceptor::InterceptorManagerControl::_narrow(object);interceptor::InterceptorManager_var manager =control->get_manager("EventQueueManager");EventQueue::EventQueueManager_var eq_mgr =EventQueue::EventQueueManager::_narrow(manager);以 下 是 Java 下 的 EventQueueManager:Java: com.inprise.vbroker.interceptor.InterceptorManagerControl control =com.inprise.vbroker.interceptor.InterceptorManagerControlHelper.narrow(orb.resolve_initial_references("<strong>VisiBroker</strong>InterceptorControl"));EventQueueManager manager =(EventQueueManager)control.get_manager("EventQueue");EventListener theListener = ...manager.register_listeners(theListener);代 码 示 例本 节 包 含 几 个 用 于 注 册 EvenListener 和 实 现 连 接 EventListener 的 Java 和 C++代 码 示 例 。事 件 队 列 23-3


事 件 监 听 器注 册 EventListenerC++:SampleServerLoader 类 包 含 由 ORB 在 初 始 化 过 程 中 调 用 的 init() 方 法 。ServerLoader 的 目 的 是 通 过 创 建 EventListener 并 将 它 注 册 在EventQueueManager 来 完 成 对 其 注 册 。#ifdef _VIS_STD#include #else#include #endif#include "vinit.h"#include "ConnEventListenerImpl.h"USE_STD_NSclass SampleServerLoader : VISInit{private:short int _conn_event_interceptors_installed;public:SampleServerLoader(){_conn_event_interceptors_installed = 0;}void ORB_init(int& argc, char* const* argv, CORBA::ORB_ptr orb){if( _conn_event_interceptors_installed) return;cout get_manager("EventQueueManager");EventQueue::EventQueueManager_var eq_mgr =EventQueue::EventQueueManager::_narrow(manager);// 将 POA 接 收 器 加 入 列 表eq_mgr->register_listener( (EventQueue::ConnEventListener*)interceptor,EventQueue::CONN_EVENT_TYPE);23-4 <strong>VisiBroker</strong> 开 发 者 指 南


事 件 监 听 器Java:cout


事 件 监 听 器#include #else#include #endif#include "vextclosure.h"#include "interceptor_c.hh"#include "IOP_c.hh"#include "EventQueue_c.hh"#include "vutil.h"// USE_STD_NS 是 由 <strong>VisiBroker</strong> 建 立 的 使 用 std namespace 的 定 义USE_STD_NS//-------------------------------------------------------------------------// 定 义 服 务 器 接 收 器 功 能//-------------------------------------------------------------------------class ConnEventListenerImpl : EventQueue::ConnEventListener{private:char * _id;public:ConnEventListenerImpl( const char* id) {_id = new char[ strlen(id) + 1];strcpy( _id,id);}~ConnEventListenerImpl() {delete[] _id;_id = NULL;}//--------------------------------------------------------------------// 当 一 个 请 求 到 达 服 务 器 端 时 , 这 一 方 法 被 调 用 。//--------------------------------------------------------------------void conn_established(const EventQueue::ConnInfo& connInfo){cout


事 件 监 听 器import org.omg.CORBA.LocalObject;public class ConnEventListenerImpl extends LocalObject implementsConnEventListener {public void conn_established(ConnInfo info) {System.out.println("Received conn_established: address = " +info.ipaddress + " port = " + info.port +" connID = " + info.connID);System.out.println("Processing the event ...");try {Thread.sleep(30000);} catch (Exception e) { e.printStackTrace(); }}public void conn_closed(ConnInfo info) {System.out.println("Received conn_closed: address = " +info.ipaddress+ " port = " + info.port +" connID = " + info.connID);}}事 件 队 列 23-7


23-8 <strong>VisiBroker</strong> 开 发 者 指 南


第章在 IIOP 上 使 用 RMI第 24 章本 节 讲 述 了 允 许 您 在 IIOP 上 使 用 RMI 的 <strong>VisiBroker</strong> <strong>Edition</strong> 工 具 , 还 说 明 了 运行 使 用 RMI-IIOP 的 Java applet 时 的 简 要 设 置 许 可 要 求 。概 述RMI ( 远 程 方 法 调 用 ) 是 一 种 允 许 在 分 布 环 境 中 创 建 和 使 用 对 象 的 Java 机 制 。 从这 种 意 义 上 讲 , RMI 是 特 定 于 语 言 (Java) 且 与 CORBA 不 兼 容 的 <strong>VisiBroker</strong>ORB。 OMG 已 发 出 了 一 种 规 范 , 即 Java 语 言 至 IDL 的 映 射 , 该 规 范 允 许 使 用RMI 编 写 的 Java 类 与 使 用 IIOP 编 码 的 CORBA 对 象 相 互 操 作 。通 过 RMI-IIOP 设 置 Java applet您 可 以 运 行 使 用 RMI-IIOP 的 applet。 但 是 , 您 需 要 设 置 “ 反 射 ” 和 “ 运 行 时间 ” 许 可 。 这 些 许 可 在 安 装 了 JRE 的 目 录 下 的 java.policy 文 件 中 设 置 。 下 面 这 个示 例 说 明 了 如 何 在 java.policy 文 件 中 设 置 许 可 :grant codeBase "http://xxx.xxx.xxx.xxx:8088/-" {permission java.lang.reflect.ReflectPermission "suppressAccessChecks";permission java.lang.RuntimePermission "accessDeclaredMembers";};java2iiop 和 java2idl 工 具<strong>VisiBroker</strong> <strong>Edition</strong> 具 有 两 个 编 译 程 序 , 这 两 个 编 译 程 序 允 许 您 使 用 <strong>VisiBroker</strong><strong>Edition</strong> ORB 改 写 现 有 的 Java 类 以 与 其 它 对 象 配 合 工 作 。● java2iiop 编 译 程 序 通 过 生 成 所 有 合 适 的 框 架 、 存 根 和 助 手 (helper) 类 , 从而 允 许 您 改 写 与 RMI 兼 容 的 类 以 使 用 IIOP。在 IIOP 上 使 用 RMI 24-1


使 用 java2iiop● java2idl 编 译 程 序 可 从 Java 类 中 生 成 IDL, 从 而 允 许 您 在 非 Java. 语 言 中 实 现这 些 类 。使 用 java2iiopjava2iiop 编 译 程 序 允 许 您 在 Java ( 而 不 是 IDL) 中 定 义 接 口 和 数 据 类 型 , 然 后这 些 接 口 和 数 据 类 型 可 用 作 CORBA 中 的 接 口 和 数 据 类 型 。 该 编 译 程 序 不 会 读 取Java 源 代 码 (java 文 件 ) 或 IDL, 而 是 读 取 Java 字 节 代 码 ( 类 文 件 )。 然 后 ,该 编 译 程 序 会 生 成 与 IIOP 兼 容 的 存 根 和 框 架 , 在 进 行 CORBA 所 需 的 所 有 汇 集 和通 信 时 需 要 这 些 存 根 和 框 架 。支 持 的 接 口在 您 运 行 java2iiop 编 译 程 序 时 , 它 生 成 的 文 件 与 在 IDL 中 编 写 过 接 口 后 生 成 的 文件 一 样 。 所 有 原 始 数 据 类 型 , 如 数 值 类 型 ( 短 型 、 整 数 型 、 长 型 、 浮 点 型 以 及 双 精度 型 )、 字 符 串 、 CORBA 对 象 或 接 口 对 象 、 任 何 对 象 、 类 型 代 码 对 象 , 都 会 被java2iiop 编 译 程 序 所 识 别 , 并 且 会 映 射 至 相 应 的 IDL 类 型 。您 可 以 在 任 何 Java 类 中 或 任 何 Java 接 口 上 使 用 java2iiop。 例 如 , 如 果 Java 接口 遵 守 以 下 一 个 规 则 :● 通 过 java.rmi.RemoteException 扩 展 java.rmi.Remote 及 其 所 有 方 法● 扩 展 org.omg.CORBA.Object则 java2iiop 会 在 IDL 中 将 该 接 口 转 换 成 CORBA 接 口 。以 下 代 码 示 例 阐 明 了 Java RMI 接 口 。 您 可 以 在 <strong>VisiBroker</strong> <strong>Edition</strong> 安 装 目 录 下的 examples/rmi-iiop 文 件 夹 中 找 到 该 示 例 。public interface Account extends java.rmi.Remote {String name() throws java.rmi.RemoteException;float getBalance() throws java.rmi.RemoteException;void setBalance(float bal) throws java.rmi.RemoteException;}运 行 java2iiop您 必 须 先 编 译 Java 类 , 然 后 才 可 以 使 用 java2iiop 编 译 程 序 。 在 生 成 字 节 代 码 后 ,您 可 以 运 行 java2iiop 以 生 成 客 户 存 根 、 服 务 器 框 架 以 及 关 联 的 辅 助 文 件 。 例 如 ,在 examples/rmi-iiop/Bank 目 录 下 的 帐 户 类 文 件 中 运 行 了 java2iiop 后 , 将 生 成 以下 文 件 :● _Account_Stub● AccountHelper● AccountHolder● AccountPOA24-2 <strong>VisiBroker</strong> 开 发 者 指 南


使 用 java2iiop● AccountPOATie● AccountOperations有 关 这 些 文 件 的 详 情 , 请 参 阅 程 序 员 参 考 。Java 类 至 IDL 的 逆 映 射在 使 用 idl2java 编 译 程 序 将 IDL 接 口 映 射 至 Java 类 时 , 接 口 名 可 以 使 用 任 何 生成 的 类 后 缀 ( 例 如 :Helper、Holder 和 POA 等 等 ),idl2java 工 具 将 通 过 修 改 接 口名 ( 在 标 识 前 加 一 个 下 划 线 前 缀 ) 来 正 确 处 理 这 种 情 况 。 例 如 , 如 果 您 在 IDL 中定 义 了 Foo 和 FooHolder 接 口 , 则 idl2java 将 生 成 Foo.java、 FooHolder.java、_FooHolder.java 和 _FooHolderHolder.java 文 件 以 及 其 它 文 件 。 另 一 方 面 , 在 使 用java2iiop 编 译 程 序 从 RMI Java 类 中 生 成 与 IIOP 兼 容 的 Java 类 时 , 该 工 具 无 法生 成 修 改 的 类 。 因 此 , 在 声 明 使 用 保 留 后 缀 的 接 口 时 , 您 不 能 将 它 们 与 同 名 的 接 口放 在 同 一 程 序 包 中 ( 例 如 , 在 使 用 java2iiop 编 译 程 序 时 , 您 不 能 将 Foo 和FooHolder 类 放 在 同 一 程 序 包 中 )。完 成 开 发 过 程在 从 接 口 中 生 成 关 联 文 件 后 , 您 需 要 为 接 口 提 供 实 现 功 能 。 请 执 行 以 下 步 骤 :1 创 建 接 口 类 实 现 功 能 。2 编 译 服 务 器 类 。3 编 写 和 编 译 客 户 端 代 码 。4 启 动 服 务 器 程 序 。5 运 行 客 户 端 程 序 。注 意 : 如 果 您 试 图 汇 集 非 兼 容 类 , 则 会 产 生 org.omg.CORBA.MARSHAL: 无 法 汇 集 非 兼 容 类 值 。 例 如 , 如 果 您 创 建 以 下 两 个 类 ,// 这 是 兼 容 类public class Value implements java.io.Serializable {java.lang.Object any;...}// 这 是 非 兼 容 类public class Something {...}and then attempt this,Value val = new Value();val.any = new Something();则 在 试 图 汇 集 val 时 会 引 发 org.omg.CORBA.MARSHAL 违 例 。在 IIOP 上 使 用 RMI 24-3


RMI-IIOP 库 实 例RMI-IIOP 库 实 例注 :帐 户 接 口 可 以 扩 展 java.rmi.Remote 接 口 , 并 且 通 过 AccountImpl 类 来 实 现 。通 过 创 建 每 个 帐 户 的 帐 户 数 据 对 象 , 然 后 将 这 些 帐 户 数 据 对 象 传 递 至 “ 帐 户 管 理器 ”, 客 户 端 类 ( 请 参 阅 第 二 个 代 码 示 例 ) 会 首 先 创 建 具 有 相 应 余 额 的 所 有 指 定 帐户 对 象 , 从 而 创 建 帐 户 。 然 后 它 会 确 认 创 建 的 帐 户 中 的 余 额 是 正 确 的 。 客 户 端 然 后会 在 帐 户 管 理 器 中 查 询 所 有 帐 户 的 列 表 , 接 着 在 每 个 帐 户 的 贷 方 存 入 $10.00, 然 后验 证 帐 户 中 的 新 余 额 是 否 正 确 。您 可 以 在 <strong>VisiBroker</strong> <strong>Edition</strong> 安 装 目 录 下 examples/rmi-iiop 文 件 夹 中 找 到 该 代码 实 例 。public class AccountImpl extends Bank.AccountPOA {public AccountImpl(Bank.AccountData data) {_name = data.getName();_balance = data.getBalance();}public String name() throws java.rmi.RemoteException {return _name;}public float getBalance() throws java.rmi.RemoteException {return _balance;}public void setBalance(float balance) throws java.rmi.RemoteException {_balance = balance;}private float _balance;private String _name;}客 户 端 类 :public class Client {public static void main(String[] args) {try {// 初 始 化 ORB。org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);// 得 到 管 理 器 Idbyte[] managerId = "RMIBankManager".getBytes();// 找 到 一 个 帐 户 管 理 器 。 给 出 POA 全 名 及 服 务 对 象 ID。Bank.AccountManager manager =Bank.AccountManagerHelper.bind(orb, "/rmi_bank_poa", managerId);// 使 用 任 何 变 量 对 数 指 明 要 创 建 的 帐 户 的 名 称 和 余 额if (args.length == 0 || args.length % 2 != 0) {args = new String[2];args[0] = "Jack B. Quick";args[1] = "123.23";}int i = 0;while (i < args.length) {String name = args[i++];float balance;try {24-4 <strong>VisiBroker</strong> 开 发 者 指 南


支 持 的 数 据 类 型balance = new Float(args[i++]).floatValue();} catch (NumberFormatException n) {balance = 0;}Bank.AccountData data = new Bank.AccountData(name, balance);Bank.Account account = manager.create(data);System.out.println("Created account for " + name+ " with opening balance of $" + balance);}java.util.Hashtable accounts = manager.getAccounts();for (java.util.Enumeration e = accounts.elements(); e.hasMoreElements();) {Bank.Account account =Bank.AccountHelper.narrow((org.omg.CORBA.Object)e.nextElement());String name = account.name();float balance = account.getBalance();System.out.println("Current balance in " + name +"'s account is $" + balance);System.out.println("Crediting $10 to " + name + "'s account.");account.setBalance(balance + (float)10.0);balance = account.getBalance();System.out.println("New balance in " + name + "'s account is $" + balance);}} catch (java.rmi.RemoteException e) {System.err.println(e);}}}支 持 的 数 据 类 型除 了 支 持 所 有 Java 原 始 数 据 类 型 外 , RMI-IIOP 还 支 持 Java 类 的 子 集 。映 射 原 始 数 据 类 型java2iiop 生 成 的 客 户 端 存 根 可 以 进 行 Java 原 始 数 据 类 型 ( 这 些 数 据 类 型 表 示 操作 要 求 ) 汇 集 , 以 便 能 够 将 这 些 数 据 类 型 传 送 至 对 象 服 务 器 。 在 汇 集 Java 原 始 数据 类 型 时 , 必 须 将 其 转 换 成 与 IIOP 兼 容 的 格 式 。 下 表 概 括 了 Java 原 始 数 据 类 型至 IDL/IIOP 类 型 的 映 射 。表 24.1 Java 类 型 至 IDL/IIOP 的 映 射Java 类 型空 型布 尔 型字 节 型字 符 型短 型整 数 型长 型IDL/IIOP 类 型空 型布 尔 型八 位 字 节 型字 符 型短 型长 型双 长 型在 IIOP 上 使 用 RMI 24-5


支 持 的 数 据 类 型表 24.1 Java 类 型 至 IDL/IIOP 的 映 射Java 类 型浮 点 型双 精 度 型java.lang.Stringjava.lang.Objectjava.io.Serializablejava.io.ExternalizableIDL/IIOP 类 型浮 点 型双 精 度 型CORBA::WStringValue任 何 类 型任 何 类 型任 何 类 型映 射 复 杂 数 据 类 型本 节 讨 论 了 接 口 、 数 组 和 Java 类 , 并 说 明 如 何 才 能 使 用 java2iiop 编 译 程 序 处 理复 杂 数 据 类 型 。接 口Java 接 口 在 IDL 中 被 表 示 为 CORBA 接 口 , 并 且 必 须 继 承 org.omg.CORBA. 对 象接 口 的 性 质 。 在 传 递 实 现 这 些 接 口 的 对 象 时 , 是 根 据 引 用 进 行 传 送 的 。数 组可 在 类 中 定 义 的 另 一 个 复 杂 数 据 类 型 是 数 组 。 如 果 有 使 用 数 组 的 接 口 或 定 义 , 则 这些 数 组 可 以 映 射 至 封 装 类 型 的 CORBA 封 装 的 序 列 。24-6 <strong>VisiBroker</strong> 开 发 者 指 南


第章使 用 动 态 管 理 的 类 型第 25 章本 章 描 述 <strong>VisiBroker</strong> <strong>Edition</strong> 的 DynAny 特 性 , 该 特 性 允 许 您 在 运 行 期 内 构 建 和 解析 数 据 类 型 。概 述DynAny 接 口 提 供 一 种 在 运 行 期 内 动 态 创 建 基 本 和 结 构 化 数 据 类 型 的 方 法 。 另 外 还 允许 从 Any 对 象 解 析 和 取 出 信 息 , 即 使 它 所 包 含 的 类 型 在 编 译 时 对 服 务 器 来 说 是 未 知的 。 使 用 DynAny 接 口 使 您 可 以 构 建 强 大 的 客 户 端 和 服 务 器 应 用 程 序 , 用 于 在 运 行时 创 建 和 解 析 数 据 类 型 。<strong>VisiBroker</strong> distribution 配 有 说 明 如 何 使 用 DynAny 的 客 户 端 和 服 务 器 应 用 程 序 实例 。 这 些 实 例 位 于 dynany 目 录 内 。 路 径 是 install_dir/vbroker/examples。 本 章中 将 引 用 这 些 实 例 程 序 来 说 明 DynAny 概 念 。DynAny 类 型DynAny 对 象 有 一 个 关 联 值 , 该 值 可 以 是 基 本 数 据 类 型 ( 例 如 boolean, int 或float), 也 可 以 是 结 构 化 数 据 类 型 。 DynAny 接 口 ( 详 细 说 明 参 见 程 序 员 参 考 ) 提供 了 确 定 所 包 含 数 据 的 类 型 以 及 设 置 和 取 出 基 本 数 据 类 型 的 值 的 方 法 。结 构 化 数 据 类 型 由 以 下 接 口 表 示 , 这 些 接 口 都 是 从 DynAny 派 生 的 。 其 中 的 每 个 接口 都 提 供 自 己 的 一 套 方 法 , 适 合 于 设 置 和 取 出 自 己 所 包 含 的 值 。表 25.1从 DynAny 派 生 的 表 示 结 构 化 数 据 类 型 的 接 口接 口 TypeCode 说 明DynArray _tk_array 具 有 固 定 数 量 的 元 素 和 同 一 数 据类 型 的 一 组 值 。DynEnum _tk_enum 单 个 枚 举 值 。使 用 动 态 管 理 的 类 型 25-1


DynAny 类 型表 25.1从 DynAny 派 生 的 表 示 结 构 化 数 据 类 型 的 接 口接 口 TypeCode 说 明DynFixed _tk_fixed 不 支 持 。DynSequence _tk_sequence 具 有 相 同 数 据 类 型 的 值 序 列 。 可以 增 加 或 减 少 的 元 素 的 数 量 。DynStruct _tk_struct 一 个 结 构 。DynUnion _tk_union 一 个 并 集 。DynValue _tk_value 不 支 持 。使 用 限 制DynAny 对 象 仅 可 以 被 创 建 它 的 进 程 在 本 地 使 用 。 如 果 尝 试 将 DynAny 对 象 用 作 一 个限 制 的 对 象 的 操 作 请 求 上 的 参 数 , 或 者 使 用 c++ ORB::object_to_string 方 法 或Java ORB.object_to_string 方 法 将 其 具 体 化 / 实 例 化 , 则 会 掷 出 MARSHAL 违 例 。此 外 , 如 果 尝 试 将 DynAny 对 象 作 为 DII 请 求 的 参 数 , 则 会 掷 出 一 个 NO_IMPLEMENT违 例 。如 CORBA 2.4 所 述 , 本 版 本 不 支 持 长 双 精 度 浮 点 型 和 固 定 型 。创 建 DynAnyDynAny 对 象 是 通 过 调 用 DynAnyFactory 对 象 上 的 一 个 操 作 来 创 建 的 。 首 先 取 得DynAnyFactory 对 象 的 参 考 , 然 后 使 用 该 对 象 创 建 新 的 DynAny 对 象 。C++:CORBA::Object_var obj = orb->resolve_initial_references("DynAnyFactory");DynamicAny::DynAnyFactory_var factory =DynamicAny::DynAnyFactory::_narrow(obj);// 创 建 动 态 structDynamicAny::DynAny_var dynany = factory->create_dyn_any_from_type_code(Printer::_tc_StructType);DynamicAny::DynStruct_var info = DynamicAny::DynStruct::_narrow(dynany);info->set_members(seq);CORBA::Any_var any = info->to_any();以 下 的 代 码 示 例 说 明 在 Java 下 创 建 DynAny 的 过 程 。Java:// 解 析 Dynamic Any FactoryDynAnyFactory factory =DynAnyFactoryHelper.narrow(orb.resolve_initial_references("DynAnyFactory"));byte[] oid = "PrinterManager".getBytes();// 创 建 打 印 机 管 理 器 对 象 。PrinterManagerImpl manager =new PrinterManagerImpl((com.inprise.vbroker.CORBA.ORB) orb, factory,serverPoa, oid);// 派 生 新 建 的 对 象 。serverPoa.activate_object_with_id(oid, manager);System.out.println(manager + " is ready.");25-2 <strong>VisiBroker</strong> 开 发 者 指 南


结 构 化 数 据 类 型初 始 化 与 存 取 DynAny 值C++ 下 的 DynAny::insert_ 方 法 或 Java 下 的 DynAny.insert_ 方 法 允许 您 用 多 种 基 本 数 据 类 型 来 初 始 化 DynAny 对 象 , 其 中 的 可 以 是 boolean、octet、char 等 。 如 果 尝 试 插 入 一 个 与 为 DynAny 所 定 义 的 TypeCode 不 匹 配 的 类 型 ,则 会 掷 出 一 个 TypeMismatch 违 例 。C++ 下 的 DynAny::get_ 方 法 或 Java 下 的 DynAny.get_ 方 法 允 许 您 存取 包 含 在 DynAny 对 象 中 的 值 , 其 中 的 可 以 是 boolean、octet、char 等 。 如果 尝 试 从 一 个 与 为 DynAny 所 定 义 的 TypeCode 不 匹 配 的 DynAny 组 件 中 存 取 值 , 则 会掷 出 一 个 TypeMismatch 违 例 。DynAny 接 口 也 提 供 复 制 、 分 配 和 转 换 值 出 入 Any 对 象 的 方 法 。 本 章 中 随 后 描 述 的示 例 程 序 提 供 使 用 这 些 方 法 的 实 例 。 参 阅 程 序 员 参 考 以 查 看 关 于 这 些 方 法 的 完 整描 述 。结 构 化 数 据 类 型以 下 的 类 型 是 从 DynAny 接 口 派 生 的 , 它 们 用 于 表 示 结 构 化 类 型 。 这 些 接 口 及 其 所提 供 的 方 法 在 程 序 员 参 考 中 描 述 。切 换 具 有 结 构 化 数 据 类 型 的 组 件数 个 从 DynAny 派 生 的 接 口 实 际 上 包 含 多 个 组 件 。 DynAny 接 口 提 供 允 许 您 在 这 些 组件 之 间 切 换 的 方 法 。 包 含 多 个 组 件 的 DynAny 派 生 对 象 保 留 到 当 前 组 件 的 指 针 。DynAny 方 法rewindnextcurrent_componentseek说 明将 当 前 组 件 指 针 重 设 定 到 第 一 个 组 件 。 如 果 对象 仅 包 含 一 个 组 件 , 则 无 效 。将 指 针 移 到 下 一 个 组 件 。 如 果 没 有 更 多 的 组 件或 对 象 仅 包 含 一 个 组 件 , 则 返 回 false 。返 回 一 个 DynAny 对 象 , 可 以 根 据 组 件 的TypeCode 将 该 对 象 窄 转 换 为 适 当 的 类 型 。将 当 前 的 组 件 指 针 设 定 到 指 定 的 从 0 开 始 的 索引 。 如 果 指 定 的 索 引 上 没 有 组 件 , 则 返 回false 。 如 果 指 定 了 一 个 负 值 索 引 , 则 将 当 前组 件 指 针 设 为 -1 ( 没 有 组 件 )。DynEnum这 个 接 口 表 示 一 个 单 个 枚 举 常 量 。 提 供 有 将 值 设 为 或 取 为 字 串 或 整 数 值 的 方 法 。使 用 动 态 管 理 的 类 型 25-3


实 例 IDLDynStruct这 个 接 口 表 示 一 个 动 态 结 构 化 struct 类 型 。 结 构 的 成 员 可 以 通 过 使 用 一 个NameValuePair 对 象 序 列 来 检 索 或 设 定 。 每 个 NameValuePair 对 象 包 含 成 员 的 名 称和 一 个 含 有 成 员 的 Type ( 类 型 ) 和 值 的 Any。您 可 以 使 用 rewind、next、current_component 和 seek 方 法 来 切 换 结 构 中 的 成 员 。提 供 有 设 定 和 取 得 结 构 的 成 员 的 方 法 。DynUnion这 个 接 口 表 示 一 个 union , 包 含 两 个 组 件 。 第 一 个 组 件 表 示 识 别 符 , 第 二 个 组 件 表示 成 员 值 。您 可 以 使 用 rewind、 next、current_component 和 seek 方 法 来 切 换 组 件 。 提 供 有 设定 和 取 得 并 集 的 识 别 符 和 成 员 值 的 方 法 。DynSequence 和 DynArrayDynSequence 或 DynArray 表 示 一 个 基 本 的 或 结 构 化 数 据 类 型 的 序 列 , 不 必 为 序 列 或阵 列 中 的 每 个 组 件 生 成 一 个 单 独 的 DynAny 对 象 。 DynSequence 中 的 组 件 数 量 可 以 改变 , 但 DynArray 中 的 组 件 数 量 是 固 定 的 。您 可 以 用 rewind、 next、 current_component 和 seek 方 法 来 切 换 DynArray 或DynSequence 中 的 成 员 。实 例 IDL以 下 的 代 码 示 例 说 明 在 实 例 客 户 和 服 务 器 应 用 中 的 IDL 。 StructType 结 构 包 括 两个 基 本 数 据 类 型 和 一 个 枚 举 型 值 。 PrinterManager 接 口 用 于 显 示 Any 的 内 容 , 其 中不 包 括 其 所 含 有 的 数 据 类 型 的 任 何 静 态 信 息 。// Printer.idlmodule Printer {enum EnumType {first, second, third, fourth};struct StructType {string str;EnumType e;float fl;};interface PrinterManager {void printAny(in any info);oneway void shutdown();};};25-4 <strong>VisiBroker</strong> 开 发 者 指 南


实 例 客 户 应 用 程 序实 例 客 户 应 用 程 序注 :以 下 的 两 个 代 码 示 例 说 明 一 个 客 户 端 应 用 , 客 户 端 应 用 可 以 在 <strong>VisiBroker</strong><strong>Edition</strong> 的 examples 目 录 下 的 dynany 目 录 中 找 到 。 路 径 是 install_dir/vbroker/examples/dynany。 该 客 户 端 应 用 使 用 DynStruct 接 口 动 态 地 创 建 StructType 结 构 。DynStruct 接 口 使 用 一 个 NameValuePair 对 象 列 表 来 表 示 结 构 成 员 及 其 相 应 的 值 。每 个 名 - 值 对 包 含 一 个 含 有 结 构 成 员 的 名 称 的 字 串 和 一 个 含 有 结 构 成 员 的 值 的 Any对 象 。在 用 常 规 方 法 初 始 化 <strong>VisiBroker</strong> ORB 并 限 制 到 PrintManager 对 象 之 后 , 客 户 执行 以 下 步 骤 :1 用 适 当 的 类 型 创 建 一 个 空 DynStruct。2 创 建 一 个 要 包 含 结 构 成 员 的 NameValuePair 对 象 序 列 。3 创 建 并 初 始 化 每 个 结 构 成 员 的 值 的 Any 对 象 。4 用 适 当 的 成 员 名 称 和 值 初 始 化 每 个 NameValuePair 。5 用 NameValuePair 序 列 初 始 化 DynStruct 对 象 。6 调 用 C++ PrinterManager::printAny 方 法 或 Java PrinterManager.printAny 方法 , 将 转 换 的 DynStruct 传 递 到 常 规 的 Any。在 将 DynAny 对 象 或 其 衍 生 类 型 之 一 作 为 操 作 请 求 的 一 个 参 数 传 递 之 前 , 您 必 须 使用 C++ DynAny::to_any 方 法 或 Java DynAny.to_any 方 法 将 其 转 换 到 Any 。// Client.C#include "Printer_c.hh"#include "dynany.h"int main(int argc, char* const* argv) {try {// 初 始 化 ORB。CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);DynamicAny::DynAnyFactory_var factory =DynamicAny::DynAnyFactory::_narrow(orb->resolve_initial_references("DynAnyFactory"));// 得 到 管 理 器 IdPortableServer::ObjectId_var managerId =PortableServer::string_to_ObjectId("PrinterManager");// 找 到 一 个 帐 户 管 理 器 。 给 出 POA 全 名 及 服 务 对 象 ID。Printer::PrinterManager_ptr manager = Printer::PrinterManager::_bind("/serverPoa", managerId);DynamicAny::NameValuePairSeq seq(3);seq.length(3);CORBA::Any strAny,enumAny,floatAny;strAny


实 例 客 户 应 用 程 序nvpairs[0].value = strAny;nvpairs[1].id = CORBA::string_dup("e");nvpairs[1].value = enumAny;nvpairs[2].id = CORBA::string_dup("fl");nvpairs[2].value = floatAny;seq[0] = nvpairs[0];seq[1] = nvpairs[1];seq[2] = nvpairs[2];// 创 建 动 态 structDynamicAny::DynStruct_var info =DynamicAny::DynStruct::_narrow(factory->create_dyn_any_from_type_code(Printer::_tc_StructType));info->set_members(seq);manager->printAny(*(info->to_any()));manager->shutdown();}catch(const CORBA::Exception& e) {cerr


实 例 服 务 器 应 用 程 序}catch (Exception e) {e.printStackTrace();}}}实 例 服 务 器 应 用 程 序以 下 的 两 个 代 码 示 例 说 明 一 个 服 务 器 应 用 , 该 服 务 器 应 用 可 以 在 <strong>VisiBroker</strong><strong>Edition</strong> distribution 的 examples 目 录 下 的 dynany 目 录 中 找 到 。 服 务 器 应 用 执 行以 下 步 骤 。1 初 始 化 <strong>VisiBroker</strong> ORB。2 为 POA 创 建 策 略 。3 创 建 PrintManager 对 象 。4 派 生 PrintManager 对 象 。5 打 印 一 条 消 息 并 等 待 进 入 的 操 作 请 求 。C++: ...int main(int argc, char* const* argv) {try {// 初 始 化 ORB。CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);int Verbose = 0;// 取 得 根 POA 的 参 考PortableServer::POA_var rootPOA =PortableServer::POA::_narrow(orb->resolve_initial_references("RootPOA"));CORBA::PolicyList policies;policies.length(1);policies[(CORBA::ULong)0] = rootPOA->create_lifespan_policy(PortableServer::PERSISTENT};// 用 正 确 的 策 略 创 建 serverPOAPortableServer::POA_var serverPOA = rootPOA->create_POA( "serverPoa",rootPOA->the_POAManager(),policies };// 解 析 Dynamic Any FactoryDynamicAny::DynAnyFactory_var factory =orb->resolve_initial_references("DynAnyFactory");PortableServer::ObjectId_var managerId =PortableServer::string_to_ObjectId("PrinterManager");// 创 建 打 印 机 管 理 器 对 象 。PrinterManagerImpl manager( orb, factory, serverPOA, managerId);// 派 生 新 建 的 对 象 。serverPOA->activate_object_with_id(managerId,&manager);// 激 活 POA 管 理 器rootPOA->the_POAManager()->activate();cout servant_to_reference(&manager)


实 例 服 务 器 应 用 程 序// 等 待 进 入 的 请 求 。orb->run();}catch(const CORBA::Exception& e) {cerr


e.printStackTrace();}}}实 例 服 务 器 应 用 程 序以 下 的 代 码 示 例 说 明 PrinterManager 在 不 知 道 Any 类 型 所 包 含 的 编 译 时 间 的 情 况下 , 如 何 执 行 这 些 步 骤 以 使 用 DynAny 处 理 Any 对 象 。1 创 建 DynAny 对 象 , 并 用 收 到 的 Any 将 其 初 始 化 。2 执 行 DynAny 对 象 的 类 型 上 的 switch。3 如 果 DynAny 包 含 基 本 数 据 类 型 , 则 直 接 打 印 该 值 。4 如 果 DynAny 包 含 Any 类 型 , 则 为 其 创 建 一 个 DynAny , 确 定 其 内 容 , 然 后 再 打 印该 值 。5 如 果 DynAny 包 含 enum, 则 为 其 创 建 一 个 DynEnum , 然 后 打 印 该 字 串 值 。6 如 果 DynAny 包 含 一 个 并 集 , 则 为 其 创 建 一 个 DynUnion , 然 后 打 印 并 集 的 识 别 符和 成 员 。7 如 果 DynAny 包 含 一 个 struct、 array、 或 sequence、 则 切 换 包 含 的 组 件 并 打 印出 各 值 。// PrinterManager 实 现class PrinterManagerImpl : public POA_Printer::PrinterManager{CORBA::ORB_var_orb;DynamicAny::DynAnyFactory_var _factory;PortableServer::POA_var _poa;PortableServer::ObjectId_var _oid;public:PrinterManagerImpl(CORBA::ORB_ptr orb,DynamicAny::DynAnyFactory_ptr DynAnyFactory,PortableServer::POA_ptr poa,PortableServer::ObjectId_ptr oid) : _orb(orb), _factory(DynAnyFactory),_poa(poa), _oid(oid) {}void printAny(const CORBA::Any& info) {try {// 创 建 一 个 DynAny 对 象DynamicAny::DynAny_var dynAny = _factory->create_dyn_any(info);display(dynAny);}catch (CORBA::Exception& e) {cout


实 例 服 务 器 应 用 程 序catch (const CORBA::Exception& e) {cout kind()) {case CORBA::tk_null:case CORBA::tk_void: {break;}case CORBA::tk_short: {cout get_short()


实 例 服 务 器 应 用 程 序display(dynAny);break;}case CORBA::tk_TypeCode: {cout get_typecode() rewind();CORBA::Boolean next = 1UL;while(next) {DynamicAny::DynAny_var d = value->current_component();display(d);next = value->next();}break;}case CORBA::tk_longlong: {cout get_longlong()


实 例 服 务 器 应 用 程 序Java:}};以 下 的 代 码 示 例 说 明 Java 下 的 PrinterManager 实 现// PrinterManagerImpl.javaimport java.util.*;import org.omg.DynamicAny.*;import org.omg.PortableServer.*;public class PrinterManagerImpl extends Printer.PrinterManagerPOA {private com.inprise.vbroker.CORBA.ORB _orb;private DynAnyFactory _factory;private POA _poa;private byte[] _oid;public PrinterManagerImpl(com.inprise.vbroker.CORBA.ORB orb,DynAnyFactory factory, POA poa, byte[] oid) {_orb = orb;_factory = factory;_poa = poa;_oid = oid;}public synchronized void printAny(org.omg.CORBA.Any info) {// 在 假 定 我 们 不 知 道 关 于 Any 中 的 类 型 的 任 何 静 态 信 息 的 情 况 下// 显 示 Any 信 息try {// 创 建 DynAny 对 象DynAny dynAny = _factory.create_dyn_any(info);display(dynAny);}catch (Exception e) {e.printStackTrace();}}public void shutdown() {try {_poa.deactivate_object(_oid);System.out.println("Server shutting down");_orb.shutdown(false);}catch (Exception e) {System.out.println(e);}}private void display(DynAny value) throws Exception {switch(value.type().kind().value()) {case org.omg.CORBA.TCKind._tk_null:case org.omg.CORBA.TCKind._tk_void: {break;}case org.omg.CORBA.TCKind._tk_short: {System.out.println(value.get_short());break;}case org.omg.CORBA.TCKind._tk_ushort: {25-12 <strong>VisiBroker</strong> 开 发 者 指 南


System.out.println(value.get_ushort());break;}case org.omg.CORBA.TCKind._tk_long: {System.out.println(value.get_long());break;}case org.omg.CORBA.TCKind._tk_ulong: {System.out.println(value.get_ulong());break;}case org.omg.CORBA.TCKind._tk_float: {System.out.println(value.get_float());break;}case org.omg.CORBA.TCKind._tk_double: {System.out.println(value.get_double());break;}case org.omg.CORBA.TCKind._tk_boolean: {System.out.println(value.get_boolean());break;}case org.omg.CORBA.TCKind._tk_char: {System.out.println(value.get_char());break;}case org.omg.CORBA.TCKind._tk_octet: {System.out.println(value.get_octet());break;}case org.omg.CORBA.TCKind._tk_string: {System.out.println(value.get_string());break;}case org.omg.CORBA.TCKind._tk_any: {DynAny dynAny = _factory.create_dyn_any(value.get_any());display(dynAny);break;}case org.omg.CORBA.TCKind._tk_TypeCode: {System.out.println(value.get_typecode());break;}case org.omg.CORBA.TCKind._tk_objref: {System.out.println(value.get_reference());break;}case org.omg.CORBA.TCKind._tk_enum: {DynEnum dynEnum = DynEnumHelper.narrow(value);System.out.println(dynEnum.get_as_string());break;}case org.omg.CORBA.TCKind._tk_union: {实 例 服 务 器 应 用 程 序使 用 动 态 管 理 的 类 型 25-13


实 例 服 务 器 应 用 程 序DynUnion dynUnion = DynUnionHelper.narrow(value);display(dynUnion.get_discriminator());display(dynUnion.member());break;}case org.omg.CORBA.TCKind._tk_struct:case org.omg.CORBA.TCKind._tk_array:case org.omg.CORBA.TCKind._tk_sequence: {value.rewind();boolean next = true;while(next) {DynAny d = value.current_component();display(d);next = value.next();}break;}case org.omg.CORBA.TCKind._tk_longlong: {System.out.println(value.get_longlong());break;}case org.omg.CORBA.TCKind._tk_ulonglong: {System.out.println(value.get_ulonglong());break;}case org.omg.CORBA.TCKind._tk_wstring: {System.out.println(value.get_wstring());break;}case org.omg.CORBA.TCKind._tk_wchar: {System.out.println(value.get_wchar());break;}default:System.out.println("Invalid type");}}}25-14 <strong>VisiBroker</strong> 开 发 者 指 南


第章使 用 valuetypes第 26 章理 解 valuetypes本 章 说 明 如 何 在 <strong>VisiBroker</strong> <strong>Edition</strong> 中 使 用 valuetype IDL 类 型 。IDL 类 型 valuetype 用 于 通 过 网 络 传 递 状 态 数 据 。 valuetype 被 认 为 是 具 有 继 承 性和 方 法 的 最 佳 struct。 Valuetypes 不 同 于 普 通 接 口 , 因 为 它 们 包 含 用 于 描 述valuetype 状 态 的 属 性 , 并 且 包 含 接 口 状 态 之 外 的 实 现 详 细 资 料 。 以 下 IDL 代 码声 明 了 一 个 简 单 的 valuetype :module Map {valuetype Point {public long x;public long y;private string label;factory create (in long x, in long y, in string z);void print();};};Valuetype 始 终 是 本 地 的 Valuetype。 它 们 不 在 <strong>VisiBroker</strong> ORB 上 注 册 , 并 且不 需 要 标 识 , 因 为 它 们 的 值 就 是 它 们 的 标 识 。 因 此 无 法 远 程 调 用 它 们 。具 体 valuetypes具 体 valuetypes 包 含 状 态 数 据 。 它 们 可 以 通 过 以 下 方 法 扩 展 IDL 结 构 的 表 现 力 :● 允 许 单 一 具 体 valuetype 派 生 和 多 个 抽 象 valuetype 派 生● 允 许 多 接 口 支 持 ( 一 个 具 体 接 口 支 持 和 多 个 抽 象 接 口 支 持 )● 允 许 任 意 递 归 值 类 型 定 义使 用 valuetypes 26-1


理 解 valuetypes● 允 许 空 值 语 义● 允 许 共 享 语 义Valuetype 派 生您 可 以 从 一 个 具 体 Valuetype 中 派 生 其 它 具 体 Valuetype。 然 而 , 您 也 可 以 从 多个 其 它 抽 象 valuetypes 中 派 生 valuetypes。共 享 语 义其 它 Valuetype 在 其 它 实 例 之 间 或 之 内 可 以 共 享 Valuetype 实 例 。 其 它 IDL 数据 类 型 , 如 struct、 unions 和 sequences, 无 法 共 享 。 共 享 的 Valuetypes 在 发送 环 境 和 接 收 环 境 之 间 结 构 相 同 。此 外 , 在 将 相 同 的 valuetype 传 递 到 两 个 或 更 多 变 量 的 操 作 中 时 , 对 于 这 两 个 变量 , 接 收 上 下 文 会 接 收 到 相 同 的 valuetype 引 用 。 与 structs、 unions 和sequences 等 IDL 数 据 类 型 不 同 ,空 语 义空 valuetypes 可 通 过 网 络 传 递 。 例 如 , 通 过 将 结 构 转 变 成 已 转 变 的 valuetype,您 可 以 传 递 空 值 结 构 。 有 关 详 情 , 请 参 阅 第 26-7 页 " 转 变 的 valuetypes"。工 厂工 厂 是 以 valuetypes 声 明 的 便 于 创 建 值 类 型 的 方 法 。 有 关 工 厂 详 情 , 请 参 阅 第26-5 页 " 实 现 工 厂 "。抽 象 valuetypesvaluetypes 类 型 只 包 含 方 法 , 不 具 有 状 态 。 无 法 用 示 例 表 示 它 们 。 抽 象valuetypes 是 具 有 纯 本 地 实 现 的 操 作 签 名 集 。例 如 , 以 下 IDL 定 义 的 抽 象 valuetype 帐 户 不 包 含 状 态 , 但 包 含 一 种 方 法 , 即get_name:abstract valuetype Account{string get_name();}现 在 定 义 了 从 抽 象 valuetypes 中 继 承 get_name 方 法 的 两 个 valuetypes。valuetype savingsAccount:Account{private long balance;}valuetype checkingAccount:Account{private long balance;}这 两 个 valuetypes 包 含 变 量 balance, 并 且 它 们 从 抽 象 valuetype Account 中 继承 了 get_name 方 法 。26-2 <strong>VisiBroker</strong> 开 发 者 指 南


实 现 valuetypes实 现 valuetypesC++:Java:要 在 应 用 程 序 中 实 现 valuetypes, 请 执 行 以 下 操 作 :1 在 IDL 文 件 中 定 义 valuetypes。2 使 用 以 下 语 言 编 译 IDL 文 件 :idl2cpp 或idl2java3 通 过 继 承 valuetype 基 础 类 来 实 现 valuetype。4 实 现 工 厂 类 以 执 行 在 IDL 中 定 义 的 任 何 工 厂 方 法 。5 执 行 create_for_unmarshal 方 法 。6 在 C++ 中 向 <strong>VisiBroker</strong> ORB 注 册 工 厂 。如 果 需 要 , 在 Java 中 向 <strong>VisiBroker</strong> ORB 注 册 工 厂 。1 执 行 _add_ref、 _remove_ref 和 _ref_countvalue 方 法 , 或 从CORBA::DefaultValueRefCountBase 中 进 行 推 导 。定 义 valuetypes在 下 面 的 IDL 示 例 中 , 您 定 义 了 一 个 用 于 在 图 形 上 定 义 点 的 名 为 “ 点 ” 的valuetype。 它 包 含 两 个 公 共 变 量 , 即 x 和 y 坐 标 , 一 个 点 标 签 专 用 变 量 , 即 值 类型 工 厂 , 以 及 用 于 打 印 点 的 打 印 方 法 。编 译 IDL 文 件C++:Java:既 然 定 义 了 IDL, 请 使 用 idl2cpp 对 其 进 行 编 译 以 创 建 C++ 源 文 件 , 或 使 用idl2java 对 其 进 行 编 译 以 创 建 Java 源 文 件 。 然 后 修 改 源 文 件 以 实 现valuetypes。如 果 编 译 上 述 IDL, 则 输 出 内 容 将 由 以 下 文 件 组 成 :● Map_c.cc● Map_c.hh● Map_s.cc● Map_s.hh● Point.java● PointDefaultFactory.java● PointHelper.java● PointHolder.java● PointValueFactory.java使 用 valuetypes 26-3


实 现 valuetypesC++:继 承 valuetype 基 础 类编 译 完 IDL 之 后 , 请 创 建 valuetype 实 现 。 实 现 类 将 继 承 基 础 类 。 该 类 包 含 在 值工 厂 中 被 调 用 的 构 建 器 , 并 包 含 在 IDL 中 声 明 的 所 有 变 量 和 方 法 。如 下 所 示 , 在 obv\PointImpl.java 中 , PointImpl 类 将 扩 展 从 IDL 中 生 成 的Point 类 。class PointImpl :public Map::OBV_Point, publicCORBA::DefaultValueRefCountBase {public:PointImpl(){}virtual ~PointImpl(){}CORBA_ValueBase* _copy_value() {return new PointImpl(x(), y(), new Map::Label(CORBA::string_dup(label())));}PointImpl( CORBA::Long x, CORBA::Long y, Map::Label_ptr label ): OBV_Point( x,y,label->_boxed_in()){}virtual void print() {cout


实 现 工 厂return new PointImpl();}};Point_init 包 含 公 共 方 法 create_for_unmarshal, 在 Map_c.hh 中 此 方 法 是 作 为 纯虚 拟 方 法 的 输 出 。 您 必 须 从 Point_init 中 派 生 类 , 并 执 行 create_for_unmarshal方 法 以 产 生 工 厂 类 。 在 编 译 IDL 文 件 时 , 它 不 会 为 此 创 建 框 架 类 。Java: public class PointDefaultFactory implements PointValueFactory {public java.io.Serializable read_value (org.omg.CORBA.portable.InputStream is){java.io.Serializable val = new PointImpl(); // Called the implementationclass// 创 建 并 初 始 化 值val = ((org.omg.CORBA_2_3.portable.InputStream)is).read_value(val);return val;}// 现 在 该 由 用 户 以 他 们 所 需 的 任 何 方 式 来 实 现 valuetype:public Point create (int x,int y,java.lang.String z) {// 实 现 :return null;}}调 用 PointImpl() 以 创 建 新 valuetype,read_value 会 从 InputStream 中 读 取 该 新valuetype。Java: 您 必 须 调 用 read_value, 否 则 工 厂 不 起 作 用 , 并 且 您 无 法 调 用 任 何 其 它 方 法 。向 <strong>VisiBroker</strong> ORB 注 册 工 厂C++:Java:调 用 ORB::register_value_factory 以 向 <strong>VisiBroker</strong> ORB 注 册 工 厂 。 有 关 注 册 工厂 的 详 情 , 请 参 阅 “ 第 26-7 页 " 注 册 valuetypes"。调 用 ORB.register_value_factory 以 向 <strong>VisiBroker</strong> ORB 注 册 工 厂 。 仅 在 未 对 工厂 valuetypenameDefaultFactory 命 名 时 执 行 此 操 作 。 有 关 注 册 工 厂 的 详 情 , 请 参阅 第 26-7 页 " 注 册 valuetypes"。实 现 工 厂在 <strong>VisiBroker</strong> ORB 接 收 valuetype 时 , 首 先 必 须 对 其 解 包 , 然 后 必 须 查 找 该 类型 的 相 应 工 厂 , 以 便 创 建 该 类 型 的 新 实 例 。 在 创 建 实 例 后 , 将 值 数 据 解 包 成 实 例 。类 型 是 通 过 作 为 调 用 的 一 部 分 来 传 递 的 RepositoryID 来 识 别 的 。 类 型 和 工 厂 之 间的 映 射 是 特 写 于 语 言 的 映 射 。以 下 代 码 示 例 包 含 使 用 JDK 1.2 实 现 “ 点 ” valuetype 工 厂 的 示 例 。使 用 valuetypes 26-5


实 现 工 厂C++:class PointFactory:public CORBA::ValueFactoryBase{public:PointFactory(){}virtual ~PointFactory(){}CORBA::ValueBase* create_for_unmarshal() {return new PointImpl();}};Java 中 的 点 valuetype 工 厂 :Java: public class PointDefaultFactory implements PointValueFactory {public java.io.Serializable read_value (org.omg.CORBA.portable.InputStreamis) {java.io.Serializable val = new PointImpl();// 创 建 并 初 始 化 值// 进 行 此 调 用 非 常 重 要 。val = ((org.omg.CORBA_2_3.portable.InputStream)is).read_value(val);return val;}public Point create (int x, int y, java.lang.String z) {// 实 现 :return NO_IMPLEMENT;}}C++:<strong>VisiBroker</strong> <strong>Edition</strong> 4.5 或 以 后 的 版 本 将 为 JDK 1.2 或 JDK 1.3 默 认 值 工 厂 方 法 生成 相 应 的 签 名 。 现 有 (4.0) 的 生 成 代 码 并 不 是 为 了 在 JDK 1.3 中 运 行 , 除 非 您 按 照以 下 方 法 修 改 默 认 值 工 厂 方 法 签 名 。 如 果 您 在 JDK 1.3 中 使 用 现 有 代 码 , 但 并 未 修改 默 认 值 工 厂 , 则 代 码 将 不 会 进 行 编 译 , 或 者 会 出 现 NO_IMPLEMENT 例 外 。 因 此 ,建 议 您 重 新 生 成 代 码 以 生 成 相 应 的 签 名 。以 下 代 码 示 例 说 明 了 应 该 如 何 修 改 默 认 值 工 厂 方 法 签 名 , 以 确 保 代 码 会 在 JDK 1.3中 进 行 编 译 。class PointFactory:public CORBA::ValueFactoryBase{public:PointFactory(){}virtual ~PointFactory(){}CORBA::ValueBase* create_for_unmarshal() {return new PointImpl();}};Java 中 用 于 显 示 生 成 的 JDK 1.3 代 码 的 方 法 签 名 的 工 厂 代 码 :Java: public class PointDefaultFactory implements PointValueFactory {public java.io.Serializable read_value(org.omg.CORBA_2_3.portable.InputStreamis) {java.io.Serializable val = new PointImpl();// 创 建 并 初 始 化 值// 进 行 此 调 用 非 常 重 要 。val = ((org.omg.CORBA_2_3.portable.InputStream)is).read_value(val);26-6 <strong>VisiBroker</strong> 开 发 者 指 南


转 变 的 valuetypes}return val;}public Point create (int x, int y, java.lang.String z) {// 实 现 :return NO_IMPLEMENT;}转 变 的 valuetypes工 厂 和 valuetypes在 <strong>VisiBroker</strong> ORB 接 收 valuetype 时 , 它 会 查 找 该 类 型 的 工 厂 。 它 将 查 找 名 为valuetypeDefaultFactory 的 工 厂 。 例 如 , 点 valuetype 的 工 厂 名 为PointDefaultFactory。 如 果 相 应 的 工 厂 不 符 合 此 命 名 方 式(valuetypeDefaultFactory), 则 必 须 注 册 相 应 的 工 厂 , 以 便 <strong>VisiBroker</strong> ORB 能 够创 建 valuetype 实 例 。如 果 <strong>VisiBroker</strong> ORB 无 法 找 到 指 定 valuetype 的 相 应 工 厂 , 则 会 掷 出MARSHAL 违 例 以 及 标 识 的 minor code ( 次 要 代 码 )。注 册 valuetypes每 种 语 言 映 射 都 指 定 了 注 册 发 生 的 方 式 和 时 间 。 如 果 使 用valuetypeDefaultFactory 命 名 规 则 创 建 了 工 厂 , 则 默 认 为 已 注 册 该 工 厂 , 因 此 不需 明 确 地 向 <strong>VisiBroker</strong> ORB 注 册 工 厂 。要 注 册 不 符 合 valuetypeDefaultFactory 命 名 规 则 的 工 厂 , 请 调 用register_value_factory。 要 注 销 工 厂 , 请 在 <strong>VisiBroker</strong> ORB 中 调 用unregister_value_factory。 通 过 在 <strong>VisiBroker</strong> ORB 中 调 用lookup_value_factory, 您 也 可 以 查 找 注 册 的 valuetype 工 厂 。转 变 的 valuetypes 允 许 您 将 无 值 的 IDL 数 据 类 型 汇 集 成 valuetypes。 例 如 , 以下 IDL 转 变 valuetype 声 明 :valuetype Label string;等 同 于 此 IDL valuetype 声 明 :valuetype Label{public string name;}通 过 将 其 它 数 据 类 型 转 变 成 valuetypes, 它 允 许 您 使 用 valuetype 的 空 语 义 和 共享 语 义 。Valuebox 完 全 通 过 生 成 的 代 码 来 实 现 。 不 需 要 用 户 代 码 。使 用 valuetypes 26-7


抽 象 接 口抽 象 接 口客 户 valuetypes抽 象 接 口 允 许 您 在 运 行 时 选 择 是 通 过 值 还 是 通 过 引 用 来 传 递 对 象 。它 们 在 以 下 方 面 不 同 于 IDL 接 口 :● 实 际 参 数 类 型 决 定 是 根 据 引 用 传 递 对 象 , 还 是 传 递 valuetype。 参 数 类 型 根 据以 下 两 个 规 则 决 定 。 如 果 参 数 类 型 是 普 通 接 口 类 型 或 子 类 型 , 接 口 类 型 是 签 名 抽象 接 口 类 型 的 子 类 型 , 并 且 已 向 <strong>VisiBroker</strong> ORB 注 册 对 象 , 则 将 该 参 数 类 型当 作 对 象 引 用 。 如 果 不 能 将 参 数 类 型 作 为 对 象 引 用 传 递 出 去 , 但 可 以 作 为 值 传 递出 去 , 则 将 该 参 数 类 型 当 作 值 。 如 果 不 能 作 为 值 传 递 出 去 , 则 会 出 现 BAD_PARAM例 外 。● 在 C++ 中 绝 对 接 口 暗 中 并 不 来 源 于 CORBA::Object, 在 Java 中 也 不 来 源 于org.omg.CORBA.Object, 因 为 它 们 可 以 表 示 对 象 引 用 或 valuetype。Valuetype并 不 一 定 要 支 持 公 用 对 象 引 用 操 作 。 如 果 可 将 抽 象 接 口 成 功 窄 转 换 成 对 象 引 用 类型 , 则 可 以 在 C++ 中 调 用 CORBA::Object 操 作 , 或 在 Java 中 调 用org.omg.CORBA.Object 操 作 。● 抽 象 接 口 只 能 从 其 它 抽 象 接 口 来 继 承 。● Valuetype 可 支 持 一 个 或 多 个 抽 象 接 口 。例 如 , 请 分 析 以 下 抽 象 接 口 。abstract interface ai{};interface itp :ai{};valuetype vtp supports ai{};interface x {void m(ai aitp);};valuetype y {void op(ai aitp);};对 于 方 法 m 的 变 量 :● itp 始 终 作 为 对 象 引 用 被 传 递 出 去 。● vtp 作 为 值 被 传 递 出 去 。通 过 在 IDL 中 声 明 客 户 的 valuetype, 您 可 以 忽 视 模 型 的 汇 集 和 解 包 , 只 负 责 编码 和 解 码 。custom valuetype customPoint{public long x;public long y;private string label;26-8 <strong>VisiBroker</strong> 开 发 者 指 南


可 截 取 的 valuetypesC++:Java:factory create(in long x, in long y, in string z);};您 必 须 从 CustomMashal 接 口 中 执 行 汇 集 和 解 包 方 法 。在 声 明 客 户 valuetype 时 , 与 普 通 valuetype 一 样 , 该 valuetype 会 扩 展 与CORBA::StreamableValue 相 对 的 CORBA::CustomValue。 编 译 程 序 没 有 为 您 的valuetype 生 成 读 取 或 编 写 的 方 法 。您 必 须 分 别 使 用 CORBA::DataInputStream 和 CORBA::DataOutputStream 执 行 自 己 的读 取 和 编 写 方 法 以 读 取 和 编 写 值 。在 声 明 客 户 valuetype 时 , 与 普 通 valuetype 一 样 , 该 valuetype 将 扩 展 与org.omg.CORBA.portable.StreamableValue 相 对 的org.omg.CORBA.portable.CustomValue。 编 译 程 序 没 有 为 您 的 valuetype 生 成 读 取或 编 写 的 方 法 。您 必 须 分 别 使 用 org.omg.CORBA.portable.DataInputStream 和org.omg.CORBA.portable.DataOutputStream 来 执 行 自 己 的 读 取 和 编 写 方 法 以 读 取 和编 写 值 。可 截 取 的 valuetypes注 :可 截 取 的 valuetypes 允 许 您 将 继 承 的 valuetype 作 为 其 父 项 。以 下 IDL 定 义 的 valuetype checkingAccount 继 承 自 基 本 类 型 Account, 并 且 可 以在 接 收 对 象 中 被 截 取 。valuetype checkingAccount:truncatable Account{private long balance;}如 果 接 收 环 境 在 派 生 的 valuetype 中 不 需 要 新 数 据 成 员 或 方 法 , 并 且 接 收 环 境 无法 识 别 派 生 的 valuetype, 则 这 很 有 用 。 然 而 , 在 将 valuetype 传 递 至 接 收 环 境中 时 , 派 生 的 valuetype ( 非 父 数 据 类 型 ) 的 任 何 状 态 数 据 都 将 丢 失 。您 无 法 使 客 户 valuetype 成 为 可 截 取 的 valuetype。使 用 valuetypes 26-9


26-10 <strong>VisiBroker</strong> 开 发 者 指 南


第章使 用 URL 命 名第 27 章注 :本 章 介 绍 如 何 使 用 URL 命 名 服 务 , 它 允 许 您 使 URL ( 统 一 资 源 定 位 符 ) 与 对 象的 IOR ( 互 操 作 对 象 引 用 ) 相 关 联 。 URL 限 制 到 对 象 后 , 客 户 端 应 用 程 序 可 以 通过 使 URL 指 定 为 字 串 ( 而 不 是 对 象 名 称 ) 获 得 对 象 的 引 用 。 如 果 要 客 户 端 应 用 程序 定 位 对 象 而 又 不 使 用 osagent 或 CORBA 命 名 服 务 , 指 定 URL 是 一 种 选 择 。所 有 这 些 介 绍 仅 适 用 于 Java。URL 命 名 服 务注 :URL 命 名 服 务 是 一 种 简 单 的 机 制 , 它 让 服 务 器 对 象 使 其 IOR 以 文 件 中 字 串 的 形 式与 URL 相 关 联 。 然 后 , 客 户 端 程 序 通 过 此 URL 定 位 对 象 , 该 URL 指 向 Web 服务 器 上 含 有 字 串 化 URL 的 文 件 。URL 命 名 服 务 支 持 用 于 注 册 对 象 的 http URL 方案 和 Java 在 运 行 时 支 持 的 任 何 URL 方 案 ( 例 如 http:、 ftp: 或 file: )(URL用 于 定 位 对 象 )。此 URL 命 名 服 务 提 供 一 种 除 使 用 智 能 代 理 或 CORBA 命 名 服 务 之 外 定 位 对 象 的 方法 。 它 使 客 户 端 应 用 程 序 能 够 定 位 任 何 厂 商 提 供 的 对 象 。 此 服 务 的 IDL 规 范 如 下所 示 。<strong>VisiBroker</strong> <strong>Edition</strong> 的 URL 命 名 服 务 支 持 Java 环 境 支 持 的 任 何 形 式 的 URL 处理 。// WebNaming.idl#pragma prefix "inprise.com"module URLNaming {exception InvalidURL{string reason;};exception CommFailure{string reason;};exception ReqFailure{string reason;};exception AlreadyExists{string reason;};abstract interface Resolver {// 读 操 作Object locate(in string url_s)使 用 URL 命 名 27-1


注 册 对 象raises (InvalidURL, CommFailure, ReqFailure);// 写 操 作void force_register_url(in string url_s, in Object obj)raises (InvalidURL, CommFailure, ReqFailure);void register_url(in string url_s, in Object obj)raises (InvalidURL, CommFailure, ReqFailure, AlreadyExists);};};注 册 对 象注 :对 象 服 务 器 通 过 限 制 到 Resolver 注 册 对 象 , 然 后 使 用 register_url 或force_register_url 方 法 使 URL 与 对 象 的 IOR 相 关 联 。 register_url 用 于 使URL 与 对 象 IOR 相 关 联 ( 如 果 之 前 没 有 关 联 存 在 )。 使 用 force_register_url 方法 使 URL 与 对 象 IOR 相 关 联 , 而 不 管 是 否 URL 已 经 限 制 到 该 对 象 。 如 果 在 同 一环 境 下 使 用 register_url 方 法 , 会 发 生 AlreadyExists 违 例 。 要 取 得 关 于 所 有 可 用方 法 的 信 息 , 请 参 阅 程 序 员 参 考 。有 关 说 明 服 务 器 端 此 功 能 使 用 方 法 的 实 例 , 请 参 阅 本 节 中 的 第 一 个 代 码 样 本 。 此 实例 使 用 force_register_url。 要 使 force_register_url 成 功 , 必 须 允 许 Web 服 务器 发 布 HTTP PUT 命 令 。 本 章 中 的 实 例 代 码 位 于 程 序 员 参 考 产 品 的 安 装 目 录java_examples 目 录 下 的 bank_URL 目 录 中 。要 获 得 解 析 器 引 用 , 请 使 用 <strong>VisiBroker</strong> ORB 的 resolve_initial_references 方法 , 如 实 例 中 所 示 。. . .public class Server {public static void main(String[] args) {if (args.length == 0) {System.out.println("Usage:vbj Server ");return;}String url = args[0];try {// 初 始 化 ORB。org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);// 取 得 根 POA 的 引 用POA rootPOA =POAHelper.narrow(orb.resolve_initial_references("RootPOA"));// 创 建 服 务 对 象AccountManagerImpl managerServant = new AccountManagerImpl();// 确 定 服 务 对 象 IDbyte[] managerId = "BankManager".getBytes();// 用 myPOA 上 的 ID 激 活 服 务 对 象rootPOA.activate_object_with_id(managerId, managerServant);// 激 活 POA 管 理 器rootPOA.the_POAManager().activate();// 创 建 对 象 引 用org.omg.CORBA.Object manager =rootPOA.servant_to_reference(managerServant);// 获 得 URLNaming Resolver27-2 <strong>VisiBroker</strong> 开 发 者 指 南


通 过 URL 定 位 对 象实 例 :实 例 :}Resolver resolver = ResolverHelper.narrow(orb.resolve_initial_references("URLNamingResolver"));// 注 册 对 象 引 用 ( 如 果 存 在 则 覆 盖 )resolver.force_register_url(url, manager);System.out.println(manager + " is ready.");// 等 待 进 入 的 请 求orb.run();} catch(Exception e) {e.printStackTrace();}}在 此 代 码 样 本 中 , args[0] 即 依 照 本 格 式 。http://://ior_file_name 用 户 所 指 定 的 存 储 字 串 化 对 象 引 用 的 文 件 名 称 。 如 果 是 使 用Gatekeeper, 而 不 是 HTTP 服 务 器 , ior_file_name 的 后 缀 必 须 是 .ior。 使 用Gatekeeper 及 其 默 认 端 口 号 码 的 实 例 如 下 所 示 :http://mars:15000/URLNaming/Bank_Manager.ior通 过 URL 定 位 对 象客 户 端 应 用 程 序 不 需 要 限 制 到 Resolver, 在 调 用 bind 方 法 时 只 需 指 定 URL 即 可 ,如 下 列 样 本 所 示 。 限 制 会 接 受 URL 作 为 对 象 名 称 。 如 果 URL 无 效 , 会 发 生InvalidURL 违 例 。 bind 方 法 为 您 透 明 调 用 locate()。 有 关 如 何 使 用 locate() 的 实例 , 请 参 阅 下 列 第 二 个 样 本 。// ResolverClient.javaimport com.inprise.vbroker.URLNaming.*;public class ResolverClient {public static void main(String[] args) {if (args.length == 0) {System.out.println("Usage:vbj Client [Account name]");return;}String url = args[0];try {// 初 始 化 ORB。org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);// 获 得 URLNaming ResolverResolver resolver = ResolverHelper.narrow(orb.resolve_initial_references("URLNamingResolver"));// 定 位 对 象Bank.AccountManager manager =Bank.AccountManagerHelper.narrow(resolver.locate(url));// 使 用 args[0] 作 为 帐 户 名 称 , 或 使 用 缺 省 值 。String name = args.length > 1 ? args[1] :"Jack B. Quick";// 要 求 帐 户 管 理 器 打 开 一 个 命 名 的 帐 户 。Bank.Account account = manager.open(name);// 得 到 帐 户 的 余 额 。使 用 URL 命 名 27-3


通 过 URL 定 位 对 象}float balance = account.balance();// 打 印 余 额 。System.out.println("The balance in " + name + "'s account is $" + balance);} catch(Exception e) {e.printStackTrace();}}使 用 Resolver.locate 方 法 获 得 对 象 引 用 :// Client.javapublic class Client {public static void main(String[] args) {if (args.length == 0) {System.out.println("Usage:vbj Client [Account name]");return;}String url = args[0];// 初 始 化 ORB。org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);// 定 位 对 象Bank.AccountManager manager = Bank.AccountManagerHelper.bind(orb, url);// 使 用 args[0] 作 为 帐 户 名 称 , 或 使 用 缺 省 值 。String name = args.length > 1 ? args[1] :"Jack B. Quick";// 要 求 帐 户 管 理 器 打 开 一 个 命 名 的 帐 户 。Bank.Account account = manager.open(name);// 得 到 帐 户 的 余 额 。float balance = account.balance();// 打 印 余 额 。System.out.println("The balance in " + name + "'s account is $" +balance);}}27-4 <strong>VisiBroker</strong> 开 发 者 指 南


第章双 向 通 信第 28 章使 用 双 向 IIOP本 章 描 述 不 使 用 Gatekeeper 时 如 何 在 <strong>VisiBroker</strong> <strong>Edition</strong> 下 建 立 双 向 通 信 。 有关 使 用 Gatekeeper 时 的 双 向 通 信 的 信 息 , 请 参 阅 <strong>VisiBroker</strong> <strong>Edition</strong> 的 用 户 指南 。注 : 在 实 现 双 向 IIOP 前 , 请 阅 读 第 28-6 页 " 安 全 注 意 事 项 "大 多 数 通 过 Internet 交 换 信 息 的 客 户 和 服 务 器 通 常 是 由 公 司 的 防 火 墙 保 护 的 。 在那 些 请 求 仅 由 客 户 发 起 的 系 统 中 , 防 火 墙 通 常 对 客 户 是 透 明 的 。 但 是 , 在 有 些 情况 , 客 户 需 要 异 步 信 息 , 也 就 是 说 , 不 针 对 请 求 的 信 息 必 须 到 达 。 客 户 端 的 防 火 墙阻 止 服 务 器 建 立 连 接 回 到 客 户 端 。 因 此 , 如 果 一 个 客 户 要 接 收 异 步 信 息 , 它 通 常 需要 额 外 的 配 置 。在 早 期 版 本 的 GIOP 和 <strong>VisiBroker</strong> 中 , 允 许 服 务 器 给 一 个 客 户 发 送 异 步 信 息 的 唯一 方 法 是 使 用 客 户 端 的 Gatekeeper 来 处 理 服 务 器 的 回 调 。当 需 要 将 异 步 信 息 传 回 客 户 端 时 ( 这 些 一 定 会 被 客 户 端 防 火 墙 丢 弃 ) 时 , 如 果 您 使用 双 向 IIOP, 而 不 是 让 服 务 器 打 开 单 独 的 到 客 户 端 的 连 接 , 则 服 务 器 使 用 客 户 发起 的 连 接 以 将 信 息 传 送 给 客 户 。CORBA 规 范 也 加 入 了 新 的 策 略 以 方 便 地 控 制 这 一特 性 。因 为 双 向 IIOP 允 许 建 立 回 调 而 无 须 使 用 Gatekeeper, 它 给 客 户 的 部 署 带 来 了 极大 的 便 利 。双 向 <strong>VisiBroker</strong> ORB 属 性有 三 个 属 性 提 供 双 向 支 持 :vbroker.orb.enableBiDir=client|server|both|none双 向 通 信 28-1


关 于 实 例vbroker.se..scm..manager.exportBiDir=true|falsevbroker.se..scm..manager.importBiDir=true|falsevbroker.orb.enableBiDir 属 性vbroker.orb.enableBiDir 属 性 可 被 用 于 服 务 器 和 客 户 上 以 实 现 双 向 通 信 。 该 属 性允 许 您 将 现 有 的 单 向 应 用 转 换 成 双 向 应 用 , 而 无 须 改 变 任 何 代 码 。vbroker.orb.enableBiDir 属 性 可 用 于 设 定 下 列 值 :值说 明client在 所 有 的 POA 和 所 有 外 发 连 接 实 现 双 向 IIOP。 该 设 定 相 当 于 用 以下 的 方 式 来 创 建 所 有 的 POA: 设 定 BiDirectional 策 略 为 both 并 设定 BiDirectional 策 略 的 策 略 门 限 为 <strong>VisiBroker</strong> ORB 级 别 上 的both 。 此 外 , 创 建 的 所 有 SCM 都 将 允 许 双 向 通 信 , 就 好 象 每 个SCM 的 exportBiDir 属 性 都 已 设 定 为 true 。server使 服 务 器 接 受 和 使 用 双 向 的 连 接 。 这 相 当 于 将 所 有 SCM 上 的importBiDir 属 性 设 定 为 true。both 将 属 性 设 置 到 client 和 server 上 。none 完 全 禁 止 双 向 GIOP 。 这 是 默 认 值 。vbroker.se..scm..manager.exportBiDir 属 性vbroker.se..scm..manager.exportBiDir 属 性 是 一 个 客 户 端 属性 。 在 默 认 情 况 下 , <strong>VisiBroker</strong> ORB 不 对 其 作 任 何 设 定 。 将 它 设 定 为 true 将 允许 在 指 定 的 服 务 器 引 擎 上 创 建 双 向 回 调 POA。 将 它 设 定 为 false 将 禁 止 在 指 定 的服 务 器 引 擎 上 创 建 双 向 POA 。vbroker.se..scm..manager.importBiDir 属 性vbroker.se..scm..manager.importBiDir 属 性 是 一 个 客 户 端 属性 。 在 默 认 情 况 下 , <strong>VisiBroker</strong> ORB 不 对 其 作 任 何 设 定 。 设 定 它 为 true 将 允 许服 务 器 端 重 新 使 用 已 由 客 户 建 立 的 用 于 发 送 请 求 到 客 户 端 的 连 接 。 设 定 它 为 false将 禁 止 对 这 种 连 接 的 重 新 使 用 。注 :在 SCM 的 创 始 过 程 中 , 这 些 属 性 仅 被 评 价 一 次 。 SCM 上 的 exportBiDir 和importBiDir 属 性 总 是 控 制 enableBiDir 属 性 。 换 句 话 说 , 如 果 这 两 种 属 性 被 设 定为 冲 突 的 值 , 则 与 SCM 相 关 的 属 性 将 生 效 。 这 允 许 您 在 全 局 范 围 内 设 定enableBiDir 属 性 和 关 闭 特 定 SCM 中 的 BiDir 。关 于 实 例示 范 如 何 使 用 这 一 特 性 的 实 例 位 于 Visibroker 安 装 目 录 的 examples/bidir-iiop子 目 录 下 。所 有 的 实 例 均 基 于 一 个 简 单 的 股 票 报 价 回 调 应 用 :1 客 户 创 建 一 个 处 理 服 票 报 价 更 新 的 CORBA 对 象 ;2 客 户 发 送 该 CORBA 对 象 的 引 用 到 服 务 器 ;3 服 务 器 调 用 该 回 调 对 象 以 定 期 更 新 服 票 报 价 。在 以 下 的 几 个 小 节 中 , 这 些 实 例 将 用 来 说 明 双 向 IIOP 特 性 的 不 同 方 面 。28-2 <strong>VisiBroker</strong> 开 发 者 指 南


在 现 有 应 用 上 实 现 双 向 IIOP在 现 有 应 用 上 实 现 双 向 IIOPC++:Java:C++:Java:C++:Java:您 可 以 在 现 有 的 <strong>VisiBroker</strong> Java 和 C++ 应 用 程 序 上 实 现 双 向 通 信 , 而 无 须 修 改任 何 源 代 码 。 有 一 个 未 使 用 Bidirectional IIOP 的 简 单 回 调 应 用 程 序 存 储 在examples/bidir-iiop/basic/ 目 录 下 。要 在 该 应 用 上 实 现 双 向 IIOP, 您 需 要 设 置 vbroker.orb.enableBiDir 属 性 :1 确 定 osagent 正 在 运 行 。2 启 动 服 务 器 。在 UNIX 系 统 中 :prompt> -Dvbroker.orb.enableBiDir=server Server &prompt> vbj -Dvbroker.orb.enableBiDir=server Server &在 Windows 系 统 中prompt> start vbj -Dvbroker.orb.enableBiDir=server Serverprompt> start vbj -Dvbroker.orb.enableBiDir=server Server3 启 动 客 户 :prompt> vbj-Dvbroker.orb.enableBiDir=client RegularClientprompt> -Dvbroker.orb.enableBiDir=client RegularClient现 在 , 现 有 的 回 调 应 用 使 用 双 向 IIOP 并 通 过 一 个 客 户 端 的 防 火 墙 工 作 。显 式 实 现 双 向 IIOP位 于 examples/bidir-iiop/basic 下 的 Client 是 从 上 述 的 RegularClient 派 生的 , 区 别 仅 在 于 这 个 客 户 在 程 序 中 方 式 实 现 了 双 向 IIOP。要 作 改 动 的 只 是 客 户 代 码 而 已 。 要 将 单 向 客 户 转 换 成 双 向 客 户 , 您 需 要 作 的 所 有 工作 是 :1 将 BiDirectional 策 略 包 含 在 回 调 POA 的 策 略 列 表 上 , 并2 将 BiDirectional 策 略 加 入 到 对 象 引 用 的 门 限 列 表 上 , 该 对 象 引 用 将 引 用 我 们 要在 其 实 现 双 向 IIOP 的 服 务 器 。3 在 客 户 端 将 exportBiDir 属 性 设 定 为 true。在 以 下 的 代 码 示 例 中 , 实 现 双 向 IIOP 的 代 码 用 粗 体 表 示 :C++: try {CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);// 得 到 管 理 器 IdPortableServer::ObjectId_var managerId =PortableServer::string_to_ObjectId("BankManager");PortableServer::ObjectId_var oid =PortableServer::string_to_ObjectId("QuoteServer");双 向 通 信 28-3


显 式 实 现 双 向 IIOPQuote::QuoteServer_var quoter = Quote::QuoteServer::_bind("/QuoteServer_poa",oid);// 建 立 回 调 对 象 ...... 先 取 得 RootPOACORBA::Object_var obj = orb->resolve_initial_references("RootPOA");PortableServer::POA_var rootPOA = PortableServer::POA::_narrow(obj);PortableServer::POAManager_var the_manager = rootPOA->the_POAManager();PortableServer::POA_var consumer_poa;// 建 立 一 个 策 略 。CORBA::Any policy_value;policy_value create_POA("QuoteConsumer_poa", the_manager, policies);QuoteConsumerImpl* consumer = new QuoteConsumerImpl;oid = PortableServer::string_to_ObjectId("consumer");consumer_poa->activate_object_with_id(oid, consumer);the_manager->activate();CORBA::Object_var obj = quoter->set_policy_overrides(policies,CORBA::ADD_OVERRIDE);quoter = Quote::QuoteServer::_narrow(obj);obj = consumer_poa->id_to_reference(oid);Quote::QuoteConsumer_var quote_consumer =Quote::QuoteConsumer::_narrow(obj);quoter->registerConsumer(quote_consumer.in());cout


显 式 实 现 双 向 IIOPorg.omg.CORBA.Policy[] policies = {// 设 定 bidir 策 略orb.create_policy(BIDIRECTIONAL_POLICY_TYPE.value, bidirPolicy)};org.omg.PortableServer.POA callbackPOA =rootPOA.create_POA("bidir", rootPOA.the_POAManager(), policies);QuoteConsumerImpl c = new QuoteConsumerImpl();callbackPOA.activate_object(c);callbackPOA.the_POAManager().activate();QuoteServer serv = QuoteServerHelper.bind(orb, "/QuoteServer_poa","QuoteServer".getBytes());serv=QuoteServerHelper.narrow(serv._set_policy_override(policies, org.omg.CORBA.SetOverrideType.ADD_OVERRIDE));serv.registerConsumer(QuoteConsumerHelper.narrow(callbackPOA.servant_to_reference(c)));System.out.println("Client:consumer registered");// 休 眠 60 s, 接 收 消 息try{Thread.currentThread().sleep(60*1000);}catch(java.lang.InterruptedException e){ }serv.unregisterConsumer(QuoteConsumerHelper.narrow(callbackPOA.servant_to_reference(c)));System.out.println("Client:consumer unregistered.Good bye.");orb.shutdown(true);...注 : 有 关 设 定 策 略 以 调 整 您 的 应 用 的 信 息 , 请 参 阅 程 序 员 参 考 。客 户 连 接 可 以 是 单 向 的 也 可 以 是 双 向 的 。 服 务 器 可 以 使 用 单 向 连 接 来 回 调 客 户 而 无须 打 开 新 的 连 接 。否 定 , 该 连 接 就 被 视 为 单 向 连 接 。要 建 立 回 调 对 象 的 POA 上 必 须 通 过 将 BiDirectional 策 略 设 定 为 BOTH 以 实 现双 向 IIOP。 该 POA 必 须 被 创 建 在 一 个 通 过 在 SCM 管 理 器 上 设 定vbroker..scm..manager.exportBiDir 属 性 已 实 现 了 双 向 支 持 的SCM 上 。 否 则 , 该 POA 将 不 能 通 过 客 户 端 发 起 的 连 接 来 接 收 服 务 器 发 出 的 请 求 。如 果 POA 未 指 定 BiDirectional 策 略 , 则 它 不 能 “ 暴 露 ” 在 外 发 连 接 中 。 要 满 足这 一 要 求 , 如 果 一 个 服 务 器 引 擎 上 已 有 一 个 已 设 定 了 exportBiDir 属 性 的 SCM,则 没 有 设 定 BiDirectional 策 略 的 POA 不 能 创 建 在 该 服 务 器 引 擎 上 。 如 果 尝 试 将POA 创 建 在 一 个 单 向 服 务 器 引 擎 (SE) 上 , 则 会 掷 出 InvalidPolicy 违 例 , 并 显示 出 错 的 ServerEnginePolicy 。注 : 使 用 同 一 客 户 连 接 的 不 同 对 象 有 可 能 会 设 定 相 互 冲 突 的 BiDirectional 策 略 门 限 。不 过 , 一 旦 一 个 连 接 被 设 定 为 单 向 , 则 不 论 策 略 以 后 有 效 与 否 , 它 将 始 终 保 持单 向 。一 旦 我 们 可 以 完 全 控 制 双 向 配 置 , 则 我 们 要 在 the iiop_tp SCM 上 实 现 双 向 IIOP时 只 需 要 执 行 :C++: prompt> -Dvbroker.se.iiop_tp.scm.iiop_tp.manager.exportBiDir=true Client双 向 通 信 28-5


安 全 注 意 事 项Java:prompt> vbj -Dvbroker.se.iiop_tp.scm.iiop_tp.manager.exportBiDir=trueClient安 全 注 意 事 项使 用 双 向 IIOP 可 能 会 引 发 重 大 的 安 全 问 题 。 在 缺 少 其 它 安 全 机 制 的 情 况 下 , 一 个恶 意 客 户 可 能 会 作 声 明 使 其 连 接 可 双 向 地 用 于 其 所 选 择 的 任 何 主 机 或 端 口 。 更 有 甚者 , 一 个 客 户 可 以 指 定 不 在 其 主 机 上 驻 留 的 安 全 敏 感 的 对 象 的 主 机 和 端 口 。 在 缺 少其 它 安 全 机 制 的 情 况 下 , 已 接 受 输 入 连 接 的 服 务 器 无 法 查 证 发 起 连 接 的 客 户 的 身份 , 也 无 法 验 证 该 客 户 的 诚 实 性 。 另 外 , 服 务 器 可 以 通 过 双 向 连 接 来 访 问 其 它 可 以访 问 的 对 象 。 这 就 是 为 什 么 我 们 鼓 励 为 回 调 对 象 使 用 单 独 的 、 双 向 SCM。 如 果 对客 户 的 诚 实 性 有 任 何 疑 虑 , 我 们 建 议 您 不 要 使 用 双 向 IIOP。为 保 证 安 全 性 , 运 行 <strong>VisiBroker</strong> 的 服 务 器 不 要 使 用 双 向 IIOP, 除 非 作 显 式 配 置 使其 可 以 使 用 双 向 IIOPrectional 。vbroker...scm..manager.importBiDir 属 性 可 以 使 您 控 制 单个 SCM 的 双 向 性 。 例 如 , 您 可 以 选 择 仅 在 一 个 使 用 SSL 来 验 证 客 户 的 服 务 器 引 擎上 实 现 双 向 IIOP 而 不 让 其 它 的 常 规 IIOP 连 接 作 双 向 使 用 。( 参 阅 第 28-1 页 " 双向 <strong>VisiBroker</strong> ORB 属 性 " 以 取 得 关 于 此 操 作 的 详 情 。) 另 外 , 您 也 可 能 想 在 客 户端 实 现 只 连 通 到 在 客 户 防 火 墙 之 外 作 回 调 的 服 务 器 的 双 向 连 接 。 要 在 客 户 和 服 务 器之 间 建 立 高 度 的 安 全 性 , 您 应 该 以 双 向 认 证 方 式 使 用 SSL ( 在 客 户 端 和 服 务 器 端将 vbroker.security.peerAuthenticationMode 设 为 REQUIRE_AND_TRUST )。28-6 <strong>VisiBroker</strong> 开 发 者 指 南


第章使 用 <strong>VisiBroker</strong> <strong>Edition</strong> 4.x BOA第 29 章本 章 描 述 如 何 使 用 <strong>VisiBroker</strong> <strong>Edition</strong> 4.x 下 的 BOA用 <strong>VisiBroker</strong> <strong>Edition</strong> 4.x 编 译 BOA 代 码C++:注 :Java:如 果 您 具 有 用 以 前 的 <strong>VisiBroker</strong> 开 发 的 BOA 代 码 , 您 可 以 在 当 前 的 版 本 下 继 续使 用 它 。要 生 成 必 要 的 BOA 基 础 代 码 , 您 必 须 使 用 idl2cpp 工 具 中 的 "-boa" 选 项 。 要 取 得关 于 使 用 idl2cpp 生 成 代 码 的 详 情 , 请 参 阅 程 序 员 参 考 。如 果 您 现 有 用 以 前 的 <strong>VisiBroker</strong> 开 发 的 BOA 代 码 , 只 要 您 记 住 以 下 内 容 , 您 就可 以 在 当 前 的 版 本 下 继 续 使 用 它 。● 要 生 成 必 要 的 BOA 基 础 代 码 , 您 必 须 使 用 idl2java 工 具 中 的 "-boa" 选 项 。 要取 得 关 于 使 用 idl2java 生 成 代 码 的 详 情 , 请 参 阅 程 序 员 参 考 。● 因 为 BOA_init() 在 org.omg.CORBA.ORB 下 已 不 再 可 用 , 所 以 您 必 须 将<strong>VisiBroker</strong> ORB 造 型 到 com.inprise.vbroker.CORBA.ORB。● 因 为 BOA 类 在 org.omg.CORBA 包 中 已 不 再 可 用 , 您 现 在 必 须 到com.inprise.vbroker.CORBA 包 中 去 查 看 它 。 要 取 得 关 于 <strong>VisiBroker</strong> ORB 包 的详 情 , 请 参 阅 程 序 员 参 考 。支 持 BOA 选 项<strong>VisiBroker</strong> <strong>Edition</strong> 3.x 所 支 持 的 所 有 命 令 行 选 项 仍 然 受 支 持 。使 用 <strong>VisiBroker</strong> <strong>Edition</strong> 4.x BOA 29-1


使 用 BOA 时 的 局 限 性 ( 仅 适 用 于 Java)使 用 BOA 时 的 局 限 性 ( 仅 适 用 于 Java)<strong>VisiBroker</strong> <strong>Edition</strong> 4.x BOA 不 支 持 两 个 特 性 :● 持 久 DSI 对 象 不 受 支 持● DSI 对 象 上 的 _boa() 不 受 支 持使 用 对 象 源 活 器BOA 对 象 源 活 器 受 <strong>VisiBroker</strong> <strong>Edition</strong> 4.x 支 持 。 但 是 , 这 些 源 活 器 只 能 和BOA 一 起 使 用 , 不 能 和 POA 一 起 使 用 。POA 使 用 服 务 对 象 源 活 器 和 服 务 对 象 定位 器 , 而 不 使 用 对 象 源 活 器 。在 本 版 的 <strong>VisiBroker</strong> 中 , 可 移 植 对 象 适 配 器 (POA) 支 持 由 <strong>VisiBroker</strong> 3.x 版中 的 BOA 提 供 的 特 性 。 由 于 提 供 了 后 向 兼 容 , 所 以 您 仍 然 可 以 在 您 的 代 码 中 使 用对 象 源 活 器 。 要 取 得 本 版 中 关 于 如 何 使 用 对 象 源 活 器 的 详 情 , 请 参 阅 第 29 章 " 使用 <strong>VisiBroker</strong> <strong>Edition</strong> 4.x BOA"。给 BOA 下 的 对 象 命 名注 :虽 然 <strong>VisiBroker</strong> <strong>Edition</strong> 4.x 不 支 持 BOA , 您 仍 然 可 以 将 它 和 智 能 代 理 一 起 使用 , 以 在 您 的 客 户 端 程 序 中 为 可 以 限 制 的 服 务 器 对 象 指 定 一 个 名 称 。对 象 名 称在 创 建 一 个 对 象 时 , 如 果 要 通 过 使 用 osagent 使 对 象 在 客 户 端 程 序 中 可 用 , 则 服 务器 必 须 指 定 对 象 名 称 。 当 服 务 器 调 用 BOA.obj_is_ready 方 法 时 , 如 果 对 象 已 命名 , 则 对 象 的 界 面 名 称 仅 在 <strong>VisiBroker</strong> <strong>Edition</strong> osagent 注 册 。 在 创 建 过 程 中 命名 的 对 象 将 返 回 永 久 对 象 引 用 , 而 在 创 建 过 程 中 未 命 名 的 对 象 将 被 创 建 为 临 时 对象 引 用 。C++: 如 果 您 在 C++ <strong>VisiBroker</strong> <strong>Edition</strong> 下 将 一 个 空 串 作 为 对 象 名 传 递 给 对 象 构 建 器 ,则 会 创 建 一 个 永 久 对 象 ( 即 在 智 能 代 理 上 注 册 的 对 象 )。 如 果 您 将 一 个 null 引 用传 递 给 构 建 器 , 则 会 创 建 一 个 临 时 对 象注 :Java:如 果 您 在 Java <strong>VisiBroker</strong> 下 , 将 一 个 空 字 串 作 为 对 象 名 传 递 给 对 象 构 建 器 , 则 会创 建 一 个 临 时 对 象 ( 即 不 在 智 能 代 理 上 注 册 的 对 象 )。 如 果 您 将 一 个 null 引 用 传递 给 构 建 器 , 则 会 创 建 一 个 临 时 对 象 。如 果 您 的 客 户 端 应 用 程 序 要 一 次 限 制 到 一 个 对 象 的 一 个 或 多 个 实 例 , 则 您 的 客 户 端程 序 中 必 须 使 用 对 象 名 称 。 对 象 名 称 在 一 个 界 面 的 多 个 实 例 中 是 不 同 的 。 如 果 在 调用 bind 方 法 时 没 有 指 定 对 象 名 称 , 则 osagent 会 返 回 任 何 适 用 的 具 有 指 定 的 界 面的 对 象 。29-2 <strong>VisiBroker</strong> 开 发 者 指 南


给 BOA 下 的 对 象 命 名注 :在 <strong>VisiBroker</strong> <strong>Edition</strong> 3.x 中 , 一 个 服 务 器 进 程 提 供 不 同 的 界 面 是 不 可 能 的 , 所 有的 界 面 都 具 有 相 同 的 对 象 名 称 , 但 在 <strong>VisiBroker</strong> <strong>Edition</strong> 4.x 中 , 不 同 的 界 面 可 以不 使 用 字 串 相 同 的 名 称 。使 用 <strong>VisiBroker</strong> <strong>Edition</strong> 4.x BOA 29-3


29-4 <strong>VisiBroker</strong> 开 发 者 指 南


第章移 植 <strong>VisiBroker</strong> 代 码第 30 章仅 适 用 于 Java:本 章 描 述 如 何 将 <strong>VisiBroker</strong> 以 前 版 本 下 的 <strong>VisiBroker</strong> 代 码 移 植 到 <strong>VisiBroker</strong><strong>Edition</strong> 下 。另 外 , 有 两 种 可 以 将 <strong>VisiBroker</strong> 3.x 下 的 Java 代 码 移 植 到 <strong>VisiBroker</strong> 4.x 下 的方 法 : 一 种 是 移 植 器 , 命 令 行 实 用 工 具 , 尝 试 将 移 植 程 序 的 一 部 分 自 动 化 ; 另 一 种是 手 动 移 植 。 我 们 建 议 以 手 动 方 式 将 <strong>VisiBroker</strong> 3.x 代 码 移 植 到 <strong>VisiBroker</strong> 4.x。使 用 本 地 <strong>VisiBroker</strong> <strong>Edition</strong> 5.x 调 用 比 升 级 <strong>VisiBroker</strong> 3.x 具 有 很 大 的 优 越 性 。但 是 , 我 们 提 供 了 一 个 移 植 器 以 帮 助 您 将 为 <strong>VisiBroker</strong> 3.x 编 写 的 代 码 移 植 到<strong>VisiBroker</strong> 4.x 下 。 该 移 植 器 试 图 实 现 自 动 转 化 而 无 须 用 户 干 预 , 但 这 并 不 总 是 可能 的 。本 节 先 描 述 关 于 如 何 使 用 移 植 器 的 信 息 。 本 节 主 要 提 供 下 列 信 息 :● 如 何 使 用 <strong>VisiBroker</strong> <strong>Edition</strong> 下 的 BOA, 如 何 将 您 的 BOA 代 码 变 成 POA,和 如 何 使 用 服 务 对 象 激 活 器 。● <strong>VisiBroker</strong> <strong>Edition</strong> 中 的 包 名 、 类 名 和 API 调 用 的 变 化 的 列 表移 植 器 ( 仅 适 用 于 Java )仅 适 用 于 Java: 当 移 植 器 解 析 原 来 的 Java 源 代 码 时 , 它 变 更 :● 包 名 前 缀● 类 名● API 调 用请 参 阅 下 表 以 查 看 关 于 这 些 移 植 变 化 的 详 情 。移 植 <strong>VisiBroker</strong> 代 码 30-1


移 植 器 ( 仅 适 用 于 Java )对 包 名 前 缀 的 变 更仅 适 用 于 Java: 移 植 器 对 包 名 作 以 下 变 更 :表 30.1对 包 名 前 缀 的 变 更<strong>VisiBroker</strong> 3.x 包 名 前 缀com.visigenic.vbrokercom.visigenic.vbroker.services.CosEventcom.visigenic.vbroker.services.CosNaming<strong>VisiBroker</strong> <strong>Edition</strong> 包 名 前 缀com.inprise.vbrokercom.inprise.vbroker.CosEventcom.inprise.vbroker.naming对 类 名 的 变 更移 植 器 将 一 些 类 名 变 更 为 <strong>VisiBroker</strong> <strong>Edition</strong> 中 使 用 的 类 。 如 果 它 不 能 确 定 一 个可 兼 容 的 类 , 则 它 会 取 代 <strong>VisiBroker</strong> 3.x 中 的 类 。表 30.2对 类 名 的 变 更<strong>VisiBroker</strong> 3.x 类 名org.omg.CORBA.BOAorg.omg.CORBA.DynamicImplementationcom.visigenic.vbroker.interceptor.BindInterceptorcom.visigenic.vbroker.interceptor.ChainBindInterceptorcom.visigenic.vbroker.interceptor.ChainBindInterceptorHelpercom.visigenic.vbroker.interceptor.ClientInterceptorcom.visigenic.vbroker.interceptor.ClientInterceptorFactorycom.visigenic.vbroker.interceptor.ChainClientInterceptorFactorycom.visigenic.vbroker.interceptor.ChainClientInterceptorFactoryHelpercom.visigenic.vbroker.interceptor.ServerInterceptorcom.visigenic.vbroker.interceptor.ServerInterceptorFactorycom.visigenic.vbroker.interceptor.ChainServerInterceptorFactorycom.visigenic.vbroker.interceptor.ChainServerInterceptorFactoryHelpercom.visigenic.vbroker.orb.ServiceInit<strong>VisiBroker</strong> <strong>Edition</strong> 类 名com.inprise.vbroker.CORBA.BOAcom.inprise.vbroker.CORBA.migration.DynamicImplementationcom.inprise.vbroker.interceptor.migration.BindInterceptorDelegatecom.inprise.vbroker.interceptor.migration.BindInterceptorManagercom.inprise.vbroker.interceptor.migration.BindInterceptorManagerHelpercom.inprise.vbroker.interceptor.migration.ClientInterceptorDelegatecom.inprise.vbroker.interceptor.migration.ClientInterceptorFactorycom.inprise.vbroker.interceptor.migration.ChainClientDelegateFactorycom.inprise.vbroker.interceptor.migration.ChainClientDelegateFactoryHelpercom.inprise.vbroker.interceptor.migration.ServerInterceptorDelegatecom.inprise.vbroker.interceptor.migration.ServerInterceptorDelegateFactorycom.inprise.vbroker.interceptor.migration.ChainServerDelegateFactorycom.inprise.vbroker.interceptor.migration.ChainServerDelegateFactoryHelpercom.inprise.vbroker.interceptor.migration.ServiceInit30-2 <strong>VisiBroker</strong> 开 发 者 指 南


调 用 移 植 器对 API 调 用 的 变 更仅 适 用 于 Java: 移 植 器 将 一 些 API 调 用 变 更 为 <strong>VisiBroker</strong> <strong>Edition</strong> 中 使 用 的 调 用 。表 30.3 对 API 调 用 的 变 更<strong>VisiBroker</strong> <strong>Edition</strong> 3.x 调 用org.omg.CORBA.ORB 实 例 上 的 BOA_init()org.omg.CORBA.ORB 实 例 上 的 bind(repId, objectName,hostName, bindOptions)com.visigenic.vbroker.services.CosEvent.EventLibrary实 例 上 的 create_channel(boa, name, debug,maxQueueLength)com.visigenic.vbroker.services.CosEvent.EventLibrary实 例 上 的 create_channel(boa, name, debug)com.visigenic.vbroker.services.CosEvent.EventLibrary实 例 上 的 create_channel(boa, name)com.visigenic.vbroker.services.CosEvent.EventLibrary实 例 上 的 create_channel(boa)<strong>VisiBroker</strong> <strong>Edition</strong> 调 用com.inprise.vbroker.orb.ORB 实 例 上 的 BOA_init()com.inprise.vbroker.orb.ORB 实 例 上 的 bind(repId,objectName, hostName, bindOptions)com.inprise.vbroker.CosEvent.EventLibrary 实 例 上 的create_channel(name, debug, maxQueueLength)com.inprise.vbroker.CosEvent.EventLibrary 实 例 上 的create_channel(name, debug)com.inprise.vbroker.CosEvent.EventLibrary 实 例 上 的create_channel(name)com.inprise.vbroker.CosEvent.EventLibrary 实 例 上 的ofcreate_channel()从 BOA 到 POA 的 变 更仅 适 用 于 Java:移 植 器 不 更 改 代 码 。 所 以 , 它 不 会 转 换 为 BOA 编 写 的 <strong>VisiBroker</strong> 3.x 代 码 以 便 使用 POA。 因 为 在 CORBA ORB 中 ,BOA 不 再 是 标 准 组 件 , 移 植 器 将 与 BOA 相关 的 调 用 造 型 为 Borland ORB 下 的 调 用 。 有 关 以 手 动 方 式 将 使 用 BOA 的 代 码 转换 到 POA 的 详 情 , 请 参 阅 第 30-4 页 " 手 动 移 植 BOA 到 POA"。接 收 器 使 用 中 的 变 更仅 适 用 于 Java: 在 某 些 情 况 下 , 无 法 自 动 移 植 代 码 并 提 供 与 <strong>VisiBroker</strong> 3.x 相 似 的 功 能 。 例 如 ,接 收 器 就 属 于 这 种 情 况 。 为 了 能 够 使 用 旧 的 代 码 , 一 个 接 收 器 的 特 殊 集 合 至 少 须 提供 签 名 兼 容 性 给 旧 的 接 收 器 。注 :当 移 植 器 不 能 确 定 如 何 移 植 代 码 时 , 它 将 使 用 移 植 包 , 这 些 移 植 包 将 试 图 封 包 使 用旧 语 义 新 API。 这 种 情 况 通 常 出 现 在 新 API 在 逻 辑 和 行 为 上 与 旧 API 完 全 不 同 的场 合 。 在 这 种 情 况 下 , 有 可 能 一 些 移 植 的 代 码 不 能 工 作 ( 可 能 无 法 调 用 移 植 的 代码 ) 或 者 移 植 的 代 码 的 工 作 方 式 与 其 在 <strong>VisiBroker</strong> 3.x 下 不 同 。调 用 移 植 器仅 适 用 于 Java: 要 运 行 移 植 器 , 请 键 入 :migrator [migrator_options]{filename |- filename}这 个 工 具 可 处 理 一 个 或 多 个 <strong>VisiBroker</strong> 3.x Java 源 文 件 , 以 便 文 件 可 以 在<strong>VisiBroker</strong> 4.x 上 运 行 。 注 意 文 件 名 前 的 前 缀 “-” 表 示 stdin。移 植 <strong>VisiBroker</strong> 代 码 30-3


使 用 移 植 的 代 码移 植 器 选 项表 30.4移 植 器 选 项选 项说 明-o 输 出 文 件 的 名 称 , 或 者 用 于 stdout 的 “-”-src_dir 要 保 存 生 成 的 文 件 的 目 录-src_suffix 源 文 件 名 后 缀 (.cc)-list_files列 出 在 代 码 生 成 过 程 中 所 编 写 的 文 件-h, -help, -usage, -?打 印 此 使 用 信 息-version显 示 软 件 版 本 号驱 动 程 序 选 项表 30.5驱 动 程 序 选 项选 项-J-VBJversion-VBJdebug-VBJclasspath-VBJprop [=]-VBJjavavm -VBJaddJar 说 明将 选 项 直 接 传 递 给 JVM打 印 VBJ 版 本打 印 VBJ 调 试 信 息指 定 classpath, 在 CLASSPATH env 变 量之 前将 名 / 值 对 传 递 给 Java VM指 定 Java VM 路 径执 行 VM 前 将 jarfile 连 接 到 CLASSPATH使 用 移 植 的 代 码要 使 用 由 移 植 器 移 植 的 代 码 , 用 户 需 要 将 migration.jar 加 入 classpath。 jar 文 件包 含 专 用 于 向 <strong>VisiBroker</strong> 4.x API 移 植 的 移 植 类 。手 动 移 植 BOA 到 POA从 以 前 的 <strong>VisiBroker</strong> 版 本 相 比 , 类 名 已 发 生 了 很 大 的 变 化 。 确 定 更 新 您 的 源 文 件以 指 向 最 新 的 类 名 。 下 列 各 表 使 用 一 个 实 例 类 名 说 明 了 名 称 的 变 化 。表 30.6C++ 下 类 名 变 化旧 类 名 称_sk_Account_sk_AccountManager_tie_Account_tie_AccountManager新 类 名 称POA_AccountPOA_AccountManagerPOA_Account_tiePOA_AccountManager_tie30-4 <strong>VisiBroker</strong> 开 发 者 指 南


手 动 移 植 BOA 到 POA表 30.7Java 下 的 类 名 变 化旧 类 名 称_st_Account_st_AccountManager_AccountImplBase_AccountManagerImplBase_tie_Account_tie_AccountManager新 类 名 称_AccountStub_AccountManagerStubAccountPOAAccountManagerPOAAccountPOATieAccountManagerPOATie查 看 实 例examples/boa/boa2poa 目 录 包 含 一 个 实 例 说 明 如 何 将 您 的 BOA 更 新 为 相 应 的POA 代 码 。本 例 使 用 以 下 方 法 将 Server.c (C++) 或 Server.java (Java) 中 的 BOA 代码 更 新 为 POA 代 码 :● 取 得 根 POA 的 一 个 引 用 , 以 代 替 BOA 初 始 化 过 程● 将 相 应 的 POA 策 略 设 置 为 模 拟 的 BOA 特 性● 定 义 服 务 对 象 (POA 的 服 务 对 象 定 义 与 BOA 不 同 )● 激 活 POA 管 理 器 (BOA 中 没 有 相 应 的 步 骤 )● 通 过 C++ orb->run() 或 Java orb.run() 而 不 是 通 过 C++ boa->impl_is_ready() 或 boa.impl_is_ready(), 来 等 待 进 入 的 请 求 。取 得 根 POA 的 引 用 C++:使 用 BOA 时 , 要 通 过 orb->BOA_init() 取 得 BOA 的 引 用 。 但 在 POA 下 , 您 要取 得 根 POA 的 引 用 。 您 可 通 过 使 用 orb->resolve_initial_references("RootPOA") 来 完 成 该 操 作 。resolve_initial_references 返 回 CORBA::object 类 型 的 一 个 值 , 然 后 , 您 要 将 该值 窄 转 换 成 所 需 要 的 类 型 。C++:CORBA::object_var obj = resolve_initial_references("RootPOA");PortableServer::POA_var rootPOA = PortableServer::POA::_narrow(obj);Java:Java:使 用 BOA 时 , 要 通 过 orb.BOA_init() 取 得 BOA 的 一 个 引 用 。 但 在 POA 下 , 您要 取 得 根 POA 的 引 用 。 您 可 以 使 用 orb.resolve_initial_references("RootPOA")来 完 成 该 操 作 。resolve_initial_references 返 回 一 个 CORBA.object 类 型 的 值 , 然后 , 您 要 将 它 窄 转 换 成 所 需 的 类 型POA rootPOA = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));设 置 POA 策 略POA 的 特 性 由 为 该 POA 所 设 置 的 策 略 来 定 义 。 每 个 POA 都 有 一 套 自 己 的 策 略 ;POA 不 能 从 其 它 POA 上 继 承 策 略 。移 植 <strong>VisiBroker</strong> 代 码 30-5


手 动 移 植 BOA 到 POAC++/Java:在 本 例 中 , 我 们 使 用 了 永 久 对 象 。 在 BOA 下 , 永 久 对 象 是 具 有 特 定 的 对 象 名 称 并在 智 能 代 理 上 作 了 注 册 的 对 象 。 单 独 的 BOA 可 以 同 时 支 持 永 久 对 象 和 临 时 对 象 。在 POA 下 , 永 久 对 象 是 比 其 创 建 过 程 存 在 更 久 的 对 象 。 单 独 的 POA 可 以 支 持 永久 对 象 或 临 时 对 象 , 但 不 能 同 时 支 持 两 者 。 支 持 的 对 象 类 型 由 POA 策 略 来 设 置 。由 于 根 POA 支 持 临 时 对 象 ( 默 认 ), 所 以 必 须 创 建 一 个 新 的 POA 以 支 持 永 久 对象 。注 : 一 旦 POA 创 建 好 之 后 , 就 不 可 能 改 变 它 的 策 略 。要 支 持 永 久 对 象 , 将 Lifespan ( 生 命 周 期 ) 策 略 设 置 为 PERSISTENT。 这 对 于C++ 和 Java 均 适 用 。C++:另 外 , 在 本 例 中 , 我 们 将 Bind Support 策 略 ( 与 <strong>VisiBroker</strong> <strong>Edition</strong> 有 关 的 策略 ) 设 置 为 BY_INSTANCE。 该 策 略 将 所 有 的 活 动 对 象 注 册 在 智 能 代 理 上 , 而 不 是 仅注 册 在 POA 上 ( 默 认 )。一 旦 设 定 了 相 应 的 策 略 , 就 可 以 用 create_POA() 来 创 建 新 的 POA。CORBA::PolicyList policies;policies.length(1);policies[(CORBA::ULong)0] =rootPOA>create_lifespan_policy(PortableServer::PERSISTENT);// 用 正 确 的 策 略 创 建 myPOAPortableServer::POAManager_var mgr = rootPOA->the_POAManager();PortableServer::POA_var myPOA =rootPOA->create_POA( "bank_agent_poa", mgr, policies );Java:在 Java 下 设 置 POA 策 略 :org.omg.CORBA.Any any = orb.create_any();BindSupportPolicyValueHelper.insert(any,BindSupportPolicyValue.BY_INSTANCE);org.omg.CORBA.Policy bsPolicy =orb.create_policy(com.inprise.vbroker.PortableServerExt.BIND_SUPPORT_POLICY_TYPE.value, any);org.omg.CORBA.Policy[] policies = {rootPOA.create_lifespan_policy(LifespanPolicyValue.PERSISTENT), bsPolicy};// 用 正 确 的 策 略 创 建 myPOAPOA myPOA = rootPOA.create_POA( "bank_agent_poa",rootPOA.the_POAManager(), policies );定 义 服 务 对 象C++:在 BOA 下 , 服 务 对 象 为 CORBA 对 象 。 在 本 例 中 , 我 们 创 建 了 帐 户 管 理 器 对 象 ,然 后 用 obj_is_ready() 将 其 导 出 。在 POA 下 , 服 务 对 象 是 提 供 抽 象 对 象 的 实 现 的 编 程 对 象 。 服 务 对 象 不 是 CORBA对 象 。 在 POA 模 式 下 , 我 们 可 以 创 建 服 务 对 象 , 然 后 用 特 定 的 ID 来 激 活 它 。 您可 以 使 用 该 ID 来 取 得 对 象 引 用 。// 创 建 服 务 对 象30-6 <strong>VisiBroker</strong> 开 发 者 指 南


AccountManagerImpl *managerServant = new AccountManagerImp;// 确 定 服 务 对 象 IDPortableServer::ObjectId_var managerId =PortableServer::string_to_ObjectId("BankManager");// 用 myPOA 上 的 ID 激 活 服 务 对 象myPOA->activate_object_with_id(managerId,managerServant);在 Java 下 定 义 和 激 活 服 务 对 象 :手 动 移 植 BOA 到 POAJava:// 创 建 服 务 对 象AccountManagerImpl managerServant = new AccountManagerImpl();// 确 定 服 务 对 象 IDbyte[] managerId = "BankManager".getBytes();// 用 myPOA 上 的 ID 激 活 服 务 对 象myPOA.activate_object_with_id(managerId, managerServant);激 活 POA 管 理 器C++:Java:POA 管 理 器 是 控 制 POA 如 何 处 理 请 求 的 对 象 在 默 认 的 情 况 下 ,POA 管 理 器 被 创建 为 保 持 状 态 。 在 该 状 态 下 , 所 有 的 请 求 都 被 送 到 一 个 保 持 队 列 中 而 不 作 处 理 。 要允 许 将 请 求 发 出 , 与 POA 相 关 联 的 POA 管 理 器 必 须 从 保 持 状 态 变 为 活 动 状 态 。这 是 POA 所 要 求 的 一 个 新 步 骤 。 BOA 中 没 有 与 它 相 当 的 步 骤 。rootPOA->the_POAManager()->activate();rootPOA.the_POAManager().activate();等 待 进 入 的 请 求C++:Java:在 BOA 下 , 我 们 调 用 impl_is_ready() 以 等 待 从 客 户 端 来 的 请 求 。 在 POA 下 ,使 用 C++ orb->run() 或 Java orb.run()。orb->run();orb.run()查 看 C++ 下 的 其 它 类 或 Java 下 的 其 它 文 件AccountImpl 和 AccountManagerImpl 类 的 变 更 相 当 简 单 。 大 部 分 的 变 化 涉 及 指 向新 类 。移 植 <strong>VisiBroker</strong> 代 码 30-7


移 植 到 新 包 名映 射 BOA 类 型 到 POA 策 略下 表 说 明 如 何 将 您 的 POA 策 略 设 置 为 模 拟 BOA 行 为 。表 30.8映 射 BOA 类 型 到 POA 策 略TPOOLTSESSION服 务 激 活 的 对 象临 时 BOA服 务 器 引 擎 策 略 , TPOOL 分 配器 的 LifeCycle 属 性 设 置 为TRANSIENT。服 务 器 引 擎 策 略 , TSESSION分 配 器 LifeCycle 属 性 设 置 为TRANSIENT。LifeCycle 属 性 设 置 为TRANSIENT ; 请 求 处 理 策 略 设置 为 USE_SERVANT_MANAGER ;隐 式 激 活 策 略 设 置 为IMPLICIT_ACTIVATION永 久 BOA服 务 器 策 略 ,TPOOL 分 配 器 的LifeCycle 属 性 设 置 为PERSISTENT ; IDAssignment策 略 设 置 为 USER_ID ;BindSupport 策 略 设 置 为BY_INSTANCE服 务 器 引 擎 策 略 , TSESSION分 配 器 LifeCycle 属 性 设 置 为PERSISTENT ; IDAssignment策 略 设 置 为 USER_ID ;BindSupport 策 略 设 置 为BY_INSTANCELifeCycle 属 性 设 置 为PERSISTENT ; 请 求 处 理 策 略设 置 为 USE_SERVANT_MANAGER; 隐 式 激 活 策 略 设 置 为IMPLICIT_ACTIVATION移 植 到 新 包 名仅 适 用 于 Java: 下 表 说 明 <strong>VisiBroker</strong> 3.x 包 名 前 缀 是 如 何 映 射 到 最 新 版 本 上 去 的 。<strong>VisiBroker</strong> 3.x 包 名com.visigenic.vbrokercom.visigenic.vbroker.services.CosEventcom.visigenic.vbroker.services.CosNaming<strong>VisiBroker</strong> <strong>Edition</strong> 4.5 包 名com.inprise.vbrokercom.inprise.vbroker.CosEventcom.inprise.vbroker.naming移 植 到 新 类 名仅 适 用 于 Java: 下 表 说 明 了 <strong>VisiBroker</strong> 3.x 类 名 是 如 何 映 射 到 最 新 版 本 上 去 的 。表 30.9<strong>VisiBroker</strong> 3.x 类 名 映 射<strong>VisiBroker</strong> <strong>Edition</strong> 3.x 类 名org.omg.CORBA.BOAorg.omg.CORBA.DynamicImplementationcom.visigenic.vbroker.interceptor.BindInterceptorcom.visigenic.vbroker.interceptor.ChainBindInterceptor<strong>VisiBroker</strong> <strong>Edition</strong> 4.5 类 名com.inprise.vbroker.CORBA.BOAcom.inprise.vbroker.CORBA.migration.DynamicImplementationcom.inprise.vbroker.interceptor.migration.BindInterceptorDelegatecom.inprise.vbroker.interceptor.migration.BindInterceptorManager30-8 <strong>VisiBroker</strong> 开 发 者 指 南


移 植 到 新 API 调 用表 30.9<strong>VisiBroker</strong> 3.x 类 名 映 射<strong>VisiBroker</strong> <strong>Edition</strong> 3.x 类 名com.visigenic.vbroker.interceptor.ChainBindInterceptorHelpercom.visigenic.vbroker.interceptor.ClientInterceptorcom.visigenic.vbroker.interceptor.ClientInterceptorFactorycom.visigenic.vbroker.interceptor.ChainClientInterceptorFactorycom.visigenic.vbroker.interceptor.ChainClientInterceptorFactoryHelpercom.visigenic.vbroker.interceptor.ServerInterceptorcom.visigenic.vbroker.interceptor.ServerInterceptorFactory<strong>VisiBroker</strong> <strong>Edition</strong> 4.5 类 名com.inprise.vbroker.interceptor.migration.BindInterceptorManagerHelpercom.inprise.vbroker.interceptor.migration.ClientInterceptorDelegatecom.inprise.vbroker.interceptor.migration.ClientInterceptorFactorycom.inprise.vbroker.interceptor.migration.ChainClientDelegateFactorycom.inprise.vbroker.interceptor.migration.ChainClientDelegateFactoryHelpercom.inprise.vbroker.interceptor.migration.ServerInterceptorDelegatecom.inprise.vbroker.interceptor.migration.ServerInterceptorDelegateFactory移 植 到 新 API 调 用仅 适 用 于 Java: 下 表 说 明 了 <strong>VisiBroker</strong> 3.x API 调 用 是 如 何 映 射 到 最 新 版 本 上 去 的 。表 30.10 <strong>VisiBroker</strong> 3.x API 调 用 映 射<strong>VisiBroker</strong> 3.x API 调 用org.omg.CORBA.ORB 实 例 上 的 BOA_init()org.omg.CORBA.ORB 实 例 上 的 bind(repId,objectName, hostName, bindOptions)com.visigenic.vbroker.services.CosEvent.EventLibrary 实 例 上 的 create_channel(boa,name, debug, maxQueueLength)com.visigenic.vbroker.services.CosEvent.EventLibrary 实 例 上 的 create_channel(boa,name, debug)com.visigenic.vbroker.services.CosEvent.EventLibrary 实 例 上 的 create_channel(boa,name)com.visigenic.vbroker.services.CosEvent.EventLibrary 实 例 上 的 create_channel(boa)<strong>VisiBroker</strong> <strong>Edition</strong> API 调 用com.inprise.vbroker.orb.ORB 实 例 上 的BOA_init()com.inprise.vbroker.orb.ORB 实 例 上 的bind(repId, objectName, hostName,bindOptions)com.inprise.vbroker.CosEvent.EventLibrary实 例 上 的 create_channel(name, debug,maxQueueLength)com.inprise.vbroker.CosEvent.EventLibrary实 例 上 的 create_channel(name, debug)com.inprise.vbroker.CosEvent.EventLibrary实 例 上 的 create_channel(name)com.inprise.vbroker.CosEvent.EventLibrary实 例 上 的 create_channel()有 关 新 包 名 、 类 名 和 API 调 用 的 详 情 , 请 参 阅 程 序 员 参 考 。移 植 接 收 器移 植 接 收 器 到 <strong>VisiBroker</strong> <strong>Edition</strong> 下 的 首 选 方 法 是 使 用 新 的 <strong>VisiBroker</strong> <strong>Edition</strong>接 收 器 。 有 关 接 收 器 工 作 原 理 的 详 情 , 请 参 阅 “ 可 移 植 接 收 器 ” 一 章 。移 植 <strong>VisiBroker</strong> 代 码 30-9


移 植 接 收 器注 :虽 然 <strong>VisiBroker</strong> <strong>Edition</strong> 的 确 提 供 了 允 许 您 原 封 不 动 地 移 植 旧 的 接 收 器 代 码 ( 参见 下 文 所 述 ) 的 封 装 器 , 但 是 , 3.x 代 码 的 <strong>VisiBroker</strong> 封 装 器 不 提 供 与<strong>VisiBroker</strong> <strong>Edition</strong> 接 收 器 相 当 的 功 能 。使 用 <strong>VisiBroker</strong> 3.x 接 收 器虽 然 <strong>VisiBroker</strong> <strong>Edition</strong> 确 保 <strong>VisiBroker</strong> 3.x 接 收 器 的 签 名 方 法 不 必 作 变 更 , 但是 , 它 对 原 来 的 接 收 器 的 安 装 和 初 始 化 步 骤 作 了 变 更 。安 装 <strong>VisiBroker</strong> 3.x 接 收 器为 了 在 <strong>VisiBroker</strong> <strong>Edition</strong> 下 使 用 早 期 的 接 收 器 , 请 :C++: 1 将 包 含 指 令 #include "migration_c.hh" 加 到 您 要 使 用 <strong>VisiBroker</strong> 3.x 接 收 器的 文 件 中 。migration_c.hh 头 文 件 包 含 适 用 于 旧 接 收 器 的 封 装 器 。Java: 当 移 植 工 具 移 植 接 收 器 时 , 它 加 入 以 下 的 声 明 以 导 入 Java 文 件 中 的 声 明 :import com.inprise.vbroker.interceptor.migration.*;如 果 您 在 手 动 移 植 接 收 器 , 则 需 要 自 已 动 手 加 入 该 声 明 以 导 出 声 明 。Java: 1 对 下 表 中 所 示 的 接 收 器 进 行 重 新 命 名 :表 30.11 在 C++ 下 对 接 收 器 进 行 重 新 命 名旧 式 名 称interceptor::BindInterceptorinterceptor::ChainBindInterceptorinterceptor.::ChainClientInterceptorinterceptor.::ChainServerInterceptorinterceptor::ClientInterceptorFactory新 式 名 称interceptor_migration::BindInterceptorDelegateinterceptor_migration::BindInterceptorManagerinterceptor_migration::ClientInterceptorDelegateinterceptor_migration::ServerInterceptorDelegateinterceptor_migration.::ClientInterceptorFactory表 30.12 在 Java 下 对 接 收 器 进 行 重 新 命 名旧 式 名 称com.(inprise|borland|visigenic).vbroker.interceptor.BindInterceptorcom.(inprise|borland|visigenic).vbroker.interceptor.ChainBindInterceptorcom.(inprise|borland|visigenic).vbroker.interceptor.ClientInterceptorcom.(inprise|borland|visigenic).vbroker.interceptor.ServerInterceptor新 式 名 称com.inprise.vbroker.interceptor.migration.BindInterceptorDelegatecom.inprise.vbroker.interceptor.migration.BindInterceptorManagercom.inprise.vbroker.interceptor.migration.ClientInterceptorDelegatecom.inprise.vbroker.interceptor.migration.ServerInterceptorDelegate30-10 <strong>VisiBroker</strong> 开 发 者 指 南


移 植 接 收 器表 30.12 在 Java 下 对 接 收 器 进 行 重 新 命 名旧 式 名 称com.(inprise|borland|visigenic).vbroker.interceptor.ClientInterceptorFactorycom.(inprise|borland|visigenic).vbroker.interceptor.ServerInterceptorFactory新 式 名 称com.inprise.vbroker.interceptor.migration.ClientInterceptorFactorycom.inprise.vbroker.interceptor.migration.ServerInterceptorFactory移 植 BindInterceptors在 <strong>VisiBroker</strong> <strong>Edition</strong> 中 , 封 装 器 模 拟 真 实 的 BindInterceptor。在 以 前 的 版 本 中 , 要 加 入 一 个 BindInterceptor, 您 需 要 :1 通 过 调 用 以 下 方 法 来 取 得 ChainBindInterceptor 的 引 用C++:ORB::resolve_initial_references("ChainBindInterceptor")或 者 :Java:通 过 调 用 Java ORB.resolve_initial_references("ChainBindInterceptor") 以 取 得ChainBindInterceptor 的 引 用 。2 给 序 列 中 加 入 新 的 接 收 器 。C++: 要 在 <strong>VisiBroker</strong> <strong>Edition</strong> for C++ 下 使 用 您 的 <strong>VisiBroker</strong> 3.x 限 制 接 收 器 代 码 ,您 应 该 :1 通 过 调 用 ORB::resolve_initial_references("ChainBindInterceptor"), 取 得interceptor_migration::ChainBindDelegateFactory 的 引 用 。2 然 后 , 创 建 您 的 interceptor_migration::BindInterceptorDelegate ( 而 不 是您 在 <strong>VisiBroker</strong> 3.x 中 所 使 用 的 interceptor ::BindInterceptor) 并 将 它 加入 序 列 上 。Java:要 在 <strong>VisiBroker</strong> <strong>Edition</strong> for Java 上 使 用 您 的 <strong>VisiBroker</strong> 3.x 限 制 接 收 器 , 您 应该 :1 通 过 调 用 ORB.resolve_initial_references("ChainBindInterceptor") 取 得interceptor_migration.ChainBindDelegateFactory 的 引 用2 然 后 , 创 建 您 的 interceptor_migration.BindInterceptorDelegate ( 而 不 是 您在 <strong>VisiBroker</strong> 3.x 中 所 使 用 的 接 收 器 .BindInterceptor) 并 将 它 加 入 序 列 。移 植 客 户 端 和 服 务 器 端 接 收 器在 以 前 的 版 本 中 , 要 加 入 ClientInterceptor 或 ServerInterceptor, 需 要 执 行 以 下步 骤 :1 实 现 接 口 :客 户 端C++移 植 <strong>VisiBroker</strong> 代 码 30-11


移 植 接 收 器Java:Java:Java:Java:Interceptor::ClientInterceptorFactoryInterceptor.ClientInterceptorFactory, 或 者服 务 器 端C++Interceptor::ServerInterceptorFactoryInterceptor.ServerInterceptorFactory该 接 口 提 供 用 于 创 建 用 户 实 现 的 ClientInterceptors 和 ServerInterceptors 的 方法 。 然 后 , 您 应 该 取 得 ChainClientDelegateFactory 或ChainServerDelegateFactory 的 引 用 , 通 过 用 它 们 , 您 可 以 将 您 的 接 收 器 加 到 序列 中 。在 <strong>VisiBroker</strong> <strong>Edition</strong> 下 , 您 应 该 :1 实 现 InterceptorDelegate客 户 端C++Interceptor_migration::ClientInterceptorDelegateInterceptor_migration.ClientInterceptorDelegate ; 或服 务 器 端C++Interceptor_migration::ServerInterceptorDelegateInterceptor_migration.ServerInterceptorDelegate2 取 得 InterceptorFactory 的 引 用Java:Java:客 户 端C++Inteceptor_migration::ClientInterceptorFactoryInteceptor_migration.ClientInterceptorFactory ; 或服 务 器 端C++Inteceptor_migration::ServerInterceptorFactoryInteceptor_migration.ServerInterceptorFactory这 些 方 法 返 回 相 应 的 InterceptorDelegate 的 实 例 。当 您 可 以 访 问 客 户 工 厂 、 服 务 器 工 厂 或 两 者 均 可 访 问 , 您 就 可 以 将 您 的 客 户 端 或 服务 器 端 接 收 器 安 装 入 相 应 的 工 厂 序 列 。要 完 成 操 作 :客 户 端 , 调 用C++30-12 <strong>VisiBroker</strong> 开 发 者 指 南


移 植 事 件 回 路 集 成 ( 仅 适 用 于 C++)Java:Java:ORB::resolve_initial_references("ChainClientDelegateFactory")ORB.resolve_initial_references("ChainClientDelegateFactory") ; 或服 务 器 端 , 调 用C++ORB::resolve_initial_references("ChainServerDelegateFactory") in C++ orORB.resolve_initial_references("ChainServerDelegateFactory")一 旦 有 了 这 些 引 用 , 您 就 可 以 用 Add() 方 法 将 它 们 加 入 序 列 。 ( 这 一 步 骤 与<strong>VisiBroker</strong> 3.x 相 同 )移 植 事 件 回 路 集 成 ( 仅 适 用 于 C++)仅 适 用 于 C++:<strong>VisiBroker</strong> 3.x 中 的 特 性 允 许 您 将 您 的 对 象 的 事 件 调 查 并 入 网 络 或 查 看 组 件 的 事 件回 路 。 <strong>VisiBroker</strong> 3.x 中 的 特 性 如 下 :● 允 许 在 第 三 方 库 上 构 建 CORBA 应 用 的 单 线 程 库 。 这 些 应 用 需 要 用 非 凹 系 统 库来 创 建 。● 用 于 在 Windows 上 构 建 单 线 程 服 务 器 的 Wdispatcher 类 。该 类 允 许 将 <strong>VisiBroker</strong> ORB 事 件 和 Windows 消 息 事 件 集 成 在 一 起 。● 用 于 在 XWindows 上 构 建 单 线 程 服 务 器 的 XDispatcher 类 。该 类 允 许 将 <strong>VisiBroker</strong> ORB 事 件 直 接 集 成 到 XWindows XtMainLoop。● Dispatcher 类 允 许 将 <strong>VisiBroker</strong> ORB 事 件 与 其 它 环 境 集 成 在 一 起 。 这 一 过 程通 常 伴 随 着 从 Dispatcher 用 户 子 类 中 派 生 客 户 子 类 和 为 所 有 的 方 法 提 供 实 现 。您 也 可 以 使 用 Dispatcher 类 直 接 查 看 <strong>VisiBroker</strong> ORB 事 件 , 处 理 特 定 文 件 描 述符 的 事 件 , 并 设 置 事 件 计 时 器 。但 是 , 在 凹 式 <strong>VisiBroker</strong> ORB 库 中 , 所 有 的 <strong>VisiBroker</strong> ORB 事 件 均 由<strong>VisiBroker</strong> ORB 线 程 来 处 理 。 通 常 , 没 有 必 要 与 其 它 的 事 件 处 理 系 统 集 成 。 在<strong>VisiBroker</strong> 4.x 中 , 本 版 本 不 包 含 单 线 程 <strong>VisiBroker</strong> ORB 库 。 因 此 ,<strong>VisiBroker</strong> 4.x 及 以 后 的 版 本 不 支 持 以 上 的 特 性 。 在 有 些 情 况 下 , 当 应 用 使 用<strong>VisiBroker</strong> 3.x 特 性 时 , 您 需 要 修 改 编 码 以 消 除 该 功 能 。 下 一 节 提 供 这 些 变 化 的指 南 。移 植 单 线 程 的 <strong>VisiBroker</strong> ORB以 下 是 移 植 单 线 程 <strong>VisiBroker</strong> ORB 的 指 南 :● 确 保 使 用 的 所 有 实 现 方 法 是 线 程 安 全 的 , 或 者 视 所 需 的 行 为 , 使 用SINGLE_THREAD_MODEL 或 MAIN_THREAD_MODEL 的 POAThreadPolicy。 在 有 些 情 况 下 , 即 使 在 使 用 这 些 策 略 之 一 时 , 您 也 需 要 保 护 实现 代 码 的 关 键 片 断 。 在 这 些 情 况 下 , 可 以 使 用 一 个 用 于 协 调 应 用 的 关 键 段 的 全 局互 斥 锁 来 取 得 同 步 。移 植 <strong>VisiBroker</strong> 代 码 30-13


移 植 事 件 回 路 集 成 ( 仅 适 用 于 C++)● 如 果 应 用 中 没 有 采 用 其 它 的 机 制 来 防 止 应 用 的 main() 返 回 , 则 使 用 ORBrun() 方 法 ( 可 选 方 法 )。 但 是 , 不 必 调 用 run() 方 法 。 所 有 的 <strong>VisiBroker</strong>ORB 线 程 都 是 通 过 使 用 ORB_init() 方 法 和 POA 管 理 器 激 活 方 法 创 建 的 。用 Xdispatcher 或 WDispatcher 类 移 植XDispatcher 和 WDispatcher 类 与 <strong>VisiBroker</strong> ORB 运 行 期 和 XWindows 或Windows 事 件 回 路 透 明 地 配 合 。 如 果 Xdispatcher 或 WDispatcher 的 一 个 实例 创 建 于 第 一 次 调 用 ORB_init 之 前 , 则 Xdispatcher 或 Wdispatcher 移 植 方 法会 派 上 用 场 。 因 此 , 如 果 确 保 应 用 是 线 程 安 全 的 ( 如 第 30-13 页 " 移 植 单 线 程 的<strong>VisiBroker</strong> ORB" 一 节 所 述 ), 您 就 可 以 直 接 删 除 XDispatcher 或 Wdispatcher的 引 用 。// ...hwnd = CreateWindow(szAppName, "AccountServer", WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT, 200, 200, NULL,NULL,hInstance, NULL);// 调 用 ORB_init 之 前 创 建 一 个 WDispatcher 实 例WDispatcher *winDispatcher = new WDispatcher(hwnd);// 初 始 化 ORBCORBA::ORB_var orb = CORBA::ORB_init(__argc, __argv); // 初 始 化 BOACORBA::BOA_var orb = orb->BOA_init(__argc, __argv); // 创 建 服 务 对 象AccountImpl server("BankManager");// 激 活 BOA 上 的 服 务 对 象boa->obj_is_ready(&server);ShowWindow(hwnd, nCmdShow);UpdateWindow(hwnd); // 进 入 消 息 回 路while(GetMessage(&msy, NULL, 0, 0) ) {TranslateMessage(&msg); DispatchMessage(&msg);}return msg.wParam;// ...本 代 码 示 例 显 示 移 植 后 的 Wdispatcher:// ...hwnd = CreateWindow(szAppName, "AccountServer", WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT, 200, 200, NULL,NULL, hInstance, NULL);// 初 始 化 ORBCORBA::ORB_var orb = CORBA::ORB_init(_argc, _argv);// 初 始 化 POACORBA::Object_var obj = orb->resolve_initial_references("RootPOA");PortableServer::POA_var rootPOA = PortableServer::POA::_narrow(obj);30-14 <strong>VisiBroker</strong> 开 发 者 指 南


移 植 事 件 回 路 集 成 ( 仅 适 用 于 C++)CORBA::PolicyList policies;policies.length(1);policies[(CORBA::ULong)0] = rootPOA->create_lifespan_policy(PortableServer::PERSISTENT);PortableServer::POAManager_var poa_mgr = rootPOA->the_POAManager();PortableServer::POA_var myPOA = rootPOA->create_POA("bank_agent_poa",poa_mgr, policies);// 创 建 服 务 对 象AccountManagerImpl managerServant;// 激 活 POA 上 的 服 务 对 象PortableServer::ObjectId_var managerId =PortableServer::string_to_ObjectId("BankManager");myPOA->activate_object_with_id(managerId, &managerServant);ShowWindow(hwnd, nCmdShow);UpdateWindow(hwnd);// 进 入 消 息 回 路while(GetMessage(&msy, NULL, 0, 0) ) {TranslateMessage(&msg);DispatchMessage(&msg);}return msg.wParam;// ...当 消 除 WDispatcher 或 Xdispatcher 时 , 不 需 要 额 外 的 步 骤 来 转 换 应 用 以 使 用POA。移 植 <strong>VisiBroker</strong> 代 码 30-15


30-16 <strong>VisiBroker</strong> 开 发 者 指 南


第章使 用 对 象 激 活 器第 31 章本 章 描 述 如 何 使 用 <strong>VisiBroker</strong> 对 象 激 活 器 。在 本 版 的 <strong>VisiBroker</strong> 中 , 可 移 植 对 象 适 配 器 (POA) 支 持 由 <strong>VisiBroker</strong> 3.x 版中 的 BOA 所 提 供 的 特 性 。 由 于 提 供 了 后 向 兼 容 , 您 仍 可 以 使 用 您 的 代 码 按 照 本 章中 所 述 来 使 用 对 象 激 活 器 。 要 取 得 本 版 中 关 于 如 何 使 用 BOA 激 活 器 的 详 情 , 请参 阅 第 29 章 " 使 用 <strong>VisiBroker</strong> <strong>Edition</strong> 4.x BOA" 和 第 30 章 " 移 植 <strong>VisiBroker</strong>代 码 "。延 迟 对 象 激 活当 一 个 服 务 器 需 要 给 大 量 的 对 象 提 供 实 现 时 , 您 可 以 通 过 单 个 Activator 使 用 服 务激 活 来 延 迟 多 个 对 象 实 现 。激 活 器 界 面您 可 以 从 C++ 或 Java 的 Activator 类 派 生 您 自 己 的 界 面 。 这 允 许 您 实 现 纯 虚(C++) activate 和 deactivate 方 法 , <strong>VisiBroker</strong> ORB 可 将 这 些 方 法 用 于 C++AccountImpl 或 Java DBObjectImpl 对 象 。 然 后 , 您 可 以 将 AccountImpl 对 象 的 实 例化 延 迟 至 BOA 收 到 对 于 该 对 象 的 一 个 请 求 。 它 也 允 许 您 在 BOA 去 激 活 对 象 的 过程 中 提 供 清 除 处 理 。以 下 的 代 码 示 例 示 范 Activator 类 (C++)。class Activator {public:virtual CORBA::Object_ptr activate(extension::ImplementationDef impl)=0;virtual void deactivate(Object_ptr, extension::ImplementationDef_ptrimpl)=0;};使 用 对 象 激 活 器 31-1


激 活 器 界 面Java:这 个 代 码 示 例 示 范 激 活 器 界 面 , 该 界 面 提 供 BOA 可 调 用 来 激 活 和 去 激 活<strong>VisiBroker</strong> ORB 对 象 的 方 法 。package com.inprise.vbroker.extension;public interface Activator {public abstract org.omg.CORBA.Object activate(ImplementationDef impl);public abstract void deactivate(org.omg.CORBA.Object obj, ImplementationDefimpl);}以 下 的 代 码 示 例 示 范 您 如 何 为 AccountImpl Interface 创 建 Activator 。C++: class extension {. . .class AccountImplActivator :public extension::Activator {public:virtual CORBA::Object_ptr activate(CORBA::ImplementationDef_ptr impl);virtual void deactivate(CORBA::Object_ptr,CORBA::ImplementationDef_ptr impl);};CORBA::Object_ptr AccountImplActivator::activate(CORBA::ImplementationDef_ptr impl) {// 当 BOA 需 要 激 活 我 们 时 , 将 AccountImpl 对 象 实 例 化 。extension::ActivationImplDef* actImplDef =extension::ActivationImplDef::_downcast(impl);CORBA::Object_var obj = new AccountImpl(actImplDef->object_name());return CORBA::_duplicate(obj);}void AccountImplActivator::deactivate(CORBA::Object_ptr obj,CORBA::ImplementationDef_ptr impl) {// 当 BOA 去 激 活 我 们 时 , 释 放 Account 对 象 。obj->_release;}}Java:以 下 的 代 码 示 例 示 范 如 何 为 DBObjectImpl Interface 创 建 Activator 。// Server.javaimport com.inprise.vbroker.extension.*;. . .class DBActivator implements Activator {private static int _count;private com.inprise.vbroker.CORBA.BOA _boa;public DBActivator(com.inprise.vbroker.CORBA.BOA boa) {_boa = boa;}public org.omg.CORBA.Object activate(com.inprise.vbroker.extension.ImplementationDef impl) {System.out.println("Activator called " + ++_count + " times");byte[] ref_data = ((ActivationImplDef) impl).id();DBObjectImpl obj = new DBObjectImpl(new String(ref_data));_boa.obj_is_ready(obj);return obj;}public void deactivate(org.omg.CORBA.Object obj,31-2 <strong>VisiBroker</strong> 开 发 者 指 南


使 用 服 务 激 活 方 法com.inprise.vbroker.extension.ImplementationDef impl} {// 这 里 什 么 也 不 用 做 ......}}. . .使 用 服 务 激 活 方 法当 一 个 服 务 器 需 要 为 大 量 的 对 象 ( 通 常 成 千 上 万 , 也 可 能 几 百 万 个 ) 提 供 实 现 , 但其 中 只 有 一 小 部 分 实 现 需 要 在 某 个 特 定 的 时 间 内 激 活 时 , 可 以 使 用 服 务 激 活 。 服 务器 可 以 提 供 一 个 单 独 的 Activator , 每 当 需 要 这 些 辅 助 对 象 时 , 就 通 知 该 激 活 器(Activator)。 服 务 器 也 可 以 在 这 些 对 象 未 使 用 时 将 它 们 去 激 活 。例 如 , 您 可 以 将 服 务 激 活 用 于 一 个 用 来 装 载 状 态 存 储 在 数 据 库 中 的 对 象 实 现 的 服 务器 。 Activator 负 责 装 载 具 有 给 定 类 型 或 逻 辑 特 性 的 所 有 对 象 。 当 在 这 些 对 象 的 引用 上 作 了 <strong>VisiBroker</strong> ORB 请 求 时 , 会 通 知 Activator 并 创 建 一 个 新 的 实 现 , 该 实现 的 状 态 从 数 据 库 载 入 。 当 Activator 确 定 对 象 不 应 该 再 存 在 于 内 存 中 时 , 如 果 该对 象 已 被 修 改 过 , 则 激 活 器 会 将 该 对 象 的 状 态 写 入 数 据 库 并 释 放 实 现 。图 31.1显 示 延 迟 激 活 服 务 的 进 程 的 图使 用 服 务 激 活 器 延 迟 对 象 激 活如 果 组 成 服 务 的 对 象 已 被 创 建 , 则 需 要 以 下 的 步 骤 来 实 现 使 用 服 务 激 活 的 服 务 器 :1 定 义 一 个 服 务 名 称 , 该 名 称 用 于 描 述 由 Activator 激 活 的 和 去 激 活 的 所 有 对 象 。2 为 那 些 是 服 务 对 象 而 不 是 永 久 对 象 的 界 面 提 供 实 现 。 当 对 象 将 自 身 构 建 成 服 务 的可 激 活 部 分 时 , 这 一 操 作 可 以 执 行 。3 实 现 根 据 需 要 创 建 对 象 实 现 的 Activator 。 在 实 现 中 , 您 可 以 从extension::Activator 派 生 出 一 个 激 活 器 界 面 , 可 以 不 考 虑 activate 和deactivate 方 法 。4 在 BOA 上 注 册 服 务 名 和 激 活 器 界 面 。使 用 对 象 激 活 器 31-3


使 用 服 务 激 活 方 法服 务 的 延 迟 对 象 激 活 实 例以 下 几 节 描 述 服 务 激 活 的 odb 实 例 , 该 实 例 位 于 您 的 <strong>VisiBroker</strong> <strong>Edition</strong> 安 装 的examples/boa/odb 目 录 下 。 实 例 目 录 包 含 以 下 文 件 :表 31.1用 于 服 务 激 活 的 odb 实 例 中 包 含 的 文 件名 称odb.idlServer.C (C++)Server.java (Java)Creator.C (C++)Creator.java (Java)Client.C (C++)Client.java (Java)Makefile说 明DB 和 DBObject 界 面 的 IDL使 用 服 务 激 活 器 创 建 对 象 , 返 回 对 象 的 IOR,并 去 激 活 对 象 。调 用 DB 界 面 创 建 100 个 对 象 并 将 生 成 的 字串 化 对 象 引 用 存 储 在 一 个 文 件 (objref.out)中 。从 一 个 文 件 中 读 取 对 象 的 字 串 化 对 象 引 用 , 并调 用 这 些 引 用 , 让 服 务 器 中 的 激 活 器 创 建 对象 。当 在 odb 子 目 录 下 调 用 make 或 nmake ( 在Windows 上 ) 时 , 构 建 以 下 的 客 户 和 服 务 器程 序 :Server.exe (C++) 或 Server(Java); Creator.exe (c++) 或 Creator(Java); Client.exe (C++) 或 Client(Java)odb 实 例 说 明 单 个 服 务 如 何 创 建 任 意 数 量 的 对 象 。 服 务 单 独 在 BOA 上 注 册 , 而 不是 每 个 对 象 在 BOA 上 注 册 , 每 个 对 象 的 引 用 数 据 存 储 为 IOR 的 一 部 分 。 这 有 利于 面 向 对 象 的 数 据 库 (OODB) 集 成 , 因 为 您 可 以 将 对 象 关 键 字 存 储 为 对 象 引 用的 一 部 分 。 当 一 个 客 户 请 求 尚 未 创 建 的 对 象 时 , BOA 调 用 一 个 用 户 定 义 的Activator。 然 后 , 应 用 会 从 永 久 存 储 库 中 载 入 相 应 的 对 象 。在 本 实 例 中 , 我 们 创 建 了 一 个 Activator , 它 负 责 激 活 和 去 激 活 命 名 为"DBService" 的 服 务 的 对 象 。 由 该 Activator 创 建 的 对 象 引 用 包 含 足 够 的 信 息 , 使<strong>VisiBroker</strong> ORB 可 以 重 新 定 位 DBService 服 务 的 Activator, 并 可 以 使 Activator根 据 要 求 重 建 这 些 对 象 。DBService 服 务 负 责 用 于 实 现 DBObject 界 面 的 对 象 。 我 们 提 供 了 一 个 可 以 允 许 人 工创 建 这 些 对 象 的 界 面 ( 包 含 在 odb.idl)。odb.idl 界 面odb.idl 界 面 允 许 人 工 创 建 实 现 DBObject odb 界 面 的 对 象 。interface DBObject {string get_name();};typedef sequence DBObjectSequence;interface DB {DBObject create_object(in string name);};DBObject 界 面 表 示 由 DB 界 面 创 建 的 对 象 , 可 以 被 视 为 一 个 服 务 对 象 。31-4 <strong>VisiBroker</strong> 开 发 者 指 南


使 用 服 务 激 活 方 法DBObjectSequence 是 一 个 DBObject 序 列 , 服 务 器 使 用 该 序 列 来 追 踪 当 前 活 动 的对 象 。DB 界 面 使 用 create_object 操 作 创 建 一 个 或 多 上 DBObject。 由 DB 界 面 创 建 的 对 象可 以 一 起 构 成 一 个 服 务 。实 现 服 务 激 活 的 对 象仅 适 用 于 C ++:idl2cpp 编 译 器 通 过 boa/odb/odb.idl 为 _sk_DBObject 框 架 类 产 生 两 种 构 建 器 。 第一 种 构 建 器 适 用 于 人 工 实 例 化 的 对 象 ; 第 二 种 构 建 器 可 以 使 对 象 变 成 服 务 的 一 部分 。 如 下 文 所 示 , DBObject 的 实 现 构 成 其 基 础 _sk_DBObject 方 法 , 其 中 使 用 的 是服 务 构 建 器 , 而 不 是 通 常 用 于 人 工 实 例 化 的 对 象 的 object_name 构 建 器 。 通 过 调 用这 种 构 建 器 , DBObject 将 自 身 构 建 成 被 称 为 DBService 的 服 务 的 一 部 分 。class DBObjectImpl:public _sk_DBObject {private:CORBA::String_var _name;public:DBObjectImpl(const char *nm, const CORBA::ReferenceData& data): _sk_DBObject("DBService", data), _name(nm) {}. . .};注 :仅 适 用 于 C++:基 础 构 建 器 需 要 一 个 服 务 名 称 和 一 个 不 透 明 的 CORBA::ReferenceData 值 - 当 这 个 对象 因 为 客 户 要 求 必 须 被 激 活 时 , Activator 使 用 这 些 参 数 来 唯 一 地 识 别 该 对 象 。 在本 实 例 中 , 用 于 区 分 多 个 实 例 的 引 用 数 据 的 编 号 范 围 为 0 ~ 99。实 现 服 务 激 活 器通 常 , 当 一 个 服 务 器 将 实 现 对 象 的 C++ 或 Java 类 实 例 化 时 , 一 个 对 象 就 被 激 活 ,然 后 调 用 C++ BOA::obj_is_ready 或 Java obj_is_ready, 接 下 来 再 调 用 C++BOA::impl_is_ready 或 Java impl_is_ready 。 要 延 迟 对 象 激 活 时 , 必 须 控 制 BOA在 对 象 激 活 过 程 中 所 调 用 的 activate 方 法 。 您 可 以 用 如 下 的 方 法 取 得 这 种 控 制 权 :从 C++ extension::Activator 或 Javacom.inprise.vbroker.extenstion.Activator 派 生 一 个 新 类 并 忽 略 activate 方 法 ,然 后 使 用 被 忽 略 的 activate 方 法 将 与 该 对 象 相 关 的 C++ 或 Java 类 实 例 化 。在 odb 实 例 中 , DBActivator 类 从 C++ extension::Activator 或 Javacom.inprise.vbroker.extenstion.Activator 衍 生 出 来 , 并 忽 略 activate 和deactivate 方 法 。 DBObject 是 通 过 activate 方 法 构 建 的 。C++: class DBActivator:public extension::Activator {virtual CORBA::Object_ptr activate(CORBA::ImplementationDef_ptr impl);virtual void deactivate(CORBA::Object_ptr,CORBA::ImplementationDef_ptr impl );public:DBActivator(CORBA::BOA_ptr boa) :_boa(boa) {}private:CORBA::BOA_ptr _boa;};使 用 对 象 激 活 器 31-5


使 用 服 务 激 活 方 法Java:这 是 一 个 在 Java 下 忽 略 激 活 和 去 激 活 的 实 例 。// Server.java实 现 Activator 的 DBActivator 类 {private static int _count;private com.inprise.vbroker.CORBA.BOA _boa;public DBActivator(com.inprise.vbroker.CORBA.BOA boa) {_boa = boa;}public org.omg.CORBA.Object activate(com.inprise.vbroker.extension.ImplementationDef impl) {System.out.printIn("Activator called " + ++_count + " times");byte[] ref_data = ((ActivationImplDef) impl).id();DBObjectImpl obj = new DBObjectImpl(new String(ref_data));_boa.obj_is_ready(obj);return obj;}public void deactivate(org.omg.CORBA.Object obj, ImplementationDef impl) {// 这 里 什 么 也 不 用 做 ......}}如 下 文 所 示 , DBActivator 类 基 于 其 在 C++ 下 的 CORBA::ReferenceData 参 数 创 建了 一 个 对 象 。 当 BOA 收 到 一 个 对 由 Activator 负 责 的 对 象 所 作 的 客 户 请 求 时 ,BOA 调 用 Activator 上 的 activate 方 法 。 在 调 用 该 方 法 时 , BOA 通 过 给Activator 传 送 一 个 ImplementationDef 参 数 来 唯 一 地 识 别 激 活 的 对 象 实 现 , 实 现可 以 从 其 中 得 到 C++ CORBA::ReferenceData 或 Java ReferenceData -- 所 请 求 的 对象 的 唯 一 标 识 。C++: CORBA::Object_ptr DBActivator::activate(CORBA::ImplementationDef_ptr impl) {extension::ActivationImplDef* actImplDef =extension::ActivationImplDef::_downcast(impl);CORBA::ReferenceData_var id(actImplDef->id());cout


使 用 服 务 激 活 方 法实 例 化 服 务 激 活 器如 下 面 的 代 码 示 例 所 示 , 通 过 在 C++ 下 的 主 服 务 器 程 序 中 使 用BOA::impl_is_ready 调 用 , 创 建 了 DBActivator 服 务 激 活 器 并 在 BOA 上 注 册 。DBActivator 服 务 激 活 器 负 责 所 有 属 于 DBService 服 务 的 对 象 。 所 有 对 DBService服 务 的 对 象 的 请 求 均 通 过 DBActivator 服 务 激 活 器 来 管 理 。 由 该 服 务 激 活 器 所 创 建的 所 有 对 象 均 具 有 引 用 , 引 用 可 以 通 知 <strong>VisiBroker</strong> ORB, 这 些 对 象 属 于DBService 服 务 。这 个 代 码 示 例 示 范 DBActivator 类 如 何 基 于 其 Java ReferenceData 参 数 创 建 一 个对 象 。C++: int main(int argc, char **argv) {CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);CORBA::BOA_ptr boa = orb->BOA_init(argc, argv);MyDB db("Database Manager");boa->obj_is_ready(&db);DBObjectImplReaper reaper;reaper.start();cout


使 用 服 务 激 活 方 法}DBObjectImpl *obj = new DBObjectImpl(name, id);_boa()->obj_is_ready(obj);_impls.length(_impls.length() + 1);_impls[_impls.length()-1] = DBObject::_duplicate(obj);return obj;第 二 种 对 BOA::obj_is_ready 的 调 用 是 在 DBActivator::activate 中 , 这 种 调 用 需要 采 用 的 显 式 。在 Java 下 使 用 服 务 激 活 器 激 活 对 象每 当 一 个 对 象 被 构 建 时 , 必 须 在 activate 中 显 式 调 用 obj_is_ready。 在 服 务 器 程序 中 , 对 bj_is_ready 有 两 种 调 用 。 一 种 调 用 出 现 在 服 务 器 创 建 一 个 服 务 对 象 的 过程 中 , 并 给 创 建 者 程 序 返 回 一 个 IOR 。Java: public DBObject create_object(String name) {System.out.println("Creating:" + name);DBObject dbObject = new DBObjectImpl(name);_boa().obj_is_ready(dbObject, "DBService", name.getBytes());return dbObject;}第 二 种 对 obj_is_ready 的 调 用 是 在 activate 中 , 这 种 调 用 需 要 采 用 显 式 。去 激 活 服 务 激 活 的 对 象 实 现仅 适 用 于 C ++:服 务 激 活 的 主 要 用 途 是 制 造 服 务 器 内 有 大 量 的 活 动 对 象 这 样 一 个 幻 像 , 但 在 特 定 的时 刻 实 际 上 只 有 其 中 的 一 小 部 分 是 活 动 的 。 要 支 持 这 一 模 型 , 服 务 器 必 须 能 够 临 时性 地 中 止 对 对 象 的 使 用 。 多 线 程 DBActivator 实 例 程 序 包 含 一 个 每 30 秒 去 激 活 所有 DBObjectImpls 的 回 收 器 线 程 。 当 deactivate 方 法 被 调 用 时 , DBActivator 就 释放 对 象 引 用 。 如 果 对 已 去 激 活 的 对 象 的 新 客 户 请 求 到 来 , 则 <strong>VisiBroker</strong> ORB 通 知Activator, 该 对 象 应 该 被 重 新 激 活 。// 当 前 活 动 的 实 现 的 静 态 序 列static VISMutex _implMtx;static DBObjectSequence _impls;// 用 于 存 储 激 活 的 实 现 的 更 新 过 的 DBActivator// 在 全 局 序 列 中 。class DBActivator:public extension::Activator {virtual CORBA::Object_ptr activate(CORBA::ImplementationDef_ptr impl) {extension::ActivationImplDef* actImplDef =extension::ActivationImplDef::_downcast(impl);CORBA::ReferenceData_var id(actImplDef->id());DBObjectImpl *obj = new DBObjectImpl((char *)id->data(), id);VISMutex_var lock(_implMtx);_impls.length(_impls.length() + 1);_impls[_impls.length()-1] = DBObject::_duplicate(obj);return obj;}virtual void deactivate(CORBA::Object_ptr,CORBA::ImplementationDef_ptr impl) {31-8 <strong>VisiBroker</strong> 开 发 者 指 南


使 用 服 务 激 活 方 法obj->_release();}};// 多 线 程 回 收 器 , 每 30s// 销 毁 所 有 已 激 活 的 对 象 。class DBObjectImplReaper :public VISThread {public:// 回 收 器 方 法virtual void start() {run();}virtual CORBA::Boolean startTimer() {vsleep(30);return 1;virtual void begin() {while (startTimer()) {doOneReaping();}}protected:virtual void doOneReaping() {VISMutex_var lock(_implMtx);for (CORBA::ULong i=0; i < _impls.length(); i++) {// 将 nil 分 配 给 各 元 素 的 操 作 将 被 释 放// 存 储 在 _var 中 的 引 用DBObject_var obj = DBObject::_duplicate(_impls[i-1];_impls[i] = DBObject::_nil();CORBA::BOA_var boa = obj->_boa();boa->deactivate_obj(obj);}_impls.length(0);}};使 用 对 象 激 活 器 31-9


31-10 <strong>VisiBroker</strong> 开 发 者 指 南


第章第 32 章CORBA 违 例本 章 介 绍 关 于 <strong>VisiBroker</strong> ORB 掷 出 的 CORBA 违 例 的 信 息 , 并 解 释 <strong>VisiBroker</strong><strong>Edition</strong> 掷 出 它 们 的 可 能 原 因 。Corba 违 例 描 述下 表 列 出 了 CORBA 违 例 , 并 说 明 <strong>VisiBroker</strong> ORB 掷 出 它 们 的 原 因 。违 例 说 明 可 能 原 因CORBA::BAD_CONTEXT 一 个 非 法 的 上 下文 被 传 递 到 了 服务 器 。如 果 客 户 调 用 操 作 , 则 操 作 可 能 会 掷 出 该 违例 。 但 是 , 被 传 递 的 上 下 文 不 包 含 操 作 所 要求 的 上 下 文 值 。CORBA::BAD_INV_ORDERCORBA::BAD_OPERATION在 违 例 操 作 要 求之 前 , 没 有 调用 必 要 的 前 提操 作 。执 行 了 一 个 非 法操 作 。在 实 际 发 送 请 求 之 前 , 可 能 曾 尝 试 调 用 过CORBA::Request::get_response() 或CORBA::Request::poll_response() 方 法 ;可 能 曾 尝 试 在 远 端 方 法 调 用 的 实 现 之 外 ,调 用 过 exception::get_client_info() 方法 。 该 功 能 仅 在 远 端 调 用 实 现 内 部 有 效 。 调用 了 已 经 关 闭 的 <strong>VisiBroker</strong> ORB 上 的 一个 操 作 。如 果 收 到 一 个 对 未 在 实 现 的 接 口 上 定 义 的 操作 的 请 求 , 则 服 务 器 会 掷 出 该 违 例 。 确 保 客户 和 服 务 器 是 从 相 同 的 IDL 编 译 而 来 的 。如 果 未 设 定 请 求 包 含 一 个 返 回 值 , 则CORBA::Request::return_value() 方 法 会 掷出 该 违 例 。 如 果 在 执 行 一 个 DII 调 用 时 , 期望 得 到 一 个 返 回 值 , 则 一 定 要 通 过 调 用CORBA::Request::set_return_type() 方 法来 设 定 返 回 值 类 型 。CORBA 违 例 32-1


Corba 违 例 描 述违 例 说 明 可 能 原 因CORBA::BAD_PARAMCORBA::BAD_TYPECODECORBA::CODESET_INCOMPATIBLECORBA::COMM_FAILURECORBA::DATA_CONVERSIONCORBA::FREE_MEM ( 仅 C++)传 递 到<strong>VisiBroker</strong>ORB 的 一 个 参 数是 非 法 的 。ORB 遇 到 了 一个 错 误 类 型 的代 码 。由 于 代 码 集 不 兼容 , 客 户 原 生 码集 与 服 务 器 原 生码 集 之 间 的 通 信失 败 。在 客 户 发 出 请 求之 后 而 在 回 答 返回 之 前 , 在 一 个操 作 的 执 行 过 程中 , 通 信 丢 失 。<strong>VisiBroker</strong>ORB 不 能 将 汇 集的 数 据 的 表 示 转换 成 其 原 生 的 表示 , 反 之 亦 然 。<strong>VisiBroker</strong>ORB 释 放 动 态 内存 失 败 。如 果 尝 试 访 问 一 个 非 法 的 索 引 , 则 序 列 会 掷出 CORBA::BAD_PARAM 违 例 。 确 定 您 在 存 储或 检 索 序 列 元 素 之 前 , 使 用 length() 方 法来 设 定 序 列 长 度 。 在 C++ 下 , 如 果 一 个 非法 的 Object_ptr 被 作 为 in 变 量 传 递 ( 例如 , 传 递 了 一 个 nil 引 用 ), 则<strong>VisiBroker</strong> ORB 会 掷 出 该 违 例 。 在 Java下 , 如 果 传 递 了 null 引 用 , 则 <strong>VisiBroker</strong>ORB 会 掷 出 该 违 例 。 在 从 IDL 到 C++ 的映 射 要 求 发 送 已 初 始 化 的 C++ 对 象 时 , 可能 曾 尝 试 发 送 一 个 NULL 指 针 。 例 如 , 如 果尝 试 将 NULL 作 为 一 个 应 该 返 回 sequence 的方 法 的 返 回 值 或 out 参 数 , 则 会 掷 出 该 违例 。 在 这 种 情 况 下 , 应 该 返 回 一 个 新 的sequence ( 可 能 长 度 为 0) 序 列 。 不 能 在C++ NULL 值 下 发 送 的 类 型 包 括 Any、Context、 struct 和 sequence。 可 能 曾 尝 试发 送 一 个 超 出 枚 举 数 据 类 型 值 域 的 值 。 可 能曾 尝 试 用 非 法 的 kind 值 来 构 建 TypeCode。可 能 曾 尝 试 将 一 个 nil 对 象 引 用 插 入 一 个Any ( 在 C++ 下 )。 可 以 曾 尝 试 将 一 个strong>null 对 象 引 用 插 入 一 个 Any ( 在Java 下 )。 可 能 使 用 DII 和 单 向 方 法 调 用指 定 了 一 个 OUT 变 量 。 如 果 传 递 到 IR 对 象的 操 作 的 变 量 与 现 有 设 置 冲 突 , 则 接 口 仓 库掷 出 该 违 例 。 参 阅 编 译 器 错 误 以 查 看 详 情 。客 户 使 用 的 代 码 集 和 服 务 器 使 用 的 代 码 集 不能 一 起 工 作 。 例 如 , 客 户 使 用 ISO 8859-1而 服 务 器 使 用 日 本 代 码 集 。C++: 由 于 现 有 连 接 的 另 一 端 发 生 故 障 ,现 有 连 接 可 能 已 关 闭 。 由 于 客 户 机 或 服 务 器机 上 的 资 源 限 制 ( 已 达 到 最 大 连 接 数 量 ),新 的 连 接 请 求 可 能 已 失 败 。 当COMM_FAILURES 因 为 系 统 违 例 而 出 现 时 , 系统 错 误 码 被 设 定 到 COMM_FAILURE 的 次 要 代码 (minor code)。 根 据 系 统 错 误 码( 如 , 在 include/sys/errno.h 或msdev\include\winerror.h 文 件 中 )检 查 minor code。 Java: 在 客 户 发 出 请 求之 后 而 在 回 答 返 回 之 前 , 如 果 在 一 个 操 作 的执 行 过 程 中 , 通 信 丢 失 , 则 掷 出 该 违 例 。如 果 尝 试 将 Unicode 字 符 与Output.write_char() 或Output.write_string 汇 集 , 则 会 失 败 。<strong>VisiBroker</strong> ORB 尝 试 释 放 的 内 存 段 可 能 被锁 住 。 堆 栈 可 能 已 毁 坏 。32-2 <strong>VisiBroker</strong> 开 发 者 指 南


Corba 违 例 描 述违 例 说 明 可 能 原 因CORBA::IMP_LIMITCORBA::INITIALIZECORBA::INTERNALCORBA::INTF_REPOSCORBA::INV_FLAGCORBA::INV_IDENTCORBA::INV_OBJREFCORBA::INV_POLICYCORBA::INVALID_TRANSACTIONCORBA::MARSHALCORBA::NO_IMPLEMENTCORBA::NO_MEMORYCORBA::NO_PERMISSION在 <strong>VisiBroker</strong>ORB 运 行 期 内一 个 实 现 限 制 被覆 盖 。必 要 的 初 始 化 没有 执 行 。出 现 了 一 个 内 部<strong>VisiBroker</strong>ORB 错 误 。接 口 仓 库 的 一 个实 例 找 不 到 。非 法 的 标 志 被 传递 到 操 作 。IDL 标 识 符 语 法错 误 。遇 到 了 一 个 非 法的 对 象 引 用 。遇 到 了 一 个 非 法的 策 略 门 限 。请 求 携 带 非 法 的事 务 上 下 文 。错 误 的 汇 集 参 数或 结 果 。找 不 到 请 求 的对 象 。<strong>VisiBroker</strong>ORB 运 行 期 内 存不 足 。调 用 者 没 有 足 够的 权 利 来 完 成调 用 。<strong>VisiBroker</strong> ORB 可 能 已 达 到 它 在 一 个 地 址空 间 中 可 以 同 时 容 纳 的 引 用 的 最 大 数 量 。 参数 的 大 小 可 以 已 超 过 允 许 的 最 大 值 。 运 行 客户 和 服 务 器 的 最 大 数 量 可 能 已 被 覆 盖 。可 能 没 有 调 用 过 ORB_init() 方 法 。 所 有 的客 户 在 执 行 任 何 与 <strong>VisiBroker</strong> ORB 相 关的 操 作 之 前 , 都 必 须 调 用 ORB_init() 方 法 。通 常 , 主 例 程 顶 层 的 程 序 启 动 一 完 成 , 就 常要 立 即 执 行 该 调 用 。可 能 出 现 了 一 个 内 部 <strong>VisiBroker</strong> ORB 错误 。 例 如 , <strong>VisiBroker</strong> ORB 的 内 部 数 据 结构 可 能 已 被 毁 坏 。如 果 一 个 对 象 实 现 在 调 用 get_interface()方 法 的 过 程 中 找 不 到 接 口 仓 库 , 则 该 违 例 会被 掷 到 客 户 端 。 确 保 有 一 个 接 口 仓 库 正 在 运行 , 并 确 保 所 要 求 的 对 象 的 接 口 定 义 已 被 载入 该 接 口 仓 库 。用 非 法 的 标 志 创 建 了 一 个 动 态 调 用 接 口 。传 递 到 接 口 仓 库 的 标 识 符 结 构 不 正 确 。 一 个非 法 的 操 作 名 称 被 用 于 动 态 调 用 接 口如 果 得 到 一 个 不 包 含 任 何 可 用 内 容 的 对 象 引用 ,<strong>VisiBroker</strong> ORB 将 掷 出 该 违 例 。 如 果字 串 化 的 对 象 引 用 不 以 字 符 “IOR:” 开头 , 则 ORB::string_to_object() 方 法 将 掷出 该 违 例 。任 何 调 用 都 可 能 掷 出 该 违 例 。 如 果 由 于 应 用于 特 定 调 用 的 策 略 不 兼 容 而 使 得 一 个 调 用 无法 执 行 , 则 会 掷 出 该 违 例 。有 关 该 违 例 的 详 情 , 请 参 阅 您 的 事 务 服 务资 料 。网 络 发 出 的 请 求 或 回 答 的 结 构 非 法 。 通 常 ,此 错 误 表 明 客 户 端 或 服 务 器 端 的 运 行 期 内 出现 问 题 。 例 如 , 如 果 服 务 器 发 出 的 一 个 回 答表 明 消 息 包 含 1000 字 节 , 但 实 际 的 消 息 长度 不 足 于 或 大 于 1000 字 节 , 则<strong>VisiBroker</strong> ORB 会 掷 出 该 违 例 。 如 果 不 正确 地 使 用 DII 或 DSI, 也 会 掷 出 MARSHAL 违例 。 例 如 , 如 果 发 送 的 实 际 参 数 的 类 型 与 操作 的 IDL 签 名 不 符 , 则 会 掷 出 该 违 例 。该 违 例 表 明 , 虽 然 被 调 用 的 操 作 存 在 ( 它具 有 IDL 定 义 ), 但 此 操 作 的 任 何 实 现 都不 存 在 。 例 如 , 如 果 在 客 户 发 起 一 个 限 制时 , 服 务 器 不 存 在 或 没 有 在 运 行 , 则 会 掷 出NO_IMPLEMENTATION。CORBA 违 例 32-3


Corba 违 例 描 述违 例 说 明 可 能 原 因CORBA::NO_RESOURCESCORBA::NO_RESPONSECORBA::OBJ_ADAPTERCORBA::OBJECT_NOT_EXISTCORBA::PERSIST_STORECORBA::REBINDCORBA::TIMEOUTCORBA::TRANSACTION_REQUIREDCORBA::TRANSACTION_ROLLEDBACKCORBA::TRANSIENT无 法 获 得 必 要 的资 源 。客 户 尝 试 检 索 一个 延 迟 的 同 步 调用 的 结 果 , 但 对该 请 求 的 回 答 不可 用 。出 现 了 一 个 管 理失 配 。所 要 求 的 对 象 不存 在 。出 现 了 一 个 永 久性 存 储 故 障 。客 户 收 到 了 一 个与 QOS 策 略 冲突 的 IOR。<strong>VisiBroker</strong>ORB 超 时 关 闭 一个 操 作请 求 携 带 一 个null 事 务 上 下文 , 但 需 要 一 个活 动 的 事 务 。与 事 务 有 关 的 一个 请 求 已 被 拒 绝或 已 打 上 了 拒 绝的 标 志 。出 现 了 一 个 错误 , 但 ORB 认为 可 以 重 试 此操 作 。如 果 不 能 新 建 一 个 新 的 线 程 , 则 会 掷 出 该 违例 。 当 一 个 远 端 客 户 尝 试 建 立 连 接 时 , 如 果服 务 器 不 能 创 建 一 个 套 接 字 ( 例 如 , 服 务器 用 尽 了 文 件 描 述 符 ), 则 服 务 器 会 掷 出 该违 例 。 minor code 包 含 服 务 器 调 用::socket() 或 ::accept() 失 败 后 所 得 到 的系 统 错 误 码 。 同 样 地 , 如 果 因 为 用 尽 文 件 描述 符 而 导 致 ::connect() 调 用 失 败 , 则 客 户端 也 会 掷 出 该 违 例 。 在 C++ 下 , 如 果 内 存不 足 , 也 可 能 会 掷 出 该 违 例 。一 个 服 务 器 尝 试 使 用 已 用 的 名 称 或 实 现 存 储库 未 知 的 名 称 在 实 现 存 储 库 上 注 册 。 由 于 应用 的 伺 服 对 象 管 理 器 出 现 问 题 , POA 出 现了 OBJ_ADAPTER 错 误 。如 果 尝 试 执 行 服 务 器 内 不 存 在 的 实 现 上 的 操作 , 则 此 服 务 器 将 掷 出 该 违 例 。 当 尝 试 调 用去 激 活 的 实 现 上 的 操 作 时 , 客 户 端 也 会 看 到该 违 例 。 例 如 , 尝 试 限 制 到 一 个 对 象 失 败 ,或 再 限 制 失 败 , 则 会 掷 出OBJECT_NOT_EXIST 。尝 试 建 立 到 数 据 库 的 连 接 时 出 现 了 问 题 , 或数 据 库 被 毁 坏 。每 当 客 户 得 到 一 个 与 已 设 定 的 QOS 策 略 冲突 的 IOR 时 , 就 会 掷 出 该 违 例 。 如 果RebindPolicy 具 有 一 个 NO_REBIND、NO_CONNECT、 VB_NOTIFY_REBIND 值 , 而 对 限制 的 对 象 引 用 的 调 用 引 发 一 条 对 象 前 转 或 位置 前 转 消 息 , 则 会 掷 出 该 违 例 。当 尝 试 建 立 连 接 或 等 待 请 求 / 回 答 时 , 如果 操 作 不 能 在 指 定 的 时 间 内 完 成 , 则 会 掷 出一 个 TIMEOUT 违 例 。有 关 该 违 例 的 详 情 , 请 参 阅 您 的 事 务 服 务资 料 。有 关 该 违 例 的 详 情 , 请 参 阅 您 的 事 务 服 务资 料 。可 能 已 出 现 了 一 个 通 信 错 误 , 但<strong>VisiBroker</strong> ORB 指 示 应 该 尝 试 再 限 制 到 发生 通 信 故 障 的 服 务 器 。 如 果 使 用enable_rebind() 方 法 将 BindOptions 设 置为 false, 或 者 适 当 地 设 置 RebindPolicy,则 不 会 出 现 该 违 例 。32-4 <strong>VisiBroker</strong> 开 发 者 指 南


Corba 违 例 描 述违 例 说 明 可 能 原 因CORBA::UNKNOWNCORBA::UnknownUser 违 例( 仅 C++ )<strong>VisiBroker</strong>ORB 不 能 确 定 被掷 出 的 违 例 。已 收 到 一 个 用 户违 例 , 但 是 客 户不 知 道 该 违 例 的编 译 时 间 。服 务 器 掷 出 的 不 是 正 确 的 违 例 , 例 如 ,Java运 行 期 违 例 。 服 务 器 与 客 户 之 间 发 生 IDL失 配 , 而 相 关 的 违 例 未 在 客 户 端 程 序 中 定义 。 在 DII 中 , 如 果 服 务 器 在 编 译 过 程 中 掷出 一 个 客 户 未 知 的 违 例 , 而 客 户 未 指 定CORBA::Request 违 例 列 表 , 则 会 掷 出 该 违例 。 设 置 服 务 器 上 的 vbroker.orb.warn=2属 性 以 查 看 是 哪 一 个 运 行 期 违 例 引 发 了 该 问题 。当 客 户 从 服 务 器 中 读 取 一 个 用 户 违 例 时 , 如果 它 不 知 道 该 违 例 类 型 的 编 译 时 间 , 则 它 会产 生 该 违 例 。 客 户 能 够 看 见 违 例 的 类 型 , 并得 到 了 包 含 违 例 内 容 的 汇 集 的 缓 冲 器 。<strong>VisiBroker</strong> ORB 无 法 自 行 对 违 例 进 行解 包 。系 统 违 例Minor code( 次 要 代 码 ) 说 明BAD_PARAM 1 注 册 、 反 注 册 或 查 看 值 工 厂 失 败2 RID 已 定 义 在 接 口 仓 库 中3 名 称 已 在 接 口 仓 库 中 的 上 下 文 中 作 用4 目 标 不 是 一 个 合 法 的 容 器5 名 称 在 继 承 的 上 下 文 中 产 生 冲 突6 不 正 确 的 抽 象 接 口 类 型MARSHAL 1 找 不 到 值 工 厂NO_IMPLEMENT 1 丢 失 本 地 值 实 现2 不 兼 容 的 值 实 现 版 本BAD_INV_ORDER 1 接 口 仓 库 中 有 存 根 , 阻 止 销 毁 对 象2 尝 试 销 毁 接 口 仓 库 中 不 能 毁 坏 的 对 象3 操 作 将 死 锁4 <strong>VisiBroker</strong> ORB 已 关 闭OBJECT_NOT_EXIST 1 尝 试 传 递 未 激 活 的 ( 未 注 册 的 ) 值 作 对 象 引 用CORBA 违 例 32-5


32-6 <strong>VisiBroker</strong> 开 发 者 指 南


索 引符 号*_interface_name() 方 法 10-5*_repository_id() 方 法 10-5*object_to_string() 方 法 10-5... 省 略 符 号 1-2:: 作 用 域 解 析 运 算 符 19-7_duplicate() 方 法 10-4_get_policy 10-9_is_a() 方 法 10-6_is_bound() 方 法 10-6_is_local() 方 法 10-6_is_remote() 方 法 10-6_narrow() 方 法 5-3_nil() 方 法 10-4_ptr, 由 idl2cpp 编 译 器 生 成 的 11-7_ref_count() 方 法 10-5_release() method 10-4_set_policy_override 方 法 10-9_tie 类模 板 类 9-2如 何 工 作 9-1委 托 者 实 现 9-1由 idl2cpp 编 译 器 生 成 的 11-9_var 类由 idl2cpp 编 译 器 生 成 11-7| 竖 线 1-2数 字4.x 接 收 器管 理 器 21-1接 口 21-1客 户 端 21-2与 可 移 植 接 收 器 配 合 使 用 21-14Aaccount.idl, 从 fromaccount_c.hh 生 成 的 文 件 4-4account_s.hh 生 成 的 文 件 4-4account.idl, 生 成 的 文 件account_c.cc 4-4account_s.cc 4-4activate() 方 法 31-1Activator 类去 激 活 ORB 对 象 31-1延 迟 对 象 激 活 31-1ActiveObjectLifeCycleInterceptor 21-3agent报 告 12-10agentaddr 文 件指 定 IP 地 址 12-8Any 19-8类 18-12API移 植 到 新 调 用 30-9安 装 命 名 服 务 14-5BBAD_OPERATION 违 例当 找 不 到 操 作 时 掷 出 19-8bind_contextnsutil 14-7bind_new_contextnsutil 14-7BindInterceptor 21-2BOAobj_is_ready() 方 法 19-2migrating to POA 30-1编 写 代 码 BOA 代 码 29-1定 义 服 务 对 象 30-6对 象 源 活 器 29-2进 入 的 请 求 30-7删 除 的 类 29-1使 用 时 的 限 制 29-2限 制 12-11映 射 到 POA 30-8在 <strong>VisiBroker</strong> 4.0 下 使 用 29-1支 持 的 选 项 29-1BOA_init对 包 的 变 更 29-1包 名移 植 到 新 包 30-8备 份 存 储 14-14编 译BOA 代 码 29-1idl 文 件 26-3编 译 程 序IDL, 特 性 汇 总 2-3编 译 和 链 接 15-23编 译 器nmake 4-11制 作 4-11变 量 , 环 境OSAGENT_PORT, 设 置 3-3PATH, 设 置 3-1VBROKER_ADM, 设 置 3-2捕 捉 违 例系 统 违 例 5-5修 改 用 户 违 例 5-8捕 捉 用 户 违 例用 户 违 例 5-8部 署描 述 4-12索 引 I-1


C应 用 4-12ChainUntypedObjectWrapper 22-6classORBInitializer 20-10CLASSPATH 3-2ClientRequestInterceptor 21-2类 20-3实 现 20-19Codec 20-7接 口 20-7类 20-7CodecFactory 20-8接 口 20-8类 20-8connect_pull_consumer 15-26connect_pull_supplier 15-26connect_push_consumer 15-26ConnEventListener 接 口 23-1connID 23-1ConnInfo 23-1connID 23-1ipaddress 23-1port 23-1ConsumerAdmin接 口 15-25CORBAORB::create_operation_list() 方 法 19-8<strong>VisiBroker</strong> 兼 容 性 2-5定 义 2-1说 明 2-1CORBA ( 一 般 对 象 请 求 代 理 结 构 2-1)CORBA 违 例 32-1CORBA::DynamicImplementation 类 19-2corbaloc URL 14-9corbaname URL 14-9CosNaming从 命 令 行 调 用 14-7CreationImplDef 结 构激 活 对 象 16-9CreationImplDef 类 16-8activation_policy 属 性 16-8args 属 性 16-8env 属 性 16-8path_name 属 性 16-8Current接 口 20-7类 20-7参 数 , 传 递输 入 , 在 DSI 中 处 理 19-8仓 库 ID取 得 10-5仓 库 id取 得 16-3策 略 10-8POA 7-3为 POA 设 置 30-5映 射 BOA 到 POA 30-8有 效 10-8策 略 门 限 10-8产 品 版 本 2-5抽 象valuetypes 26-2接 口 26-8初 始 化DynAny 的 值 25-3初 始 化 命 服 务 ( 仅 Java) 14-12触 发 器仅 第 一 个 实 例 , 查 看 13-6什 么 是 触 发 器 ? 13-2处 理 系 统 违 例 5-3创 建DII 请 求 18-7DynAnys 25-2软 件 组 件 2-1存 根例 程 4-4存 取DynAny 的 值 25-3错 误 日 志 文 件 3-3D-D_VIS_INCLUDE_IR flag 17-7-D_VIS_INCLUDE_IR 标 志 17-8DataExpress 适 配 器 14-14deactivate() 方 法 31-1DII 2-3接 收 结 果 18-15初 始 化 DII 请 求 18-10创 建 DII 请 求 18-7创 建 请 求 18-6发 送 和 接 收 多 个 请 求 18-18发 送 请 求 18-15接 口 仓 库 17-1, 18-20接 收 多 个 请 求 18-19普 通 对 象 引 用 18-5请 求 18-18设 置 请 求 变 量 18-10设 置 上 下 文 18-10使 用 idl2java 编 译 器 18-5, 19-1特 性 汇 总 2-3disconnect_push_consumer 15-27DynamicImplementation 类 19-2派 生 实 例 19-3DynAnycurrent_component 方 法 25-3next 方 法 25-3rewind 方 法 25-3to_any method 25-5查 询 方 法 25-3创 建 25-2I-2 <strong>VisiBroker</strong> 开 发 者 指 南


存 取 与 初 始 化 25-3概 述 25-1结 构 化 数 据 类 型 25-3类 型 25-1实 例 IDL 25-4实 例 服 务 器 应 用 25-7实 例 客 户 程 序 25-5实 例 应 用 25-4使 用 限 制 25-2DynArray数 据 类 型 25-4DynEnum数 据 类 型 25-3DynSequence数 据 类 型 25-4DynStruct数 据 类 型 25-4DynUnion数 据 类 型 25-4代 理 对 象限 制 进 程 , 过 程 中 创 建 10-2代 理 接 收 者 15-2代 理 提 供 者 15-2代 码编 译 BOA 代 码 29-1代 码 生 成 4-4导 入 声 明 14-23点 对 点 通 讯 12-7调 用移 植 到 新 API 调 用 30-9调 用 特 性 汇 总 2-3定 位 服 务代 理 , 可 访 问 13-2定 位 服 务 代 理 的 组 件 13-2什 么 是 定 位 服 务 ? 13-1特 性 汇 总 2-2增 强 型 对 象 定 位 2-2智 能 代 理什 么 是 ? 13-5定 义 接 口 名 称 11-2动 态 调 用 接 口协 议 桥 接 19-1动 态 调 用 接 口 . 参 见 DII 18-1动 态 框 架 接 口 2-3, 19-3DynamicImplementation 类 , 派 生 19-2ServerRequest 类 19-7编 译 对 象 服 务 器 19-2返 回 值 19-8服 务 器 对 象 , 实 现 19-8概 述 19-1激 活 对 象 19-9派 生 类 19-2实 例位 置 19-2输 入 参 数 19-8特 性 汇 总 2-3协 议 桥 接 19-1端 口 号监 听 器 7-30队 列 长 度设 置 15-21对 象IDL, 指 定 4-3从 接 口 仓 库 存 取 信 息 17-7多 个 实 例 , 区 分 16-8复 制 12-9关 联 URL 27-1激 活 31-4, 31-5动 态 变 更 属 性 16-9可 执 行 程 序 的 路 径 16-9列 出 16-4去 激 活 31-8容 错 , 提 供 12-8设 置 激 活 策 略 16-9设 置 路 径 16-9使 用 CreationImplDef 结 构 16-9使 用 OAD 连 接 12-2通 过 URL 定 位 27-1无 状 态 , 调 用 方 法 12-8限 制 12-11用 DSI 动 态 创 建 , 步 骤 19-2用 定 位 服 务 找 到 13-1与 智 能 代 理 连 接 12-1在 网 络 上 报 告 对 象 12-10注 册OAD 16-9状 态 , 调 用 方 法 12-8对 象 定 位增 强 型 , 定 位 服 务 2-2对 象 封 装 器 22-13idl2cpp 要 求 22-2idl2java 要 求 22-2post_method 22-4pre_method 22-3安 装 非 型 别 22-5, 22-6程 序 实 例 22-2非 型 别 22-2非 型 别 工 厂 22-4介 绍 22-1客 户 端 和 服 务 器 共 存 22-12派 生 型 别 封 装 器 22-13删 除 非 型 别 工 厂 22-10删 除 型 别 封 装 器 22-18添 加 非 型 别 22-7添 加 型 别 封 装 器 22-14同 时 使 用 型 别 和 非 型 别 封 装 器 22-18型 别 22-2, 22-11调 用 的 顺 序 22-12实 现 22-4使 用 22-4自 定 义 ORB 2-4对 象 管 理 组 2-1对 象 激 活 2-3服 务 激 活 31-3索 引 I-3


延 迟 31-6延 迟 的 方 法 的 实 例 31-4支 持 2-3对 象 激 活 守 护 程 序 请 参 阅 OAD 2-3对 象 名 称使 用 限 制 可 以 10-2对 象 请 求 代 理 。 请 参 阅 ORB 2-1对 象 实 现动 态 改 变 16-9容 错 12-8有 状 态 对 象 实 现 12-8对 象 数 据 库 激 励 器特 性 汇 总 2-4对 象 移 植 12-9对 象 引 用仓 库 ID, 取 得 10-5操 作 10-3超 级 类 型 , 转 换 为 10-8对 象 名 , 取 得 10-5复 制 10-4获 得 nil 引 用 10-4检 查 是 否 是 nil 引 用 10-3界 面 名 , 取 得 10-5类 型 , 确 定 10-6类 型 , 使 用 _is_a() 方 法 10-6类 型 的 实 例 , 确 定 10-6内 存 管 理 11-7取 得 对 象 和 界 面 名 10-5取 得 引 用 数 10-5确 定 位 置 和 状 态 10-6散 列 值 , 取 得 10-6释 放 10-4拓 宽 10-8相 当 的 实 现 , 检 查 10-6引 用 数 , 取 得 10-5窄 转 换 10-7, 10-8转 换 成 字 串 10-5转 换 类 型 10-7状 态 , 确 定 10-6子 类 型 , 确 定 是 否 是 10-6字 串 , 转 换 成 10-5多 Home 主 机接 口 使 用 , 指 定 12-6描 述 12-5多 线 程特 性 汇 总 2-3EEventChannel 15-3, 15-4接 口 15-24EventChannelFactory接 口 15-24EventLibrary 15-21, 15-22用 于 Java 15-22EventListener 23-1EventQueueManager 接 口 23-1Ffactory_name 14-7发 送DII 请 求 18-15多 个 请 求 18-18反 注 册 对 象OAD 16-11oadutil, 使 用 16-11方 法 10-9*_interface_name() 10-5*_object_name() 10-5*_repository_id() 10-5*object_to_string() 10-5_duplicate() 10-4_get_policy 10-9_is_a() 10-6_is_bound() 10-6_is_local() 10-6_is_remote() 10-6_narrow() 5-3_nil() 10-4_ref_count() 10-5_release() 10-4activate() 31-1boa.obj_is_ready() 19-2deactivate() 31-1invoke() 19-1, 19-2实 现 的 实 例 19-3is_nil() 10-3minor() 5-3oneway, 定 义 11-10open() 19-8release() 10-4string_to_object() 10-5无 状 态 对 象 , 调 用 12-8方 法 _set_policy_override 方 法 10-9分 布 式 应 用分 布 式 应 用 开 发 过 程 4-1封 包 的 valuetypes 26-7符 号省 略 符 号 ... 1-2竖 线 | 1-2服 务在 网 络 上 报 告 服 务 12-10服 务 对 象定 义 30-6服 务 激 活服 务 激 活 的 对 象 , 实 现 31-4去 激 活 服 务 激 活 的 对 象 31-8实 例 31-4实 例 化 对 象 激 活 器 31-6延 迟 , 实 现 31-3, 31-4延 迟 对 象 激 活 31-3服 务 激 活 器实 例 化 31-6实 现 31-5, 31-6服 务 器I-4 <strong>VisiBroker</strong> 开 发 者 指 南


tie 机 制 实 例 9-4设 置 激 活 策 略 16-9设 置 路 径 16-9实 现 4-8线 程 化 注 意 事 项 8-8服 务 器 端可 移 植 性 2-4服 务 器 服 务 对 象生 成 4-4服 务 器 激 活实 现 服 务 激 活 31-5服 务 器 请 求 接 收 器POA 作 用 域 20-13实 例 20-28服 务 器 应 用DynAny 实 例 25-7服 务 质 量 10-8界 面 10-9复 杂 名 14-4复 制 对 象 引 用 10-4复 制 在 OAD 注 册 上 的 对 象 12-9负 载 平 衡定 位 服 务 , 使 用 13-2在 主 机 之 间 移 植 对 象 12-9Gget_listeners 23-1概 述命 名 服 务 14-1事 件 服 务 15-1根POA 30-5根 NamingContext 14-3工 厂valuetypes 26-5默 认 26-7工 具CORBA 服 务 2-6idl2cpp 4-4idl2ir 2-5oadutil unreg 16-11oadutil, 注 册 对 象 16-6osfind 12-10vregedit 3-2编 程 2-5管 理 2-6公 用 对 象 请 求 代 理 。 请 参 阅 CORBA 2-1共 享 语 义 26-7构 建 代 码nmake 4-11制 作 4-11关 闭nsutil 14-7管 理 命 令oadutil list 16-4oadutil unreg 16-11osfind 12-10广 播 地 址 12-6广 播 消 息 12-1H互 操 作 性 2-7C++ <strong>VisiBroker</strong> 2-7Java <strong>VisiBroker</strong> 2-7ORB 互 操 作 性 2-7与 其 它 ORB 产 品 之 间 2-8环 境 变 量CLASSPATH 3-2OAD 16-2OSAGENT_ADDR 12-8OSAGENT_LOCAL_FILE 12-6OSAGENT_PORT设 置 3-3PATH, 设 置 3-1VBROKER_ADM设 置 3-2覆 盖 Windows 注 册 表 3-2汇 集 26-8使 用 java2iiop 24-5获 得nil 引 用 10-4Iid 字 段NameComponent 14-4IDLDynAny 实 例 25-4idl2cpp 生 成 的 客 户 代 码 11-6OAD 接 口 16-13oneway 方 法 , 定 义 11-10编 译 器 4-4构 造 , 在 接 口 仓 库 中 表 示 17-2继 承 , 指 定 11-10接 口 仓 库 , 中 所 包 含 的 信 息 17-1实 例 规 范 11-2映 射 到 Java 4-3映 射 至 Java 2-8指 定 对 象 4-3idl2cpp 编 译 器 4-4_op1 方 法 11-8_ptr, 生 成 11-7_tie, 生 成 的 11-9_var, 生 成 11-7oneway 方 法 , 定 义 11-10op1 method 11-6接 口 继 承 , 指 定 11-10客 户 代 码 , 生 成 11-6如 何 生 成 代 码 11-1属 性 的 方 法 , 生 成 的 11-9属 性 方 法 11-9idl2ir 编 译 程 序索 引 I-5


命 令 信 息 2-5说 明 2-5idl2ir 编 译 器 17-4idl2java 编 译 器-portable 标 志 18-5, 19-1使 用 DII 生 成 存 根 代 码 I 18-5用 DII 生 成 存 根 代 码 19-1importBiDir 28-6Interceptor类 20-2InterfaceDef object在 接 口 仓 库 中 17-2invoke() 方 法 19-1, 19-2实 现 的 实 例 19-3IOR 接 收 器 20-1IORCreationInterceptor 21-4IORInfoExt类 20-13IORInterceptor接 口 20-6类 20-6IP 子 网 掩 码localaddr 文 件 , 包 含 在 12-6ipaddress 23-1IP 子 网 掩 码广 播 消 息 , 指 定 范 围 12-4IR 请 参 阅 接 口 仓 库 2-4irep 工 具查 看 接 口 仓 库 17-4创 建 接 口 仓 库 17-2用 该 工 具 创 建 一 个 接 口 仓 库 17-2is_nil() 方 法 10-3JJavaJava 开 发 套 件 (JDK) 2-7运 行 期 环 境 2-7java2iiop映 射 复 杂 数 据 类 型 24-6映 射 原 始 类 型 24-5JDBC 适 配 器 14-14激 活 2-3POA 管 理 器 30-7服 务 激 活 31-3激 活 对 象OAD, 传 递 的 变 量 16-11动 态 变 更 属 性 16-9延 迟 31-1, 31-4用 服 务 激 活 器 延 迟 对 象 激 活 31-3激 活 器 类延 迟 对 象 激 活 31-4集 群 14-18记 录 输 出 3-3继 承valuetype 基 础 类 26-4从 实 现 , 允 许 9-1接 口 11-10检 查是 否 是 nil 引 用 10-3简 单 名 14-4减 少 应 用 开 发 成 本 2-1建 立 代 码 4-10将 对 象 引 用 转 换 成 字 串 10-5接 口Codec 20-7CodecFactory 20-8ConnEventListeners 23-1Current 20-7EventListener 23-1EventQueueManager 23-1IDL, 定 义 4-3IORInterceptor 20-6ORBInitializer 20-10ORBInitInfo 20-10ORInfoExt 20-13报 告 12-10查 询 17-8抽 象 26-8继 承 11-10继 承 , 指 定 11-10接 口 仓 库 中 的 描 述 17-1接 收 器 20-2使 用 java2iiop 24-6属 性 11-9接 口 仓 库 2-4_get_interface() 方 法 17-2查 看 内 容 17-4存 取 对 象 信 息 17-7的 内 容 17-2对 象 类 型 存 储 在 17-5多 少 ? 17-2继 承 的 接 口 17-7结 构 17-4, 17-5描 述 17-1内 容 17-5什 么 是 ? 17-1实 例 17-8识 别 对 象 17-5特 性 汇 总 2-4通 过 idl2ir 植 入 2-5用 idl2ir 更 新 内 容 17-4接 口 的 继 承指 定 11-10接 口 定 义 语 言 . 参 见 IDL 4-3接 口 名 称在 OAD 上 反 注 册 对 象 16-11接 收 多 个 请 求 18-18接 收 器ActiveObjectLifeCycleInterceptor 21-3BindInterceptor 21-2ClientRequestInterceptor 21-2IORCreationInterceptor 21-4POALifeCycleInterceptor 21-3I-6 <strong>VisiBroker</strong> 开 发 者 指 南


ServerRequestInterceptor 21-4程 序 实 例 21-6创 建 接 收 器 对 象 21-6服 务 器 21-3服 务 器 端 21-14接 口 20-2客 户 端 21-14默 认 接 收 器 类 21-5向 ORB 注 册 接 收 器 21-5之 间 传 递 数 据 21-13装 载 21-6自 定 义 ORB 2-4接 收 器 接 口实 例 21-6向 ORB 注 册 21-5结 构 化数 据 类 型 25-3结 构 化 数 据 类 型 25-3解 包 26-8解 析nsutil 14-7解 析 器 界 面使 URL 与 对 象 相 关 联 27-2界 面服 务 质 量 10-9界 面 名取 得 10-5进 程 内 事 件 通 道 15-21, 15-22禁 用智 能 代 理 12-2K开 发定 义 对 象 接 口 4-3实 例 应 用 4-1可 插 入 备 份 存 储类 型 14-14配 置 14-15属 性 文 件 14-15可 插 入 的 备 份 存 储 14-14可 截 取 的 valuetypes 26-9可 移 植 对 象 适 配 器策 略 7-3可 移 植 接 收 器Current 20-7IOR 接 收 器 20-1, 20-6PICurrent 20-7POA 作 用 域 服 务 器 请 求 20-13编 译 步 骤 20-36创 建 20-8概 述 20-1, 20-14接 收 器 20-2扩 展 20-13类 型 20-1请 求 接 收 器 20-1, 20-3请 求 拦 截 点 20-3实 例 ?? 20-36与 4.x 配 合 使 用 21-14注 册 20-10可 移 植 性服 务 器 端 2-4客 户实 现 4-5使 用 开 设 线 程 池 8-3客 户 valuetypes 26-8客 户 程 序DynAny 实 例 25-5客 户 存 根生 成 4-4客 户 端使 用 一 个 会 话 一 个 线 程 8-6通 过 URL 定 位 对 象 27-1指 定 URL 27-1客 户 和 服 务 器运 行 4-11, 4-13空 语 义 26-7框 架 4-4Llocaladdr 文 件 , 指 定 接 口 使 用 12-6拉 式 模 型 15-4拦 截 点调 用 顺 序 21-14请 求 拦 截 点 20-3类_tie 9-1, 9-2, 11-9_var 11-7Any 18-12ClientRequestInterceptor 20-3Codec 20-7CodecFactory 20-8CORBADynamicImplementation 19-2CreationImplDef 16-8Current 20-7DynamicImplementation 19-2Interceptor 20-2IORInterceptor 20-6NamedValue 18-11NVList 19-8ARG_IN 参 数 19-8ARG_INOUT 参 数 19-8ARG_OUT 参 数 19-8ORBInitInfo 20-11ORInfoExt 20-13PullSupplierPOA 15-16Repository 17-7ServerRequest 19-7TypeCode 18-13请 求 18-6移 植 到 新 类 名 30-8索 引 I-7


类 型Any 19-8DynAny 25-1接 口 仓 库 中 的 描 述 17-1实 例 , 确 定 是 否 是 10-6为 对 象 引 用 确 定 10-6系 统 违 例 , 确 定 5-3子 类 型 , 确 定 是 否 是 10-6类 型 字 段NameComponent 14-4连 接包 含 对 象 的 客 户 端 应 用 2-1点 对 点 通 讯 12-7管 理 , 特 性 汇 总 2-3智 能 代 理 在 不 同 局 域 网 中 12-4连 接 管 理 2-3连 接 提 供 者 到 EventChannel 15-4列 表nsutil 14-7列 出 , 实 现 库 的 内 容 16-13Mmakefile, Solaris 示 例 4-11maxQueueLength 15-21minor code系 统 违 例 , 取 得 和 设 置 5-3minor() 方 法 5-3ModuleDef object在 接 口 仓 库 中 17-2门 限策 略 10-8面 向 对 象 的 方 法软 件 组 件 创 建 2-1名 称定 义 14-4复 杂 14-4简 单 14-4解 析 14-4限 制 名 称 到 对 象 14-1字 串 化 14-4名 称 解 析 14-4命 令惯 例 1-2命 名 服 务安 装 14-5概 述 14-1集 群 14-18可 插 入 的 备 份 存 储 14-14配 置 14-6启 动 14-5, 14-6, 14-8容 错 14-22失 效 恢 复 14-21实 例 程 序 14-23属 性 14-13命 名 服 务 实 用 工 具 14-6命 名 上 下 文定 义 14-3类 14-11默 认 14-12由 对 象 实 现 使 用 14-3由 客 户 应 用 使 用 14-3默 认 的 命 名 上 下 文 14-12取 得 14-12默 认 工 厂 26-7NNameComponentid 字 段 14-4定 义 14-4类 型 字 段 14-4NamedValue对 18-11对 象 18-10类 18-11namespace 14-1NameValuePair 25-5Naming Contexts工 厂 14-3NamingContextbootstrapping 14-3工 厂 14-3NamingContextExt 14-11new_contextnsutil 14-7nmake 编 译 器 4-11nmake, 编 译 4-11nsutil 14-6NT 服 务osagent 12-2控 制 台 模 式 12-2NVList 类 19-8ARG_IN 参 数 19-8ARG_INOUT 参 数 19-8ARG_OUT 参 数 19-8实 现 变 量 列 表 18-10内 存 管 理对 象 引 用 的 11-7内 置 适 配 器 14-14OOADIDL 接 口 16-13impl_rep 文 件 16-1编 程 接 口 16-13传 递 的 变 量 16-11存 储 在 实 现 库 中 的 信 息 16-1存 储 注 册 信 息 16-4反 注 册 对 象 16-11复 制 注 册 的 对 象 12-9列 出 对 象 16-4启 动 16-2I-8 <strong>VisiBroker</strong> 开 发 者 指 南


设 定 激 活 策 略 16-9实 现 库 16-1移 植 注 册 对 象 12-10指 定 超 时 16-2注 册 对 象 16-9OAD 命 令设 置 环 境 变 量 16-2oadj报 告 12-10oadutil反 注 册 实 现 16-11列 出 用 OAD 生 成 的 对 象 16-4oadutil 工 具显 示 实 现 库 的 内 容 16-13注 册 对 象 实 现 16-1object referencespersistent 29-2OMG 2-1公 共 对 象 服 务 规 范 15-2事 件 服 务 15-1通 知 服 务 15-1oneway 方 法 , 定 义 11-10open() 方 法 19-8OpenFusion 通 知 服 务 15-1OperationDef object在 接 口 仓 库 中 17-2ORBresolve_initial_references 14-8创 建 proxy 12-11定 义 12-11对 象 实 现 16-4功 能 2-1互 操 作 性 2-7使 用 接 收 器 和 对 象 封 装 器 自 定 义 2-4域 12-3ORBDefaultInitRef 属 性 14-10ORBInitializerclass 20-10接 口 20-10实 现 20-16注 册 20-11, 20-15ORBInitInfo接 口 20-10类 20-11ORBInitRef 14-7ORBInitRef property 14-9ORInfoExt接 口 20-13OSAgent保 证 可 用 性 12-3定 位 对 象 12-2检 测 其 它 代 理 程 序 12-5检 查 客 户 端 是 否 存 在 ( 心 跳 ) 12-3启 动 12-2启 用 12-2详 细 输 出 12-2智 能 代 理 12-1osagentobject name 29-2报 告 12-10启 动 智 能 代 理 4-11限 制 12-11OSAGENT_ADDR 环 境 变 量 12-8OSAGENT_LOCAL_FILE 环 境 变 量 12-6OSAGENT_PORT 环 境 变 量设 置 3-3OSAgent ( 智 能 代 理 )<strong>VisiBroker</strong> 结 构 2-2osfind命 令 信 息 12-10PPATH, 设 置 3-1POAPOA 管 理 器 7-24ServantLocators 7-20策 略 7-3处 理 请 求 7-33创 建 7-3, 7-5从 BOA 类 型 映 射 30-8从 BOA 移 植 30-1调 度 属 性 7-27定 义 7-1定 义 服 务 对 象 30-6服 务 对 象使 用 7-15服 务 对 象 管 理 器 7-15管 理 POA 7-24激 活 对 象 7-15激 活 管 理 器 30-7监 听 器 端 口 属 性 7-30进 入 的 请 求 30-7取 得 根 引 用 30-5设 置 策 略 30-5收 听 属 性 7-27POALifeCycleInterceptor 21-3proxy 对 象限 制 12-11ProxyPullConsumer接 口 15-26ProxyPullSupplier接 口 15-26ProxyPushConsumer 15-3, 15-4接 口 15-26ProxyPushSupplier 15-3, 15-4PullConsume 15-18PullConsume.java 15-15PullConsumer接 口 15-27PullModel 15-16PullSupplier接 口 15-27, 15-28PullSupplierPOA索 引 I-9


类 15-16PullSupply 15-16PullSupply.java 15-15PushConsumer接 口 15-27派 生 15-9实 例 15-6实 现 15-13PushModel 15-16PushSupplier实 现 15-6PushSupplierImpl 15-6派 生 PushConsumer 15-9派 生 推 型 提 供 者 15-6配 置 命 名 服 务 14-6QQoS 10-8启 动OAD 16-2启 动 命 名 服 务 14-5, 14-6, 14-8启 用 再 限 制使 用 智 能 代 理 12-8请 求在 POA 下 等 待 进 入 的 请 求 30-7在 BOA 下 等 待 进 入 的 请 求 30-7请 求 接 收 器 20-1, 20-3POA 作 用 域 服 务 器 请 求 20-13拦 截 点 20-3实 例 20-28取 得对 象 和 界 面 名 10-5引 用 数 10-5取 得 名 称取 得 10-5取 得 默 认 的 命 名 上 下 文 14-12去 激 活服 务 激 活 的 对 象 实 现 31-8去 激 活 对 象 31-8去 限 制nsutil 14-7全 局 范 围 对 象智 能 代 理 , 注 册 到 12-1Rrebind_contextnsutil 14-7ref_data 参 数 16-8register_listener 23-1RelativeConnectionTimeoutPolicy 10-11release() 方 法 10-4Repository 类 17-7Request 类 18-6RequestInterceptor实 现 20-19REQUIRE_AND_TRUST 28-6日 志 文 件 3-3容 错 2-2, 14-22对 象 实 现 12-8复 制 在 OAD 注 册 上 的 对 象 12-9为 对 象 提 供 12-8SServerRequest 类 19-7ServerRequestInterceptor 21-4实 现 20-19ServiceInit 类 21-7ServiceLoader 接 口 21-6, 21-7Smart Agentobject name 29-2string_to_object() 方 法 10-5SupplierAdmin接 口 15-25SVCnameroot 14-7SVCnameroot 属 性 14-9散 列 值 , 取 得 对 象 引 用 10-6生 成_var 类 11-7方 法 11-8客 户 存 根 和 服 务 器 服 务 对 象 4-4类 模 板 11-9生 成 的 文 件= 由 idl 编 译 器 生 成 4-4失 效 恢 复 14-21什 么 是 CORBA? 9-1什 么 是 CORBA? 15-1, 22-1, 25-1实 例_tie class 9-2, 9-3Dynamic Implementation 类 , 派 生 19-3多 个 实 例 , 区 分 16-8激 活 31-4激 活 对 象 31-2, 31-4, 31-5, 31-6, 31-8区 分 16-8推 型 接 收 者 15-6推 型 提 供 者 15-6为 对 象 引 用 确 定 10-6用 定 位 服 务 找 到 13-1智 能 代 理 localaddr 文 件 12-6实 例 程 序命 名 服 务 14-23实 例 激 活 对 象 31-6实 例 应 用编 译 实 例 4-11部 署 应 用 4-12定 义 对 象 接 口 4-3服 务 器 服 务 对 象 4-4建 立 实 例 4-10开 发 过 程 4-1启 动 服 务 器 4-11生 成 客 户 存 根 4-4实 现 服 务 器 4-8I-10 <strong>VisiBroker</strong> 开 发 者 指 南


实 现 客 户 4-5使 用 <strong>VisiBroker</strong> 4-1用 IDL 编 写 帐 户 接 口 4-3运 行 实 例 4-11实 现NamedValue 对 象 列 表 18-10OAD, 传 递 的 变 量 16-11报 告 12-10服 务 器 4-8复 制 12-9激 活 2-3, 31-4, 31-5客 户 4-5列 出 16-4去 激 活 31-8去 激 活 服 务 激 活 的 对 象 31-8容 错 , 提 供 12-8使 用 一 个 会 话 一 个 线 程 8-6推 型 提 供 者 15-6无 状 态 , 调 用 方 法 12-8限 制 12-11相 当 , 检 查 10-6延 迟 31-3, 31-4用 DSI 动 态 创 建 , 步 骤 19-2用 OAD 反 注 册 16-12与 智 能 代 理 连 接 12-1在 OAD 反 注 册 16-11在 OAD 上 反 注 册 16-11在 OAD 上 注 册 16-4支 持 2-3状 态 , 调 用 方 法 12-8实 现 valuetypes 26-3实 现 仓 库 2-4特 性 汇 总 2-4实 现 工 厂 26-5实 现 工 厂 类 26-4实 现 库impl_rep 文 件 16-1OAD 16-4反 注 册 对 象 16-11内 容 , 显 示 16-13使 用 OAD 16-2用 OAD 指 定 目 录 16-2在 OAD 上 反 注 册 时 删 除 16-11注 册 信 息 存 储 16-1实 现 库 数 据 的 impl_rep 文 件 16-1实 现 推 型 接 收 者 15-13实 用 工 具idl2ir 17-4irep 17-2osagent 4-11事 件 队 列 23-1ConnEventListener 接 口 23-1EventListener 接 口 23-1EventQueueManager 接 口 23-1连 接 事 件 23-1事 件 监 听 器 23-1事 件 类 型 23-1事 件 服 务概 述 15-1拉 式 模 型 15-4启 动 15-20设 置 队 列 长 度 15-21通 信 模 型 15-3推 式 模 型 15-3事 件 监 听 器 23-1ConnInfo 23-1事 件 类 型 23-1连 接 类 型 23-1事 件 通 道进 程 内 实 现 15-21使 用 15-4释 放 对 象 引 用 10-4输 出 , 记 录 3-3输 入 / 输 出 变 量方 法 调 用 请 求 18-11输 入 参 数 , 在 DSI 中 处 理 19-8属 性ORBDefaultInitRef 14-10ORBInitRef 14-9SVCnameroot 14-9命 名 服 务 14-13, 14-15属 性 , 接 口 11-9数 据 类 型DynArray 25-4DynEnum 25-3DynSequrence 25-4DynStruct 25-4DynUnion 25-4结 构 化 25-3在 组 件 中 切 换 25-3说 明 文 件 1-1TTypeCode 类 18-13typecodes, 接 口 仓 库 , 表 示 为 17-2提 供 者连 接 到 EventChannel 15-4提 供 者 - 接 收 者 通 信 模 式 15-1推 式 模 型 15-3推 型 提 供 者派 生 15-6实 例 15-6拓 宽 对 象 引 用 10-8UUDP 协 议 12-1unregistered_listener 23-1UntypedObjectWrapperpost_method 22-6pre_method 22-6URL命 名 服 务 27-1索 引 I-11


Vvaluetypes 26-1编 译 IDL 文 件 26-3抽 象 26-2抽 象 接 口 26-8定 义 26-3概 述 26-1工 厂 26-1, 26-7继 承 值 类 型 基 础 类 26-4具 体 26-1可 截 取 26-9客 户 26-8来 源 26-1实 现 26-3实 现 工 厂 26-5实 现 工 厂 类 26-4向 ORB 注 册 工 厂 26-5已 转 变 26-7注 册 26-7vbroker.security.peerAuthenticationMode 28-6VBROKER_ADM 环 境 变 量设 置 3-2<strong>VisiBroker</strong>CORBA 兼 容 性 2-5说 明 2-2特 性 2-2<strong>VisiBroker</strong> 的 特 性IDL 编 译 程 序 2-3编 译 程 序 , IDL 2-3对 象 激 活 2-3对 象 数 据 库 集 成 2-4多 线 程 2-3激 活 对 象 和 实 现 2-3接 口 仓 库 2-4连 接 管 理 2-3实 现 仓 库 2-4实 现 激 活 2-3线 程 管 理 2-3<strong>VisiBroker</strong> 特 性 2-2定 位 服 务 2-2动 态 调 用 2-3智 能 代 理 的 IDL 接 口 2-2智 能 代 理 结 构 2-2VISObjectWrapper::ChainUntypedObjectWrapper 22-5删 除 工 厂 22-10添 加 工 厂 22-7UntypedObjectWrapperpost_method 22-5pre_method 22-5UntypedObjectWrapperFactory 22-4Visual C++, nmake 编 译 器 4-11vregedit 工 具 3-2Wweb sitesCORBA 规 范 2-5Web 命 名使 URL 与 对 象 相 关 联 27-1完 成 状 态 5-3系 统 违 例 , 取 得 5-3网 络报 告 对 象 和 服 务 12-10违 例BAD_OPERATION 19-8CORBA 定 义 的 系 统 违 例 5-1CORBA, 概 述 5-1捕 捉 用 户 违 例 5-8处 理 5-3违 例 完 成 状 态 5-3系 统SystemException 类 5-1造 型 到 一 个 系 统 违 例 5-3增 加 字 段 到 用 户 违 例 5-9窄 变 化 到 系 统 违 例 5-4掷 出 5-7位 置 , 为 对 象 引 用 确 定 10-6文 件impl_rep 16-1java. 策 略 24-1localaddr 12-6编 译 , 生 成 4-4文 件 扩 展 4-4无 状 态 对 象 , 调 用 方 法 12-8X系 统 违 例CompletionStatus values 5-3CORBA 定 义 的 5-1minor code, 取 得 和 设 置 5-3SystemException 类 5-1捕 捉 5-5处 理 5-3完 成 状 态 , 取 得 5-3窄 转 换 违 例 到 5-4限 制DynAny 的 使 用 25-2nsutil 14-7ORB 任 务 12-11进 程 10-2普 通 对 象 引 用 18-5使 用 BOA 29-2限 制 , 对 象创 建 的 代 理 对 象 10-2由 by _bind() 执 行 的 动 作 10-2由 ORB 建 立 的 连 接 10-2限 制 对 象确 定 位 置 状 态 10-6线 程I-12 <strong>VisiBroker</strong> 开 发 者 指 南


多 线 程 , 特 性 汇 总 2-3线 程 管 理 2-3线 程 化工 作 线 程 8-2, 8-5开 设 线 程 池 策 略 8-2使 用 同 步 阻 挡 8-8线 程 策 略 8-1一 个 会 话 一 个 线 程 策 略 8-5相 当 的 实 现 , 检 查 10-6销 毁nsutil 14-7选 项BOA 选 项 29-1Y延 迟对 象 激 活 31-3延 迟 对 象 激 活服 务 激 活 31-4延 迟 方 法 31-1延 迟 方 法 31-1移 植从 BOA 到 POA 30-1代 码 30-1定 义 服 务 对 象 30-6对 象 12-9激 活 POA 管 理 器 30-7进 入 的 请 求 30-7设 置 POA 策 略 30-5实 例 化 对 象 12-9映 射 BOA 类 型 到 POA 30-8有 状 态 对 象 12-9在 OAD 注 册 上 的 对 象 12-10主 机 之 间 对 象 12-9移 植 到新 API 调 用 30-9新 包 名 30-8新 类 名 30-8引 用 数 10-5递 增 10-4取 得 10-5引 用 数 据 16-8应 用定 义 对 象 接 口 4-3应 用 , 运 行 4-11服 务 器 对 象 , 启 动 4-12客 户 程 序 , 启 动 4-12智 能 代 理 , 启 动 4-11应 用 程 序开 设 线 程 池 8-3一 个 会 话 一 个 线 程 8-6应 用 开 发 成 本 , 减 少 2-1映 射IDL 至 Java 2-8永 久 对 象ODA, 特 性 汇 总 2-4用 户 违 例UserException 类 5-6捕 捉 违 例 , 修 改 对 象 以 5-8定 义 5-7增 加 字 段 到 5-9掷 出 违 例 , 修 改 对 象 以 5-7字 段 , 增 加 到 5-9有 效 的 策 略 10-8域 , 运 行 多 个 12-3运 算 符作 用 域 解 析 (::) 19-7运 行 应 用 4-11服 务 器 对 象 , 启 动 4-12客 户 程 序 , 启 动 4-12智 能 代 理 , 启 动 4-11Z再 限 制nsutil 14-7造 型 , 到 一 个 系 统 违 例 5-3增 加 字 段 到 用 户 违 例 5-9窄 转 换对 象 引 用 10-8违 例 到 系 统 违 例 5-4支 持实 现 和 对 象 激 活 2-3指 定IP 地 址 12-8指 针_ptr definition 11-7掷 出 用 户 违 例 5-7掷 出 用 户 违 例 , 对 象 修 改 以 5-7制 作 , 编 译 4-11智 能 代 理localaddr 文 件 , 指 定 接 口 使 用 12-6OAD, 协 作 12-2OSAgent 12-1OSAGENT_ADDR 环 境 变 量 12-8OSAGENT_LOCAL_FILE 文 件 12-6保 证 可 用 性 12-3点 对 点 通 讯 12-7定 位 12-1对 象 自 动 注 册 12-3多 Home 主 机使 用 12-5检 测 其 它 代 理 程 序 12-5检 查 客 户 端 是 否 存 在 ( 心 跳 ) 12-3禁 用 12-2可 用 性 , 保 证 12-3连 接 网 络 , 不 同 局 域 12-4启 动 12-2启 动 多 个 代 理 程 序 12-2容 错 , 为 对 象 提 供 12-8什 么 是 ? 12-1使 用 OAD 连 接 到 对 象 12-2特 性 汇 总 2-2索 引 I-13


通 讯 12-1限 制 12-11详 细 输 出 12-2与 其 它 代 理 程 序 协 作 12-2域 , 在 多 个 域 下 运 行 12-3在 OAD 上 反 注 册 时 16-11智 能 代 理 (OSAgent)结 构 2-2智 能 服 务定 位 服 务 , 合 作 13-1中 括 号 1-2注 册OAD, 存 储 在 实 现 库 中 的 信 息 16-1valuetypes 26-7工 厂 26-5智 能 代 理 s 12-1注 册 对 象 16-8oadutil, 使 用 16-6状 态为 对 象 引 用 确 定 10-6状 态 , 对 象 , 调 用 方 法 12-8状 态 , 完 成系 统 违 例 , 取 得 5-3子 类 型 , 确 定 10-6子 网 掩 码 12-4, 12-6字 串转 换 成 对 象 引 用 10-5字 串 化使 用 object_to_string() 方 法 10-5字 串 化 的 名 称 14-4作 用 域 解 析 运 算 符 (::) 19-7I-14 <strong>VisiBroker</strong> 开 发 者 指 南

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!