How to write a UNO component in Java |
Contents |
|||||||||
Introduction |
|||||||||
Introduction |
|||||||||
In this tutorial the implementation of an UNO component in the programming language Java is treated. To the better comprehensibility this tutorial is based on a component for the examination of an object of the OpenOffice API (Instance Inspector). Components like the Instance Inspector should be accessible as beans which you can incorporate into your programs. Actually components implement OpenOffice API services which are an abstract concept providing certain interfaces and properties. You can receive further information for the creation of UNO components in the programming language C++ under the following HTTP address: http://udk.openoffice.org/cpp/man/component_tutorial.html |
|||||||||
Writing a component |
|||||||||
In general a component can be devided into two main parts and therefore into two classes:
The necessary classes could be nested as follows:
The class InstanceInspector should provide two methods which are called by the Java Loader. One method (__getServiceFactory()) returns a XSingleServiceFactory for creating the component. The other method (__writeRegistryServiceInfo()) writes the service information into the given registry key. The local class _InstanceInspector implements three interfaces and is responsible for the concrete implementation of the service description (method inspect()). |
|||||||||
The UNO Base Interface and IDL |
|||||||||
An interface is a collection of methods that provide a certain functionality. In order to provide a language-independent programming environment, all interfaces must be described in an interface definition language (IDL). As a rule, UNO interfaces are specified in the UNO IDL and must be derived from a mandatory base interface (com.sun.star.uno.XInterface). This base interface provides three methods: queryInterface(), acquire(), and release(). Because UNO supports multiple interfaces, the queryInterface() method is necessary for navigating between the different interfaces (comparable to COM). The acquire() and release() methods handle the life cycle of UNO objects (global reference counting). Cyclic references are handled by the com.sun.star.lang.XComponent interface. Error handling is based on exceptions. IDL's similarity with the common programming language C++ is remarkable, however IDL contains exclusively syntax for data description and no statements. The UNO IDL file for the Instance Inspector could look as follows:
The IDL compiler idlc transforms interface definitions written in IDL into urd files (Uno Reflection Data). The urd files are then going to be merged into the type library (rdb). For more details on building a component you should take a look at the section How to build a component or the document Mapping of UNO IDL to Java. |
|||||||||
Getting a factory for the component |
|||||||||
The Service Manager is the central location where components are instantiated. It comes with a list of all available services registered. If a component is requested the Service Manager searches its list for a given service, in order to get the assigned factory. The Java Loader extracts the factory of a component with the aid of a static method called __getServiceFactory. This method should be implemented to return a customized factory for the component. Otherwise the Java Loader will return a default factory.
A special class FactoryHelper provides methods for implementing components. This class has default implementations for getting the service factory (method __getServiceFactory) and for writing the service info into the registry (method writeRegistryServiceInfo). Please note, if you implement the service as inner class, then it must be a static inner class. If not, then the constructors of the inner class expect an instance of the outer class as first parameter. However, the FactoryHelper class cannot provide one. The field __serviceName in your class should specifiy the name of your service.
If the property is not specified the default factory sets the components name (class name) as the service name. |
|||||||||
Register the component |
|||||||||
Every component should be registered with
its implementation name for the service. Therefore the method __writeRegistryServiceInfo
is responsible for writing the service information into the registry. Registration tools,such
as regcomp.exe, need to know what java class contains that method. This information has to be
placed into the manifest file. The entry has this format:
|
|||||||||
Supporting several services |
|||||||||
If the component should support more than one service all these services should be specified in the field __serviceName.
Furthermore the component should be able to access the service manager. In order to set the service manager at the component the default factory uses the optional method __setServiceManager. |
|||||||||
How to build a component |
|||||||||
The following steps describe the build process by the example of the Instance Inspector with the operating system Windows. First you should set the necessary variables. Perhaps you should adapt also the following commands to other operating systems requirements. The idl compiler idlc transforms the interface definitions written in idl into an urd file:
The urd file is then going to be merged into the type library (rdb):
Regmerge is a small tool to merge different registry files under a specified key into another registry file:
The javamaker generates the appropriate java file for each idl type:
Compile the java files:
Use the existing manifest file 'Manifest' and archive all the java files
into 'InstanceInspector.jar':
Registering the service, id est the jar-file:
|
|||||||||
|
|||||||||
Deployment hints |
|||||||||
All interfaces, which are used by the component, have to be known to the Java Virtual Machine.
The standard interfaces are contained in the ridl.jar file. That jar is always in the classpath
and hence the VM can locate the interface classes. If you define your own interfaces, then you usually do not want to put them into the ridljar (builds ridl.jar) project from the beginning. Instead you probably like to keep them in the jar file of your component, or in a separate class or jar file during development. If the latter is the case, then you must make sure that the interfaces are in the classpath during registration and when running your component. This can be achieved by editing the SytemClasspath entry (office_dir\user\config\java.ini, or javarc) or the user classpath in the options dialog (tools menu, StarOffice/Security). Also, do not forget to merge the interface with the applicat.rdb. |
|||||||||
|
|||||||||
Author: Bertram
Nolte (
2002-01-11 10:29
) |
|||||||||
|