OpenOfficeはUNO(Universal Network Objects)を使用してAPIを実装している。
OpenOffice.org for Developersの[SDK]-[SDK Download (1.0.2 SDK should be used for OOo 1.0.3.x)]からOpenOffice SDK をダウンロードするとドキュメントが充実しているので、ある程度は理解できるようになるのではないだろうか。
まずは、[SDK]-[Developer’s Guide (part of SDK)]からたどれる、2 First Steps を読んでみると言うのもよさそう。
LinuxでOpenOfficeでUNOを起動オプションで使えるようにするには、次のようにコマンドをうつ。ただし、ユーザーインタフェース用画面を表示して動かしたい場合は -headless はいらない。
“-accept=socket,host=localhost,port=8100;urp;StarOffice.ServiceManager” &
設定ファイルを書き変える方法は1.0.2と1.1.xでは設定方法が違うので注意が必要。ここでは1.1.xでの対応方法を書いておく。
$OfficePath/share/registry/data/org/openoffice/Setup.xcu をエディタで開いて編集する。<node oor:name=”Office”/>というエレメントのボディ部に、次のpropエレメントを追加する。
<value>socket,host=localhost,port=8100;urp;</value>
</prop>
この設定により、OpenOffice.orgを起動すると、8100ポートでソケット経由のUNOリモートプロトコル(urp)通信ができるようになる。
ネットワークインストールをしてあり、個人単位でこの設定をしたい場合には、$OfficePath/user/registry/data/org/openoffice/Setup.xcuにここで示したpropエレメントを追加する。
あとはsofficeをコマンド実行すればよい。動作確認はnetstatコマンドなどで8100ポートが開いているかみればいい。
$ netstat -a | grep 8100
tcp 0 0 localhost.localdom:8100 *:* LISTEN
OpenOffice.org SDK のサンプルをちょっとだけさわって、Impressの新規ファイルを開いて閉じる処理をuseConnection3メソッドとして追加してみた。
import com.sun.star.lang.XComponent;
import com.sun.star.sheet.XSpreadsheetDocument;
import com.sun.star.sheet.XSpreadsheets;
import com.sun.star.sheet.XSpreadsheet;
import com.sun.star.sheet.XSpreadsheetView;
import com.sun.star.table.XCell;
import com.sun.star.frame.XModel;
import com.sun.star.frame.XController;
import com.sun.star.frame.XComponentLoader;
import com.sun.star.bridge.XUnoUrlResolver;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.beans.XPropertySet;
public class FirstConnection extends java.lang.Object {
private XComponentContext xRemoteContext = null;
private XMultiComponentFactory xRemoteServiceManager = null;
public static void main(String[] args) {
FirstConnection firstConnection1 = new FirstConnection();
try {
firstConnection1.useConnection();
firstConnection1.useConnection3();
} catch (java.lang.Exception e) {
e.printStackTrace();
} finally {
System.exit(0);
}
}
protected void useConnection3() throws java.lang.Exception {
try {
xRemoteServiceManager = this.getRemoteServiceManager("uno:socket,host=localhost,port=8100;urp;StarOffice.ServiceManager");
// get the Desktop, we need its XComponentLoader interface to load a new document
Object desktop = xRemoteServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", xRemoteContext);
// query the XComponentLoader interface from the desktop
XComponentLoader xComponentLoader = (XComponentLoader)UnoRuntime.queryInterface(XComponentLoader.class, desktop);
// create empty array of PropertyValue structs, needed for loadComponentFromURL
// Preparing properties for loading the document
//PropertyValue[] loadProps = new PropertyValue[1];
PropertyValue[] loadProps = new PropertyValue[0];
// Setting the flag for hidding the open document
//loadProps[ 0 ] = new PropertyValue();
//loadProps[ 0 ].Name = "Hidden";
//loadProps[ 0 ].Value = new Boolean(true);
// load new impress file
XComponent xImpressComponent = xComponentLoader.loadComponentFromURL("private:factory/simpress", "_blank", 0, loadProps);
xImpressComponent.dispose();
}
catch( com.sun.star.lang.DisposedException e ) {
xRemoteContext = null;
throw e;
}
}
protected void useConnection2() throws java.lang.Exception {
try {
xRemoteServiceManager = this.getRemoteServiceManager("uno:socket,host=localhost,port=8100;urp;StarOffice.ServiceManager");
// get the Desktop, we need its XComponentLoader interface to load a new document
Object desktop = xRemoteServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", xRemoteContext);
// query the XComponentLoader interface from the desktop
XComponentLoader xComponentLoader = (XComponentLoader)UnoRuntime.queryInterface(XComponentLoader.class, desktop);
// create empty array of PropertyValue structs, needed for loadComponentFromURL
PropertyValue[] loadProps = new PropertyValue[0];
// load new calc file
XComponent xSpreadsheetComponent = xComponentLoader.loadComponentFromURL("private:factory/scalc", "_blank", 0, loadProps);
// query its XSpreadsheetDocument interface, we want to use getSheets()
XSpreadsheetDocument xSpreadsheetDocument = (XSpreadsheetDocument)UnoRuntime.queryInterface(XSpreadsheetDocument.class, xSpreadsheetComponent);
// use getSheets to get spreadsheets container
XSpreadsheets xSpreadsheets = xSpreadsheetDocument.getSheets();
//insert new sheet at position 0 and get it by name, then query its XSpreadsheet interface
xSpreadsheets.insertNewByName("MySheet", (short)0);
Object sheet = xSpreadsheets.getByName("MySheet");
XSpreadsheet xSpreadsheet = (XSpreadsheet)UnoRuntime.queryInterface(XSpreadsheet.class, sheet);
// use XSpreadsheet interface to get the cell A1 at position 0,0 and enter 21 as value
XCell xCell = xSpreadsheet.getCellByPosition(0, 0);
xCell.setValue(21);
// enter another value into the cell A2 at position 0,1
xCell = xSpreadsheet.getCellByPosition(0, 1);
xCell.setValue(21);
// sum up the two cells
xCell = xSpreadsheet.getCellByPosition(0, 2);
xCell.setFormula("=sum(A1:A2)");
// we want to access the cell property CellStyle, so query the cell’s XPropertySet interface
XPropertySet xCellProps = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, xCell);
// assign the cell style "Result" to our formula, which is available out of the box
xCellProps.setPropertyValue("CellStyle", "Result");
// we want to make our new sheet the current sheet, so we need to ask the model
// for the controller: first query the XModel interface from our spreadsheet component
XModel xSpreadsheetModel = (XModel)UnoRuntime.queryInterface(XModel.class, xSpreadsheetComponent);
// then get the current controller from the model
XController xSpreadsheetController = xSpreadsheetModel.getCurrentController();
// get the XSpreadsheetView interface from the controller, we want to call its method
// setActiveSheet
XSpreadsheetView xSpreadsheetView = (XSpreadsheetView)UnoRuntime.queryInterface(XSpreadsheetView.class, xSpreadsheetController);
// make our newly inserted sheet the active sheet using setActiveSheet
xSpreadsheetView.setActiveSheet(xSpreadsheet);
}
catch( com.sun.star.lang.DisposedException e ) { //works from Patch 1
xRemoteContext = null;
throw e;
}
}
protected void useConnection() throws java.lang.Exception {
String service = "uno:socket,host=localhost,port=8100;urp;StarOffice.ServiceManager";
try {
xRemoteServiceManager = this.getRemoteServiceManager(service);
String available = (null != xRemoteServiceManager ? "available" : "not available");
System.out.println("remote ServiceManager is " + available);
//
// do something with the service manager…
//
} catch (com.sun.star.connection.NoConnectException e) {
System.err.println("No process listening on the resource");
e.printStackTrace();
throw e;
} catch (com.sun.star.lang.DisposedException e) { //works from Patch 1
xRemoteContext = null;
throw e;
}
}
protected XMultiComponentFactory getRemoteServiceManager(String unoUrl)
throws java.lang.Exception
{
if (xRemoteContext == null) {
// First step: create local component context, get local servicemanager and
// ask it to create a UnoUrlResolver object with an XUnoUrlResolver interface
XComponentContext xLocalContext =
com.sun.star.comp.helper.Bootstrap.createInitialComponentContext(null);
XMultiComponentFactory xLocalServiceManager = xLocalContext.getServiceManager();
Object urlResolver = xLocalServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", xLocalContext );
// query XUnoUrlResolver interface from urlResolver object
XUnoUrlResolver xUnoUrlResolver = (XUnoUrlResolver) UnoRuntime.queryInterface(XUnoUrlResolver.class, urlResolver);
// Second step: use xUrlResolver interface to import the remote StarOffice.ServiceManager,
// retrieve its property DefaultContext and get the remote servicemanager
Object initialObject = xUnoUrlResolver.resolve(unoUrl);
XPropertySet xPropertySet = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, initialObject);
Object context = xPropertySet.getPropertyValue("DefaultContext");
xRemoteContext = (XComponentContext)UnoRuntime.queryInterface(XComponentContext.class, context);
}
return xRemoteContext.getServiceManager();
}
}