Language:

The Free and Open Productivity Suite
Apache OpenOffice 4.1.3 released

Transparent Use of Office UNO Components

Introduction

This document is about making the use of office UNO components transparent to the user.

If some client code wants to use office UNO components, then the typical use case is, that the client code is first looking for an existing office installation. If an installation is found, it is checked if the office process is already running. If no office process is running, an office process is started. After that the client code connects to the running office using remote UNO mechanisms in order to get the remote component context of that office. After this, the client code can use the remote component context to access arbitrary office UNO components. From the perspective of the client code there is no difference between local and remote components.

The idea is, that the component context is provided in a more transparent way. Especially the location of an existing office installation and the detection of a running office process should be hidden from the user.

Transparent Use from Java

The UNO component context is the root object for all UNO client applications. It must be passed to a component during its instantiation and therefore basically provides an environment for components. The component context also provides the service manager, which is used to create components. The idea is, that a bootstrap method is provided, which bootstraps the component context from a UNO installation. A simple client application may then look like:

// get the remote office component context
XComponentContext xContext = 
 com.sun.star.comp.helper.Bootstrap.bootstrap();

// get the remote office service manager
XMultiComponentFactory xServiceManager =
 xContext.getServiceManager();

// get an instance of the remote office desktop UNO service
Object desktop = xServiceManager.createInstanceWithContext(
  "com.sun.star.frame.Desktop", xContext );

// query the XComponentLoader interface from the desktop
XComponentLoader xComponentLoader =
  (XComponentLoader)UnoRuntime.queryInterface(
    XComponentLoader.class, desktop );

// load a spreadsheet document
String loadURL = "private:factory/scalc";
PropertyValue[] loadProps = new PropertyValue[0];
xComponentLoader.loadComponentFromURL(
 loadURL, "_blank", 0, loadProps);

One of the requirements for a Java client application is, that Java finds the com.sun.star.comp.helper.Bootstrap class and all the UNO types (e.g. UNO interfaces) and other Java UNO language binding classes (e.g. com.sun.star.uno.AnyConverter) used by the client code. A natural approach would be to add the UNO jar files to the Java CLASSPATH, but this requires the knowledge of the location of a UNO installation. Other approaches would be to use the Java extension mechanism or to deploy the jar files containing the UNO types in the client jar file. Both of those approaches have several drawbacks, the most important one is the problem of type conflicts, e.g. if a deployed component adds new UNO types. We therefore decided to use a more dynamic approach, namely to provide a customized class loader. The customized class loader will have an extended search path, which will also include the path to a UNO installation. The UNO installation will be auto-detected on the system by a provided search algorithm.

Customized Class Loader

The concept is based on the requirement that every class that uses UNO types or other classes that come with a office installation gets loaded by a customized class loader. This customized class loader knows the location of a UNO installation and loads every class from a jar or class file that belongs to the office installation. That means, the customized class loader must be instantiated and initialized before the first class that uses UNO is loaded.

For convenience we will provide some tooling in the SDK, which allows to build a client jar file, which can be invoked by

java -jar MyApplication.jar

A client application created by using the SDK tooling will automatically load the class com.sun.star.lib.loader.Loader, which sets up the customized class loader for loading the application class. In order to achieve this, the SDK tooling creates a manifest file that contains the following Main-Class entry

Main-Class: com.sun.star.lib.loader.Loader

The customized loader needs a special entry in the manifest file that specifies the name of the class that contains the client application code:

Name: com/sun/star/lib/loader/Loader.class
Application-Class: MyApplication

The implementation of com.sun.star.lib.loader.Loader.main will read this entry and call the main method of the application class after the customized class loader has been created and set up properly. The SDK tooling will take over the task to write the correct manifest entry for the application class.

Finding a UNO installation

The location of a UNO installation can be specified by the Java system property com.sun.star.lib.loader.unopath. The system property can be passed to the client application by using the -D flag, e.g

java -Dcom.sun.star.lib.loader.unopath=/opt/OpenOffice.org/program -jar MyApplication.jar

In addition, it is possible to specify a UNO installation by setting the environment variable UNO_PATH to the program directory of a UNO installation, e.g.

setenv UNO_PATH /opt/OpenOffice.org/program

Note, that this is not working with Java 1.3.1 and Java 1.4, because environment variables are not supported in those Java versions.

If no UNO installation is specified by the user, the default UNO installation on the system is searched for. The search algorithm is platform dependent.

On the Windows platform, the UNO installation is found by reading the default value of the key "Software\OpenOffice.org\UNO\InstallPath" from the root key HKEY_CURRENT_USER in the Windows Registry. If this key is missing, the key is read from the root key HKEY_LOCAL_MACHINE. One of those keys is always written during the installation of an office. In a single user installation the key is written to HKEY_CURRENT_USER, in a multi-user installation of an administrator to HKEY_LOCAL_MACHINE. Note, that the default installation is the last installed office, but with the restriction, that HKEY_CURRENT_USER has a higher priority than HKEY_LOCAL_MACHINE. The reading from the Windows Registry requires, that the native library unowinreg.dll is part of the application jar file or can be found in the java.library.path. The SDK tooling automatically will put the native library into the jar file containing the client application.

On the Unix/Linux platforms, the UNO installation is found from the PATH environment variable. Note, that for Java 1.3.1 and Java 1.4 the installation is found by using the which command, because environment variables are not supported with those Java versions. Both methods require that the soffice executable or a symbolic link is in one of the directories listed in the PATH environment variable. For older versions than OOo 2.0 the above described methods may fail. In this case the UNO installation is taken from the .sversionrc file in the user's home directory. The default installation is the last entry in the .sversionrc file which points to a UNO installation. Note, that there won't be a .sversionrc file with OOo 2.0 anymore.

The bootstrap method

The com.sun.star.comp.helper.Bootstrap.bootstrap() method is implemented in that way, that it first bootstraps a local component context by calling the method com.sun.star.comp.helper.Bootstrap.createInitialComponentContext(null). Then it tries to establish a named pipe connection to a running office by using the com.sun.star.bridge.UnoUrlResolver service. If the connection fails, an office process is started. After that, it tries to connect to the running office again. If the connection succeeds, it gets the remote component context, which is returned.

Note, that the office process can only be started, if the juh.jar file is located in the classes directory of an office installation. If the juh.jar file is copied to another location, the bootstrap method fails.

Transparent Use from C++

Also for C++ a bootstrap function is provided, which bootstraps the component context from a UNO installation. An example for a simple client application shows the following code snipplet:

// get the remote office component context
Reference< XComponentContext > xContext( ::cppu::bootstrap() );

// get the remote office service manager
Reference< XMultiComponentFactory > xServiceManager(
  xContext->getServiceManager() );

// get an instance of the remote office desktop UNO service
// and query the XComponentLoader interface
Reference < XComponentLoader > xComponentLoader(
  xServiceManager->createInstanceWithContext( OUString(
  RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ) ),
  xContext ), UNO_QUERY );

// open a spreadsheet document
Reference< XComponent > xComponent(
  xComponentLoader->loadComponentFromURL(
  OUString( RTL_CONSTASCII_USTRINGPARAM( "private:factory/scalc" ) ),
  OUString( RTL_CONSTASCII_USTRINGPARAM( "_blank" ) ), 0,
  Sequence < ::com::sun::star::beans::PropertyValue >() ) );

A C++ client application which uses UNO is linked to the C++ UNO libraries, which can be found in the program directory of a UNO installation. When running the client application, the C++ UNO libraries are found only, if the UNO program directory is included in the PATH (Windows) or LD_LIBRARY_PATH (Unix/Linux) environment variable.

Application Loader

As this requires the knowledge of the location of a UNO installation, we will provide an application loader (unoapploader.exe for Windows, unoapploader for Unix/Linux), which detects a UNO installation on the system and adds the program directory of the UNO installation to the PATH / LD_LIBRARY_PATH environment variable. After that, the application process is loaded and started, whereby the new process inherits the environment of the calling process, including the modified PATH / LD_LIBRARY_PATH environment variable.

For convenience we will provide some tooling in the SDK, which allows to build a client executable file (e.g. myapplication for Unix/Linux), which can be invoked by

./myapplication

In this case, the myapplication executable is simply the renamed unoapploader executable. All the application code is part of a second executable file, which must have the same name as the first executable, but prefixed by a underscore '_', that means in the example above the second executable is named _myapplication.

On the Unix/Linux platforms the application loader writes error messages to the stderr stream. On the Windows platform error messages are written to the error file <application name>-error.log in the application's executable file directory. If this fails, the error file is written to the directory designated for temporary files.

Note, that the C++ application loader is only available with OOo 2.0.

Finding a UNO installation

A UNO installation can be specified by the user by setting the UNO_PATH environment variable to the program directory of a UNO installation, e.g.

setenv UNO_PATH /opt/OpenOffice.org/program

If no UNO installation is specified by the user, the default installation on the system is taken.

On the Windows platform, the default installation is read from the default value of the key "Software\OpenOffice.org\UNO\InstallPath" from the root key HKEY_CURRENT_USER in the Windows Registry. If this key is missing, the key is read from the root key HKEY_LOCAL_MACHINE.

On the Unix/Linux platforms, the default installation is found from the PATH environment variable. This requires that the soffice executable or a symbolic link is in one of the directories listed in the PATH environment variable.

The bootstrap function

The ::cppu::bootstrap() function is implemented in a similar way as the Java com.sun.star.comp.helper.Bootstrap.bootstrap() method. It first bootstraps a local component context by calling the ::cppu::defaultBootstrap_InitialComponentContext() function and then tries to establish a named pipe connection to a running office by using the com.sun.star.bridge.UnoUrlResolver service. If the connection fails, an office process is started. After that, it tries to connect to the running office again. If the connection succeeds, it gets the remote component context, which is returned.

Author: Thomas Benisch. Last changed: $Date: 2004/12/05 13:42:29 $.

Apache Software Foundation

Copyright & License | Privacy | Contact Us | Donate | Thanks

Apache and the Apache feather logo are trademarks of The Apache Software Foundation. OpenOffice, OpenOffice.org and the seagull logo are registered trademarks of The Apache Software Foundation. Other names appearing on the site may be trademarks of their respective owners.