1. 程式人生 > >Domino資料遷移

Domino資料遷移

    實際專案中,有時需要將Domino系統的資料遷移到J2EE系統中,因此需要通過Domino的介面獲取Domino的資料然後存放到J2EE系統中。

    Domino提供了Java訪問介面(NCSO.jar),通過它可以很方便的訪問Domino。以下是實際專案中開發的資料遷移功能部分程式碼,僅供參考。

/**
 * DominoDataImporter domino資料處理介面,負責將domino資料存入到J2EE系統
 *
 * @version 1.0 2011-5-16
 * @author zhanzhengqiang
 */
public interface DominoDataImporter {

    /**
     * 文件處理
     * @param document 待處理文件
     * @return true 成功,false失敗
     */
    public boolean dealDocument(DominoDocument document);
}    

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Vector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import lotus.domino.DateTime;
import lotus.domino.Document;
import lotus.domino.EmbeddedObject;
import lotus.domino.Item;
import lotus.domino.NotesException;
import lotus.domino.RichTextItem;

/**
 * DominoDocument Domino文件封裝類,提供文件中各種資料的訪問方法
 *
 * @version 1.0 2011-5-16
 * @author zhanzhengqiang
 */
public class DominoDocument {

    /**
     * 日誌物件
     */
    private static Log log = LogFactory.getLog(DominoDocument.class);
    
    /**
     * Domino文件
     */
    private Document document;
    
    /**
     * 構造方法
     * @param document
     */
    public DominoDocument(Document document) {
        this.document = document;
    }
    
    /**
     * 獲取字串域(單值域)值
     * @param itemName
     * @return 沒有返回""
     */
    public String getString(String itemName) {
        String retValue = "";
        try {
            if (document.hasItem(itemName)) {
                retValue = document.getItemValueString(itemName);
            } else {
                log.debug("域" + itemName + "不存在");
            }
        } catch (NotesException e) {
            log.error("獲取域" + itemName + "的值失敗:" + e.getMessage());
            retValue = "";
        }
        if (log.isDebugEnabled()) {
            log.debug("獲取到域[" + itemName + "]的值為:" + retValue);
        }
        return retValue;
    }
    
    /**
     * 獲取字串列表(多值域)值
     * @param itemName
     * @return 域值列表
     */
    public List getStringList(String itemName) {
        List retValue = new ArrayList();
        try {
            if (document.hasItem(itemName)) {
                log.debug("多值域域值列表:");
                Vector retItem = document.getItemValue(itemName);
                for (int i = 0; i < retItem.size(); i++) {
                    if (log.isDebugEnabled()) {
                        log.debug("域值" + (i+1) + "為:" + retItem.get(i));
                    }
                    retValue.add(retItem.get(i));
                }
            } else {
                log.debug("域" + itemName + "不存在");
            }
        } catch (NotesException e) {
            log.error("獲取域" + itemName + "的值失敗:" + e.getMessage());
        }
        return retValue;
    }
    
    /**
     * 獲取日期時間域值
     * @param itemName
     * @return
     */
    public Date getDateTime(String itemName) {
        Date retValue = null;
        try {
            if (document.hasItem(itemName)) {
                Vector retItem = document.getItemValueDateTimeArray(itemName);
                if (!retItem.isEmpty()) {
                    DateTime dateTime = (DateTime)retItem.get(0);
                    retValue = dateTime.toJavaDate();
                }
            } else {
                log.debug("域" + itemName + "不存在");
            }
        } catch (NotesException e) {
            log.error("獲取日期時間域" + itemName + "的值失敗:" + e.getMessage());
        }
        if (log.isDebugEnabled()) {
            log.debug("獲取到日期時間域[" + itemName + "]的值為:" + retValue);
        }
        return retValue;
    }
    
    /**
     * 獲取整數域值
     * @param itemName
     * @return
     */
    public int getInteger(String itemName) {
        int retValue = 0;
        try {
            if (document.hasItem(itemName)) {
                retValue = document.getItemValueInteger(itemName);
            } else {
                log.debug("域" + itemName + "不存在");
            }
        } catch (NotesException e) {
            log.error("獲取整數域" + itemName + "的值失敗:" + e.getMessage());
        }
        if (log.isDebugEnabled()) {
            log.debug("獲取到整數域[" + itemName + "]的值為:" + retValue);
        }
        return retValue;
    }
    
    /**
     * 根據域名獲取域中存放的檔案
     * @param fieldName
     * @return
     */
    public EmbeddedObject getFileByFieldName(String fieldName) {
        EmbeddedObject retValue = null;
        try {
            if (document.hasItem(fieldName)) {
                Item item = document.getFirstItem(fieldName);
                if (item.getType() == Item.RICHTEXT) {
                    // 轉換為RichTextItem
                    RichTextItem rtfItem = (RichTextItem)item;
                    // 取EmbeddedObject
                    Vector embeddedObjects = rtfItem.getEmbeddedObjects();
                    for (int i = 0; i < embeddedObjects.size(); i++) {
                        EmbeddedObject obj = (EmbeddedObject)embeddedObjects.get(i);
                        if (obj.getType() == EmbeddedObject.EMBED_ATTACHMENT) {
                            retValue = obj;
                            break;
                        }
                    }
                }
            } else {
                log.debug("RTF域[" + fieldName + "]不存在");
            }
        } catch (NotesException e) {
            log.error("獲取RTF域" + fieldName + "的值失敗:" + e.getMessage());
        }
        
        // 輸出除錯資訊
        if (log.isDebugEnabled()) {
            if (retValue != null) {
                try {
                    log.debug("獲取RTF域[" + fieldName + "]對應檔案為:" + retValue.getName());
                } catch (NotesException e) {}
            } else {
                log.debug("RTF域[" + fieldName + "]暫時沒有檔案");
            }
        }
        
        return retValue;
    }
    
    /**
     * 根據檔名獲取檔案
     * @param fileName
     * @return
     */
    public EmbeddedObject getFileByName(String fileName) {
        EmbeddedObject retValue = null;
        try {
            if (document.hasEmbedded()) {
                retValue = document.getAttachment(fileName);
            }
        } catch (NotesException e) {
            log.error("獲取檔案[" + fileName + "]出錯:" + e.getMessage());
        }
        if (log.isDebugEnabled()) {
            log.debug("檔案[" + fileName + "]不存在");
        }
        return retValue;
    }
    
    /**
     * 獲取所有檔案, 根據檔名獲取附件,如果檔名含特殊字元會導致獲取檔案為null
     * 如檔案:"附件3:關於中共×××黨支部黨員大會會議選舉結果的報告.doc"
     * @return
     */
    public List getAllFiles() {
        List retValue = new ArrayList();
        try {
            if (document.hasEmbedded()) {
                Vector items = document.getItems();
                for (int i = 0; i < items.size(); i++) {
                    Item item = (Item)items.get(i);
                    // 如果不是附件則跳過
                    if (item.getType() != Item.ATTACHMENT) {
                        continue;
                    }
                    // 根據附件名稱獲取附件物件
                    String attachName = item.getValueString();
                    if (log.isDebugEnabled()) {
                        log.debug("檔名稱:" + attachName);
                    }
                    EmbeddedObject attach = document.getAttachment(attachName);
                    if (attach != null) {
                        retValue.add(attach);
                    } else {
                        log.error("獲取檔案[" + attachName + "]失敗");
                    }
                }
            } else {
                log.debug("文件中沒有引入檔案");
            }
        } catch (NotesException e) {
            log.error("獲取文件所有附加檔案出錯:" + e.getMessage());
        }
        
        // 輸出除錯資訊
        if (log.isDebugEnabled()) {
            log.debug("獲取到檔案列表如下:");
            for (int i = 0; i < retValue.size(); i++) {
                EmbeddedObject obj = (EmbeddedObject)retValue.get(i);
                try {
                    log.debug("第" + (i+1) + "個檔案:" + obj.getName());
                } catch (NotesException e) {}
            }
        }
        return retValue;
    }

    /**
     * 獲取所有檔案
     * @return
     */
    public List getAllFiles2() {
        List retValue = new ArrayList();
        HashMap fileNames = new HashMap();
        try {
            if (document.hasEmbedded()) {
                Vector items = document.getItems();
                for (int i = 0; i < items.size(); i++) {
                    Item item = (Item)items.get(i);
                    // 如果不是RichTextItem則跳過
                    if (item.getType() != Item.RICHTEXT) {
                        continue;
                    }
                    Vector embeddedObjects = ((RichTextItem)item).getEmbeddedObjects();
                    if (embeddedObjects.size() <= 0) {
                        log.debug("域[" + item.getName() + "]不包含檔案");
                    }    
                    
                    for (int k = 0; k < embeddedObjects.size(); k++) {
                        EmbeddedObject embeddedObject = (EmbeddedObject)embeddedObjects.get(k);
                        if (embeddedObject.getType() == EmbeddedObject.EMBED_ATTACHMENT) {
                            // 判斷是否已經新增,沒有新增
                            String gettedFileName = embeddedObject.getName();
                            if (fileNames.get(gettedFileName) == null) {
                                retValue.add(embeddedObject);
                                fileNames.put(gettedFileName, "");
                                if (log.isDebugEnabled()) {
                                    log.debug("獲取到檔案:" + gettedFileName);
                                }
                            }
                        }
                    }
                }
            } else {
                log.debug("文件中沒有引入檔案");
            }
        } catch (NotesException e) {
            log.error("獲取文件所有附加檔案出錯:" + e.getMessage());
        }
        
        // 輸出除錯資訊
        if (log.isDebugEnabled()) {
            log.debug("獲取到檔案列表如下:");
            for (int i = 0; i < retValue.size(); i++) {
                EmbeddedObject obj = (EmbeddedObject)retValue.get(i);
                try {
                    log.debug("第" + (i+1) + "個檔案:" + obj.getName());
                } catch (NotesException e) {}
            }
        }
        return retValue;
    }
    
    /**
     * 獲取文件UNID
     * @return 如果不存在則返回null
     */
    public String getUNID() {
        String unid = null;
        try {
            unid = document.getUniversalID();
        } catch (NotesException e) {
            log.error("獲取文件UNID出錯");
        }
        return unid;
    }
    
    /**
     * @return the document
     */
    public Document getDocument() {
        return document;
    }
}

/**
 * ImportParams Domino資料匯入引數封裝類
 *
 * @version 1.0 2011-5-18
 * @author zhanzhengqiang
 */
public class ImportParams {

    /**
     * Domino伺服器地址
     */
    private String server;
    
    /**
     * Domino伺服器埠
     */
    private String port;
    
    /**
     * 連線Domino伺服器使用者名稱
     */
    private String userName;
    
    /**
     * 連線Domino伺服器密碼
     */
    private String password;
    
    /**
     * 匯入Domino資料庫路徑
     */
    private String database;
    
    /**
     * 匯入Domino資料庫檢視
     */
    private String view;
    
    /**
     * 匯入Domino資料查詢條件
     * 如FORM=\"frmDispDocComFile\"&IsTrashDoc!=\"false\"
     */
    private String formula;
    
    /**
     * 匯入Domino文件UnID
     */
    private String unid;

    // 忽略seter,getter方法及構造方法
}

import lotus.domino.Database;
import lotus.domino.Document;
import lotus.domino.DocumentCollection;
import lotus.domino.NotesException;
import lotus.domino.NotesFactory;
import lotus.domino.Session;
import lotus.domino.View;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * DominoDataImportUtil Domino資料匯入工具類,
 *     負責連線Domino資料庫,獲取文件記錄,文件的處理由DominoDataImporter介面實現類完成
 *
 * @version 1.0 2011-5-16
 * @author zhanzhengqiang
 */
public class DominoDataImportUtil {
    
    /**
     * 日誌物件 
     */
    private static Log log = LogFactory.getLog(DominoDataImportUtil.class);
    
    /**
     * 匯入失敗文件數上限,超過上限匯入終止 
     */
    private static final int IMPORT_FAIL_NUM_LIMIT = 10;
    
    /**
     * 私有構造方法
     */
    private DominoDataImportUtil() {
    }
    
    /**
     * 基於查詢條件做資料庫匯入,如果沒有查詢條件,則匯入整個資料庫
     * @param importParams 匯入引數
     * @param dominoDataImporter 文件匯入處理物件,負責文件匯入的業務處理
     * @param int[] 第一個元素為匯入成功文件數,第二個元素為匯入失敗文件數
     * @throws Exception
     */
    public static int[] importByCondition(ImportParams importParams, 
        DominoDataImporter dominoDataImporter) throws Exception {
        // 獲取Session
        Session session = getSession(importParams.getServer(), importParams.getPort(),
                importParams.getUserName(), importParams.getPassword());
        
        // 連線資料庫
        Database database = getDataBase(session, importParams.getDatabase());
        
        // 獲取資料庫文件
        DocumentCollection documents = getDocuments(database, importParams.getFormula());
        
        // 計算總文件數
        int count = documents.getCount();
        // 匯入成功文件數
        int succNum = 0;
        // 匯入失敗文件數
        int failNum = 0;
        
        // 迴圈處理文件
        Document document = documents.getFirstDocument();
        while (document != null) {
            // 處理文件
            boolean isSucc = dominoDataImporter.dealDocument(new DominoDocument(document));
            // 計算匯入成功或失敗文件數
            if (isSucc) {
                succNum = succNum + 1;
            } else {
                failNum = failNum + 1;
                // 記錄到失敗日誌檔案
            }
            // 失敗匯入文件超過上線時,終止匯入
            if (failNum > IMPORT_FAIL_NUM_LIMIT) {
                break;
            }
            // 獲取下一個文件
            document = documents.getNextDocument();
        }
        
        // 構造返回陣列
        int[] retValue = new int[] {succNum, count - succNum};
        
        // 返回結果
        return retValue;
    }
    
    /**
     * 根據檢視進行資料庫匯入
     * @param importParams 匯入引數
     * @param dominoDataImporter 文件匯入處理物件,負責文件匯入的業務處理
     * @param int[] 第一個元素為匯入成功文件數,第二個元素為匯入失敗文件數
     * @throws Exception
     */
    public static int[] importByView(ImportParams importParams,  
            DominoDataImporter dominoDataImporter) throws Exception {
        // 獲取Session
        Session session = getSession(importParams.getServer(), importParams.getPort(),
                importParams.getUserName(), importParams.getPassword());
        // 連線資料庫
        Database database = getDataBase(session, importParams.getDatabase());
        
        // 獲取資料庫檢視
        View view = getView(database, importParams.getView());
        
        // 計算總文件數
        int count = view.getEntryCount();
        // 匯入成功文件數
        int succNum = 0;
        // 匯入失敗文件數
        int failNum = 0;
        
        // 迴圈處理文件
        Document document = view.getFirstDocument();
        while (document != null) {
            // 處理文件
            boolean isSucc = dominoDataImporter.dealDocument(new DominoDocument(document));
            // 計算匯入成功或失敗文件數
            if (isSucc) {
                succNum = succNum + 1;
            } else {
                failNum = failNum + 1;
            }
            // 失敗匯入文件超過上線時,終止匯入
            if (failNum > IMPORT_FAIL_NUM_LIMIT) {
                break;
            }
            // 獲取下一個文件
            document = view.getNextDocument(document);
        }
        
        // 構造返回陣列
        int[] retValue = new int[] {succNum, count - succNum};
        
        // 返回結果
        return retValue;
    }
    
    /**
     * 根據文件UnID匯入文件
     * @param importParams 匯入引數
     * @param dominoDataImporter 文件匯入處理物件,負責文件匯入的業務處理
     * @return true 匯入成功,false 匯入失敗
     * @throws Exception
     */
    public static boolean importByUnID(ImportParams importParams,
            DominoDataImporter dominoDataImporter) throws Exception{
        // 獲取Session
        Session session = getSession(importParams.getServer(), importParams.getPort(),
                importParams.getUserName(), importParams.getPassword());
        // 連線資料庫
        Database database = getDataBase(session, importParams.getDatabase());
        // 根據UnId獲取文件
        if (log.isDebugEnabled()) {
            log.debug("匯入文件UnID為:" + importParams.getUnid());
        }
        
        // 如果資料庫沒有開啟,則開啟資料庫
        openDataBaseIfNot(database);
        
        // 根據文件UnID獲取文件
        Document document = null;
        try {
            document = database.getDocumentByUNID(importParams.getUnid());
        } catch (NotesException e) {
            throw new Exception("UnID為" + importParams.getUnid() + "的文件不存在");
        }
        if (document == null) {
            throw new Exception("UnID為" + importParams.getUnid() + "的文件為空");
        }
        // 匯入文件
        boolean result = dominoDataImporter.dealDocument(new DominoDocument(document));
        
        // 返回匯入結果
        return result;
    }
    
    /**
     * 獲取Domino Session
     * @return
     */
    private static Session getSession(String server, String port, 
            String userName, String password) throws Exception{
        // 輸出配置引數
        if (log.isDebugEnabled()) {
            log.debug("server:" + server + ", port:" + port 
                    + ", username:" + userName + ", password:" + password);
        }
        // 獲取Session
        Session session = null;
        try {
            String hostString = server;
            if (port != null && port.trim().equals("")) {
                hostString = server + ":" + port;
            }
            session = NotesFactory.createSession(hostString, userName, password);
        } catch (NotesException e) {
            throw new Exception("建立Session失敗,請檢查相關引數是否正確", e.getCause());
        }
        // 如果獲取Sesion為空,則丟擲異常
        if (session == null) {
            throw new Exception("建立Session為空,請檢查相關引數是否正確");
        }
        return session;
    }

    /**
     * 獲取資料庫
     * @param session Domino Session
     * @param dbPath 資料庫路徑 
     * @return
     * @throws Exception
     */
    private static Database getDataBase(Session session, String dbPath) throws Exception{
        if (log.isDebugEnabled()) {
            log.debug("資料庫路徑:" + dbPath);
        }
        // 定義返回資料庫
        Database database = null;
        try {
            database = session.getDatabase(null, dbPath, false);
        } catch(NotesException e) {
            throw new Exception("獲取資料庫[" + dbPath + "]失敗", e.getCause()) ;
        }
        // 獲取資料庫為空,丟擲異常
        if (database == null) {
            throw new Exception("獲取資料庫[" + dbPath + "]為空");
        }
        return database;
    }
    
    /**
     * 開啟資料庫,如果資料庫沒有開啟
     * @param database 資料庫
     * @throws Exception
     */
    private static void openDataBaseIfNot(Database database) throws Exception {
        // 如果資料庫已經開啟,則直接返回
        if (database.isOpen()) {
            return;
        }
        // 開啟資料庫,如果開啟失敗則丟擲異常
        if (!database.open()) {
            throw new Exception("開啟資料庫[" + database.getFilePath() + "]失敗");
        }
    }
    
    /**
     * 獲取資料庫檢視
     * @param database 資料庫
     * @param viewName 檢視名
     * @return
     * @throws Exception
     */
    private static View getView(Database database, String viewName) throws Exception {
        if (log.isDebugEnabled()) {
            log.debug("資料庫路徑:" + database.getFilePath() + ", 檢視名稱:" + viewName);
        }
        // 如果資料庫沒有開啟,則開啟資料庫
        openDataBaseIfNot(database);
        
        // 定義返回檢視
        View view = null;
        try {
            view = database.getView(viewName);
        } catch (NotesException e) {
            String message = "獲取資料庫[" + database.getFilePath() + "]的檢視[" + viewName + "]失敗";
            throw new Exception(message, e.getCause());
        }
        // 獲取檢視為空,丟擲異常
        if (view == null) {
            throw new Exception("獲取資料庫[" + database.getFilePath() + "]的檢視[" + viewName + "]為空");
        }
        if (log.isDebugEnabled()) {
            log.debug("共有文件數:" + view.getEntryCount());
        }
        return view;
    }
    
    /**
     * 獲取所有資料庫文件
     * @param database 資料庫
     * @param formula 查詢文件條件
     * @return
     * @throws Exception
     */
    private static DocumentCollection getDocuments(Database database, String formula) throws Exception{
        if (log.isDebugEnabled()) {
            log.debug("從資料庫[" + database.getFilePath() + "]中獲取滿足條件[" + formula + "]的文件");
        }
        // 如果資料庫沒有開啟,則開啟資料庫
        openDataBaseIfNot(database);
        
        // 獲取文件
        DocumentCollection documents = null;
        try {
            // 如果查詢條件為空,則獲取所有文件
            if (StringUtils.isEmpty(formula)) {
                documents = database.getAllDocuments();
            } else {
                documents = database.search(formula);
            }
        } catch (NotesException e) {
            String message = "獲取資料庫[" + database.getFilePath() + "]中滿足條件[" + formula + "]的文件失敗";
            throw new Exception(message, e.getCause());
        }
        if (log.isDebugEnabled()) {
            log.debug("共有文件數:" + documents.getCount());
        }
        return documents;
    }
}
        Domino介面詳細說明可以參考Domino自帶的幫助手冊。