• [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

     

  • 相关阅读:
    adb、monkey常用命令
    震惊!90%的程序员不知道的Java知识!
    Android,重新出发!
    Fiddler 手机抓包 手机联网异常解决方案
    技术贴汇总
    Android开发日常-listview滚动方法梳理
    JavaScript基本语法
    Spring Boot Profile
    Spring Boot配置文件占位符
    @PropertySource和@ImportSource
  • 原文地址:https://www.cnblogs.com/zhengyun_ustc/p/171645.html
Copyright © 2020-2023  润新知