zoukankan      html  css  js  c++  java
  • [Domino]如何用java远程访问Domino邮箱数据

     

    [Domino]如何远程访问Domino邮箱数据

    编写者

    日期

    关键词

    郑昀@ultrapower

    2005-6-9

    Domino Notes Java DIIOP IOR

    CORBA Eclipse

     

    应用场景

    我们需要远程访问IBM Lotus Domino R6服务器,从中获取用户邮箱的邮件信息等关键数据。我们不需要提供每一个用户密码以及ID文件。

    技术关键词

    Java

    Java Lotus Notes/Domino 是理想的开发组合。

    DIIOP

    IIOPInternet Inter-ORB Protocol一种传输层协议。它用于CORBA 2.0及兼容平台上。IIOP协议是要建立以下几个部分:一个IIOPHTTP的网关,使用这个网关可以让CORBA客户访问WWW资源;一个HTTPIIOP的网关,通过这个网关可以访问CORBA资源;一个为IIOPHTTP提供资源的服务器,一个能够将IIOP作为可识别协议的浏览器。

    其中ORBObject Request Broker(请求对象代理)一个中间件。它可以建立对象之间的client/server关系。通过ORB,一个client可以透明的引用同一台机器上或网络上的一个server对象的方法。ORB解释该调用并负责查找一个实现该请求的对象,找到后,把参数传给该对象,调用它的方法,最后返回结果。

    那么,DIIOPDomino IIOP什么意思呢就是一个服务器端的任务通过Domino ORB来使得Domino ServerJava applets交互双方使用IIOP来交互和交换对象数据。

    IOR

    IORInteroperable Object Reference

    实际上,就是Domino服务器上的一个文件diiop_ior.txt的内容,类似于:

    IOR:01012d032900000049444c3a6c6f………………………

    ,它在c:\lotus\domino\data\domino\html文件夹下。

    客户端java程序向domino服务器发出CORBA请求服务器通过HTTP协议返回给客户端IOR字符串,之后客户端通过IIOP协议与服务器进行通讯。

    从这一点来看,IOR 实际上是一个对象的字符串编码,包含对Domino服务器的 CORBA 访问的识别信息。客户java程序将字符串 IOR 解码,就可以用它来寻找到对应的主机并建立远程会话了。

    Domino对象

    Domino对象类的结构基于包容模型,包容模型定义了对象的范围。容器对象通常被用来访问它所包含的子对象。
    关闭一个容器对象意味着其包含的全部子对象也将被关闭。例如,你建立了一个Database对象,使用它创建了一个Document对象,如果关闭了 Database对象,Document 对象也会随之关闭。如果容器对象超时,它将会被自动关闭,其包含的对象也将被自动关闭。因此你应该在容器对象超时或关闭前保存你的任何改变。

    Domino Database

    Domino中的Database,指的是在一个名字下存储的,一个集合,包含了Document以及相应的formviewfolderJava中有lotus.domino.Database

    我们通常可以通过session对象的getDatabase方法,或者DbDirectory对象的getFirstDatabase/ getNextDatabase方法,来获取Database对象的实例。

    Domino View

    Database集合中有着各种ViewJava中有lotus.domino.View。可以通过Database对象的getView方法,来获取View对象的实例。

    Domino Document

    Domino中的Document,指的是在一个Database的一个条目,包含了filedstextnumbersgraphics等等。Java中有lotus.domino.Document

    可以通过Database对象的getView方法,来获取View对象的实例。

    环境准备

    客户端java开发:

    安装Lotus Notes Client

    安装Eclipse 3.1 with Eclipse-JDT-SDK

    安装JRE 1.3.1Lotus Notes/Domino R5/6版本使用的是 Java 1.3.1,所以必须安装该软件以使用正确的版本来编译项目。(Lotus Notes/Domino 7 使用 JDK 1.4。)虽然许多 Java 代理和程序都可以编译,而且没什么问题,但可能会陷入另一些问题,比如使用一个 JDK 版本构建程序,却在另一个版本上运行。

    从服务器端Lotus目录下复制NCSO.jar以及NCSO.cab文件。远端访问Domino Server,需要这个jar包。

    Domino 提供了两个 JAR 文件,用于编程访问 Domino 对象。这两个文件是 Notes.jar NCSO.jarNotes.jar 用来访问 本地的 Domino 服务器(此时 Lotus Domino Java 程序运行在相同的服务器上)。NCSO.jar 包含了用来访问远程服务器的其他 CORBA/IIOP 代码。

    在决定使用哪个 JAR 文件时,请考虑以下因素:

    • 运行的 Java 程序和 Lotus Domino 的相对关系如何?如果它们运行在相同的机器上,那么使用 Notes.jar 可以获得更好的性能。
    • 您关心可扩展性吗?即使现在您是在相同的机器上运行 Java 程序(单独的 Java 程序和非 J2EE 的程序)和 Lotus Domino,将来您可能会发现需要将其扩展到专用的服务器上。在这种情况中,请使用 NCSO.jar ,这样可以获得更好的适应能力。
    • Java 程序要在一个应用服务器上运行吗?在 WebSphere 的情况中,即使它与 Lotus Domino 在相同的机器上,也需要使用 NCSO.jar

     如果你不用超级管理员用户名密码创建连接session,而是采用Domino Server ID,那么请从Domino服务器上Lotus目录下复制一个server.id文件以备用。

    如果你想直接使用diiop_ior.txt把这个diiop_ior.txt复制到本地。

    Domino服务器端配置:

    必须配置的项目:

    必须设置 Domino 服务器监听 IIOP 请求

    首先确保安装了DIIOP,你可以在安装过程中选择DIIOP,这样当安装结束,启动Domino Server Console时,就会看到提示“

    DIIOP Server     Listen for connect requests on TCP Port:63148

    DIIOP Server     Ultility task”。

    可以在 Domino Console中执行 show task load diiop 命令,可以帮助判断现在是否已经安装了 DIIOP。如果还没有安装,请从 Domino 安装光盘上安装 DIIOP

     

    否则,就要修改lotus目录下的Notes.ini文件了。找到以ServerTask开头的一行,找找看等号后面的字符串中是否有DIIOP,如果没有,就加上一个,然后重新启动Domino Server。这样,Domino启动时就会自动加载DIIOP

    ServerTask一行类似于:

    ServerTasks=Update,Replica,Router,AMgr, AdminP,CalConn,Sched,DIIOP,HTTP,LDAP

     

    如何获取IOR

    DIIOP 进程启动时,它在 Domino HTTP 根目录(Windows Domino 默认的安装目录为 C:\lotus\domino\data\domino\html)中创建一个名为 diiop_ior.txt IORInternet Object Reference)对象。

    如何得到这个diiop_ior.txt内容(也就是IOR),有两个办法:

    第一个就是,您通过HTTP方式向服务器请求这个文件。那么这个时候,如果您使用 Lotus Domino 作为 HTTP 服务器,就必须告诉 DIIOP 将这些文件放到您的 HTTP 服务器的根 HTML 目录中。配置方法如下所示:

    1.        运行Domino Admin 6,点击“XXX Domain”图标,打开 Domino Server 文档。

    2.        选择 Internet Protocols 属性页 - DIIOP 子属性页。

    3.        External HTML directory 字段中,输入非 Domino HTTP 服务器的根 HTML 目录的完整路径名。

    4.        保存这个 Server 文档,并重新启动 DIIOP

    第二个办法,是把这个diiop_ior.txt复制到客户端机器上,直接使用

     

    TCP/IP连接检查:

    远程访问还需要设置 Domino Server和客户端进行 TCP/IP 连接。Domino Server必须能够通过 TCP/IP 进行访问。必须能够用 Internet 名称从客户端ping 到服务器。

    DIIOP设置:

    检查 Domino Directory Server 文档。转至 Ports 选项卡,然后转向 Internet Ports 选项卡。查看 Web 选项卡(用于 HTTP)并找到 DIIOP 选项卡。这些部分有用于指定端口号以及启用/禁用端口的字段。通常,HTTP 的端口号是 80DIIOP 的端口号是 63148。下图显示了 Internet Ports--DIIOP 选项卡:

    No.

    Items

    Descriptions

    1

    Name and Password

    DIIOP 验证需要名称和密码

    2

    Anonymous

    DIIOP 验证不需要名称和密码

    3

    Enforce server access settings

    DIIOP 使用 Security 选项卡下的 Server Access 设置

     

    如果访问数据库时不知道文件名称(例如,要使用 DbDirectory.getFirstDatabase),那么必须允许通过网络浏览文件名。转至 Internet Protocols 选项卡、HTTP 选项卡和 R5 Basics 选项卡。然后将“Allow HTTP clients to browse databases”设为 Yes


     

    配置权限:

    必须给你当前建立session的用户配置权限,否则你将会遇到下面的错误:

    NotesException: You must have permission to sign documents for server based agents

        at lotus.domino.NotesExceptionHelper.read(Unknown Source)

        at lotus.domino.NotesExceptionHolder._read(Unknown Source)

        at lotus.priv.CORBA.iiop.RepImpl.invoke(Unknown Source)

        at lotus.priv.CORBA.portable.ObjectImpl._invoke(Unknown Source)

        at lotus.domino.corba._IDocumentStub.send(Unknown Source)

        at lotus.domino.cso.Document.send(Unknown Source)

        at SendMail.send(SendMail.java:203)

        at SendMail.main(SendMail.java:28)

    转至 Security 选项卡,找到“Programmability  Restrictions”,在“Run unrestricted methods and operations:”和“Sign agents to run on behalf of someone else:”后面输入你的用户名:

    总之,如果你遇到了权限错误,就到这里来配置。


    开始编写

    Add External JARs

    Eclipse 3.1,选中你的项目,右键菜单中“Build PathàAdd External Archives”,在文件选择对话框中找到并选中你前面复制到本地的NCSO.jar,如下图所示。

    添加了 JAR 文件之后,可以使用项目中 Notes Java API 定义的类和接口。 Domino Designer on-line help 中有关于 Notes Java API 的文档。

    然后选择 JRE System Library采用1.3.1版本的。

    获取IOR

    首先,我们去获取IOR

     

    还是前面说过的两种办法。

    第一种,与Domino Server联系获取:

    Code

    String dominoHost = "192.168.1.223";  // 这里填写主机名或IP地址

    String strIOR = null;

          URL url = new URL("http://" + dominoHost + "/diiop_ior.txt");

          InputStream in = url.openStream();

          BufferedReader br = new BufferedReader(new InputStreamReader(in));

          for (boolean bExit = false; !bExit; ) {

            String line = br.readLine();

            if (line == null) {

              bExit = true;

            }

            else {

              if (strIOR == null)

                strIOR = line;

              else

                strIOR = strIOR + line;

              if (strIOR.startsWith("IOR:"))

                bExit = true;

            }

          }

          br.close();

    第二种,取得本地文件:

    Code

    FileInputStream fin = new FileInputStream("c:\\diiop_ior.txt");

    InputStreamReader fisr = new InputStreamReader(fin);

    BufferedReader br = new BufferedReader(fisr);

    String ior = br.readLine();

    fin.close();

     

    创建session

    我们调用NotesFactorycreateSessionWithIOR方法,通过前面获取的IOR,创建一个session对象。

    Code

    Session s = NotesFactory.createSessionWithIOR(ior,

                                    "super admin" ,"admin password");

     

    打开names.nsf

    我们调用sessiongetDatabase方法,打开指定服务器上的names.nsf”数据库

    Code

    final static String DB_NAMES = "names.nsf";

    Database dbCache = s.getDatabase(s.getServerName(),

                                          DB_NAMES, false);

     

    得到Users View

    我们调用DatabasegetView方法,打开指定数据库上的($Users)”视图

    Code

    View view = dbCache.getView("($Users)");

     

    遍历Users View

    我们可以遍历指定数据库上的($Users)”视图,得到每一个用户的Document

    也可以指定一个用户,专门取得他的Mail File

    Code

    Document docKey = view.getDocumentByKey("zheng yun");

                            if (docKey == null)

                          System.out.println("docKey not found!");

                       else

                         {

                              strMailFile = docKey.getItemValueString("MailFile");

                          if (strMailFile == null)

                                 System.out.println("strMailFile is null!");

                          else

                                 System.out.println("strMailFile = " + strMailFile);

                    }

    输出结果就是:mail\zyun.nsf或者mail\zyun

    这样,我们就知道了该用户的邮箱所在的数据库文件的路径了。

     

    打开邮箱数据库文件

    知道了一名用户的邮箱文件名称,我们可以再用sessiongetDatabase方法打开该数据库:

    Code

    Database dbMail = s.getDatabase(s.getServerName(),

       "mail\\zyun.nsf", false);

    if(dbMail == null)

       System.out.println("cannot open database");

     

    遍历邮箱数据库的所有Document

    根据DocumentCollection dc = dbMail.getAllDocuments();我们获得了该数据库中存储的所有Document的集合,这就是所有的邮件。于是可以遍历了:

    Code

    if (dbMail != null)

    {

           DocumentCollection dc = dbMail.getAllDocuments();

           System.out.println("Mail database : " +

                             dbMail.getTitle() + " is " +

               ((int)(dbMail.getSize()/1024)) + "KB long and has " +

               dc.getCount() + " documents");

              

           String fn = dbMail.getFileName();

        String title = dbMail.getTitle();

        System.out.println(fn.toUpperCase() + " - " + title);

       

        Document doc = dc.getFirstDocument();

        while (doc != null) {

        System.out.println(

                   doc.getItemValueString("Subject"));

        System.out.println("~~~~~~~~~~~~~~~~~~~~\r\n");

        System.out.println("From=" + doc.getItemValueString("From"));

        System.out.println("~~~~~~~~~~~~~~~~~~~~\r\n");

        System.out.println("Body=" + doc.getItemValueString("Body"));

        System.out.println("~~~~~~~~~~~~~~~~~~~~\r\n");

       

        String readFlag = doc.getItemValueString("Readed");

        if(readFlag == null || readFlag!= "1" )

        {

            doc.appendItemValue("Readed ",

                   "1");

            if (doc.save())

                System.out.println("Document created and saved");

                else

                System.out.println("Something went wrong");

        }

        else

            System.out.println("发现已经打上了标记!");

       

        String docNoteID = doc.getNoteID();

        System.out.println("NoteID = " + docNoteID);

        String docNoteURL = doc.getNotesURL();

        System.out.println("NoteURL = " + docNoteURL);

                                    

        doc.recycle();

        doc = dc.getNextDocument(); }

     

    我们通过String readFlag = doc.getItemValueString("Readed");可以获得这个邮件的“Readed”字段(自定义字段)。如果这个字段不存在,说明我们是第一次浏览该封邮件。这样的话,我们通过doc.appendItemValue("Readed ", "1");以及doc.save(),给该封邮件增加这个已浏览标示字段。

     

    另外,转《通过JAVA-CORBA访问Domino》中一段很有帮助的话:

    如何从lotus.domino.NotesException 中获取错误信息:

    在你编写dominojava/corba应用程序时,不可避免的要同异常处理打交道,NotesException当然是每个开发人员都不愿见到的但又不得不经常面对的问题。

    如果你在写程序时尽是简单的采用

    try{

     ….

    }catch(Exception e){

     e.printStackTrace();

    }

    的形式捕捉异常,那么一旦代码抛出异常,你将变得一筹莫展,因为屏幕上不会打印出任何对你提供帮助的信息,这方面的资料更是凤毛翎角, IBM的官方文档中都没有丰富的错误信息提示。错误捕捉代码应该这样写:

    try{

     ….

    }catch(Exception e){

    if(ex instanceof lotus.domino.NotesException){

    System.out.println( "通过CORBA访问数据库发生错误,错误代码为"

    +((lotus.domino.NotesException)ex).id);

    }

    e. printStackTrace();

    }

    这是屏幕上将打印出错误代码,有了错误代码,我们还要知道错误代码的含义,这就要到IDL文件中去查了。在corba.dll文件中NotesError这个接口定义了全部错误代码(自己要做一下简单的加法才能知道那里面错误代码的具体值),错误代码的变量名正是错误信息。这样你便可以对出现的问题了然于胸了,对你解决突发性事件很有帮助。

     

    参考资料:

    1:《JavaDomino Objects的访问》,by Robert Perron,Steve

    2:《用Java通过DIIOP远程操作Domino服务器》

    3:《通过JAVA-CORBA访问Domino

    4:《LotusNotesEclipse管理和运行Java程序》

     

     

    编写者

    日期

    关键词

    郑昀@ultrapower

    2005-6-9

    Domino Notes Java DIIOP IOR

    CORBA Eclipse

     

  • 相关阅读:
    thinkphp5 tp5 命名空间 报错 Namespace declaration statement has to be the very first statement in the script
    开启 php 错误 提示 php-fpm 重启 nginx 500错误 解决办法 wdlinux lnmp 一键包 php脚本无法解析执行
    js 设置 cookie 定时 弹出层 提示层 下次访问 不再显示 弹窗 getCookie setCookie setTimeout
    php 二维数组 转字符串 implode 方便 mysql in 查询
    nginx 重启 ps -ef|grep nginx kill -HUP 主进程号
    jquery bootstrap help-block input 表单 提示 帮助 信息
    jquery 倒计时 60秒 短信 验证码 js ajax 获取
    jQuery如何获取同一个类标签的所有的值 遍历
    linux下C语言文件操作相关函数
    gcc,gdb用法
  • 原文地址:https://www.cnblogs.com/zhengyun_ustc/p/171645.html
Copyright © 2011-2022 走看看