LibreOffice Developer's Guide: Chapter 16 - JavaBean for Office Components
This chapter describes the OOoBean
component, a generic Java Bean wrapper for LibreOffice components. It is assumed that the reader is familiar with the Java Beans technology. Additional information about Java Beans can be found at https://docs.oracle.com/javase/tutorial/javabeans/.
With the OOoBean
, a developer can easily write Java applications, harnessing the power of LibreOffice. It encapsulates a connection to a locally running LibreOffice process, and hides the complexity of establishing and maintaining that connection from the developer.
It also allows embedding of LibreOffice documents within the Java environment. It provides a Java AWT window into which the backend LibreOffice process draws its visual representation. This window can then be plugged into the UI hierarchy of the hosting Java application. The embedded document is controlled from the Java environment, since the OOoBean
allows developers to access the complete LibreOffice API from their Java environment giving them full control over the embedded document, its appearance and behavior.
Using the OOoBean
The Java class OOoBean
can be instantiated directly, or application classes can be derived from this class. If a real Java Bean is to be created, which for example can be used in Java Bean UI builders, it has to be subclassed. The application class then might use the UNO bootstrapping mechanism to find the OOoBean
, LibreOffice and its API classes. This mechanism is not built into OOoBean
itself because it can not be used to find itself. And once the OOoBean
class has been found, you intrinsically also find the LibreOffice installation and the API classes.
A standard LibreOffice is a prerequisite. The LibreOffice executable, as well as the UNO libraries and runtime, is found using the Java Class Loader. Moving or copying the needed class files will not result in a working OOoBean
.
The OOoBean by Example
The OOoBeanViewer
is a Java application that displays LibreOffice documents in a Java AWT applet, which allows for the control of some toolboxes, the menu bar and the status bar, as well as storing and loading the document content to/from an internal buffer.
The OOoBeanViewer
utilizes the class OOoBean
directly without subclassing it:
public class OOoBeanViewer extends java.applet.Applet
{
...
private OOoBean aBean;
...
public void init()
{
aBean = new OOoBean();
}
...
{
add( aBean );
}
}
Initially, the OOoBean component does not contain a document. A document can be created with the loadFromURL method:
private void createBlankDoc(String url, String desc)
{
//Create a blank document
try
{
aBean.loadFromURL( url, null );
....
}
catch ( com.sun.star.comp.beans.SystemWindowException aExc )
{
// this exception will be thrown when no system window parent can be found
...
}
catch ( com.sun.star.comp.beans.NoConnectionException aExc )
{
// this exception is thrown
// when no connection to a [PRODUCTNAME] instance can be established
...
}
catch ( Exception aExc )
{
...
}
}
Some tool windows of the document window within the Java Bean can be controlled directly by the OOoBean API. For example, to toggle visibility of the menu bar:
aBean.setMenuBarVisible( !aBean.isMenuBarVisible() );
The examples above provide an overview of how the OOoBean
API is used to create Java Beans that can be used in Java applications and applets. For concrete Java Beans, you usually subclass OOoBean
and create appropriate BeanInfo classes for integrating within an IDE (Integrated Development Environment), such as the Bean Development Kit or Forte for Java. Developers can use the examples as a guideline when using the OOoBean
API to write new beans, or use or extend the example beans.
API Overview
The OOoBean offers methods that can be applied to all LibreOffice document types.
Methods of com.sun.star.comp.beans.OOoBean
| |
---|---|
OOoBean()
|
constructor - creates an OOoBean with an implicit connection
|
OOoBean(OfficeConnection)
|
constructor - creates an OOoBean with an explicit connection
|
setOOoStartTimeOut(...)
|
void - sets the timeout for methods which start LibreOffice
|
setOOoCallTimeOut(...)
|
void - sets the timeout for other methods
|
SetOOoCheckCycle(...)
|
void - sets repeat period for cyclic LibreOffice alive check
|
setOOoConnection(...)
|
void - sets an explicit connection to a LibreOffice instance
|
startOOoConnection(...)
|
void - starts a connection with an explicit connection URL
|
isOOoConnected()
|
boolean - returns whether the OOoBean is connected to a LibreOffice
|
stopOOoConnection()
|
void - stops the current connection to LibreOffice
|
getOOoConnection()
|
OfficeConnection - returns the current connection to LibreOffice
|
getMultiServiceFactory()
|
XMultiServiceFactory -- returns the service factory of the connected LibreOffice |
getOOoDesktop()
|
XDesktop - returns the desktop object of the connected LibreOffice |
clearDocument()
|
void -- resets the Bean to an empty document
|
clear()
|
void - removes the document from the Bean
|
aquireSystemWindow()
|
void - has to be called when the Bean has a parent component which has a valid system window
|
releaseSystemWindow()
|
void -- has to be called before the parent component loses its system window, e.g. before it is removed from its parent component
|
loadFromURL()
|
void -- loads a document into the Bean
|
loadFromStream()
|
void -- loads a document from a Java stream int o the Bean
|
loadFromByteArray()
|
void -- loads a document from a byte array into the Bean
|
storeToURL()
|
void - stores the document in the Bean to an URL
|
storeToStream()
|
void - stores the document in the Bean to a stream
|
storeToByteArray()
|
void - stores the document in the Bean to a byte array
|
getFrame()
|
Frame -- returns a wrapper for Frame
|
getController()
|
Controller -- returns a wrapper for Controller
|
getDocument()
|
Document -- returns a wrapper for OfficeDocument
|
setAllBarsVisible()
|
void - sets visibility of all tool bars, known by this Bean
|
set...BarVisible()
|
void - sets visibility of a specific tool bar
|
is...BarVisible()
|
boolean - returns visibility of a specific tool bar
|
Configuring the Office Bean
The fundamental framework of the Office Bean is contained in the officebean.jar archive file that depends on a local library officebean.dll or libofficebean.so, depending on the platform. The interaction between the backend LibreOffice process, officebean local library, Office Bean and the Java environment is shown in the illustration below.
The Office Bean allows the developer to connect to and communicate with the LibreOffice process through a named pipe. It also starts up a LibreOffice instance if it cannot connect to a running office. This is implemented in the Office Bean local library. The Office Bean depends on three configuration settings to make this work. It has to find the local library, needs the location of the LibreOffice executable, and the bean and office must know the pipe name to use.
Default Configuration
The Office Bean uses default values for all the configuration settings, if none are provided:
- Since OpenOffice.org 1.1.0 the officebean.jar is located in the <OfficePath>/program/classes directory.
- It looks for the local library (Windows: officebean.dll, Unix: libofficebean.so) relative to the officebean.jar in the <OfficePath>/program directory. The local library depends on the following shared libraries:
- The library sal3 (Windows: sal3.dll, Unix: libsal3.so) is located in the <OfficePath>/program folder. It maybe necessary to add the <OfficePath>/program folder to the PATH environment variable if the bean cannot find sal3.
- The library jawt.dll is needed in Windows. If the bean cannot find it, check the Java Runtime Environment binaries (<JRE>/bin) in your PATH environment variable.
- It expects the LibreOffice installation in the default install location for the current platform. The soffice executable is in the program folder of a standard installation.
- The pipe name is created using the value of the
user.name
Java property. The name of the pipe is created by appending "_office
" to the name of the currently logged on user, for example, if the user.name is "JohnDoe
", the name of the pipe is "JohnDoe_office
".
Based on these default values, the Office Bean tries to connect to an office. The office must run in listening mode. That is, it must have been started with the -accept command line option. If there is no running office, then it attempts to start one. The exact parameters used by the bean are:
# WINDOWS soffice.exe -bean -accept=pipe,name=<user.name>_Office;urp;StarOffice.NamingService
# UNIX soffice -bean "-accept=pipe,name=<user.name>_Office;urp;StarOffice.NamingService"
In case an office document is displayed outside of the Java frame, then the office has probably been started with wrong or no arguments. Providing the proper command-line arguments is necessary, so that the LibreOffice process can open a correctly named pipe, through which it communicates with the Java application. Only if this pipe can be established, the office will display the document in the Java window.
You can avoid providing the command-line options by editing the file <OfficePath>\user\config\registry\instance\org\openoffice\Setup.xml. Within the <Office/>
element, the developer adds an <ooSetupConnectionURL/>
element with settings for a named pipe. The following example shows a user-specific Setup.xml that configures a named pipe for a user named JohnDoe
:
<?xml version="1.0" encoding="UTF-8"?>
<Setup state="modified" cfg:package="org.openoffice"
xmlns="http://openoffice.org/2000/registry/components/Setup"
xmlns:cfg="http://openoffice.org/2000/registry/instance"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance">
<Office>
<ooSetupConnectionURL cfg:type="string">
pipe,name=JohnDoe_Office;urp;StarOffice.NamingService
</ooSetupConnectionURL>
<Factories cfg:element-type="Factory">
<Factory cfg:name="com.sun.star.text.TextDocument">
<ooSetupFactoryWindowAttributes cfg:type="string">
193,17,1231,1076;1;
</ooSetupFactoryWindowAttributes>
</Factory>
</Factories>
</Office>
</Setup>
With this user-specific Setup.xml file, the office opens a named pipe JohnDoe_Office
whenever it starts up. It does not matter if the user double clicks a document, runs the Quickstarter, or starts a new, empty document from a LibreOffice template.
Customized Configuration
Besides these default values, the Office Bean can be configured to use other parameters. There are three possibilities:
- starting the connection with an explicit UNO URL including path and pipe name parameters
- creating the connection manually and handing this object to the
OOoBean
- creating the
OOoBean
with such a manually created connection object.
The first method that a developer uses to configure the Office Bean is through the UNO URL passed in the setUnoUrl()
call. The syntax of the UNO URL is as follows:
url := 'uno:localoffice'[','<params>]';urp;StarOffice.NamingService' params := <path>[','<pipe>] path := 'path='<pathv> pipe := 'pipe='<pipev> pathv := platform_specific_path_to_the_local_office_distribution pipev := local_office_connection_pipe_name
Here is an example of how to use setUnoUrl()
in code:
OfficeConnection officeConnection = new LocalOfficeConnection();
officeConnection.setUnoUrl(
“uno:localoffice,path=/home/user/staroffice6.0/program;urp;StarOffice.NamingService”);
aBean = new OOoBean( officeConnection );
Internal Architecture
These details are not needed for developers utilizing the OOoBean
class. This information is directed to developers who want to adapt the OOoBean
mechanisms to other technologies, e.g. to implement access to a remote LibreOffice instance.
Internally, the OOoBean
consists of three major parts which are all included in the officebean.jar file. The classes LocalOfficeWindow
and LocalOfficeConnection
implement a fundamental framework that makes it possible to connect to the office and display the document window of a local LibreOffice installation in an AWT or Swing frame.
The Internal Office Bean API
The Office Bean API is exported in two Java interfaces, com.sun.star.comp.beans.OfficeConnection
and com.sun.star.comp.beans.OfficeWindow
.
An implementation of com.sun.star.comp.beans.OfficeConnection
is provided in the class com.sun.star.comp.beans.LocalOfficeConnection
. The class com.sun.star.comp.beans.LocalOfficeWindow
implements com.sun.star.comp.beans.OfficeWindow
. The relationship between the Office Bean interfaces and their implementation classes is shown in the illustration below.
The following sections describe the Office Bean interfaces OfficeConnection
and OfficeWindow
. Refer to the section Using the OOoBean for an explanation of how the implementation classes are used.
OfficeConnection Interface
The com.sun.star.comp.beans.OfficeConnection
interface contains the methods used to configure, initiate,and manage the connection to LibreOffice. These methods are:
public void setUnoUrl(String URL) throws java.net.MalformedURLException
public com.sun.star.uno.XComponentContext getComponentContext()
public OfficeWindow createOfficeWindow(Container container)
public void setContainerFactory(ContainerFactory containerFactory)
The client uses setUnoUrl()
to specify to the Office Bean how it connects to the LibreOffice process. See the section Configuring the Office Bean for a description of the syntax of the URL. A java.net.MalformedURLException
is thrown by the concrete implementation if the client passes a badly formed URL as an argument.
The method getComponentContext()
gets an object that implements the com.sun.star.uno.XComponentContext interface from the Office Bean. This object is then used to obtain objects implementing the full LibreOffice API from the backend LibreOffice process.
A call to createOfficeWindow()
requests a new OfficeWindow
from the OfficeConnection
. The client obtains the java.awt.Component
from the OfficeWindow
to plug into its UI. See the getAWTComponent()
method below on how to obtain the Component from the OfficeWindow
. The client provides java.awt.Container
that indicates to the implementation what kind of OfficeWindow
it is to create.
The method setContainerFactory()
specifies to the Office Bean the factory object it uses to create Java AWT windows to display popup windows in the Java environment. This factory object implements the com.sun.star.comp.beans.ContainerFactory
interface. See below for a definition of the ContainerFactory
interface.
If the client does not implement its own ContainerFactory
interface, the Office Bean uses its own default ContainerFactory
creating instances of java.awt.Canvas
.
OfficeWindow Interface
The com.sun.star.comp.beans.OfficeWindow
interface encapsulates the relationship between the AWT window that the client plugs into its UI, and the com.sun.star.awt.XWindowPeer object, which the LibreOffice process uses to draw into the window. It provides two public methods:
public java.awt.Component getAWTComponent()
public com.sun.star.awt.XWindowPeer getUNOWindowPeer()
The client uses getAWTComponent()
to obtain the Component window associated with an OfficeWindow. This Component is then added to the clients UI hierarchy.
The method getUNOWindowPeer()
obtains the UNO com.sun.star.awt.XWindowPeer object associated with an OfficeWindow
.
ContainerFactory Interface
The interface com.sun.star.comp.beans.ContainerFactory
defines a factory class that the client implements if it needs to control how popup windows generated by the backend LibreOffice process are presented within the Java environment. The factory has only one method:
public java.awt.Container createContainer()
It returns a java.awt.Container
.
LocalOfficeConnection and LocalOfficeWindow
The class LocalOfficeConnection
implements a connection to a locally running LibreOffice process that is an implementation of the interface OfficeConnection
. Its method createOfficeWindow()
creates an instance of the class LocalOfficeWindow
, that is an implementation of the interface OfficeWindow
.
Where LocalOfficeConnection
keeps a single connection to the LibreOffice process, there are multiple, shared LocalOfficeWindow
instances for multiple beans. The LocalOfficeWindow
implements the embedding of the local LibreOffice document window into a java.awt.Container
.