前一段時間在公司一直不能夠登陸B(tài)logjava,所以沒有時間更新博客。今天周二休息所以就繼續(xù)我的OpenOffice.org之戀吧?。海?br />
這次應該說Java調用OOo具體類的業(yè)務代碼了。
OOo的技術架構設計是與平臺無關的,其構建在操作系統(tǒng)層之上的模塊層次除了一部分VCL庫以外,都達到了平臺無關,平臺無關是SUN的一貫作風。這部分代碼占到了整個OOo的90%以上,而那部分VCL庫平臺有關的代碼是為了直接調用各個平臺之間與GUI有關的圖形圖像組件的最小公約數(shù)。這個就像jdk中的awt/swing一樣,他們對各個操作系統(tǒng)都有的GUI組件進行了封裝,而對沒有的組件進行了本地模擬。swt做的正好與之相反,當然這個已經(jīng)離題了:)暫不討論這些。
OOo安裝完成以后,在${OOoPath}/program/classes目錄之下會有一些jar包存在,這些主要用于其自定義UNO組件擴展的內部類庫。我們會主要使用到如下四個類包: jurt.jar、unoil.jar、ridl.jar 與
juh.jar將其加入到我們項目的classpath之中。接下來我們就可以引用其類苦中的類來自定義我們需要的具體功能了。
服務管理器
UNO 引入了
服務管理器的概念。服務管理器可以被視為創(chuàng)建
服務的“工廠”?,F(xiàn)在,只需將服務看
作可用于執(zhí)行特定任務的 UNO 對象即可。稍后我們將更精確地定義術語“服務”。
例如,可以使用以下服務:
com.sun.star.frame.Desktop
維護加載的文檔:用于加載文檔,獲得當前文檔以及訪問所有加載的文檔
com.sun.star.configuration.ConfigurationProvider
生成對 OOo 配置(例如工具 – 選項對話框中的設置)的訪問權限
com.sun.star.sdb.DatabaseContext
維護與 OOo 一起注冊的數(shù)據(jù)庫
com.sun.star.system.SystemShellExecute
在當前平臺上執(zhí)行為應用程序注冊的系統(tǒng)命令或文檔
com.sun.star.text.GlobalSettings
管理文本文檔的全局視圖和打印設置
這些類是以后我們能夠使用到的比較主要的類。服務的功能是其始終存在于組件上下文中。組件上下文包括創(chuàng)建了服務以及服務使用的其他數(shù)據(jù)的服務管理器。
我們自定義的類被視為 OOo 進程的客戶機,而此時的 OOo 是服務器。該服務器有自己的組件上下文和服務管理器,可從客戶機程序進行訪問以使用辦公軟件功能。該客戶機程序初始化 UNO,并從 OOo 進程獲得組件上下文。在內部,此初始化進程創(chuàng)建一個本地服務管理器,建立與一個正在運行的OOo 進程的管道連接(如有必要,則啟動一個新進程)并返回遠程組件上下文。
public class HelloWorld {
public static void main(String[] args) {
try {
// get the remote office component context
com.sun.star.uno.XComponentContext xContext =
com.sun.star.comp.helper.Bootstrap.bootstrap();
System.out.println("HelloWorld OOo
");
com.sun.star.lang.XMultiComponentFactory xMCF =
xContext.getServiceManager();
String available = (xMCF != null ? "available" : "not available");
System.out.println( "remote ServiceManager is " + available );
}
catch (java.lang.Exception e){
e.printStackTrace();
}
finally {
System.exit(0);
}
}
}
com.sun.star.comp.helper.Bootstrap.bootstrap() 方法初始化 UNO,并返回一個正在運行的 OOo 進程的遠程組件上下文。而由腳本調用的UNO的方法就不是這樣初始化的啦:)
第一個初始化步驟完成后,您可以使用組件上下文的方法 getServiceManager() 獲得OOo 進程的遠程服務管理器,這就使您可以通過 API 訪問可用的完整辦公軟件功能。
在OOo's sdk的doc中描述各個類用的說明語言是c++,而且其使用的名稱是
service而非class,這個大家注意一下。
我們的上下文中的
對象是一個軟件工件,具有您可調用的方法。使用 OOo 完成某些操作時需要對象。但從哪里獲得這些對象呢?
新對象
通常情況下,新對象或第一次訪問所需的對象是由 OOo 中的服務管理器創(chuàng)建的。在如下示例中,遠程服務管理器創(chuàng)建遠程 Desktop 對象,該對象用于處理 OOo 中的應用程序窗口和已加載的文檔:
Object desktop = xRemoteServiceManager.createInstanceWithContext(
"com.sun.star.frame.Desktop", xRemoteContext);
OOo中還有和我們java中的接口類似概念的
interface:接口指定共同定義對象的一個方面的屬性集和方法集。
OOo中引入接口和服務的概念是出于以下幾個原因:
- 接口和服務將規(guī)范從實現(xiàn)中分離出來
接口或服務的規(guī)范是抽象的,也就是說,它沒有定義支持某項功能的對象如何在內部實現(xiàn)此支持。通過 OOo API 的抽象規(guī)范,可以在 API 下分離出實現(xiàn),并安裝其他實現(xiàn)(如果需要)。
2. 服務名稱允許按規(guī)范名稱而不是類名稱創(chuàng)建實例
在 Java 中,使用 new 運算符來創(chuàng)建類實例。此方法有所限制:獲得的類為硬編碼。以后您無法在不編輯代碼的情況下將其更換為其他類。服務的概念解決了這個問題。OOo 中的中心對象工廠(即全局服務管理器)被請求創(chuàng)建一個對象,此對象不需要被定義內部實現(xiàn)就可以用于特定目的。這是可以實現(xiàn)的,因為通過服務名稱可以從工廠定制服務,并且工廠決定返回的服務實現(xiàn)。獲得哪種實現(xiàn)沒有什么區(qū)別,因為您只使用明確定義的服務接口。
3. 多繼承接口使細顆粒狀接口便于管理
如果抽象接口是細顆粒狀,即小型且僅描述對象的一個方面而不是多個方面,則可以更好的重復使用。但那樣的話,就需要多個此類接口來描述一個有用的對象。一方面,多繼承接口允許具有細顆粒狀接口;另一方面,又允許通過將接口組織成集合來輕松地管理這些接口。由于在辦公軟件環(huán)境中對象很可能共享多個方面,因此,此細顆粒狀可以使接口重復使用,從而獲得行為一致的對象。例如,可以使用統(tǒng)一的方式來處理文字,無論處理的是正文、文字框、頁眉或頁腳文字、腳注、表格單元格還是繪圖形狀中的文字。不需要為這些不同的文字處理定義單獨的接口。
使用接口
由于必須通過 UNO 對象的接口來訪問它們,因此會對某些語言(例如 Java )造成影響。因為在這些語言中,只有編譯器所需的對象引用類型正確時才能從中調用方法。在 Java 中,在訪問對象實現(xiàn)的接口之前,通常就可以轉換對象類型。但使用 UNO 對象時是不同的:必須, UNO環(huán)境在需要訪問對象支持的接口的方法時獲得相應的引用,但編譯器對此不知情。只有這時才能安全地轉換對象類型。
Java UNO 環(huán)境含有用于此目的的 queryInterface() 方法。它看起來似乎非常復雜,但當您了解了 queryInterface() 是與跨進程安全轉換 UNO 類型相關的,就會很快習慣它。
1 XToolkit xToolkit = (XToolkit) UnoRuntime.queryInterface(
2 XToolkit.class, xMultiComponentFactory
3 .createInstanceWithContext("com.sun.star.awt.Toolkit",
4 xScriptContext.getComponentContext()));