起点R3使用JAVA获取Domino数据(上篇)

      Lotus Domino 作为一种全球领先的协作、消息传递和 Web 支持软件,正在迅速地在中国企事业推广。Domino 已经成为帮助每个人更灵活和更高效地工作的强大支持。如何从 DOMINO 数据库中获取数据,使这些数据为其他系统可用,已经成为许多企业迫切需要解决的问题。然而 domino 不同于普通的关系型数据库,由 ibm/lotus 自主研发,有自己的标准和特殊性,是一种另类的数据库类型。开发具有访问 DOMINO 服务器的应用程序的方法有许多种,但是普遍存在的问题是功能有很大的局限性,都要在依赖于 lotous notes 这一庞大而昂贵的客户端软件。随着 java 语言和 CORBA 中间件技术的日趋成熟,新版本的 Domino 也提供了 corba 服务,使这一问题得到彻底的解决。java/corba 访问 domino 的优点在于采用此技术开发的应用程序在不用安装 lotus notes 的情况下获取远程 domino 服务器上的数据,真正做到了瘦客户端,为企业节省了不必要的开支,同时也极大的降低了应用程序部署的难度。由于这一技术刚刚发展两三年,国内基本上没有相应的中文资料,corba 技术也属于比较高级的开发技术,绝大多数开发工程师都没有接触过,因此许多做数据集成的开发人员对 domino 的开发望而生畏。本文旨在为开发人员提供一个全面的 java/corba 访问 domino 的技术解决方案,并通过例程指导开发人员掌握这一新技术。其中也有笔者在开发过程中的一些经验与教训,相信对广大开发人员一定会有相当大的帮助。

      起点R3能够通过以下三种方式来获取Domino数据,第一种方式是Notes本地获取;第二种是DIIOP方式远程获取;第三种是Corba访问Domino,第一第二种方式只能在Windows平台下,第三种方式能够实现跨平台访问Domino。本文分为上下两篇,本文为上篇,先介绍第一第二两种方式获取数据,下篇再介绍第三种方式。

      在起点R3的Domino采集器中,有如下代码:     

if(properties.getProperty("local")==null){
    session = NotesFactory.createSession(((CrawlTask)job.getCrawltask()).getResourceuri() ,((CrawlTask)job.getCrawltask()).getAccount() , ((CrawlTask)job.getCrawltask()).getPassword());
}else{
    session = NotesFactory.createSession();
}

 即如果传入的插件参数中有local=true,则使用本地Notes访问数据,否则,通过DIIOP访问Domino数据,需要注意的是,起点R3在采集Domion数据的时候需要将Domino或者Notes的安装目录加入到PATH中,获取到session之后,通过以下代码获取数据库信息:   

db = session.getDatabase(session.getServerName(), properties.getProperty("database"));
documentList = db.getAllDocuments() ;
然后可以遍历documentList获得数据库中的所有文档。

对Domino数据库的遍历有两种方式,第一种是通过 documentList.getFirstDocument()和documentList.getNextDocument() 顺序获取文档,第二种方式是documentList.getLastDocument()和documentList.getPrevDocument() 逆序获取文档,最终获取到的是Document对象,然后通过以下代码来对Document的域进行遍历:

Vector id = fieldDoc.getItems();
for (int i = 0; i < id.size(); i++) {
	try{
		Item item = (Item)id.get(i) ;
		MetaType metaType = new MetaType(item.getName(),String.valueOf(item.getType())) ;
		if (item != null && item.getType() == 1280) { //表示是文本
			Vector values = item.getValues() ;
			if(values!=null && values.size()>0){
		StringBuffer strb = new StringBuffer() ;
		for(Object value : values){
			if(strb.length()>0){
				strb.append(" ") ;
			}
			if(value!=null){
				strb.append(value.toString()) ;
			}
		}
		metaType.setValue(strb.toString()) ;
		outputText.getMetadata().add(item.getName(), metaType.getValue()) ;
	}else{
		metaType.setValue(item.getValueString()) ;
		outputText.getMetadata().add(item.getName(), metaType.getValue()) ;
	}
//							metaType.setValue(item.getValueString()) ;
//							outputText.getMetadata().add(item.getName(), metaType.getValue()) ;
    } else if (item != null && item.getType() == 1024) { //表示是时间
	DateTime dateTime = item.getDateTimeValue() ;
	if(dateTime!=null){
		metaType.setValue(String.valueOf(item.getDateTimeValue())) ;
		outputText.getMetadata().add(item.getName(), metaType.getValue()) ;
	}
    } else if (item != null && item.getType() == 768) { //表示是整型
	metaType.setValue(String.valueOf(item.getValueInteger())) ;
	outputText.getMetadata().add(item.getName(), metaType.getValue()) ;
    } else if (item != null && item.getType() == 1) { //表示是rtf域
	metaType.setValue(item.getValueString()) ;
	outputText.getMetadata().add(item.getName(), metaType.getValue()) ;
    } else{
	Vector values = item.getValues() ;
	if(values!=null && values.size()>0){
		StringBuffer strb = new StringBuffer() ;
		for(Object value : values){
			if(strb.length()>0){
				strb.append(" ") ;
			}
			if(value!=null){
				strb.append(value.toString()) ;
			}
		}
		metaType.setValue(strb.toString()) ;
		outputText.getMetadata().add(item.getName(), metaType.getValue()) ;
	}else{
		metaType.setValue(item.getValueString()) ;
		outputText.getMetadata().add(item.getName(), metaType.getValue()) ;
	}
		}
		dataList.add(metaType);
	}catch(Exception ex){}
}

重点是集中特殊域的获取,其中,域类型1280是文本,1024是时间,768是数字,1表示RTF域,还有文本列表域等。

RTF域的获取需要使用以下代码:

if (item != null && item.getType() == 1) { //表示是rtf域
/**
 * 处理RTF域中的文本内容
 */
if(properties!=null && "false".equals(properties.getProperty("rtftext"))){}else{
	outputText.getMetadata().add(item.getName(), item.getValueString()) ;
}
java.util.Vector vector = document.getItems();
for(int i=0; i<vector.size() ; i++){
	Item itmWjbt = (Item)vector.get(i) ;
	if(itmWjbt != null && itmWjbt.getName().equals("$FILE") && zipData.getFileMap().get(itmWjbt.getValueString())==null){
		EmbeddedObject eo = document.getAttachment(itmWjbt.getValueString());
		InputStream input = eo.getInputStream();
                          //从input中获取数据保存到文件或其他输出流
		input.close() ;
	}
}

文本列表域的获取需要使用 Vector values = item.getValues() ,然后

for(Object value : values){
	if(strb.length()>0){
		strb.append(" ") ;
	}
	if(value!=null){
		strb.append(value.toString()) ;
	}
}

 

    在上篇中介绍了从JAVA中获取Domino数据库中的文档信息,但有一个缺点,就是必须要有本地Notes,即限制了只能在Windows下使用,在有些情况下,可能需要在其他操作系统中通过JAVA获取Domino数据,本文即为介绍在JAVA中使用CORBA实现跨操作系统访问Domino。本文介绍的Domino版本应该要在R5以上,R5以下版本未经验证,无法确认是否可行。注意,本文中需要使用lotus.domino.corba包,网络上找到这个库源码非常不容易,作者也是花费了不少时间才从国外一个小网站上下载到,如果有需要,请联系作者。Corba访问Domino过程比较复杂,大致如下:

String ior = http://127.0.0.1/diiop_ior.txt;
Properties props = new Properties(); 
props.put("org.openorb.orb.core.ORB", "org.openorb.orb.core.ORB"); 
ORB orb = ORB.init(new String[]{}, props); 
// 通过 IOR 得到 IObjectServer 对象
org.omg.CORBA.Object obj = orb.string_to_object(ior); 
IObjectServer ios = IObjectServerHelper.narrow(obj); 
// 通过 IObjectServer 获得 ISession 
ProtocolVersion maxVersion = new ProtocolVersion(IBase.DOM_MAJOR_MINIMUM_VERSION, IBase.DOM_MINOR_MINIMUM_VERSION); 
ProtocolVersion minVersion = new ProtocolVersion(IBase.DOM_MAJOR_VERSION,IBase.DOM_MINOR_VERSION); 
SessionData sd = ios.createSession(maxVersion, minVersion, ((CrawlTask)job.getCrawltask()).getAccount() , ((CrawlTask)job.getCrawltask()).getPassword()); 
session = sd.sesObject; 

通过账号和密码访问登录Domino后获得session,然后通过session获得数据库信息,如下:

// 使用 ISession 
dbCache = session.getDatabase(sd.serverName, properties.getProperty("database"), false); 
dCdata = dbCache.db.getAllDocuments();//iDatabase.search("1=1", null, 10); 
IDatabaseHolder idatabaseholder = new IDatabaseHolder(); 
IntHolder intholder = new IntHolder(); 



IDocument document = dCdata.dcObject.getFirstDocMDB(idatabaseholder, intholder); 

一样是或得到document,类型为IDocument,dCdata.dcObject即是文档列表,对此对象遍历即可

document = dCdata.dcObject.getNextDocMDB(document ,idatabaseholder, intholder); 

对IDocument对象的遍历也和DIIOP也有一些差别:

ItemData[] id = fieldDoc.getData().items;
for (int i = 0; i < id.length; i++) {
	MetaType metaType = new MetaType(id[i].name,String.valueOf(id[i].type)) ;
	ItemValue item = id[i].values;
	if (id[i].type == 1280) { //表示是文本
		metaType.setValue(item.StringValue()) ;
	} else if (id[i].type == 1024) { //表示是时间
		DateTime dateTime = item.TimeObject() ;
		if(dateTime!=null){
			metaType.setValue(String.valueOf(dateTime.toString())) ;
		}
	} else if (id[i].type == 768) { //表示是整型
		metaType.setValue(String.valueOf(String.valueOf(item.DoubleValue()))) ;
	} else if (id[i].type == 1) { //表示是rtf域
		//获得RTF域的附件信息
	} else{
		metaType.setValue(item.StringValue()) ;
	}
}

类型代码和上篇中介绍的都是一样的,但RTF域的附件信息获取方式不太一样,需要对items[i].RTObject对象进行进一步处理,处理过程如下:

IRichTextItem rtf = items[i].RTObject ;
if(item.StringValue()!=null){
	outputText.getMetadata().add(items[i].name, item.StringValue()) ;
}else if(rtf.getValueAsString()!=null){
	outputText.getMetadata().add(items[i].name, rtf.getValueAsString()) ;
}
{
	NameAndObject[] ed = rtf.getEmbeddedObjects() ;
	if(ed.length>0){
		for(NameAndObject nameObject : ed){
			EmbeddedData eo = document.getAttachment(nameObject.name) ;
			if(eo!=null && eo.embedObject!=null && eo.embedObject.getFileSize()>0){
				BooleanHolder holder = new BooleanHolder(true); 
				IntHolder inholder = new IntHolder();
				byte[] data  = null ;
				java.io.ByteArrayOutputStream output = new java.io.ByteArrayOutputStream() ;
				try{
					while((data = eo.embedObject.getFile(inholder, holder))!=null && data.length>0){
						output.write(data) ;
					}
				}catch(Exception ex){
					ex.printStackTrace();
				}
				java.io.ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray()) ;
				//获得输入流,自定义后续处理过程
				input.close() ;
			}
		}
	}
}

最后是关闭session和db, db.recycle();

你可能感兴趣的:(java,ios,应用服务器,企业应用,Lotus)