Documentation/DevGuide/Professional UNO

This chapter provides in-depth information about UNO and the use of UNO in various programming languages. There are four sections:


 * 1) The Professional UNO - Introduction gives an outline of the UNO architecture.
 * 2) The section Professional UNO - API Concepts supplies background information on the API reference.
 * 3) The section Professional UNO - UNO Concepts describes the mechanics of UNO, i.e. it shows how UNO objects connect and communicate with each other.
 * 4) The section Professional UNO - UNO Language Bindings elaborates on the use of UNO from Java, C++, LibreOffice Basic, COM automation, and CLI.

Introduction
The goal of UNO (Universal Network Objects) is to provide an environment for network objects across programming language and platform boundaries. UNO objects run and communicate everywhere. UNO reaches this goal by providing the following fundamental framework:


 * UNO objects are specified in an abstract meta language, called UNOIDL (UNO Interface Definition Language), which is similar to CORBA IDL or MIDL. From UNOIDL specifications, language dependent header files and libraries can be generated to implement UNO objects in the target language. UNO objects in the form of compiled and bound libraries are called components. Components must support certain base interfaces to be able to run in the UNO environment.


 * To instantiate components in a target environment UNO uses a factory concept. This factory is called the service manager. It maintains a database of registered components which are known by their name and can be created by name. The service manager might ask Linux to load and instantiate a shared object written in C++ or it might call upon the local Java VM to instantiate a Java class. This is transparent for the developer, there is no need to care about a component's implementation language. Communication takes place exclusively over interface calls as specified in UNOIDL.


 * UNO provides bridges to send method calls and receive return values between processes and between objects written in different implementation languages. The remote bridges use a special UNO remote protocol (URP) for this purpose which is supported for sockets and pipes. Both ends of the bridge must be UNO environments, therefore a language-specific UNO runtime environment to connect to another UNO process in any of the supported languages is required. These runtime environments are provided as language bindings.


 * Most objects of LibreOffice are able to communicate in a UNO environment. The specification for the programmable features of LibreOffice is called the LibreOffice API.

API Concepts
The LibreOffice API is a language independent approach to specify the functionality of LibreOffice. Its main goals are to provide an API to access the functionality of LibreOffice, to enable users to extend the functionality by their own solutions and new features, and to make the internal implementation of LibreOffice exchangeable.

A long term target on the LibreOffice roadmap is to split the existing LibreOffice into small components which are combined to provide the complete LibreOffice functionality. Such components are manageable, they interact with each other to provide high level features and they are exchangeable with other implementations providing the same functionality, even if these new implementations are implemented in a different programming language. When this target will be reached, the API, the components and the fundamental concepts will provide a construction kit, which makes LibreOffice adaptable to a wide range of specialized solutions and not only an office suite with a predefined and static functionality.

This section provides you with a thorough understanding of the concepts behind the LibreOffice API. In the API reference there are UNOIDL data types which are unknown outside of the API. The reference provides abstract specifications which sometimes can make you wonder how they map to implementations you can actually use.

The data types of the API reference are explained in Data Types. The relationship between API specifications and LibreOffice implementations is treated in Understanding the API Reference.

Data Types
The data types in the API reference are UNO types which have to be mapped to the types of any programming language that can be used with the LibreOffice API. In First Steps the most important UNO types were introduced. However, there is much more to be said about simple types, interfaces, properties and services in UNO. There are special flags, conditions and relationships between these entities which you will want to know if you are working with UNO on a professional level.

This section explains the types of the API reference from the perspective of a developer who wants to use the LibreOffice API. If you are interested in writing your own components, and you must define new interfaces and types, please refer to the chapter Writing UNO Components, which describes how to write your own UNOIDL specifications and how to create UNO components.

Simple Types
UNO provides a set of predefined, simple types which are listed in the following table:

The chapters about language bindings Java Language Binding, C++ Language Binding, LibreOffice Basic and Automation Bridge describe how these types are mapped to the types of your target language.

The Any Type
The special type  can represent values of all other UNO types. In the target languages, the  type requires special treatment. There is an AnyConverter in Java and special operators in C++. For details, see UNO Language Bindings.

Interfaces
Communication between UNO objects is based on object interfaces. Interfaces can be seen from the outside or the inside of an object.

From the outside of an object, an interface provides a functionality or special aspect of the object. Interfaces provide access to objects by publishing a set of operations that cover a certain aspect of an object without telling anything about its internals.

The concept of interfaces is quite natural and frequently used in everyday life. Interfaces allow the creation of things that fit in with each other without knowing internal details about them. A power plug that fits into a standard socket or a one-size-fits-all working glove are simple examples. They all work by standardizing the minimal conditions that must be met to make things work together.

A more advanced example would be the "remote control aspect" of a simple TV system. One possible feature of a TV system is a remote control. The remote control functions can be described by an XPower and an XChannel interface. The illustration below shows a RemoteControl object with these interfaces:



The XPower interface has the functions turnOn and turnOff to control the power and the XChannel interface has the functions select, next , previous to control the current channel. The user of these interfaces does not care if he uses an original remote control that came with a TV set or a universal remote control as long as it carries out these functions. The user is only dissatisfied if some of the functions promised by the interface do not work with a remote control.

From the inside of an object, or from the perspective of someone who implements a UNO object, interfaces are abstract specifications. The abstract specification of all the interfaces in the LibreOffice API has the advantage that user and implementer can enter into a contract, agreeing to adhere to the interface specification. A program that strictly uses the LibreOffice API according to the specification will always work, while an implementer can do whatever he wants with his objects, as long as he serves the contract.

UNO uses the interface type to describe such aspects of UNO objects. By convention, all interface names start with the letter X to distinguish them from other types. All interface types must inherit the com.sun.star.uno.XInterface root interface, either directly or in the inheritance hierarchy. XInterface is explained in Using UNO Interfaces. The interface types define methods (sometimes also called operations) to provide access to the specified UNO objects.

Interfaces allow access to the data inside an object through dedicated methods (member functions) which encapsulate the data of the object. The methods always have a parameter list and a return value, and they may define exceptions for smart error handling.

The exception concept in the OpenOffice.org API is comparable with the exception concepts known from Java or C++. All operations can raise com.sun.star.uno.RuntimeException without explicit specification, but all other exceptions must be specified. UNO exceptions are explained in the section Exception Handling.

Consider the following two examples for interface definitions in UNOIDL (UNO Interface Definition Language) notation. UNOIDL interfaces resemble Java interfaces, and methods look similar to Java method signatures. However, note the flags in square brackets in the following example:

The [oneway] flag indicates that an operation can be executed asynchronously if the underlying method invocation system does support this feature. For example, a UNO Remote Protocol (URP) bridge is a system that supports oneway calls.

There are also parameter flags. Each parameter definition begins with one of the direction flags in, out, or inout to specify the use of the parameter:


 * in specifies that the parameter will be used as an input parameter only
 * out specifies that the parameter will be used as an output parameter only
 * inout specifies that the parameter will be used as an input and output parameter

These parameter flags do not appear in the API reference. The fact that a parameter is an [out] or [inout] parameter is explained in the method details.

Interfaces consisting of methods form the basis for service specifications.

Services
We have seen that a single-inheritance interface describes only one aspect of an object. However, it is quite common that objects have more than one aspect. UNO uses multiple-inheritance interfaces and services to specify complete objects which can have many aspects.

LibreOffice objects can inherit services, including interfaces, from only one parent object. However, objects can implement multiple interfaces. Inherited methods can be provided by the parent of the object; implemented methods must be provided by the object itself. Although LibreOffice does not support true multiple-inheritance, objects can implement multiple interfaces, which gives them the appearance of having inherited methods from several other objects. When the term multiple-inheritance interface is used in LibreOffice, it actually refers to multiple interface implementation.

In a first step, all the various aspects of an object (which are typically represented by single-inheritance interfaces) are grouped together in one multiple-inheritance interface type. If such an object is obtainable by calling specific factory methods, this step is all that is needed. The factory methods are specified to return values of the given, multiple-inheritance interface type. If, however, such an object is available as a general service at the global component context, a service description must be provided in a second step. This service description will be of the new style, mapping the service name (under which the service is available at the component context) to the given, multiple-inheritance interface type.

For backward compatibility, there are also old-style services, which comprise a set of single-inheritance interfaces and properties that are needed to support a certain functionality. Such a service can include other old-style services as well. The main drawback of an old-style service is that it is unclear whether it describes objects that can be obtained through specific factory methods (and for which there would therefore be no new-style service description), or whether it describes a general service that is available at the global component context, and for which there would thus be a new-style service description.

From the perspective of a user of a UNO object, the object offers one or sometimes even several independent, multiple-inheritance interfaces or old-style services described in the API reference. The services are utilized through method calls grouped in interfaces, and through properties, which are handled through special interfaces as well. Because the access to the functionality is provided by interfaces only, the implementation is irrelevant to a user who wants to use an object.

From the perspective of an implementer of a UNO object, multiple-inheritance interfaces and old-style services are used to define a functionality independently of a programming language and without giving instructions about the internal implementation of the object. Implementing an object means that it must support all specified interfaces and properties. It is possible that a UNO object implements more than one independent, multiple-inheritance interface or old-style service. Sometimes it is useful to implement two or more independent, multiple-inheritance interfaces or services because they have related functionality, or because they support different views to the object.

The RemoteControl service illustration shows the relationship between interfaces and services. The language independent specification of an old-style service with several interfaces is used to implement a UNO object that fulfills the specification. Such a UNO object is sometimes called a "component," although that term is more correctly used to describe deployment entities within a UNO environment. The illustration uses an old-style service description that directly supports multiple interfaces; for a new-style service description, the only difference would be that it would only support one multiple-inheritance interface, which in turn would inherit the other interfaces.



The functionality of a TV system with a TV set and a remote control can be described in terms of service specifications. The interfaces  and   described above would be part of a service specification. The new service  consists of the three interfaces ,   and   to control the power, the channel selection, the additional power function   and a   function.



Referencing Interfaces
References to interfaces in a service definition mean that an implementation of this service must offer the specified interfaces. However, optional interfaces are possible. If a multiple-inheritance interface inherits an optional interface, or an old-style service contains an optional interface, any given UNO object may or may not support this interface. If you utilize an optional interface of a UNO object, always check if the result of  is equal to   and react accordingly - otherwise your code will not be compatible with implementations without the optional interface and you might end up with null pointer exceptions. The following UNOIDL snippet shows a fragment of the specification for the old-style service in the LibreOffice API. Note the flag optional in square brackets, which makes the interfaces  and   non-mandatory.

Service Constructors
New-style services can have constructors, similar to interface methods:

In the above example, there are three explicit constructors, named,  , and. The first has no parameters, the second has two normal parameters, and the third has a special rest parameter, which accepts an arbitrary number of any values. Constructor parameters may only be, and a rest parameter must be the only parameter of a constructor, and must be of type   also, unlike an interface method, a service constructor does not specify a return type.

The various language bindings map the UNO constructors into language-specific constructs, which can be used in client code to obtain instances of those services, given a component context. The general convention (followed,for example, by the Java and C++ language bindings) is to map each constructor to a static method (resp. function) with the same name, that takes as a first parameter an com.sun.star.uno.XComponentContext, followed by all the parameters specified in the constructor, and returns an (appropriately typed) service instance. If an instance cannot be obtained, a com.sun.star.uno.DeploymentException is thrown. The above  would map to the following Java 1.5 class, for example:

Service constructors can also have exception specifications, which are treated in the same way as exception specifications of interface methods. (If a constructor has no exception specification, it may only throw runtime exceptions, com.sun.star.uno.DeploymentException in particular.)

If a new-style service is written using the short form,

then it has an implicit constructor. The exact behavior of the implicit constructor is language-binding - specific, but it is typically named, takes no arguments besides the com.sun.star.uno.XComponentContext , and may only throw runtime exceptions.

Including Properties
When the structure of the LibreOffice API was founded, the designers discovered that the objects in an office environment would have huge numbers of qualities that did not appear to be part of the structure of the objects, rather they seemed to be superficial changes to the underlying objects. It was also clear that not all qualities would be present in each object of a certain kind. Therefore, instead of defining a complicated pedigree of optional and non-optional interfaces for each and every quality, the concept of properties was introduced. Properties are data in an object that are provided by name over a generic interface for property access, that contains getPropertyValue and setPropertyValue access methods. The concept of properties has other advantages, and there is more to know about properties. Please refer to Properties for further information about properties.

Old-style services can list supported properties directly in the UNOIDL specification. A  defines a member variable with a specific type that is accessible at the implementing component by a specific name. It is possible to add further restrictions to a property through additional flags. The following old-style service references one interface and three optional properties. All known API types can be valid property types:

Possible property flags are:


 * The property does not have to be supported by the implementing component.
 * The property does not have to be supported by the implementing component.


 * The value of the property cannot be changed using com.sun.star.beans.XPropertySet.
 * The value of the property cannot be changed using com.sun.star.beans.XPropertySet.


 * Changes of property values are broadcast to com.sun.star.beans.XPropertyChangeListener, if any were registered through com.sun.star.beans.XPropertySet.
 * Changes of property values are broadcast to com.sun.star.beans.XPropertyChangeListener, if any were registered through com.sun.star.beans.XPropertySet.


 * The property broadcasts an event before its value changes. Listeners have the right to veto the change.
 * The property broadcasts an event before its value changes. Listeners have the right to veto the change.


 * Possibly the property value cannot be determined in some cases, for example, in multiple selections with different values.
 * Possibly the property value cannot be determined in some cases, for example, in multiple selections with different values.


 * The value might be stored in a style sheet or in the environment instead of the object itself.
 * The value might be stored in a style sheet or in the environment instead of the object itself.


 * In addition to the range of the property type, the value can be void. It is similar to a null value in databases.
 * In addition to the range of the property type, the value can be void. It is similar to a null value in databases.


 * The property is removable, this is used for dynamic properties.
 * The property is removable, this is used for dynamic properties.


 * The property will not be stored if the object is serialized
 * The property will not be stored if the object is serialized

Referencing other Services
Old-style services can include other old-style services. Such references may be optional. That a service is included by another service has nothing to do with implementation inheritance, only the specifications are combined. It is up to the implementer if he inherits or delegates the necessary functionality, or if he implements it from scratch.

The old-style service com.sun.star.text.Paragraph in the following UNOIDL example includes one mandatory service com.sun.star.text.TextContent and five optional services. Every  must be a. It can be a  and it is used to support formatting properties for paragraphs and characters:

If all the old-style services in the example above were multiple-inheritance interface types instead, the structure would be similar: the multiple-inheritance interface type  would inherit the mandatory interface   and the optional interfaces ,  , etc.

Service Implementations in Components
A component is a shared library or Java archive containing implementations of one or more services in one of the target programming languages supported by UNO. Such a component must meet basic requirements, mostly different for the different target language, and it must support the specification of the implemented services. That means all specified interfaces and properties must be implemented. Components must be registered in the UNO runtime system. After the registration all implemented services can be used by ordering an instance of the service at the appropriate service factory and accessing the functionality over interfaces.

Based on our example specifications for a  and a   service, a component   could simulate a remote TV system:



Such a  component could be a jar file or a shared library. It would contain two service implementations,  and. Once the  component is registered with the global service manager, users can call the factory method of the service manager and ask for a   or a   service. Then they could use their functionality over the interfaces,   and. When a new implementation of these services with better performance or new features is available later on, the old component can be replaced without breaking existing code, provided that the new features are introduced by adding interfaces.

Structs
A  type defines several elements in a record. The elements of a struct are UNO types with a unique name within the struct. Structs have the disadvantage not to encapsulate data, but the absence of  and   methods can help to avoid the overhead of method calls over a UNO bridge. UNO supports single inheritance for struct types. A derived  recursively inherits all elements of the parent and its parents.

A new feature of LibreOffice is the polymorphic struct type. A polymorphic struct type template is similar to a plain struct type, but it has one or more type parameters, and its members can have these parameters as types. A polymorphic struct type template is not itself a UNO type - it has to be instantiated with actual type arguments to be used as a type.

In the example,  will be an instantiated polymorphic struct type with the same form as the plain struct type

Polymorphic struct types were added primarily to support rich interface type attributes that are as expressive as,  , or   properties (see com.sun.star.beans.Ambiguous , com.sun.star.beans.Defaulted , com.sun.star.beans.Optional ), but they are probably useful in other contexts, too.

Predefined Values
The API offers many predefined values, that are used as method parameters, or returned by methods. In UNO IDL there are two different data types for predefined values: constants and enumerations.

const
A  defines a named value of a valid UNO IDL type. The value depends on the specified type and can be a literal (integer number, floating point number or a character), an identifier of another const type or an arithmetic term using the operators:,  ,  ,  ,  ,  ,  ,  ,  ,  ,.

Since a wide selection of types and values is possible in a const, const is occasionally used to build bit vectors which encode combined values.

Usually const definitions are part of a constants group.

constants
The constants type defines a named group of const values. A const in a constants group is denoted by the group name and the const name. In the UNO IDL example below,  refers to the value 2:

enum
An  type is equivalent to an enumeration type in C++. It contains an ordered list of one or more identifiers representing long values of the enum type. By default, the values are numbered sequentially, beginning with 0 and adding 1 for each new value. If an enum value has been assigned a value, all following enum values without a predefined value get a value starting from this assigned value.

If enums are used during debugging, you should be able to derive the numeric value of an enum by counting its position in the API reference. However, never use literal numeric values instead of enums in your programs.

Sequences
A  type is a set of elements of the same type, that has a variable number of elements. In UNO IDL, the used element always references an existing and known type or another sequence type. A sequence can occur as a normal type in all other type definitions.

Modules
Modules are namespaces, similar to namespaces in C++ or packages in Java. They group services, interfaces, structs, exceptions, enums, typedefs, constant groups and submodules with related functional content or behavior. They are utilized to specify coherent blocks in the API, this allows for a well-structured API. For example, the module com.sun.star.text contains interfaces and other types for text handling. Some other typical modules are com.sun.star.uno, com.sun.star.drawing , com.sun.star.sheet and com.sun.star.table. Identifiers inside a module do not clash with identifiers in other modules, therefore it is possible for the same name to occur more than once. The global index of the API reference shows that this does happen.

Although it may seem that the modules correspond with the various parts of LibreOffice, there is no direct relationship between the API modules and the LibreOffice applications Writer, Calc and Draw. Interfaces from the module com.sun.star.text are used in Calc and Draw. Modules like com.sun.star.style or com.sun.star.document provide generic services and interfaces that are not specific to any one part of LibreOffice.

The modules you see in the API reference were defined by nesting UNO IDL types in module instructions. For example, the module com.sun.star.uno contains the interface :

Exceptions
An  type indicates an error to the caller of a function. The type of exception gives a basic description of the kind of error that occurred. In addition, the UNO IDL  types contain elements which allow for an exact specification and a detailed description of the error. The  type supports inheritance, this is frequently used to define a hierarchy of errors. Exceptions are only used to raise errors, not as method parameters or return types.

UNO IDL requires that all exceptions must inherit from com.sun.star.uno.Exception. This is a precondition for the UNO runtime.

Exceptions may only be thrown by operations which were specified to do so. In contrast, com.sun.star.uno.RuntimeException s can always occur.

Singletons
Singletons are used to specify named objects where exactly one instance can exist in the life of a UNO component context. A singleton references one interface type and specifies that the only existing instance of this singleton can be reached over the component context using the name of the singleton. If no instance of the singleton exists, the component context will instantiate a new one. An example of such a new-style singleton is

The various language bindings offer language-specific ways to obtain the instance of a new-style singleton, given a component context. For example, in Java and C++ there is a static method (resp. function) named get, that takes as its only argument a com.sun.star.uno.XComponentContext and returns the (appropriately typed) singleton instance. If the instance cannot be obtained, a com.sun.star.uno.DeploymentException is thrown.

There are also old-style singletons, which reference (old-style) services instead of interfaces. However, for old-style services, the language bindings offer no get functionality.

Specification, Implementation and Instances
The API specifications you find in the API reference are abstract. The service descriptions of the API reference are not about classes that previously exist somewhere. The specifications are created first, then the UNO implementation is created according to the specification. That holds true even for legacy implementations that had to be adapted to UNO.

Moreover, since a component developer is free to implement services and interfaces as required, there is not necessarily a one-to-one relationship between a certain service specification and a real object. The real object can be capable of more things than specified in a service definition. For example, if you order a service at the factory or receive an object from a getter or  method, the specified features will be present, but there may be additional features. For instance, the text document model has a few interfaces which are not included in the specification for the com.sun.star.text.TextDocument.

Because of the optional interfaces and properties, it is impossible to comprehend fully from the API reference what a given instance of an object in LibreOffice is capable of. The optional interfaces and properties are correct for an abstract specification, but it means that when you leave the scope of mandatory interfaces and properties, the reference only defines how things are allowed to work, not how they actually work.

Another important point is the fact that there are several entry points where object implementations are actually available. You cannot instantiate every old-style service that can be found in the API reference by means of the global service manager. The reasons are:


 * Some old-style services need a certain context. For instance, it does not make sense to instantiate a com.sun.star.text.TextFrame independently of an existing text document or any other surrounding where it could be of any use. Such services are usually not created by the global service manager, but by document factories which have the necessary knowledge to create objects that work in a certain surrounding. That does not mean you will never be able to get a text frame from the global service manager to insert. So, if you wish to use a service in the API reference, ask yourself where you can get an instance that supports this service, and consider the context in which you want to use it. If the context is a document, it is quite possible that the document factory will be able to create the object.


 * Old-style services are not only used to specify possible class implementations. Sometimes they are used to specifying nothing but groups of properties that can be referenced by other old-style services. That is, there are services with no interfaces at all. You cannot create such a service at the service manager.


 * A few old-style services need special treatment. For example, you cannot ask the service manager to create an instance of a com.sun.star.text.TextDocument . You must load it using the method  at the desktop's com.sun.star.frame.XComponentLoader interface.

In the first and the last case above, using multiple-inheritance interface types instead of old-style services would have been the right design choice, but the mentioned services predate the availability of multiple-inheritance interface types in UNO.

Consequently, it is sometimes confusing to look up a needed functionality in the API reference, for you need a basic understanding how a functionality works, which services are involved, where they are available etc., before you can really utilize the reference. This manual aims at giving you this understanding about the LibreOffice document models, the database integration and the application itself.

Object Composition
Interfaces support single and multiple inheritance, and they are all based on com.sun.star.uno.XInterface. In the API reference, this is mirrored in the Base Hierarchy section of any interface specification. If you look up an interface, always check the base hierarchy section to understand the full range of supported methods. For instance, if you look up com.sun.star.text.XText, you see two methods,  and  , but there are nine more methods provided by the inherited interfaces. The same applies to exceptions and sometimes also to structs, which support single inheritance as well.

The service specifications in the API reference can contain a section Included Services, which is similar to the above in that a single included old-style service might encompass a whole world of services. However, the fact that a service is included has nothing to do with class inheritance. In which manner a service implementation technically includes other services, by inheriting from base implementations, by aggregation, some other kind of delegation or simply by re-implementing everything is by no means defined (which it is not, either, for UNO interface inheritance). And it is uninteresting for an API user – he can absolutely rely on the availability of the described functionality, but he must never rely on inner details of the implementation, which classes provide the functionality, where they inherit from and what they delegate to other classes.

UNO Concepts
Now that you have an advanced understanding of LibreOffice API concepts, and you understand the specification of UNO objects, we are ready to explore UNO, i.e. to see how UNO objects connect and communicate with each other.

UNO Interprocess Connections
UNO objects in different environments connect via the interprocess bridge. You can execute calls on UNO object instances, that are located in a different process. This is done by converting the method name and the arguments into a byte stream representation, and sending this package to the remote process, for example, through a socket connection. Most of the examples in this manual use the interprocess bridge to communicate with the LibreOffice.

This section deals with the creation of UNO interprocess connections using the UNO API.

Starting LibreOffice in Listening Mode
Most examples in this developers guide connect to a running LibreOffice and perform API calls, which are then executed in LibreOffice. By default, the office does not listen on a resource for security reasons. This makes it necessary to make LibreOffice listen on an interproces connection resource, for example, a socket. Currently this can be done in two ways:


 * Start the office with an additional parameter:

soffice -accept=socket,host=0,port=2002;urp;

This string has to be quoted on unix shells, because the semicolon ' ' is interpreted by the shells


 * Place the same string without  into a configuration file. You can edit the file
 * /share/registry/data/org/openoffice/Setup.xcu
 * and replace the tag

with

If the tag is not present, add it within the tag

This change affects the whole installation. If you want to configure it for a certain user in a network installation, add the same tag within the node  to the file Setup.xcu in the user dependent configuration directory /user/registry/data/org/openoffice/

Choose the procedure that suits your requirements and launch LibreOffice in listening mode now. Check if it is listening by calling netstat -a or -na on the command-line. An output similar to the following shows that the office is listening:

TCP :8100 : 0 Listening

If you use the -n option, netstat displays addresses and port numbers in numerical form. This is sometimes useful on UNIX systems where it is possible to assign logical names to ports.

If the office is not listening, it probably was not started with the proper connection URL parameter. Check the Setup.xcu file or your command-line for typing errors and try again.

The various parts of the connection URL will be discussed in the next section.

Importing a UNO Object
The most common use case of interprocess connections is to import a reference to a UNO object from an exporting server. For instance, most of the Java examples described in this manual retrieve a reference to the LibreOffice. The correct way to do this is using the com.sun.star.bridge.UnoUrlResolver service. Its main interface com.sun.star.bridge.XUnoUrlResolver is defined in the following way:

The string passed to the  method is called a UNO URL. It must have the following format:



An example URL could be uno:socket,host=localhost,port=2002;urp;StarOffice.ServiceManager. The parts of this URL are:

 The URL schema uno:. This identifies the URL as UNO URL and distinguishes it from others, such as http: or ftp: URLs. A string which characterizes the type of connection to be used to access the other process. Optionally, directly after this string, a comma separated list of name-value pairs can follow, where name and value are separated by a '='. The currently supported connection types are described in Opening a Connection. The connection type specifies the transport mechanism used to transfer a byte stream, for example, TCP/IP sockets or named pipes. A string which characterizes the type of protocol used to communicate over the established byte stream connection. The string can be followed by a comma separated list of name-value pairs, which can be used to customize the protocol to specific needs. The suggested protocol is urp (UNO Remote Protocol). Some useful parameters are explained below. Refer to the document named UNO-URL at www.openoffice.org/udk for the complete specification. A process must explicitly export a certain object by a distinct name. It is not possible to access an arbitrary UNO object (which would be possible with IOR in CORBA, for instance). 

The following example demonstrates how to import an object using the UnoUrlResolver:

The usage of the  has certain disadvantages. You cannot:


 * be notified when the bridge terminates for whatever reasons
 * close the underlying interprocess connection
 * offer a local object as an initial object to the remote process

These issues are addressed by the underlying API, which is explained in Opening a Connection.

Characteristics of the Interprocess Bridge
The whole bridge is threadsafe and allows multiple threads to execute remote calls. The dispatcher thread inside the bridge cannot block because it never executes calls. It instead passes the requests to worker threads.


 * A synchronous call sends the request through the connection and lets the requesting thread wait for the reply. All calls that have a return value, an out parameter, or throw an exceptions other than a RuntimeException must be synchronous.


 * An asynchronous (or ) call sends the request through the connection and immediately returns without waiting for a reply. It is currently specified at the IDL interface if a request is synchronous or asynchronous by using the [oneway] modifier.

For synchronous requests, thread identity is guaranteed. When process A calls process B, and process B calls process A, the same thread waiting in process A will take over the new request. This avoids deadlocks when the same mutex is locked again. For asynchronous requests, this is not possible because there is no thread waiting in process A. Such requests are executed in a new thread. The series of calls between two processes is guaranteed. If two asynchronous requests from process A are sent to process B, the second request waits until the first request is finished.

Although the remote bridge supports asynchronous calls, this feature is disabled by default. Every call is executed synchronously. The oneway flag of UNO interface methods is ignored. However, the bridge can be started in a mode that enables the oneway feature and thus executes calls flagged with the  modifier as asynchronous calls. To do this, the protocol part of the connection string on both sides of the remote bridge must be extended by. For example:

for starting the office and

as UNO URL for connecting to it.

Opening a Connection
The method to import a UNO object using the  has drawbacks as described in the previous chapter. The layer below the  offers full flexibility in interprocess connection handling.

UNO interprocess bridges are established on the com.sun.star.connection.XConnection interface, which encapsulates a reliable bidirectional byte stream connection (such as a TCP/IP connection).

There are different mechanisms to establish an interprocess connection. Most of these mechanisms follow a similar pattern. One process listens on a resource and waits for one or more processes to connect to this resource.

This pattern has been abstracted by the services com.sun.star.connection.Acceptor that exports the com.sun.star.connection.XAcceptor interface and com.sun.star.connection.Connector that exports the com.sun.star.connection.XConnector interface.

The acceptor service is used in the listening process while the connector service is used in the actively connecting service. The methods  and   get the connection string as a parameter. This is the connection part of the UNO URL (between uno: and ;urp).

The connection string consists of a connection type followed by a comma separated list of name-value pairs. The following table shows the connection types that are supported by default.

Creating the Bridge


The  instance can now be used to establish a UNO interprocess bridge on top of the connection, regardless if the connection was established with a Connector or Acceptor service (or another method). To do this, you must instantiate the service com.sun.star.bridge.BridgeFactory. It supports the com.sun.star.bridge.XBridgeFactory interface.

The  service administrates all UNO interprocess connections. The  method creates a new bridge:


 * You can give the bridge a distinct name with the sName argument. Later the bridge can be retrieved by using the  method with this name. This allows two independent code pieces to share the same interprocess bridge. If you call   with the name of an already working interprocess bridge, a   is thrown. When you pass an empty string, you always create a new anonymous bridge, which can never be retrieved by   and which never throws a.


 * The second parameter specifies the protocol to be used on the connection. Currently, only the 'urp' protocol is supported. In the UNO URL, this string is separated by two ';'. The urp string may be followed by a comma separated list of name-value pairs describing properties for the bridge protocol. The urp specification can be found on the wiki Uno Remote Protocol.


 * The third parameter is the  interface as it was retrieved by Connector/Acceptor service.


 * The fourth parameter is a UNO object, which supports the com.sun.star.bridge.XInstanceProvider interface. This parameter may be a null reference if you do not want to export a local object to the remote process.

The  returns a com.sun.star.bridge.XBridge interface.

The  method retrieves an initial object from the remote counterpart. The local  call arrives in the remote process as an   call. The object returned can be controlled by the string. It completely depends on the implementation of, which object it returns.

The  interface can be queried for a com.sun.star.lang.XComponent interface, that adds a com.sun.star.lang.XEventListener to the bridge. This listener will be terminated when the underlying connection closes (see above). You can also call  on the   interface explicitly, which closes the underlying connection and initiates the bridge shutdown procedure.

Closing a Connection
The closure of an interprocess connection can occur for the following reasons:


 * The bridge is not used anymore. The interprocess bridge will close the connection when all the proxies to remote objects and all stubs to local objects have been released. This is the normal way for a remote bridge to destroy itself. The user of the interprocess bridge does not need to close the interprocess connection directly - it is done automatically. When one of the communicating processes is implemented in Java, the closure of a bridge is delayed to that point in time when the VM finalizes the last proxies/stubs. Therefore it is unspecified when the interprocess bridge will be closed.


 * The interprocess bridge is directly disposed by calling its  method.


 * The remote counterpart process crashes.


 * The connection fails. For example, failure may be due to a dialup internet connection going down.


 * An error in marshaling/unmarshaling occurs due to a bug in the interprocess bridge implementation, or an IDL type is not available in one of the processes.

Except for the first reason, all other connection closures initiate an interprocess bridge shutdown procedure. All pending synchronous requests abort with a com.sun.star.lang.DisposedException, which is derived from the com.sun.star.uno.RuntimeException. Every call that is initiated on a disposed proxy throws a. After all threads have left the bridge (there may be a synchronous call from the former remote counterpart in the process), the bridge explicitly releases all stubs to the original objects in the local process, which were previously held by the former remote counterpart. The bridge then notifies all registered listeners about the disposed state using com.sun.star.lang.XEventListener. The example code for a connection-aware client below shows how to use this mechanism. The bridge itself is destroyed, after the last proxy has been released.

Unfortunately, the various listed error conditions are not distinguishable.

Example: A Connection Aware Client
The following example shows an advanced client which can be informed about the status of the remote bridge. A complete example for a simple client is given in First Steps.

The following Java example opens a small awt window containing the buttons new writer and new calc that opens a new document and a status label. It connects to a running office when a button is clicked for the first time. Therefore it uses the connector/bridge factory combination, and registers itself as an event listener at the interprocess bridge.

When the office is terminated, the disposing event is terminated, and the Java program sets the text in the status label to 'disconnected' and clears the office desktop reference. The next time a button is pressed, the program knows that it has to re-establish the connection.

The method  retrieves the   reference on demand:

This is the button event handler:

And the disposing handler clears the  reference:

Service Manager and Component Context
This chapter discusses the root object for connections to LibreOffice (and to any UNO application) – the service manager. The root object serves as the entry point for every UNO application and is passed to every UNO component during instantiation.

Two different concepts to get the root object currently exist. StarOffice 6.0 and OpenOffice.org 1.0 use the previous concept. Newer versions or product patches use the newer concept and provide the previous concept for compatibility issues only. First we will look at the previous concept, the service manager as it is used in the main parts of the underlying LibreOffice implementation of this guide. Second, we will introduce the component context — which is the newer concept and explain the migration path.

Service Manager
The com.sun.star.lang.ServiceManager is the main factory in every UNO application. It instantiates services by their service name, to enumerate all implementations of a certain service, and to add or remove factories for a certain service at runtime. The service manager is passed to every UNO component during instantiation.

XMultiServiceFactory Interface
The main interface of the service manager is the com.sun.star.lang.XMultiServiceFactory interface. It offers three methods:,   and.


 * returns a default constructed service instance. The returned service is guaranteed to support at least all interfaces, which were specified for the requested servicename. The returned  reference can now be queried for the interfaces specified at the service description.


 * When using the service name, the caller does not have any influence on which concrete implementation is instantiated. If multiple implementations for a service exist, the service manager is free to decide which one to employ. This in general does not make a difference to the caller because every implementation does fulfill the service contract. Performance or other details may make a difference. So it is also possible to pass the implementation name instead of the service name, but it is not advised to do so as the implementation name may change.


 * In case the service manager does not provide an implementation for a request, a null reference is returned, so it is mandatory to check. Every UNO exception may be thrown during instantiation. Some may be described in the specification of the service that is to be instantiated, for instance, because of a misconfiguration of the concrete implementation. Another reason may be the lack of a certain bridge, for instance the Java-C++ bridge, in case a Java component shall be instantiated from C++ code.


 * instantiates the service with additional parameters. A service signals that it expects parameters during instantiation by supporting the com.sun.star.lang.XInitialization interface. The service definition should describe the meaning of each element of the sequence. There maybe services which can only be instantiated with parameters.


 * returns every servicename the service manager does support.

XContentEnumerationAccess Interface
The com.sun.star.container.XContentEnumerationAccess interface allows the creation of an enumeration of all implementations of a concrete servicename.

The  method returns a com.sun.star.container.XEnumeration interface. Note that it may return an empty reference in case the enumeration is empty.

In the above case, the returned any of the method  contains a com.sun.star.lang.XSingleServiceFactory interface for each implementation of this specific service. You can, for instance, iterate over all implementations of a certain service and check each one for additional implemented services. The  interface provides such a method. With this method, you can instantiate a feature rich implementation of a service.

XSet Interface
The com.sun.star.container.XSet interface allows the insertion or removal of com.sun.star.lang.XSingleServiceFactory or com.sun.star.lang.XSingleComponentFactory implementations to the service manager at runtime without making the changes permanent. When the office application terminates, all the changes are lost. The object must also support the com.sun.star.lang.XServiceInfo interface that provides information about the implementation name and supported services of the component implementation.

This feature may be of particular interest during the development phase. For instance, you can connect to a running office, insert a new factory into the service manager and directly instantiate the new service without having it registered before.

The chapter Special Service Manager Configurations shows an example that demonstrates how a factory is inserted into the service manager.

Component Context
The service manager was described above as the main factory that is passed to every new instantiated component. Often a component needs more functionality or information that must be exchangeable after deployment of an application. In this context, the service manager approach is limited.

Therefore, the concept of the component context was created. In future, it will be the central object in every UNO application. It is basically a read-only container offering named values. One of the named values is the service manager. The component context is passed to a component during its instantiation. This can be understood as an environment where components live (the relationship is similar to shell environment variables and an executable program).



ComponentContext API
The component context only supports the com.sun.star.uno.XComponentContext interface.

The  method returns a named value. The  is a convenient way to retrieve the value named. It returns the  singleton, because most components need to access the service manager. The component context offers at least three kinds of named values:

Singletons (/singletons/...)
 * The singleton concept was introduced in Professional UNO - API Concepts - Data Types. In OpenOffice.org 1.0.2 there is only the   singleton. From OpenOffice 1.x a singleton   has been added, which can be used to expand macros in configuration files. Other possible singletons can be found in the IDL reference.

Implementation properties (not yet defined)
 * These properties customize a certain implementation and are specified in the module description of each component. A module description is an xml-based description of a module (DLL or jar file) which contains the formal description of one or more components.

Service properties (not yet defined)
 * These properties can customize a certain service independent of the implementation and are specified in the IDL specification of a service. Note that service context properties are different from service properties. Service context properties are not subject to change and are the same for every instance of the service that shares the same component context. Service properties are different for each instance and can be changed at runtime through the  interface.

Note, that in the scheme above, the  has a reference to the service manager, but not conversely.

Besides the interfaces discussed above, the  supports the com.sun.star.lang.XMultiComponentFactory interface.

It replaces the  interface. It has an additional  parameter for the two object creation methods. This parameter enables the caller to define the component context that the new instance of the component receives. Most components use their initial component context to instantiate new components. This allows for context propagation.



The illustration above shows the context propagation. A user might want a special component to get a customized context. Therefore, the user creates a new context by simply wrapping an existing one. The user overrides the desired values and delegates the properties that he is not interested into the original C1 context. The user defines which context Instance A and B receive. Instance A and B propagate their context to every new object that they create. Thus, the user has established two instance trees, the first tree completely uses the context Ctx C1, while the second tree uses Ctx C2.

Availability
The final API for the component context is available in StarOffice 6.0 and OpenOffice 1.0. Use this API instead of the API explained in the service manager section. Currently the component context does not have a persistent storage, so named values can not be added to the context of a deployed LibreOffice. Presently, there is no additional benefit from the new API until there is a future release.

Compatibility Issues and Migration Path


As discussed previously, both concepts are currently used within the office. The ServiceManager supports the interfaces com.sun.star.lang.XMultiServiceFactory and com.sun.star.lang.XMultiComponentFactory. Calls to the  interface are delegated to the   interface. The service manager uses its own  reference to fill the missing parameter. The component context of the  can be retrieved through the   interface as 'DefaultContext'.

This solution allows the use of the same service manager instance, regardless if it uses the old or new style API. In the future, the whole LibreOffice code will only use the new API. However, the old API will still remain to ensure compatibility.

Using UNO Interfaces
Every UNO object must inherit from the interface com.sun.star.uno.XInterface. Before using an object, know how to use it and how long it will function. By prescribing  to be the base interface for each and every UNO interface, UNO lays the groundwork for object communication. For historic reasons, the UNOIDL description of XInterface lists the functionality that is associated with  in the C++ (or binary UNO) language binding; other language bindings offer similar functionality by different mechanisms:

The methods  and   handle the lifetime of the UNO object by reference counting. Detailed information about Reference counting is discussed in Lifetime of UNO objects. All current language bindings take care of  and   internally whenever there is a reference to a UNO object.

The  method obtains other interfaces exported by the object. The caller asks the implementation of the object if it supports the interface specified by the type argument. The  parameter must denote a UNO interface type. The call may return with an interface reference of the requested type or with a void. In C++ or Java simply test if the result is not equal null.

Unknowingly, we encountered  when the service manager was asked to create a service instance:

The IDL specification of  shows:

The above code shows that  provides an instance of the given service, but it only returns a com.sun.star.uno.XInterface. This is mapped to java.lang.Object by the Java UNO binding afterwards.

In order to access a service, you need to know which interfaces the service exports. This information is available in the IDL reference. For instance, for the com.sun.star.bridge.UnoUrlResolver service, you learn:

This means the service you ordered at the service manager must support com.sun.star.bridge.XUnoUrlResolver. Next query the returned object for this interface:

The object decides whether or not it returns the interface. You have encountered a bug if the object does not return an interface that is specified to be mandatory in a service. When the interface reference is retrieved, invoke a call on the reference according to the interface specification. You can follow this strategy with every service you instantiate at a service manager, leading to success.

With this method, you may not only get UNO objects through the service manager, but also by normal interface calls:

The returned interface types are specified in the operations, so that calls can be invoked directly on the returned interface. Often, an object implementing multiple interfaces are returned, instead of an object implementing one certain interface.

You can then query the returned object for the other interfaces specified in the given old-style service, here com.sun.star.drawing.Text.

UNO has a number of generic interfaces. For example, the interface com.sun.star.frame.XComponentLoader :

It becomes difficult to find which interfaces are supported beside, because the kind of returned document (text, calc, draw, etc.) depends on the incoming URL.

These dependencies are described in the appropriate chapters of this manual.

Tools such as the  component is a quick method to find out which interfaces a certain object supports. The  component comes with the LibreOffice SDK that allows the inspection of a certain objects at runtime. Do not rely on implementation details of certain objects. If an object supports more interfaces than specified in the service description, query the interface and perform calls. The code may only work for this distinct office version and not work with an update of the office!

There are certain specifications a  implementation must not violate:


 * If  on a specific object returned a valid interface reference for a given type, it must return a valid reference for any successive   calls on this object for the same type.
 * If  on a specific object returned a null reference for a given type, it must always return a null reference for the same type.
 * If  on reference A returns reference B,   on B for Type A must return interface reference A or calls made on the returned reference must be equivalent to calls made on reference A.
 * If  on a reference A returns reference B,   on A and B for XInterface must return the same interface reference (object identity).

These specifications must not be violated because a UNO runtime environment may choose to cache  calls. The rules are basically identical to the rules of QueryInterface in MS COM.

Properties
Properties are name-value pairs belonging to a service and determine the characteristics of an object in a service instance. Usually, properties are used for non-structural attributes, such as font, size or color of objects, whereas get and set methods are used for structural attributes like a parent or sub-object.

In almost all cases, com.sun.star.beans.XPropertySet is used to access properties by name. Other interfaces, for example, are com.sun.star.beans.XPropertyAccess which is used to set and retrieve all properties at once or com.sun.star.beans.XMultiPropertySet which is used to access several specified properties at once. This is useful on remote connections. Additionally, there are interfaces to access properties by numeric ID, such as com.sun.star.beans.XFastPropertySet.

Example: query and change the properties
The following example demonstrates how to query and change the properties of a given text document cursor using its XPropertySet interface:

A possible output of this code could be:

before: CharWeight=100.0 after: CharWeight=150.0

Example: dealing with multiple properties at once
The following example deals with multiple properties at once:

Properties can be assigned flags to determine a specific behavior of the property, such as read-only, bound, constrained or void. Possible flags are specified in com.sun.star.beans.PropertyAttribute. Read-only properties cannot be set. Bound properties broadcast changes of their value to registered listeners and constrained properties veto changes to these listeners.

Properties might have a status specifying where the value comes from. See com.sun.star.beans.XPropertyState. The value determines if the value comes from the object, a style sheet or if it cannot be determined at all. For example, in a multi-selection with multiple values within this selection.

Example: obtain status information of property values
The following example shows how to find out status information about property values:

The property state of character weight is queried for a string like this:

first second

And the output is:

CharWeight property is NULL CharWeight property state has an ambiguous value

The description of properties available for a certain object is given by com.sun.star.beans.XPropertySetInfo. Multiple objects can share the same property information for their description. This makes it easier for introspective caches that are used in scripting languages where the properties are accessed directly, without directly calling the methods of the interfaces mentioned above.

Example: find out which properties an object provides
This example shows how to find out which properties an object provides using com.sun.star.beans.XPropertySetInfo :

The following is an example output for the code above. The output shows the names of the text cursor properties, and their handle, type and property attributes. The handle is not unique, since the specific object does not implement com.sun.star.beans.XFastPropertySet, so proper handles are not needed here.

Using default connect string: socket,host=localhost,port=8100 Opening an empty Writer document Property #0: Name Handle<93> Type Attributes Property #1: Name<BottomBorder> Handle<93> Type<com.sun.star.table.BorderLine> Attributes<MAYBEVOID|0> Property #2: Name<BottomBorderDistance> Handle<93> Type Attributes<MAYBEVOID|0> Property #3: Name<BreakType> Handle<81> Type<com.sun.star.style.BreakType> Attributes<MAYBEVOID|0>

...

Property #133: Name<TopBorderDistance> Handle<93> Type Attributes<MAYBEVOID|0> Property #134: Name<UnvisitedCharStyleName> Handle<38> =Type Attributes<MAYBEVOID|0> Property #135: Name<VisitedCharStyleName> Handle<38> Type Attributes<MAYBEVOID|0>

In some cases properties are used to specify the options in a sequence of com.sun.star.beans.PropertyValue. See com.sun.star.view.PrintOptions or com.sun.star.document.MediaDescriptor for examples of properties in sequences. These are not accessed by the methods mentioned above, but by accessing the sequence specified in the language binding.

Example: sequences of property values
This example illustrates how to deal with sequences of property values:

Usually the properties supported by an object, as well as their type and flags are fixed over the lifetime of the object. There may be exceptions. If the properties can be added and removed externally, the interface com.sun.star.beans.XPropertyContainer has to be used. In this case, the fixed com.sun.star.beans.XPropertySetInfo changes its supplied information over the lifetime of the object. Listeners for such changes can register at com.sun.star.beans.XPropertyChangeListener.

The following diagram shows the relationship between the property-related interfaces.



Interface attributes
Starting with OpenOffice.org 2.x interface attributes are comparable in expressiveness to the properties described above:


 * A  (with type   and name  ) corresponds to an.
 * A  corresponds to an.
 * A  corresponds to an.
 * A  corresponds to an.
 * A  corresponds to an.
 * A  corresponds to an.
 * A  corresponds to an.
 * A  corresponds to an.

Interface attributes offer the following advantages compared to properties:


 * The attributes an object supports follows directly from the description of the interface types the object supports.
 * Accessing an interface attribute is type-safe, whereas accessing a property uses the generic any. This is an advantage mainly in statically typed languages like Java and C++, where accessing an interface attribute typically also requires less code to be written than for accessing a generic property.

The main disadvantage is that the set of interface attributes supported by an object is static, so that scenarios that exploit the dynamic nature of, and so on, do not map well to interface attributes. In cases where it might be useful to have all the interface attributes supported by an object also accessible via  etc., the Java and C++ language bindings offer experimental, not yet published support to do just that. See www.openoffice.org to find out more.

Collections and Containers
Collections and containers are concepts for objects that contain multiple sub-objects where the number of sub-objects is usually not predetermined. While the term collection is used when the sub-objects are implicitly determined by the collection itself, the term container is used when it is possible to add new sub-objects and remove existing sub-objects explicitly. Thus, containers add methods like  and   to the collection interfaces.



In general, the LibreOffice API collection and container interfaces contain any type that can be represented by the UNO type any. However, many container instances can be bound to a specific type or subtypes of this type. This is a runtime and specification agreement, and cannot be checked at runtime.

The base interface for collections is com.sun.star.container.XElementAccess that determines the types of the sub-object, if they are determined by the collection, and the number of contained sub-objects. Based on, there are three main types of collection interfaces:


 * com.sun.star.container.XIndexAccess Offers direct access to the sub-objects by a subsequent numeric index beginning with 0.
 * com.sun.star.container.XNameAccess Offers direct access to the sub-objects by a unique name for each sub object.
 * com.sun.star.container.XEnumerationAccess Creates uni-directional iterators that enumerate all sub-objects in an undefined order.

com.sun.star.container.XIndexAccess is extended by com.sun.star.container.XIndexReplace to replace existing sub-objects by index, and com.sun.star.container.XIndexContainer to insert and remove sub-objects. You can find the same similarity for com.sun.star.container.XNameAccess and other specific collection types.

All containers support com.sun.star.container.XContainer that has interfaces to register com.sun.star.container.XContainerListener interfaces. This way it is possible for an application to learn about insertion and removal of sub-objects in and from the container.

Refer to the module com.sun.star.container in the API reference for details about collection and container interfaces.

The following examples demonstrate the usage of the three main collection interfaces. First, we iterate through an indexed collection. The index always starts with 0 and is continuous:

Our next example iterates through a collection with named objects. The element names are unique within the collection and case-sensitive.

The next example shows how we iterate through a collection using an enumerator. The order of the enumeration is undefined. It is only defined that all elements are enumerated. The behavior is undefined, if the collection is modified after creation of the enumerator.

For an example showing the use of containers, see Styles where a new style is added into the style family.

Event Model
Events are a well known concept in graphical user interface (GUI) models, although they can be used in many contexts. The purpose of events is to notify an application about changes in the components used by the application. In a GUI environment, for example, an event might be the click on a button. Your application might be registered to this button and thus be able to execute certain code when this button is clicked.

The LibreOffice event model is similar to the JavaBeans event model. Events in LibreOffice are, for example, the creation or activation of a document, as well as the change of the current selection within a view. Applications interested in these events can register handlers (listener interfaces) that are called when the event occurs. Usually these listeners are registered at the object container where the event occurs or to the object itself. These listener interfaces are named.



Event listeners are subclasses of com.sun.star.lang.XEventListener that receives one event by itself, the deletion of the object to which the listener is registered. On this event, the listener has to unregister from the object, otherwise it would keep it alive with its interface reference counter.

Many event listeners can handle several events. If the events are generic, usually a single callback method is used. Otherwise, multiple callback methods are used. These methods are called with at least one argument: com.sun.star.lang.EventObject. This argument specifies the source of the event, therefore, making it possible to register a single event listener to multiple objects and still know where an event is coming from. Advanced listeners might get an extended version of this event descriptor struct.

Exception Handling
UNO uses exceptions as a mechanism to propagate errors from the called method to the caller. This error mechanism is preferred instead of error codes (as in MS COM) to allow a better separation of the error handling code from the code logic. Furthermore, Java, C++ and other high-level programming languages provide an exception handling mechanism, so that this can be mapped easily into these languages.

In IDL, an exception is a structured container for data, comparable to IDL structs. Exceptions cannot be passed as a return value or method argument, because the IDL compiler does not allow this. They can be specified in raise clauses and transported in an any. There are two kinds of exceptions, user-defined exceptions and runtime exceptions.

User-Defined Exceptions
The designer of an interface should declare exceptions for every possible error condition that might occur. Different exceptions can be declared for different conditions to distinguish between different error conditions.

The implementation may throw the specified exceptions and exceptions derived from the specified exceptions. The implementation must not throw unspecified exceptions, that is, the implementation must not throw an exception if no exception is specified. This applies to all exceptions except for RuntimeExceptions, described later.

When a user-defined exception is thrown, the object should be left in the state it was in before the call. If this cannot be guaranteed, then the exception specification must describe the state of the object. Note that this is not recommended.

Every UNO IDL exception must be derived from com.sun.star.uno.Exception, whether directly or indirectly. Its UNO IDL specification looks like this:

The exception has two members:

The following .IDL file snippet shows a method with a proper exception specification and proper documentation.
 * The message should contain a detailed readable description of the error (in English), which is useful for debugging purposes, though it cannot be evaluated at runtime. There is currently no concept of having localized error messages.
 * The Context member should contain the object that initially threw the exception.

Runtime Exceptions
Throwing a runtime exception signals an exceptional state. Runtime exceptions and exceptions derived from runtime exceptions cannot be specified in the raise clause of interface methods in IDL.

These are a few reasons for throwing a runtime exception are:


 * The connection of an underlying interprocess bridge has broken down during the call.
 * An already disposed object is called (see com.sun.star.lang.XComponent and the called object cannot fulfill its specification because of its disposed state.
 * A method parameter was passed in an explicitly forbidden manner. For instance, a null interface reference was passed as a method argument where the specification of the interface explicitly forbids this.

Every UNO call may throw a com.sun.star.uno.RuntimeException, except acquire and release. This is independent of how many calls have been completed successfully. Every caller should ensure that its own object is kept in a consistent state even if a call to another object replied with a runtime exception. The caller should also ensure that no resource leaks occur in these cases. For example, allocated memory, file descriptors, etc.

If a runtime exception occurs, the caller does not know if the call has been completed successfully or not. The com.sun.star.uno.RuntimeException is derived from com.sun.star.uno.Exception. Note, that in the Java UNO binding, the com.sun.star.uno.Exception is derived from java.lang.Exception, while the com.sun.star.uno.RuntimeException is directly derived from java.lang.RuntimeException.

A common misuse of the runtime exception is to reuse it for an exception that was forgotten during interface specification. This should be avoided under all circumstances. Consider, defining a new interface.

An exception should not be misused as a new kind of programming flow mechanism. It should always be possible that during a session of a program, no exception is thrown. If this is not the case, the interface design should be reviewed.

Good Exception Handling
This section provides tips on exception handling strategies. Under certain circumstances, the code snippets we call bad below might make sense, but often they do not.


 * Do not throw exceptions with empty messages

Often, especially in C++ code where you generally do not have a stack trace, the message within the exception is the only method that informs the caller about the reason and origin of the exception. The message is important, especially when the exception comes from a generic interface where all kinds of UNO exceptions can be thrown.

When writing exceptions, put descriptive text into them. To transfer the text to another exception, make sure to copy the text.


 * Do not catch exceptions without handling them

Many people write helper functions to simplify recurring coding tasks. However, often code will be written like the following:

This code is ineffective, because the error is hidden. The caller will never know that an error has occurred. This is fine as long as test programs are written or to try out certain aspects of the API (although even test programs should be written correctly). Exceptions must be addressed because the compiler can not perform correctly. In real applications, handle the exception.

The appropriate solution depends on the appropriate handling of exceptions. The following is the minimum each programmer should do:

The code above dumps the exception and its stack trace, so that a message about the occurrence of the exception is received on stderr. This is acceptable during development phase, but it is insufficient for deployed code. Your customer does not watch the  window.

The level where the error can be handled must be determined. Sometimes, it would be better not to catch the exception locally, but further up the exception chain. The user can then be informed of the error through dialog boxes. Note that you can even specify exceptions on the  function:

As a general rule, if you cannot recover from an exception in a helper function, let the caller determine the outcome. Note that you can even throw exceptions at the  method.

Lifetime of UNO Objects
The UNO component model has a strong impact on the lifetime of UNO objects, in contrast to CORBA, where object lifetime is completely unspecified. UNO uses the same mechanism as Microsoft COM by handling the lifetime of objects by reference counting.

Each UNO runtime environment defines its own specification on lifetime management. While in C++ UNO, each object maintains its own reference count. Java UNO uses the normal Java garbage collector mechanism. The UNO core of each runtime environment needs to ensure that it upholds the semantics of reference counting towards other UNO environments.

The last paragraph of this chapter explains the differences between the lifetime of Java and C++ objects in detail.

acquire and release
Every UNO interface is derived from com.sun.star.uno.XInterface :

UNO objects must maintain an internal reference counter. Calling  on a UNO interface increases the reference count by one. Calling  on UNO interfaces decreases the reference count by one. If the reference count drops to zero, the UNO object may be destroyed. Destruction of an object is sometimes called death of an object or that the object dies. The reference count of an object must always be non-negative.

Once  is called on the UNO object, there is a reference or a hard reference to the object, as opposed to a weak reference. Calling  on the object is often called releasing or clearing the reference.

The UNO object does not export the state of the reference count, that is,  and   do not have return values. Generally, the UNO object should not make any assumptions on the concrete value of the reference count, except for the transition from one to zero.

The invocation of a method is allowed first when  has been called before. For every call to, there must be a corresponding release call, otherwise the object leaks.

The XComponent Interface
A central problem of reference counting systems is cyclic references. Assume Object A keeps a reference on object B and B keeps a direct or indirect reference on object A. Even if all the external references to A and B are released, the objects are not destroyed, which results in a resource leak.



In UNO, the developer must explicitly decide when to the break cyclic references. To support this concept, the interface com.sun.star.lang.XComponent exists. When an  is disposed of, it can inform other objects that have expressed interest to be notified.

Other objects can add themselves as com.sun.star.lang.XEventListener to an. When the  method is called, the object notifies all   through the   method and releases all interface references, thus breaking the cyclic reference.



A disposed object is unable to comply with its specification, so it is necessary to ensure that an object is not disposed of before calling it. UNO uses an owner/userconcept for this purpose. Only the owner of an object is allowed to call dispose and there can only be one owner per object. The owner is always free to dispose of the object. The user of an object knows that the object may be disposed of at anytime. The user adds an event listener to discover when an object is being disposed. When the user is notified, the user releases the interface reference to the object. In this case, the user should not call, because the disposed object releases the reference to the user.

This solves the problem described above. However, there are a few conditions which still have to be met.



If an object is called while it is disposed of, it should behave passively. For instance, if  is called, the call should be ignored. If methods are called while the object is no longer able to comply with its interface specification, it should throw a com.sun.star.lang.DisposedException, derived from com.sun.star.uno.RuntimeException. This is one of the rare situations in which an implementation should throw a. The situation described above can always occur in a multithreaded environment, even if the caller has added an event listener to avoid calling objects which were disposed of by the owner.

The owner/user concept may not always be appropriate, especially when there is more than one possible owner. In these cases, there should be no owner but only users. In a multithreaded scenario,  might be called several times. The implementation of an object should be able to cope with such a situation.

The  implementation should always notify the   listeners that the object is being destroyed, not only when   is called, but when the object is deleted. When the object is deleted, the reference count of the object drops to zero. This may happen when the listeners do not hold a reference on the broadcaster object.

The  does not have to be implemented when there is only one owner and no further users.

Children of the XEventListener Interface
The com.sun.star.lang.XEventListener interface is the base for all listener interfaces. This means that not only, but every listener must implement  , and every broadcaster object that allows any kind of listener to register, must call   on the listeners as soon as it dies. However, not every broadcaster is forced to implement the  interface with the   method, because it may define its own condition when it is disposed.

In a chain of broadcaster objects where every element is a listener of its predecessor and only the root object is an  that is being disposed, all the other chain links must handle the   call coming from their predecessor and call   on their registered listeners.

Weak Objects and References
A strategy to avoid cyclic references is to use weak references. Having a weak reference to an object means that you can reestablish a hard reference to the object again if the object still exists, and there is another hard reference to it.

In the cyclic reference shown in the illustration Cyclic Reference, object B could be specified to hold a hard reference on object A, but object A only keeps a weak reference to B. If object A needs to invoke a method on B, it temporarily tries to make the reference hard. If this succeeds, it invokes the method and releases the hard reference afterwards.

To be able to create a weak reference on an object, the object needs to support it explicitly by exporting the com.sun.star.uno.XWeak interface. The illustration Object C calls dispose on XComponent of Object B, depicts the UNO mechanism for weak references.

When an object is assigned to a weak reference, the weak reference calls  at the original object and adds itself (with the com.sun.star.uno.XReference interface) as reference to the adapter.



When a hard reference is established from the weak reference, it calls the  method at the com.sun.star.uno.XAdapter interface of the adapter object. When the original object is still alive, it gets a reference for it, otherwise a null reference is returned.

The adapter notifies the destruction of the original object to all weak references which breaks the cyclic reference between the adapter and weak reference.

Writing UNO Components describes the helper classes in C++ and Java that implement a Xweak interface and a weak reference.

Differences Between the Lifetime of C++ and Java Objects
The implementation of the reference count specification is different in Java UNO and C++ UNO. In C++ UNO, every object maintains its own reference counter. When you implement a C++ UNO object, instantiate it, acquire it and afterwards release it, the destructor of the object is called immediately. The following example uses the standard helper class  and prints a message when the destructor is called.

The following method creates a new, acquires it and releases it for demonstration purposes. The call to release immediately leads to the destruction of. If the  template is used, you do not need to care about   and.

This piece of code produces the following output:

constructed before release destroyed after release

Java UNO objects behave differently, because they are finalized by the garbage collector at a time of its choosing. com.sun.star.uno.XInterface has no methods in the Java UNO language binding, therefore no methods need to be implemented, although MyUnoObject implements XInterface:

The output of this code depends on the Java VM implementation. The output "finalizer called" is not a usual result. Be aware of the side effects when UNO brings Java and C++ together.

When a UNO C++ object is mapped to Java, a Java proxy object is created that keeps a hard UNO reference to the C++ object. The UNO core takes care of this. The Java proxy only clears the reference when it enters the  method, thus the destruction of the C++ object is delayed until the Java VM collects some garbage.

When a UNO Java object is mapped to C++, a C++ proxy object is created that keeps a hard UNO reference to the Java object. Internally, the Java UNO bridge keeps a Java reference to the original Java object. When the C++ proxy is no longer used, it is destroyed immediately. The Java UNO bridge is notified and immediately frees the Java reference to the original Java object. When the Java object is finalized depends on the garbage collector.

When a Java program is connected to a running LibreOffice, the UNO objects in the office process are not destroyed until the garbage collector finalizes the Java proxies or until the interprocess connection is closed (see UNO Interprocess Connections).

Object Identity
UNO guarantees if two object references are identical, that a check is performed and it always leads to a correct result, whether it be true or false. This is different from CORBA, where a return of false does not necessarily mean that the objects are different.

Every UNO runtime environment defines how this check should be performed. In Java UNO, there is a static  function at the   class. In C++, the check is performed with the  function that queries both references for   and compares the resulting   pointers.

This has a direct effect in the API design. For instance, look at com.sun.star.lang.XComponent :

The method  that takes a listener reference, is logical if the implementation can check for object identity, otherwise it could not identify the listener that has to be removed. CORBA interfaces are not designed in this manner. They need an object ID, because object identity is not guaranteed.

UNO Language Bindings
This chapter documents the mapping of UNO to various programming languages or component models. This language binding is sometimes called a UNO Runtime Environment (URE). Each URE needs to fulfill the specifications given in the earlier chapters. The use of UNO services and interfaces are also explained in this chapter. Refer to Writing UNO Components for information about the implementation of UNO objects.

Each section provides detail information for the following topics:


 * Mapping of all UNO types to the programming language types.
 * Mapping of the UNO exception handling to the programming language.
 * Mapping of the fundamental object features (querying interfaces, object lifetime, object identity).
 * Bootstrapping of a service manager.Other programming language specific material (like core libraries in C++ UNO).

Java, C++, LibreOffice Basic, and all languages supporting MS OLE automation or the Common Language Infrastructure (CLI) on the win32 platform are currently supported. In the future, the number of supported language bindings may be extended.

Java Language Binding
The Java language binding gives developers the choice of using Java or UNO components for client programs. A Java program can access components written in other languages and built with a different compiler, as well as remote objects, because of the seamless interaction of UNO bridges.

Java delivers a rich set of classes that can be used within client programs or component implementations. However, when it comes to interaction with other UNO objects, use UNO interfaces, because only those are known to the bridge and can be mapped into other environments.

To control the office from a client program, the client needs a Java 1.3 (or later) installation, a free socket port, and the following jar files juh.jar, jurt.jar, ridl.jar, and unoil.jar. A Java installation on the server-side is not necessary. A step-by-step description is given in the chapter First Steps

When using Java components, the office is installed with Java support. Also make sure that Java is enabled: there is a switch that can be set to achieve this in the Tools - Options - OpenOffice - Security dialog. All necessary jar files should have been installed during the LibreOffice setup. A detailed explanation can be found in the chapter Storing the Service Manager for Further Use.

The Java UNO Runtime is documented in the Java UNO Reference which can be found in the LibreOffice Software development Kit (SDK) or on www.openoffice.org/api/.

Getting a Service Manager
Office objects that provide the desired functionality are required when writing a client application that accesses the office. The root of all these objects is the service manager component, therefore clients need to instantiate it. Service manager runs in the office process, therefore office must be running first when you use Java components that are instantiated by the office. In a client-server scenario, the office has to be launched directly. The interprocess communication uses a remote protocol that can be provided as a command-line argument to the office:

The client obtains a reference to the global service manager of the office (the server) using a local com.sun.star.bridge.UnoUrlResolver. The global service manager of the office is used to get objects from the other side of the bridge. In this case, an instance of the com.sun.star.frame.Desktop is acquired:

As the example shows, a local component context is created through the  class (a Java UNO runtime class). Its implementation provides a service manager that is limited in the number of services it can create. The names of these services are:


 * com.sun.star.lang.ServiceManager
 * com.sun.star.lang.MultiServiceFactory
 * com.sun.star.loader.Java
 * com.sun.star.loader.Java2
 * com.sun.star.bridge.UnoUrlResolver
 * com.sun.star.bridge.BridgeFactory
 * com.sun.star.connection.Connector
 * com.sun.star.connection.Acceptor

They are sufficient to establish a remote connection and obtain the fully featured service manager provided by the office.

Transparent Use of Office UNO Components
If some client code wants to use office UNO components, then a typical use case is that the client code first looks for an existing office installation. If an installation is found, the client checks 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 bootstrap method
Therefore, the remote office component context is provided in a more transparent way by the  method, which bootstraps the component context from a UNO installation. A simple client application may then look like:

The  method first bootstraps a local component context and then tries to establish a named pipe connection to a running office. If no office is running, an office process is started. If the connection succeeds, the remote component context is returned.

SDK tooling
For convenience, the LibreOffice Software Development Kit (SDK) provides some tooling for writing Java client applications.

One of the requirements for a Java client application is that Java finds the  class and all the UNO types (for example, UNO interfaces) and other Java UNO language binding classes (for example,  ) 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, for example, if a deployed component adds new UNO types. The SDK tooling therefore provides a more dynamic approach, namely a customized class loader. The customized class loader has an extended search path, which also includes the path to a UNO installation. The UNO installation is auto-detected on the system by using a 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 recognizes the location of a UNO installation and loads every class from a jar or class file that belongs to the office installation. That means that the customized class loader must be instantiated and initialized before the first class that uses UNO is loaded.

The SDK tooling allows to build a client jar file, which can be invoked by the following:

The client jar file contains the following files:

META-INF/MANIFEST.MF com/sun/star/lib/loader/InstallationFinder$StreamGobbler.class com/sun/star/lib/loader/InstallationFinder.class com/sun/star/lib/loader/Loader$CustomURLClassLoader.class com/sun/star/lib/loader/Loader.class com/sun/star/lib/loader/WinRegKey.class com/sun/star/lib/loader/WinRegKeyException.class win/unowinreg.dll SimpleBootstrap_java.class

A client application created by using the SDK tooling will automatically load the class, 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: SimpleBootstrap_java

The implementation of  reads this entry and calls 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 of writing 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. The system property can be passed to the client application by using the -D flag, e.g

In addition, it is possible to specify a UNO installation by setting the environment variable  to the program directory of a UNO installation, for example,

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

On the Windows platform, the UNO installation is found by reading the default value of the key ' ' 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  is part of the application jar file or can be found in the. 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  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 OpenOffice.org 2.x 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  file which points to a UNO installation. Note that there won't be a  file with OpenOffice.org 2.x anymore.

Handling Interfaces
The service manager is created in the server process and the Java UNO remote bridge ensures that its  is transported back to the client. A Java proxy object is constructed that can be used by the client code. This object is called the initial object, because it is the first object created by the bridge. When another object is obtained through this object, then the bridge creates a new proxy. For instance, if a function is called that returns an interface. That is, the original object is actually running in the server process (the office) and calls to the proxy are forwarded by the bridge. Not only interfaces are converted, but function arguments, return values and exceptions.

The Java bridge maps objects on a per-interface basis, that is, in the first step only the interface is converted that is returned by a function described in the API reference. For example, if you have the service manager and use it to create another component, you initially get a com.sun.star.uno.XInterface :

You know from the service description that Factory implements a com.sun.star.lang.XMultiServiceFactory interface. However, you cannot cast the object or call the interface function on the object, since the object is only a proxy for just one interface,. Therefore, you have to use a mechanism that is provided with the Java bridge that generates proxy objects on demand. For example:

If  is a proxy, then   hands out another proxy for   provided that the original object implements it.

Interface proxies can be used as arguments in function calls on other proxy objects. For example:

In the server process, the obj object would receive the original ret object as a function argument.

It is also possible to have Java components on the client side. As well, they can be used as function arguments, then the bridge would set up proxies for them in the server process.

Not all language concepts of UNO have a corresponding language element in Java. For example, there are no structs and all-purpose out parameters. Refer to Type Mappings for how those concepts are mapped.

Interface handling normally involves the ability of com.sun.star.uno.XInterface to acquire and release objects by reference counting. In Java, the programmer does not bother with  and , since the Java UNO runtime automatically acquires objects on the server side when   is used. Conversely, when the Java garbage collector deletes your references, the Java UNO runtime releases the corresponding office objects. If a UNO object is written in Java, no reference counting is used to control its lifetime. The garbage collector takes that responsibility.

Sometimes it is necessary to find out if two interfaces belong to the same object. In Java, you would compare the references with the equality operator '=='. This works as long as the interfaces refer to a local Java object. Often the interfaces are proxies and the real objects reside in a remote process. There can be several proxies that belong to the same object, because objects are bridged on a per-interface basis. Those proxies are Java objects and comparing their references would not establish them as parts of the same object. To determine if interfaces are part of the same UNO object, use the method  at the   class:

Mapping of Simple Types
The following table shows the mapping of simple UNO types to the corresponding Java types.

The mapping between the values of the corresponding UNO and Java types is obvious, except for a few cases that are explained in the following sections:

Mapping of Unsigned Integer Types
An unsigned UNO integer type encompasses the range from 0 to 2N − 1, inclusive, while the corresponding signed Java integer type encompasses the range from −2N− 1 to 2N− 1 − 1, inclusive (where N is 16, 32, or 64 for unsigned short, unsigned long, or unsigned hyper, respectively). The mapping is done modulo N, that is: 0 is mapped to 0; 2N− 1 − 1 is mapped to 2N− 1 − 1; 2N− 1 is mapped to −2N− 1; and 2N − 1 is mapped to −1.

Users should be careful when using any of the deprecated UNO unsigned integer types. A user is responsible for correctly interpreting values of signed Java integer types as unsigned integer values in such cases.

Mapping of String
The mapping between the UNO string type and java.lang.String is straightforward, except for three details:


 * Only non-null references to  are allowed in the context of UNO.
 * The length of a string that can be represented by a  object is limited. It is an error to use a longer UNO string value in the context of the Java language binding.
 * An object of type  can represent an arbitrary sequence of UTF-16 code units, whereas a value of the UNO string type is an arbitrary sequence of Unicode scalar values. This only matters in so far as some individual UTF-16 code units (namely the individual high- and low-surrogate code points in the range D800–DFFF) have no corresponding Unicode scalar values, and are thus forbidden in the context of UNO. For example, the Java string " " is illegal in this context, while the string " " would be legal. See www.unicode.org for more information on the details of Unicode.

Mapping of Type
The Java class  is used to represent the UNO type; only non-null references to   are valid. (It is a historic mistake that  is not final. You should never derive from it in your code.)

In many places in the Java UNO runtime, there are convenience functions that take values of type  where conceptually a value of   would be expected. For example, there are two overloaded versions of the method, one with a parameter of type   and one with a parameter of type. See the documentation of  for the details of how values of   are interpreted in such a context.

Mapping of Any
There is a dedicated  type, but it is not always used. An any in the API reference is represented by a  in Java UNO. An Object reference can be used to refer to all possible Java objects. This does not work with primitive types, but if you need to use them as an any, there are Java wrapper classes available that allow primitive types to be used as objects. Also, a Java Object always brings along its type information by means of an instance of. Therefore a variable declared as:

can be used with all objects and its type information is available by calling:

Those qualities of  are sufficient to replace the   in most cases. Even Java interfaces generated from IDL interfaces do not contain s, instead   references are used in place of  s. Cases where an explicit   is needed to not lose information contain unsigned integer types, all interface types except the basic , and the void type.

To facilitate the handling of the Any type, use the  class. It is documented in the Java UNO reference. The following list sums up its methods:

The Java  is needed in situations when the type needs to be specified explicitly. Assume there is a C++ component with an interface function which is declared in UNOIDL as:

The corresponding C++ implementation could be:

In the example, the any is checked if it contains the expected interface. If it does, it is assigned accordingly. If the any contained a different interface, a query would be performed for the expected interface. If the function is called from Java, then an interface has to be supplied that is an object. That object could implement several interfaces and the bridge would use the basic. If this is not the interface that is expected, then the C++ implementation has to call  to obtain the desired interface. In a remote scenario, those  calls could lead to a noticeable performance loss. If you use a Java Any as a parameter for, the intended interface is sent across the bridge.

It is a historic mistake that  is not final. You should never derive from it in your code.

Mapping of Sequence Types
A UNO sequence type with a given component type is mapped to the Java array type with corresponding component type.


 * UNO  is mapped to Java.
 * UNO  is mapped to Java.

Only non-null references to those Java array types are valid. As usual, non-null references to other Java array types that are assignment compatible to a given array type can also be used, but doing so can cause. In Java, the maximal length of an array is limited; therefore, it is an error if a UNO sequence that is too long is used in the context of the Java language binding.

Mapping of Enum Types
An UNO enum type is mapped to a public, final Java class with the same name, derived from the class. Only non-null references to the generated final classes are valid.

The base class  declares a protected member to store the actual value, a protected constructor to initialize the value and a public   method to get the actual value. The generated final class has a protected constructor and a public method  that returns an instance with the value of the first enum member as a default. For each member of a UNO enum type, the corresponding Java class declares a public static member of the given Java type that is initialized with the value of the UNO enum member. The Java class for the enum type has an additional public method  that returns the instance with the specified value. The following IDL definition for com.sun.star.uno.TypeClass :

is mapped to:

Mapping of Struct Types
A plain UNO struct type is mapped to a public Java class with the same name. Only non-null references to such a class are valid. Each member of the UNO struct type is mapped to a public field with the same name and corresponding type. The class provides a default constructor which initializes all members with default values, and a constructor which takes explicit values for all struct members. If a plain struct type inherits from another struct type, the generated class extends the class of the inherited struct type.

is mapped to:

Similar to a plain struct type, a polymorphic UNO struct type template is also mapped to a Java class. The only difference is how struct members with parametric types are handled, and this handling in turn differs between Java 1.5 and older versions.

Take, for example, the polymorphic struct type template:

In Java 1.5, a polymorphic struct type template with a list of type parameters is mapped to a generic Java class with a corresponding list of unbounded type parameters. For com.sun.star.beans.Optional, that means that the corresponding Java 1.5 class looks something like the following example:

Instances of such polymorphic struct type templates map to Java 1.5 in a natural way. For example, UNO  maps to Java. However, UNO type arguments that would normally map to primitive Java types map to corresponding Java wrapper types instead:


 * maps to
 * maps to
 * and  map to
 * and  map to
 * and  map to
 * maps to
 * maps to
 * maps to

For example, UNO  maps to Java. Also note that UNO type arguments of both any and com.sun.star.uno.XInterface map to, and thus, for example, both   and   map to Java.

Still, there are a few problems and pitfalls when dealing with parametric members of default-constructed polymorphic struct type instances:


 * One problem is that such members are initialized to  by the default constructor, but   is generally not a legal value in the context of Java UNO, except for values of any or interface type. For example, new   is of type com.sun.star.beans.PropertyValue (a struct type), but is a null reference. Similarly, new   is also a null reference (instead of a reference to , say). The chosen solution is to generally allow null references as values of Java class fields that correspond to parametric members of polymorphic UNO struct types. However, to avoid any problems, it is a good idea to not rely on the default constructor in such situations, and instead initialize any problematic fields explicitly. (Note that this is not really a problem for  , as   will always be false for a default-constructed instance and thus, because of the documented conventions for com.sun.star.beans.Optional , the actual contents of   should be ignored, anyway; in other cases, like with com.sun.star.beans.Ambiguous , this can be a real issue, however.)
 * Another pitfall is that a parametric member of type any of a default-constructed polymorphic struct type instance (think new  in Java 1.5,  ;   in C++) has different values in the Java language binding and the C++ language binding. In Java, it contains a null reference of type   (i.e., the Java value  ), whereas in C++ it contains  . Again, to avoid any problems, it is best not to rely on the default constructor in such situations.

In Java versions prior to 1.5, which do not support generics, a polymorphic struct type template is mapped to a plain Java class in such a way that any parametric members are mapped to class fields of type. This is generally less favorable than using generics, as it reduces type-safety, but it has the advantage that it is compatible with Java 1.5 (actually, a single Java class file is generated for a given UNO struct type template, and that class file works with both Java 1.5 and older versions). In a pre-1.5 Java, the  example will look something like the following:

How  is used to represent values of arbitrary UNO types is detailed as follows:


 * Values of the UNO types,  ,  ,  ,  ,  ,  , and   are represented by non-null references to the corresponding Java types  ,  ,  ,  ,  ,  ,  , and.
 * Values of the UNO types unsigned short, unsigned long, and unsigned hyper are represented by non-null references to the corresponding Java types,  , and  . Whether a value of such a Java type corresponds to a signed or unsigned UNO type must be deducible from context.
 * Values of the UNO types,  ,  , and the UNO sequence, enum, struct, and interface types (which all map to Java reference types) are represented by their standard Java mappings.
 * The UNO type void and UNO exception types cannot be used as type arguments of instantiated polymorphic struct types.

This is similar to how  is used to represent values of the UNO any type. The difference is that there is nothing like  here, which is used to disambiguate those cases where different UNO types map to the same subclass of. Instead, here it must always be deducible from context exactly which UNO type a given Java reference represents.

The problems and pitfalls mentioned for Java 1.5, regarding parametric members of default-constructed polymorphic struct type instances, apply for older Java versions as well.

Mapping of Exception Types
A UNO exception type is mapped to a public Java class with the same name. Only non-null references to such a class are valid.

There are two UNO exceptions that are the base for all other exceptions. These are the com.sun.star.uno.Exception and com.sun.star.uno.RuntimeException that are inherited by all other exceptions. The corresponding exceptions in Java inherit from Java exceptions:

The com.sun.star.uno.Exception in Java:

The com.sun.star.uno.RuntimeException in Java:

As shown, the  member has no direct counterpart in the respective Java class. Instead, the constructor argument Message is used to initialize the base class, which is a Java exception. The message is accessible through the inherited  method. All other members of a UNO exception type are mapped to public fields with the same name and corresponding Java type. A generated Java exception class always has a default constructor that initializes all members with default values, and a constructor which takes values for all members.

If an exception inherits from another exception, the generated class extends the class of the inherited exception.

Mapping of Interface Types
A UNO interface type is mapped to a public Java interface with the same name. Unlike for Java classes that represent UNO sequence, enum, struct, and exception types, a null reference is actually a legal value for a Java interface that represents a UNO interface type - the Java null reference represents the UNO null reference.

If a UNO interface type inherits one ore more other interface types, the Java interface extends the corresponding Java interfaces.

The UNO interface type com.sun.star.uno.XInterface is special: Only when that type is used as a base type of another interface type is it mapped to the Java type. In all other cases (when used as the component type of a sequence type, as a member of a struct or exception type, or as a parameter or return type of an interface method) it is mapped to. Nevertheless, valid Java values of that type are only the Java null reference and references to those instances of  that implement.

A UNO interface attribute of the form

[attribute] Type Name { get raises (ExceptionG1, ..., ExceptionGM); set raises (ExceptionS1, ..., ExceptionSM); };

is represented by two Java interface methods

Type getName throws ExceptionG1, ..., ExceptionGM; void setName(Type value) throws ExceptionS1, ..., ExceptionSM;

If the attribute is marked, then there is no set method. Whether or not the attribute is marked bound has no impact on the signatures of the generated Java methods.

A UNO interface method of the form

Type0 name([in] Type1 arg1, [out] Type2 arg2, [inout] Type3 arg3) raises (Exception1, ..., ExceptionN);

is represented by a Java interface method

Type0 name(Type1 arg1, Type2[] arg2, Type3[] arg3) throws Exception1, ..., ExceptionN;

Whether or not the UNO method is marked  has no impact on the signature of the generated Java method. As can be seen,  and   parameters are handled specially. To help explain this, take the example UNOIDL definitions

The semantics of a UNO method call are such that the values of any  or   parameters are passed from the caller to the callee, and, if the method is not marked   and the execution terminated successfully, the callee passes back to the caller the return value and the values of any   or   parameters. Thus, the handling of  parameters and the return value maps naturally to the semantics of Java method calls. UNO  and   parameters, however, are mapped to arrays of the corresponding Java types. Each such array must have at least one element (i.e., its length must be at least one; practically, there is no reason why it should ever be larger). Therefore, the Java interface corresponding to the UNO interface XFoo looks like the following:

This is how  would be mapped to Java:

When providing a value as an  parameter, the caller has to write the input value into the element at index zero of the array. When the function returns successfully, the value at index zero reflects the output value, which may be the unmodified input value, a modified copy of the input value, or a completely new value. The object  implements  :

When a method receives an argument that is an out parameter, upon successful return, it has to provide a value by storing it at index null of the array.

Mapping of UNOIDL Typedefs
UNOIDL typedefs are not visible in the Java language binding. Each occurrence of a typedef is replaced with the aliased type when mapping from UNOIDL to Java.

Mapping of Individual UNOIDL Constants
An individual UNOIDL constant

is mapped to a public Java interface with the same name:

Note that the use of individual constants is deprecated.

Mapping of UNOIDL Constant Groups
A UNOIDL constant group

is mapped to a public Java interface with the same name:

Each constant defined in the group is mapped to a field of the interface with the same name and corresponding type and value.

Mapping of UNOIDL Modules
A UNOIDL module is mapped to a Java package with the same name. This follows from the fact that each named UNO and UNOIDL entity is mapped to a Java class with the same name. (UNOIDL uses " " to separate the individual identifiers within a name, as in " ", whereas UNO itself and Java both use " ", as in " "; therefore, the name of a UNOIDL entity has to be converted in the obvious way before it can be used as a name in Java.) UNO and UNOIDL entities not enclosed in any module (that is, whose names do not contain any " " or " ", respectively), are mapped to Java classes in an unnamed package.

Mapping of Services
A new-style services is mapped to a public Java class with the same name. The class has one or more public static methods that correspond to the explicit or implicit constructors of the service.

For a new-style service with a given interface type, an explicit constructor of the form

is represented by the Java method

A UNO rest parameter  is mapped to a Java rest parameter   in Java 1.5, and to   in older versions of Java.

If a new-style service has an implicit constructor, the corresponding Java method is of the form

The semantics of both explicit and implicit service constructors in Java are as follows:


 * The first argument to a service constructor is always a com.sun.star.uno.XComponentContext, which must be non-null. Any further arguments are used to initialize the created service (see below).


 * The service constructor first uses com.sun.star.uno.XComponentContext:getServiceManager to obtain a service manager (a com.sun.star.lang.XMultiComponentFactory ) from the given component context.


 * The service constructor then uses com.sun.star.lang.XMultiComponentFactory:createInstanceWithArgumentsAndContext to create a service instance, passing it the list of arguments (without the initial ). If the service constructor has a single rest parameter, its sequence of any values is used directly, otherwise the given arguments are made into a sequence of any values. In the case of an implicit service constructor, no arguments are passed, and com.sun.star.lang.XMultiComponentFactory:createInstanceWithContext is used instead.


 * If any of the above steps fails with an exception that the service constructor may throw (according to its exception specification), the service constructor also fails by throwing that exception. Otherwise, if any of the above steps fails with an exception that the service constructor may not throw, the service constructor instead fails by throwing a com.sun.star.uno.DeploymentException . Finally, if no service instance could be created (because either the given component context has no service manager, or the service manager does not support the requested service), the service constructor fails by throwing a com.sun.star.uno.DeploymentException . The net effect is that a service constructor either returns a non-null instance of the requested service, or throws an exception; a service constructor will never return a null instance.

Old-style services are not mapped into the Java language binding.

Mapping of Singletons
A new-style singleton of the form

is mapped to a public Java class with the same name. The class has a single method

The semantics of such a singleton getter method in Java are as follows:


 * The com.sun.star.uno.XComponentContext argument must be non-null.


 * The singleton getter uses com.sun.star.uno.XComponentContext:getValueByName to obtain the singleton instance (within the " " name space).


 * If no singleton instance could be obtained, the singleton getter fails by throwing a com.sun.star.uno.DeploymentException . The net effect is that a singleton getter either returns the requested non-null singleton instance, or throws an exception; a singleton getter will never return a null instance.

Old-style singletons are not mapped into the Java language binding.

Inexact approximation of UNO Value Semantics
Some UNO types that are generally considered to be value types are mapped to reference types in Java. Namely, these are the UNO types string, type, any, and the UNO sequence, enum, struct, and exception types. The problem is that when a value of such a type (a Java object) is used:


 * As the value stored in an any
 * As the value of a sequence component
 * As the value of a struct or exception member
 * As the value of an interface attribute
 * As an argument or return value in an interface method invocation
 * As an argument in a service constructor invocation
 * As a raised exception

then Java does not create a clone of that object, but instead shares the object via multiple references to it. If the object is now modified through any one of its references, all other references observe the modification, too. This violates the intended value semantics.

The solution chosen in the Java language binding is to forbid modification of any Java objects that are used to represent UNO values in any of the situations listed above. Note that for Java objects that represent values of the UNO type string, or a UNO enum type, this is trivially warranted, as the corresponding Java types are immutable. This would also hold for the UNO type type, if the Java class  were final.

In the sense used here, modifying a Java object A includes modifying any other Java object B that is both (1) reachable from A by following one or more references, and (2) used to represent a UNO value in any of the situations listed above. For a Java object that represents a UNO any value, the restriction to not modify it only applies to a wrapping object of type  (which should really be immutable), or to an unwrapped object that represents a UNO value of type   or type, or of a sequence, enum, struct or exception type.

Note that the types,  ,  ,  ,  ,  ,  , and  , used to represent certain UNO values as any values or as parametric members of instantiated polymorphic struct types, are immutable, anyway, and so need not be considered specially here.

C++ Language Binding
This chapter describes the UNO C++ language binding. It provides an experienced C++ programmer the first steps in UNO to establish UNO interprocess connections to a remote LibreOffice and to use its UNO objects.

Library Overview
The illustration below gives an overview about the core libraries of the UNO component model.



These shared libraries can be found in the  /program folder of your LibreOffice installation. The label (C) in the illustration above means C linkage and (C++) means C++ linkage. For all libraries, a C++ compiler to build is required.

The basis for all UNO libraries is the sal library. It contains the system abstraction layer (sal) and additional runtime library functionality, but does not contain any UNO-specific information. The commonly used C-functions of the sal library can be accessed through C++ inline wrapper classes. This allows functions to be called from any other programming language, because most programming languages have some mechanism to call a C function.

The salhelper library is a small C++ library which offers additional runtime library functionality, that could not be implemented inline.

The cppu (C++UNO) library is the core UNO library. It offers methods to access the UNO type library, and allows the creation, copying and comparing values of UNO data types in a generic manner. Moreover, all UNO bridges (= mappings + environments) are administered in this library.

The examples msci_uno.dll, libsunpro5_uno.so and libgcc2_uno.so are only examples for language binding libraries for certain C++ compilers.

The cppuhelper library is a C++ library that contains important base classes for UNO objects and functions to bootstrap the UNO core. C++ Components and UNO programs have to link the cppuhelper library.

All the libraries shown above will be kept compatible in all future releases of UNO. You will be able to build and link your application and component once, and run it with the current and later versions of LibreOffice.

System Abstraction Layer
C++ UNO client programs and C++ UNO components use the system abstraction layer (sal) for types, files, threads, interprocess communication, and string handling. The sal library offers operating system dependent functionality as C functions. The aim is to minimize or to eliminate operating system dependent  in libraries above sal. Sal offers high performance access because sal is a thin layer above the API offered by each operating system.

Sal exports only C symbols. The inline C++ wrapper exists for convenience. Refer to the UNO C++ reference that is part of the LibreOffice SDK or in the References section of udk.openoffice.org to gain a full overview of the features provided by the sal library. In the following sections, the C++ wrapper classes will be discussed. The sal types used for UNO types are discussed in section Type Mappings. If you want to use them, look up the names of the appropriate include files in the C++ reference.

File Access
The classes listed below manage platform independent file access. They are C++ classes that call corresponding C functions internally.


 * osl::FileBase
 * osl::VolumeInfo
 * osl::FileStatus
 * osl::File
 * osl::DirectoryItem
 * osl::Directory

An unfamiliar concept is the use of absolute filenames throughout the whole API. In a multithreaded program, the current working directory cannot be relied on, thus relative paths must be explicitly made absolute by the caller.

Threadsafe Reference Counting
The functions  and   in the global C++ namespace increase and decrease a 4-byte counter in a threadsafe manner. This is needed for reference counted objects. Many UNO APIs control object lifetime through refcounting. Since concurrent incrementing the same counter does not increase the reference count reliably, these functions should be used. This is faster than using a mutex on most platforms.

Threads and Thread Synchronization
The class osl::Thread is meant to be used as a base class for your own threads. Overwrite the  method.

The following classes are commonly used synchronization primitives:


 * osl::Mutex
 * osl::Condition
 * osl::Semaphore

Socket and Pipe
The following classes allow you to use interprocess communication in a platform independent manner:


 * osl::Socket
 * osl::Pipe

Strings
The classes rtl::OString (8-bit, encoded) and rtl::OUString (16-bit, UTF-16) are the base-string classes for UNO programs. The strings store their data in a heap memory block. The string is refcounted and incapable of changing, thus it makes copying faster and creation is an expensive operation. An OUString can be created using the static function  or it can be constructed from an 8-bit string with encoding using this constructor:

It can be converted into an 8-bit string, for example, for  using the   function that takes an encoding, such as RTL_TEXTENCODING_ASCII_US.

For fast string concatenation, the classes rtl::OStringBuffer and rtl::OUStringBuffer should be used, because they offer methods to concatenate strings and numbers. After preparing a new string buffer, use the  method to create the new   or. The following example illustrates this:

Establishing Interprocess Connections
Any language binding supported by UNO establishes interprocess connections using a local service manager to create the services necessary to connect to the office. Refer to chapter UNO Interprocess Connections for additional information. The following client program connects to a running office and retrieves the com.sun.star.lang.XMultiServiceFactory in C++:

Transparent Use of Office UNO Components
When writing C++ client applications, the office component context can be obtained in a more transparent way. For more details see section Transparent Use of Office UNO Components (Java).

The bootstrap function
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:

The  function is implemented in a similar way as the Java   method. It first bootstraps a local component context by calling the  function and then tries to establish a named pipe connection to a running office by using the   service. If no office is running, an office process is started. If the connection succeeds, the remote component context is returned.

SDK tooling
For convenience the LibreOffice Software Development Kit (SDK) provides some tooling for writing C++ client applications.

Application Loader
A C++ client application that 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  (Windows) or   (Unix/Linux) environment variable.

As this requires the knowledge of the location of a UNO installation, the SDK provides an application loader ( for Windows,   for Unix/Linux), which detects a UNO installation on the system and adds the program directory of the UNO installation to the   /   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  /   environment variable.

The SDK tooling allows to build a client executable file (e.g.  for Unix/Linux), which can be invoked by

In this case, the  executable is simply the renamed   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.

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

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

export UNO_PATH=/opt/libreoffice7.3/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\LibreOffice\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.

Mapping of Simple Types
The following table shows the mapping of simple UNO types to the corresponding C++ types.

For historic reasons, the UNO type  is mapped to some C++ type , which has two distinct values   and  , and which need not be the C++   type. The mapping between the values of UNO boolean and  and   is straightforward, but it is an error to use any potential value of   that is distinct from both   and.

The UNO integer types are mapped to C++ integer types with ranges that are guaranteed to be at least as large as the ranges of the corresponding UNO types. However, the ranges of the C++ types might be larger, in which case it would be an error to use values outside of the range of the corresponding UNO types within the context of UNO. Currently, it would not be possible to create C++ language bindings for C++ environments that offer no suitable integral types that meet the minimal range guarantees.

The UNO floating point types  and   are mapped to C++ floating point types   and , which must be capable of representing at least all the values of the corresponding UNO types. However, the C++ types might be capable of representing more values, for which it is implementation-defined how they are handled in the context of UNO. Currently, it would not be possible to create C++ language bindings for C++ environments that offer no suitable  and   types.

The UNO char type is mapped to the integral C++ type, which is guaranteed to at least encompass the range from 0 to 65535. Values of UNO char are mapped to values of  in the obvious manner. If the range of  is larger, it is an error to use values outside of that range.

For the C++ typedef types,  ,  ,  ,  , and  , it is guaranteed that no two of them are synonyms for the same fundamental C++ type. This guarantee does not extend to the three types,  , and  , however.

Mapping of String
The mapping between the UNO  type and   is straightforward, except for two details:


 * The length of a string that can be represented by an  object is limited. It is an error to use a longer UNO   value in the context of the C++ language binding.
 * An object of type  can represent an arbitrary sequence of UTF-16 code units, whereas a value of the UNO   type is an arbitrary sequence of Unicode scalar values. This only matters in so far as some individual UTF-16 code units (namely the individual high- and low-surrogate code points in the range D800-DFFF) have no corresponding Unicode scalar values, and are thus forbidden in the context of UNO. For example, the C++ string

is illegal in this context, while the string

would be legal. See www.unicode.org for more information on the details of Unicode.

Mapping of Type
The UNO type type is mapped to. It holds the name of a type and the com.sun.star.uno.TypeClass. The type allows you to obtain a  that contains all the information defined in the IDL. For a given UNO type, a corresponding  instance can be obtained through the   class template:

Some C++ types that represent UNO types cannot be used as C++ template arguments, or ambiguously represent more than one UNO type, so there are special C++ types,  , and   that can be used as arguments for   in those cases.

The overloaded  function was an older mechanism to obtain   instances. It is deprecated now (certain uses of  in template code would not work as intended), and   should be used instead.

Mapping of Any
The IDL any is mapped to. It holds an instance of an arbitrary UNO type. Only UNO types can be stored within the any, because the data from the type library are required for any handling.

A default constructed Any contains the void type and no value. You can assign a value to the Any using the operator <<= and retrieve a value using the operator >>=.

The extraction operator >>= carries out widening conversions when no loss of data can occur, but data cannot be directed downward. If the extraction was successful, the operator returns, otherwise.

Instead of using the operator for extracting, you can also get a pointer to the data within the. This may be faster, but it is more complicated to use. With the pointer, care has to be used during casting and proper type handling, and the lifetime of the  must exceed the pointer usage.

You can also construct an  from a pointer to a C++ UNO type that can be useful. For instance:

Mapping of Struct Types
A plain UNO struct type is mapped to a C++ struct with the same name. Each member of the UNO struct type is mapped to a public data member with the same name and corresponding type. The C++ struct provides a default constructor which initializes all members with default values, and a constructor which takes explicit values for all members. If a plain struct type inherits from another struct type, the generated C++ struct derives from the C++ struct corresponding to the inherited UNO struct type.

A polymorphic UNO struct type template with a list of type parameters is mapped to a C++ struct template with a corresponding list of type parameters. For example, the C++ template corresponding to com.sun.star.beans.Optional looks something like

As can be seen in the example above, the default constructor uses default initialization to give values to any parametric data members. This has a number of consequences:


 * Some compilers do not implement default initialization correctly for all types. For example, Microsoft Visual C++ .NET 2003 leaves objects of primitive types uninitialized, instead of zero-initializing them. (Which means, for example, that after  the expression   has an undefined value, instead of being zero.)
 * The default value of a UNO enum type is its first member. A (deprecated) feature of UNO enum types is to give specific numeric values to individual members. Now, if a UNO enum type whose first member has a numeric value other than zero is used as the type of a parametric member, default-initializing that member will give it the numeric value zero, even if zero does not correspond to the default member of the UNO enum type (it need not even correspond to any member of the UNO enum type).
 * Another pitfall is that a parametric member of type any of a default-constructed polymorphic struct type instance (think  in C++,   in Java 1.5) has different values in the C++ language binding and the Java language binding. In C++, it contains void, whereas in Java it contains a null reference of type  . To avoid any problems, it is best not to rely on the default constructor in such situations.

On some platforms, the C++ typedef types  (representing the UNO type  ) and   (representing the UNO type  ) are synonyms for the same fundamental C++ type. This could lead to problems when either of those types is used as a type argument of a polymorphic struct type. The chosen solution is to generally forbid the (deprecated) UNO types,  , and   as type arguments of polymorphic struct types.

getCppuType(static_cast< com::sun::star::beans::Optional< sal_Unicode > >(0))

and

getCppuType(static_cast< com::sun::star::beans::Optional< sal_uInt16 > >(0))

cannot return different data for the two different UNO types (as the two function calls are to the same identical function on those platforms). The chosen solution is to generally forbid the (deprecated) UNO types,  , and   as type arguments of polymorphic struct types.

Mapping of Interface Types
A value of a UNO interface type (which is a null reference or a reference to an object implementing the given interface type) is mapped to the template class:

The template is used to get a type safe interface reference, because only a correctly typed interface pointer can be assigned to the reference. The example below assigns an instance of the desktop service to the  reference:

The constructor of  calls   on the interface and the destructor calls   on the interface. These references are often called smart pointers. Always use the  template consistently to avoid reference counting bugs.

The  class makes it simple to invoke   for a certain type:

The  is a dummy parameter that tells the constructor to query the first constructor argument for the   interface. If the  returns successfully, it is assigned to the   reference. You can check if querying was successful by calling  on the new reference.

Methods on interfaces can be invoked using the operator ->:

xSMgr->createInstance(...);

The  returns the interface pointer without acquiring it, that is, without incrementing the refcount.

You can explicitly release the interface reference by calling  at the reference or by assigning a default constructed reference.

You can check if two interface references belong to the same object using the operator.

Mapping of Sequence Types
An IDL sequence is mapped to:

template com::sun::star::uno::Sequence< t >

The sequence class is a reference to a reference counted handle that is allocated on the heap.

The sequence follows a copy-on-modify strategy. If a sequence is about to be modified, it is checked if the reference count of the sequence is 1. If this is the case, it gets modified directly, otherwise a copy of the sequence is created that has a reference count of 1.

A sequence can be created with an arbitrary UNO type as element type, but do not use a non-UNO type. The full reflection data provided by the type library are needed for construction, destruction and comparison.

You can construct a sequence with an initial number of elements. Each element is default constructed.

You can also initialize a sequence from an array of the same type by using a different constructor. The new sequence is allocated on the heap and all elements are copied from the source.

Complex UNO types like structs can be stored within sequences, too:

The size of sequences can be changed using the  method, which takes the new number of elements as a parameter. For instance:

The above code shows an enumeration is transformed into a sequence, using an inefficient method. The  default constructs a new element at the end of the sequence. If the sequence is shrunk by, the elements at the end are destroyed.

The sequence is meant as a transportation container only, therefore it lacks methods for efficient insertion and removal of elements. Use a C++ Standard Template Library vector as an intermediate container to manipulate a list of elements and finally copy the elements into the sequence.

Sequences of a specific type are a fully supported UNO type. There can also be a sequence of sequences. This is similar to a multidimensional array with the exception that each row may vary in length. For instance:

is a valid sequence of.

The maximal length of a  is limited; therefore, it is an error if a UNO sequence that is too long is used in the context of the C++ language binding.

Mapping of Services
A new-style service is mapped to a C++ class with the same name. The class has one or more public static member functions that correspond to the explicit or implicit constructors of the service.

For a new-style service with a given interface type, an explicit constructor of the form

name([in] Type1 arg1, [in] Type2 arg2) raises (Exception1, ..., ExceptionN);

is represented by the C++ member function

If a service constructor has a rest parameter, it is mapped to a parameter of type  in C++.

If a new-style service has an implicit constructor, the corresponding C++ member function is of the form

The semantics of both explicit and implicit service constructors in C++ are as follows. They are the same as for Java:


 * The first argument to a service constructor is always a com.sun.star.uno.XComponentContext, which must be a non-null reference. Any further arguments are used to initialize the created service (see below).
 * The service constructor first uses com.sun.star.uno.XComponentContext:getServiceManager to obtain a service manager (a com.sun.star.lang.XMultiComponentFactory ) from the given component context.
 * The service constructor then uses com.sun.star.lang.XMultiComponentFactory:createInstanceWithArgumentsAndContext to create a service instance, passing it the list of arguments without the initial . If the service constructor has a single rest parameter, its sequence of any values is used directly, otherwise the given arguments are made into a sequence of any values. In the case of an implicit service constructor, no arguments are passed, and com.sun.star.lang.XMultiComponentFactory:createInstanceWithContext is used instead.
 * If any of the above steps fails with an exception that the service constructor may throw (according to its exception specification), the service constructor also fails by throwing that exception. Otherwise, if any of the above steps fails with an exception that the service constructor may not throw, the service constructor instead fails by throwing a com.sun.star.uno.DeploymentException . Finally, if no service instance could be created (because either the given component context has no service manager, or the service manager does not support the requested service), the service constructor fails by throwing a com.sun.star.uno.DeploymentException . The net effect is that a service constructor either returns a non-null instance of the requested service, or throws an exception; a service constructor will never return a null instance.

Old-style services are not mapped into the C++ language binding.

Mapping of Singletons
A new-style singleton of the form

singleton Name: XIfc;

is mapped to a C++ class with the same name. The class has a single member function

The semantics of such a singleton getter function in C++ are as follows (they are the same as for Java):


 * The com.sun.star.uno.XComponentContext argument must be non-null.
 * The singleton getter uses com.sun.star.uno.XComponentContext:getValueByName to obtain the singleton instance (within the " " name space).
 * If no singleton instance could be obtained, the singleton getter fails by throwing a com.sun.star.uno.DeploymentException . The net effect is that a singleton getter either returns the requested non-null singleton instance, or throws an exception; a singleton getter will never return a null instance.

Old-style services are not mapped into the C++ language binding.

Using Weak References
The C++ binding offers a method to hold UNO objects weakly, that is, not holding a hard reference to it. A hard reference prevents an object from being destroyed, whereas an object that is held weakly can be deleted anytime. The advantage of weak references is used to avoid cyclic references between objects.

An object must actively support weak references by supporting the com.sun.star.uno.XWeak interface. The concept is explained in detail in chapter Lifetime of UNO objects.

Weak references are often used for caching. For instance, if you want to reuse an existing object, but do not want to hold it forever to avoid cyclic references.

Weak references are implemented as a template class:

You can simply assign weak references to hard references and conversely. The following examples stress this:

A call on a weak reference can not be invoked directly. Make the weak reference hard and check whether it succeeded or not. You never know if you will get the reference, therefore always handle both cases properly.

It is more expensive to use weak references instead of hard references. When assigning a weak reference to a hard reference, a mutex gets locked and some heap allocation may occur. When the object is located in a different process, at least one remote call takes place, meaning an overhead of approximately a millisecond.

The XWeak mechanism does not support notification at object destruction. For this purpose, objects must export XComponent and add com.sun.star.lang.XEventListener.

Exception Handling in C++
For throwing and catching of UNO exceptions, use the normal C++ exception handling mechanisms. Calls to UNO interfaces may only throw the  or derived exceptions. The following example catches every possible exception:

If you want to react differently for each possible exception type, look up the exceptions that may be thrown by a certain method. For instance the  method in com.sun.star.bridge.XUnoUrlResolver is allowed to throw three kinds of exceptions. Catch each exception type separately:

When implementing your own UNO objects (see C++ Component), throw exceptions using the normal C++ throw statement:

Note that only exceptions derived from  may be thrown at UNO interface methods. Other exceptions (for instance the C++ std::exception) cannot be bridged by the UNO runtime if the caller and called object are not within the same UNO Runtime Environment. Moreover, most current Unix C++ compilers, for instance gcc 3.0.x, do not compile code. During compilation, exception specifications are loosen in derived classes by throwing exceptions other than the exceptions specified in the interface that it is derived. Throwing unspecified exceptions leads to a std::unexpected exception and causes the program to abort on Unix systems.

LibreOffice Basic
LibreOffice Basic provides access to the LibreOffice API from within the office application. It hides the complexity of interfaces and simplifies the use of properties by making UNO objects look like Basic objects. It offers convenient Runtime Library (RTL) functions and special Basic properties for UNO. Furthermore, Basic procedures can be easily hooked up to GUI elements, such as menus, toolbar icons and GUI event handlers.

This chapter describes how to access UNO using the LibreOffice Basic scripting language. In the following sections, LibreOffice Basic is referred to as Basic.

Accessing UNO Services
UNO objects are used through their interface methods and properties. Basic simplifies this by mapping UNO interfaces and properties to Basic object methods and properties.

First, in Basic it is not necessary to distinguish between the different interfaces an object supports when calling a method. The following illustration shows an example of an UNO service that supports three interfaces:



In Java and C++, it is necessary to obtain a reference to each interface before calling one of its methods. In Basic, every method of every supported interface can be called directly at the object without querying for the appropriate interface in advance. The ' ' operator is used:

Additionally, LibreOffice Basic interprets pairs of get and set methods at UNO objects as Basic object properties if they follow this pattern:

SomeType getSomeProperty void setSomeProperty(SomeType aValue)

In this pattern, LibreOffice Basic offers a property of type  named. This functionality is based on the com.sun.star.beans.Introspection service. For additional details, see UNO Reflection API.

The get and set methods can always be used directly. In our example service above, the methods  and , or read and write a Basic property   are used:

If there is only a get method, but no associated set method, the property is considered to be read only.

Properties an object provides through com.sun.star.beans.XPropertySet are available through the  operator. The methods of com.sun.star.beans.XPropertySet can be used also. The object  in the following example has three integer properties ,   and  :

Basic uses com.sun.star.container.XNameAccess to provide named elements in a collection through the. operator. However, XNameAccess only provides read access. If a collection offers write access through com.sun.star.container.XNameReplace or com.sun.star.container.XNameContainer, use the appropriate methods explicitly:

Instantiating UNO Services
In Basic, instantiate services using the Basic Runtime Library (RTL) function. This function expects a fully qualified service name and returns an object supporting this service, if it is available:

This call instantiates the com.sun.star.ucb.SimpleFileAccess service. To ensure that the function was successful, the returned object can be checked with the  function:

Instead of using  to instantiate a service, it is also possible to get the global UNO com.sun.star.lang.ServiceManager of the LibreOffice process by calling. Once obtained, use  directly:

The advantage of  is that additional information and pass in arguments is received when services are instantiated using the service manager. For instance, to initialize a service with arguments, the  method of com.sun.star.lang.XMultiServiceFactory has to be used at the service manager, because there is no appropriate Basic RTL function to do that. Example:

The object returned by  is a normal Basic UNO object supporting com.sun.star.lang.ServiceManager. Its properties and methods are accessed as described above.

Using new-style service constructors
Beginning with OpenOffice.org 3.2 OpenOffice Basic supports UNO new-style service constructors. For more details see section Services. For the sample service used above constructors could be defined like this:

UNO services are mapped to OpenOffice Basic objects. They have to be addressed by using the complete UNO namespace path. The constructors can be accessed as methods of these service objects:

Of course the service object doesn't need to be stored in a variable before, the instantiation can also be done in one single statement:

Internally the UNO default context is used to create the and passed to the service. It's also possible to use an own context instead by adding it as first argument:

If a new-style service only has an implicit constructor it's mapped to a method "create" without parameters in OpenOffice.org Basic.

Built in properties
The Basic RTL provides special properties as API entry points. They are described in more detail in Features of LibreOffice Basic:

Getting Information about UNO Objects
The Basic RTL retrieves information about UNO objects. There are functions to evaluate objects during runtime and object properties used to inspect objects during debugging.

Checking for interfaces during runtime
Although Basic does not support the queryInterface concept like C++ and Java, it can be useful to know if a certain interface is supported by a UNO Basic object or not. The function  detects this.

The first parameter  expects is the object that should be tested. Parameter(s) of one or more fully qualified interface names can be passed to the function next. The function returns  if all these interfaces are supported by the object, otherwise.

Testing if an object is a struct during runtime
As described in the section Mapping of Structs above, structs are handled differently from objects, because they are treated as values. Use the  function to check it the UNO Basic object represents an object or a struct. This function expects one parameter and returns  if this parameter is a UNO struct, otherwise. Example:

Testing objects for identity during runtime
To find out if two UNO LibreOffice Basic objects refer to the same UNO object instance, use the function. Basic is not able to apply the comparison operator = to arguments of type object, for example,  will produce a runtime error.

Basic hides interfaces behind LibreOffice Basic objects that could lead to problems when developers are using API structures. It can be difficult to understand the API reference and find the correct method of accessing an object to reach a certain goal.

To assist during development and debugging, every UNO object in LibreOffice Basic has special properties that provide information about the object structure. These properties are all prefixed with  to emphasize their use for development and debugging purposes. The type of these properties is. To display the properties use the  function.

Inspecting interfaces during debugging
The  lists all interfaces supported by the object. In the following example, the object returned by the function  described in the previous section is taken as an example object.

This call displays a message box:



The list contains all interfaces supported by the object. For interfaces that are derived from other interfaces, the super interfaces are indented as shown above for com.sun.star.container.XSet, which is derived from com.sun.star.container.XEnumerationAccess based upon com.sun.star.container.XElementAccess.

Inspecting properties during debugging
The  lists all properties supported by the object through com.sun.star.beans.XPropertySet and through get and set methods that could be mapped to Basic object properties:

This code produces a message box like the following example:



Inspecting Methods During Debugging
The  lists all methods supported by an object. Example:

This code displays:



The notations used in  and   refer to internal implementation type names in Basic. The  prefix can be ignored. The remaining names correspond with the normal Basic type notation. The  is the same type as. Additional information about Basic types is available in the next chapter.

Inspector tools
Using these Dbg_ properties is a very crude method to discover the contents of an API objects. Use instead Xray tool or MRI tool.

The list of elements may be inconveniently long for MsgBox display. Code is available to write all Dbg_ elements to a new Writer document. See LibreOffice Macros > Tools > Debug > WritedbgInfo. The Tools library must be loaded to use this routine:

Mapping of UNO and Basic Types
Basic and UNO use different type systems. While LibreOffice Basic is compatible to Visual Basic and its type system, UNO types correspond to the IDL specification (see Data Types), therefore it is necessary to map these two type systems. This chapter describes which Basic types have to be used for the different UNO types.

Mapping of Simple Types
In general, the LibreOffice Basic type system is not rigid. Unlike C++ and Java, LibreOffice Basic does not require the declaration of variables, unless the  command is used that forces the declaration. To declare variables, the  command is used. Also, a LibreOffice Basic type can be optionally specified through the  command. The general syntax is:

All variables declared without a specific type have the type. Variables of type  can be assigned values of arbitrary Basic types. Undeclared variables are  unless type postfixes are used with their names. Postfixes can be used in  commands as well. The following table contains a complete list of types supported by Basic and their corresponding postfixes:

Consider the following Dim examples.

The correlation below is used to map types from UNO to Basic and vice versa.

The simple UNO type type is mapped to the com.sun.star.reflection.XIdlClass interface to retrieve type specific information. For further details, refer to UNO Reflection API.

When UNO methods or properties are accessed, and the target UNO type is known, Basic automatically chooses the appropriate types:

Occasionally, LibreOffice Basic does not know the required target type, especially if a parameter of an interface method or a property has the type. In this situation, LibreOffice Basic mechanically converts the LibreOffice Basic type into the UNO type shown in the table above, although a different type may be expected. The only mechanism provided by LibreOffice Basic is an automatic downcast of numeric values:

Long and Integer values are always converted to the shortest possible integer type:


 * to  if -128 <= Value <= 127
 * to  if -32768 <= Value <= 32767

The  values are converted to integers in the same manner if they have no decimal places.

This mechanism is used, because some internal C++ tools used to implement UNO functionality in LibreOffice provide an automatic upcast but no downcast. Therefore, it can be successful to pass a  value to an interface expecting a   value, but not vice versa.

In the following example,  is an object that supports com.sun.star.container.XNameContainer and contains elements of type. Assume  is a valid entry.

The method call fails, therefore the implementation should throw the appropriate exception that is converted to a LibreOffice Basic error by the LibreOffice Basic RTL. It may happen that an implementation also accepts unsuitable types and does not throw an exception. Ensure that the values used are suitable for their UNO target by using numeric values that do not exceed the target range or converting them to the correct Basic type before applying them to UNO.

Always use the type  to declare variables for UNO Basic objects, not the type. The LibreOffice Basic type  is tailored for pure LibreOffice Basic objects and not for UNO LibreOffice Basic objects. The  variables are best for UNO Basic objects to avoid problems that can result from the  Basic specific behavior of the type  :

Mapping of Sequences and Arrays
Many UNO interfaces use sequences, as well as simple types. The LibreOffice Basic counterpart for sequences are arrays. Arrays are standard elements of the Basic language. The example below shows how they are declared:

Basic does not have a special index operator like [] in C++ and Java. Array elements are accessed using normal parentheses :

As the examples show, the indices in  commands differ from C++ and Java array declarations. They do not describe the number of elements, but the largest allowed index. There is one more array element than the given index. This is important for the mapping of LibreOffice Basic arrays to UNO sequences, because UNO sequences follow the C++/Java array semantic.

When the UNO API requires a sequence, the Basic programmer uses an appropriate array. In the following example,  is an object that has a property   of type. To assign a sequence of length 10 with the values 0, 1, 2, ... 9 to this property, the following code can be used:

The Basic programmer must be aware of the different index semantics during programming. In the following example, the programmer passed a sequence with one element, but actually passed two elements:

It can be useful to use a LibreOffice Basic RTL function called  to create, initialize and assign it to a   variable in a single step, especially for small sequences:

Sometimes it is necessary to pass an empty sequence to a UNO interface. In Basic, empty sequences can be declared by omitting the index from the Dim command:

Sequences returned by UNO are also represented in Basic as arrays, but these arrays do not have to be declared as arrays beforehand. Variables used to accept a sequence should be declared as. To access an array returned by UNO, it is necessary to get information about the number of elements it contains with the Basic RTL functions  and.

The function  returns the lower index and   returns the upper index. The following code shows a loop going through all elements of a returned sequence:

The function  is a standard Basic function and is not specific in a UNO context. Basic arrays do not necessarily start with index 0, because it is possible to write something similar to:

This causes the array to have a lower index of 3. However, sequences returned by UNO always have the start index 0. Usually only  is used and the example above can be simplified to:

The element count of a sequence/array can be calculated easily:

For empty arrays/sequences  returns -1. This way the semantic of  stays consistent as the element count is then calculated correctly as:

UNO also supports sequences of sequences. In Basic, this corresponds with arrays of arrays. Do not mix up sequences of sequences with multidimensional arrays. In multidimensional arrays, all sub arrays always have the same number of elements, whereas in sequences of sequences every element sequence can have a different size. Example:

To create an array of arrays in Basic, sub arrays are used as elements of a master array:

In this situation, the runtime function  is useful. The example code can then be written much shorter:

If you nest, more compact code can be written, but it becomes difficult to understand the resulting arrays:

Sequences of higher order can be handled accordingly.

Mapping of Structs
UNO struct types can be instantiated with the  command as a single instance and array.

For instantiated polymorphic struct types, there is a special syntax of the  command, giving the type as a string literal instead of as a name:

The string literal representing a UNO name is built according to the following rules:


 * The strings representing the relevant simple UNO types are " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", and " ", respectively.
 * The string representing a UNO sequence type is " " followed by the string representing the component type.
 * The string representing a UNO enum, plain struct, or interface type is the name of that type.
 * The string representing an instantiated polymorphic struct type is the name of the polymorphic struct type template, followed by "<", followed by the representations of the type arguments (separated from one another by ","), followed by ">".

No spurious spaces or other characters may be introduced into these string representations.

UNO struct instances are handled like UNO objects. Struct members are accessed using the. operator. The  property is supported. The properties  and   are not supported because they do not apply to structs. Inspectors Xray tool or MRI tool can display UNO struct instances.

Objects and structs are different. Objects are handled as references and structs as values. When structs are assigned to variables, the structs are copied. This is important when modifying an object property that is a struct, because a struct property has to be reassigned to the object after reading and modifying it.

In the following example,  is an object that has the properties   and.

Both  and   should be modified. The following code shows how this is done for an object:
 * The object provided by  supports a string property.
 * The struct provided by  supports a string property.

The following code shows how it is done correctly for the struct (and possible mistakes):

Mapping of Enums and Constant Groups
Use the fully qualified names to address the values of an enum type by their names. The following examples assume that  and   support com.sun.star.beans.XPropertySet with a property   of the enum type com.sun.star.beans.PropertyState :

Basic does not support Enum types. In Basic, enum values coming from UNO are converted to  values. As long as Basic knows if a property or an interface method parameter expects an enum type, then the  value is internally converted to the right enum type. Problems appear with Basic when interface access methods expect an :

The explicit access could fail, because  is passed as parameter of type   to , therefore Basic does not know that a value of type PropertyState is expected. There is still a problem, because the Basic type for com.sun.star.beans.PropertyState is. This problem is solved in the implementation of the com.sun.star.beans.XPropertySet interface. For enum types, the implicit property access using the Basic property syntax  is preferred to calling generic methods using the type. In situations where only a generic interface method that expects an enum for an, there is no solution for Basic.

Constant groups are used to specify a set of constant values in IDL. In Basic, these constants can be accessed using their fully qualified names. The following code displays some constants from com.sun.star.beans.PropertyConcept :

A constant group or enum can be assigned to an object. This method is used to shorten code if more than one enum or constant value has to be accessed:

Case Sensitivity
Generally Basic is case insensitive. However, this does not always apply to the communication between UNO and Basic. To avoid problems with case sensitivity write the UNO related code as if Basic was case sensitive. This facilitates the translation of a Basic program to another language, and Basic code becomes easier to read and understand. The following discusses problems that might occur.

Identifiers that differ in case are considered to be identical when they are used with UNO object properties, methods and struct members.

The exceptions to this is if a Basic property is obtained through com.sun.star.container.XNameAccess as described above, its name has to be written exactly as it is in the API reference. Basic uses the name as a string parameter that is not interpreted when accessing com.sun.star.container.XNameAccess using its methods.

Exception Handling
Unlike UNO, Basic does not support exceptions. All exceptions thrown by UNO are caught by the Basic runtime system and transformed to a Basic error. Executing the following code results in a Basic error that interrupts the code execution and displays an error message:

The  object used in the example contains all the available Basic libraries in a running office instance. The Basic libraries contained in  is accessed using com.sun.star.container.XNameAccess. An exception was provoked by trying to obtain a non-existing library. The  object is explained in more detail in Advanced Library Organization.

The call to  results in this error box:



However, the Basic runtime system is not always able to recognize the Exception type. Sometimes only the exception message can be displayed that has to be provided by the object implementation.

Exceptions transformed to Basic errors can be handled just like any Basic error using the  command:

When the exception occurs, the execution continues at the  label. In the error handler, some properties are used to get information about the error. The  is the error code that is 1 for UNO exceptions. The  contains the text of the error message. Executing the program results in the following output:



Another message box "After the Error" is displayed after the above dialog box, because  goes to the code line below the line where the exception was thrown. The  command is required so that the error handler code would not be executed again.

Listeners
Many interfaces in UNO are used to register listener objects implementing special listener interfaces, so that a listener gets feedback when its appropriate listener methods are called. LibreOffice Basic does not support the concept of object implementation, therefore a special RTL function named  has been introduced. It uses a prefix for method names that can be called back from UNO. The  expects a method name prefix and the type name of the desired listener interface. It returns an object that supports this interface that can be used to register the listener.

The following example instantiates an com.sun.star.container.XContainerListener. Note the prefix :

The next step is to implement the listener methods. In this example, the listener interface has the following methods:

In the example,  is specified as a name prefix, therefore the following subs have to be implemented in Basic.



Every listener type has a corresponding  struct type that contains information about the event. When a listener method is called, an instance of this  type is passed as a parameter. In the Basic listener methods these  objects can be evaluated by adding an appropriate   parameter to the procedure header. The following code shows how the listener methods in the example could be implemented:

It is necessary to implement all listener methods, including the listener methods of the parent interfaces of a listener. Basic runtime errors will occur whenever an event occurs and no corresponding Basic sub is found, especially with, because the broadcaster might be destroyed a long time after the Basic program was ran. In this situation, Basic shows a "Method not found" message. There is no indication of which method cannot be found or why Basic is looking for a method.

We are listening for events at the basic library container. Our simple implementation for events triggered by user actions in the Tools - Macro - Organizer dialog displays a message box with the corresponding listener method name and a message box with the  of the event struct. For the  method, the type of the event object is com.sun.star.lang.EventObject. All other methods belong to com.sun.star.container.XContainerListener, therefore the type of the event object is com.sun.star.container.ContainerEvent. This type is derived from com.sun.star.lang.EventObject and contains additional container related information.

If the event object is not needed, the parameter could be left out of the implementation. For example, the  method could be:

The event objects passed to the listener methods can be accessed like other struct objects. The following code shows an enhanced implementation of the  method that evaluates the com.sun.star.container.ContainerEvent to display the name of the module removed from   and the module source code:

When the user removes Module1, the following message boxes are displayed by :





When all necessary listener methods are implemented, add the listener to the broadcaster object by calling the appropriate add method. To register an, the corresponding registration method at our container is  :

The listener for container events is now registered permanently. When a container event occurs, the container calls the appropriate method of the com.sun.star.container.XContainerListener interface in our Basic code.

Automation Bridge
The LibreOffice software supports Microsoft's Automation technology. This offers programmers the possibility to control the office from external programs. There is a range of efficient IDEs and tools available for developers to choose from.

Automation is language independent. The respective compilers or interpreters must, however, support Automation. The compilers transform the source code into Automation compatible computing instructions. For example, the string and array types of your language can be used without caring about their internal representation in Automation, which is  and. A client program that controls LibreOffice can be represented by an executable (Visual Basic, C++) or a script (JScript, VB Script). The latter requires an additional program to run the scripts, such as Windows Scripting Host (WSH) or Internet Explorer.

UNO was not designed to be compatible with Automation and COM, although there are similarities. LibreOffice deploys a bridging mechanism provided by the Automation Bridge to make UNO and Automation work together. The bridge consists of UNO services, however, it is not necessary to have a special knowledge about them to write Automation clients for LibreOffice. For additional information, see The Bridge Services.

Different languages have different capabilities. There are differences in the manner that the same task is handled, depending on the language used. Examples in Visual Basic, VB Script and JScript are provided. They will show when a language requires special handling or has a quality to be aware of. Although Automation is supposed to work across languages, there are subtleties that require a particular treatment by the bridge or a style of coding. For example, JScript does not know out parameters, therefore Array objects have to be used. Currently, the bridge has been tested with C++, JScript, VBScript and Visual Basic, although other languages can be used as well.

The name Automation Bridge implies the use of the Automation technology. Automation is part of the collection of technologies commonly referred to as ActiveX or OLE, therefore the term OLE Bridge is misleading and should be avoided. Sometimes the bridge is called COM bridge, which is also wrong, since the only interfaces which are processed by the bridge are IUnknown and IDispatch.

Requirements
The Automation technology can only be used with LibreOffice on a Windows platform (Windows 95, 98, NT4, ME, 2000, XP). There are COM implementations on Macintosh OS and UNIX, but there has been no effort to support Automation on these platforms.

Using Automation involves creating objects in a COM-like fashion, that is, using functions like  in VB or   in C. This requires the LibreOffice automation objects to be registered with the Windows system registry. This registration is carried out whenever an office is installed on the system. If the registration did not take place, for example because the binaries were just copied to a certain location, then Automation clients will not work correctly or not at all. Refer to The Service Manager Component for additional information.

A Quick Tour
The following example shows how to access LibreOffice functionality through Automation. Note the inline comments. The only automation specific call is  in the first line, the remaining are LibreOffice API calls. The helper functions  and   are shown at the end of the listing

This script created a new document and started the office, if necessary. The script also wrote text, created and populated a table, used different background and pen colors. Only one object is created as an ActiveX component called. The service manager is then used to create additional objects which in turn provided other objects. All those objects provide functionality that can be used by invoking the appropriate functions and properties. A developer must learn which objects provide the desired functionality and how to obtain them. The chapter First Steps introduces the main LibreOffice objects available to the programmer.

Instantiation
The service manager is the starting point for all Automation clients. The service manager requires to be created before obtaining any UNO object. Since the service manager is a COM component, it has a  and a programmatic identifier which is. It is instantiated like any ActiveX component, depending on the language used:

In Visual C++, use classes which facilitate the usage of COM pointers. If you use the Active Template Library (ATL), then the following example looks like this:

JScript with WSH
The service manager can also be created remotely, that is. on a different machine, taking the security aspects into account. For example, set up launch and access rights for the service manager in the system registry (see DCOM).

The code for the service manager resides in the office executable soffice.exe. COM starts up the executable whenever a client tries to obtain the class factory for the service manager, so that the client can use it.

Registry Entries
For the instantiation to succeed, the service manager must be properly registered with the system registry. The keys and values shown in the tables below are all written during setup. It is not necessary to edit them to use the Automation capability of the office. Automation works immediately after installation. There are three different keys under  that have the following values and subkeys:

The value of the key  reflects the path of the office executable.

Or, copy the following lines to your editor, edit the path to soffice.exe in the second line, and save and use it as a .reg file.

All keys have duplicates under.

The service manager is an ActiveX component, but does not support self-registration. That is, the office does not support the command line arguments  or.

The service manager, as well as all the objects that it creates and that originate from it indirectly as return values of function calls are proper automation objects. They can also be accessed remotely through DCOM.

From UNO Objects to Automation Objects
The service manager is based on the UNO service manager and similar to all other UNO components, is not compatible with Automation. The service manager can be accessed through the COM API, because the service manager is an Active X component contained in an executable that is the LibreOffice. When a client creates the service manager, for example by calling, and the office is not running, it is started up by the COM system. The office then creates a class factory for the service manager and registers it with COM. At that point, COM uses the factory to instantiate the service manager and return it to the client.

When the function  is called, the UNO service manager is converted into an Automation object. The actual conversion is carried out by the UNO service com.sun.star.bridge.oleautomation.BridgeSupplier (see The Bridge Services). The resulting Automation object contains the UNO object and translates calls to  into calls to the respective UNO interface function. The supplied function arguments, as well as the return values of the UNO function are converted according to the defined mappings (see Type Mappings). Returned objects are converted into Automation objects, so that all objects obtained are always proper Automation objects.

Using UNO from Automation
With the IDL descriptions and documentation, start writing code that uses an interface. This requires knowledge about the programming language, especially how UNO interfaces can be accessed in that language and how function calls work.

In some languages, such as C++, the use of interfaces and their functions is simple, because the IDL descriptions map well with the respective C++ counterparts. For example, the syntax of functions are similar, and interfaces and out parameters can also be realized. The C++ language is not the best choice for Automation, because all interface calls have to use, which is difficult to use in C++. In other languages, such as VB and JScript, the  interface is hidden behind an object syntax that leads to shorter and more understandable code.

Different interfaces can have functions with the same name. There is no way to call a function which belongs to a particular interface, because interfaces can not be requested in Automation. If a UNO object provides two functions with the same name, it is undefined which function will be called. A solution for this issue is planned for the future.

Not all languages treat method parameters in the same manner, especially when it comes to input parameters that are reused as output parameters. From the perspective of a VB programmer an out parameter does not look different from an in parameter. However, to realize out parameters in Jscript, use an  or   that is a special construct provided by the Automation bridge. JScript does not support out parameters through calls by reference.

Calling Functions and Accessing Properties
The essence of Automation objects is the IDispatch interface. All function calls, including the access to properties, ultimately require a call to. When using C++, the use of  is rather cumbersome. For example, the following code calls

First the COM ID for the method name  is retrieved from , then the ID is used to   the method.

Before calling a certain function on the  interface, get the   by calling. The s are generated by the bridge, as required. There is no fixed mapping from member names to s, that is, the   for the same function of a second instance of an object might be different. Once a  is created for a function or property name, it remains the same during the lifetime of this object.

Helper classes can make it easier. The next example shows the same call realized with helper classes from the Active Template Library:

Some frameworks allow the inclusion of COM type libraries that is an easier interface to Automation objects during development. These helpers cannot be used with UNO, because the SDK does not provide COM type libraries for UNO components. While COM offers various methods to invoke functions on COM objects, UNO supports  only.

Programming of Automation objects is simpler with VB or JScript, because the  interface is hidden and functions can be called directly. Also, there is no need to wrap the arguments into s.

Pairs of get/set functions following the pattern

are handled as COM object properties.

Accessing such a property in C++ is similar to calling a method. First, obtain a, then call   with the proper arguments.

When the property is an, or  , the flag   must be used. This is also the case when a value is passed by reference.

The following example shows using the ATL helper it looks simple:

The following example using VB and JScript it is simpler:

Service properties are not mapped to COM object properties. Use interfaces, such as com.sun.star.beans.XPropertySet to work with service properties.

Return Values
There are three possible ways to return values in UNO:


 * function return values
 * parameters
 * parameters

Return values are commonplace in most languages, whereas  and   parameters are not necessarily supported. For example, in JScript.

To receive a return value in C++ provide a  argument to

The following examples show that using VB or JScript is simple:

When a function has inout parameters then provide arguments by reference in C++:

The VB code below is simple because VB uses call by reference by default. After the call to, value contains the function output:

The type of argument corresponds to the UNO type according to the default mapping, cf. Type Mappings. If in doubt, use s.

However, there is one exception. If a function takes a character as an argument and is called from VB, use an , because there is no character type in VB. For convenience, the COM bridge also accepts a String as   and   parameter:

JScript does not have  or   parameters. As a workaround, the bridge accepts JScript  objects. Index 0 contains the value.

Out parameters are similar to  parameters in that the argument does not need to be initialized.

Interfaces
Many UNO interface functions take interfaces as arguments. If this is the case, there are three possibilities to get an instance that supports the needed interface:


 * Ask the service manager to create a service that implements that interface.
 * Call a function on a UNO object that returns that particular interface.
 * Provide an interface implementation if a listener object is required. Refer to Automation Objects with UNO Interfaces for additional information.

If  is called on the service manager or another UNO function that returns an interface, the returned object is wrapped, so that it appears to be a COM dispatch object. When it is passed into a call to a UNO function then the original UNO object is extracted from the wrapper and the bridge makes sure that the proper interface is passed to the function. If UNO objects are used, UNO interfaces do not have to be dealt with. Ensure that the object obtained from a call to a UNO object implements the proper interface before it is passed back into another UNO call.

Structs
Automation does not know about structs as they exist in other languages, for example, in C++. Instead, it uses Automation objects that contain a set of properties similar to the fields of a C++ struct. Setting or reading a member ultimately requires a call to. However in languages, such as VB, VBScript, and JScript, the interface call is obscured by the programming language. Accessing the properties is as easy as with C++ structs.

Whenever a UNO function requires a struct as an argument, the struct must be obtained from the UNO environment. It is not possible to declare a struct. For example, assume there is an office function  that takes a struct of type Size. The struct is declared as follows:

You cannot write code similar to the following example (VBScript):

The com.sun.star.reflection.CoreReflection service or the  function that is called on the service manager object can be used to create the struct. The following example uses the  service

The next example shows how  is used.

The  function is provided by the service manager object that is initially created by   (Visual Basic) or

The corresponding C++ examples look complicated, but ultimately the same steps are necessary. The method  on the   service is called and returns a com.sun.star.reflection.XIdlClass which can be asked to create an instance using  :

The  example.

JScript:

Using Automation Objects from UNO
This language binding offers a way of accessing Automation objects from UNO. For an Automation object to be usable, it must be properly registered on the system and have a programmatic identifier (ProgId) with which an instance can be created. From UNO, all Automation objects are accessed via com.sun.star.script.XInvocation. com.sun.star.script.XInvocation is a scripting interface that is intended for dynamically performing calls similar to. Since StarBasic uses com.sun.star.script.XInvocation to communicate with objects, Automation objects can be used from StarBasic.

Instantiation
To obtain an instance of an Automation object it is easiest to use the service com.sun.star.bridge.oleautomation.Factory. It provides an com.sun.star.lang.XMultiServiceFactory interface which is used to get the desired object. For example:

In StarBasic it looks quite simple:

StarBasic function CreateObject offers a simpler code:

Accessing Automation Objects
All Automation objects are accessed through com.sun.star.script.XInvocation interface. The function com.sun.star.script.XInvocation:getIntrospection is not implemented. To call a method, com.sun.star.script.XInvocation:invoke is used. com.sun.star.script.XInvocation:invoke is also used to access properties with additional arguments. The methods com.sun.star.script.XInvocation:setValue and com.sun.star.script.XInvocation:getValue set or retrieve a property value. These methods can only be used with properties that do not have additional arguments.

com.sun.star.script.XInvocation:hasMethod returns true for a name that represents a method or a property with arguments. And last, com.sun.star.script.XInvocation:hasProperty returns true for a name that represents a property with no arguments. Refer to the IDL documentation for more information about com.sun.star.script.XInvocation.

Properties with Arguments
Unlike UNO properties, Automation properties can have arguments. Therefore, com.sun.star.script.XInvocation:setValue and com.sun.star.script.XInvocation:getValue method are not suitable for those properties. Instead com.sun.star.script.XInvocation:invoke is used. If a property takes arguments, then com.sun.star.script.XInvocation:hasProperty returns false and com.sun.star.script.XInvocation:hasMethod returns true. com.sun.star.script.XInvocation:invoke must also be used if the arguments of the property are optional and not provided in the call.

The bridge must recognize a write operation on a property. To achieve this, the caller has to provide the actual property value (not additional arguments) in a structure of type com.sun.star.bridge.oleautomation.PropertyPutArgument. Similar to, the property value must be the last in the argument list. For example:

In StarBasic, com.sun.star.bridge.oleautomation.PropertyPutArgument is implicitly used:

The property value that is obtained in a property get operation is the return value of com.sun.star.script.XInvocation:invoke.

Optional Parameters, Default Values, Variable Argument Lists
The bridge supports all these special parameters. Optional parameters can be left out of the argument list of com.sun.star.script.XInvocation:invoke. However, if a value is omitted, then all following arguments from the parameter list must also be omitted. This only applies for positional arguments and not for named arguments.

If the Automation object specifies a default value for an optional parameter, then the bridge supplies it, if no argument was provided by the caller.

If a method takes a variable argument list, then one can provide the respective UNO arguments as ordinary arguments to com.sun.star.script.XInvocation:invoke. would require those arguments in a.

Named Arguments
To provide named arguments in an com.sun.star.script.XInvocation:invoke call, one has to use instances of com.sun.star.bridge.oleautomation.NamedArgument for each argument. This is the struct in UNOIDL:

In a call both, named arguments and positional arguments can be used together. The order is, first the positional arguments (the ordinary arguments), followed by named arguments. When named arguments are used, then arguments can be omitted even if arguments are provided that follow the omitted parameter. For example, assume that a method takes five arguments, which are all optional, then the argument lists for com.sun.star.script.XInvocation could be as follows:


 * all provided: {A, B, C, D, E}
 * arguments omitted: {A,B,C,D} or {A,B} but not {A, C, D}
 * named arguments : {nA, nC, nB, nD}, {nC, nD}
 * mixed arguments: { A, B, nD}, {A, nC}

Named arguments can also be used with properties that have additional arguments. However, the property value itself cannot be a named argument, since it is already regarded as a named argument. Therefore, it is always the last argument.

Type Mappings
When a UNO object is called from an Automation environment, such as VB, then depending on the signature of the called method, values of Automation types are converted to values of UNO types. If values are returned, either as out-arguments or return value, then values of UNO types are converted to values of Automation types. The results of these conversions are governed by the values to be converted and the respective type mapping.

The type mapping describes how a type from the Automation environment is represented in the UNO environment and vice versa. Automation types and UNO types are defined in the respective IDL languages, MIDL and UNO IDL. Therefore, the type mapping will refer to the IDL types.

The IDL types have a certain representation in a particular language. This mapping from IDL types to language specific types must be known in order to use the Automation bridge properly. Languages for which a UNO language binding exists will find the mapping in the language binding documentation. Automation capable languages can provide information about how Automation types are to be used (for example, Visual Basic, Delphi).

Some Automation languages may not provide a complete mapping for all Automation types. For example, JScript cannot provide float values. If you use C or C++, then all Automation types can be used directly.

A method call to an Automation object is performed through. Invoke takes an argument of type, which contains the actual arguments for the method in an array of. These s are to be regarded as holders for the actual types. In most Automation languages you are not even aware of. For example:

In this example, the argument is a long and the return value is a string. That is,  would receive a   that contains a long and returns a   that contains a string.

When an Automation object is called from UNO through com.sun.star.script.XInvocation:invoke, then all arguments are provided as anys. The any, similiar to the, acts as a holder for the actual type. To call Automation objects from UNO you will probably use StarBasic. Then the com.sun.star.script.XInvocation interface is hidden, as in  in Visual Basic.

The bridge converts values according to the type mapping specified at Default Mappings. Moreover, it tries to coerce a conversion if a value does not have a type that conforms with the default mapping (Conversion Mappings).

In some situations, it may be necessary for an Automation client to tell the bridge what the argument is supposed to be. For this purpose you can use the Value Object (Value Objects).

Default Mappings
The following table shows the mapping of UNO and Automation types. It is a bidirectional mapping (which is partly true for the UNO sequence, which will be explained later on) and therefore it can be read from left to right and vice versa. The mapping of Automation types to UNO types applies when:


 * A method of a UNO object is called from an Automation environment and values are passed for in or in/out parameters.
 * A method of an Automation object is called from the UNO environment and the method returns a value.
 * A method of an Automation object is called from the UNO environment and the method returns values in in/out or out - parameters.

The mapping of UNO types to Automation types applies when:


 * A method of an Automation object is called from an UNO environment and values are passed for in or in/out-parameters.
 * A method of a UNO object is called from an Automation environment and the method returns a value.
 * A method of a UNO object is called from an Automation environment and the method returns values in in/out or out-parameters.

The following sections discuss the respective mappings in more detail.

Mapping of Simple Types
Many languages have equivalents for the IDL simple types, such as integer and floating point types. Some languages, however, may not support all these types. For example, JScript is a typeless language and only recognizes a general number type. Internally, it uses four byte signed integer values and double values to represent a number. When a UNO method is called that takes a float as an argument, and that value is at some point returned to the caller, then the values may differ slightly. This is because the bridge converts the double to a float, which is eventually converted back to a double.

If a UNO method takes an any as argument and the implementation expects a certain type within the any, then the bridge is not always able to provide the expected value. Assuming, that a UNO method takes an any that is supposed to contain a short and the method is to be called from JScript, then the bridge will provide an any containing a four byte integer. This may result in an exception from the initiator of the call The solution is to use a Value Object (Value Objects).

Unlike Automation, there are unsigned integer types in UNO. To provide a positive value that exceeds the maximum value of the corresponding signed type, you have to use the corresponding negative value. For example, to call the following UNO function in VB with the value 32768 (0x8000) you need to pass -32768.

The rule for calculating the negative equivalent is:

signed_value = unsigned_value - (max_unsigned +1)

In the preceding example, unsigned_value is the value that we want to pass, and which is 32768. This value is one too many for the VB type Integer, that is why we have to provide a negative value. max_unsigned has the value 65535 for a two byte integer. So the equation is

-32768 = 32768 - (65535 + 1)

Alternatively you can use a type with a greater value range. The Automation bridge will then perform a narrowing conversion.

For more information about conversions see chapter Conversion Mappings.

Mapping of Hyper and Decimal
Automation does not have an 8 byte integer value that compares to a UNO hyper. However, the Automation type Decimal has a value space big enough to represent a hyper. Therefore, when calling UNO methods from Automation, use Decimal whenever the UNO method requires a hyper or unsigned hyper.

The Decimal type may not be supported by all Automation capable language. Examples are JScript and VBScript, which should not be used when calling these UNO methods. This is because provided values may be rounded and hence the results are tainted.

Visual Basic has the restriction that Decimal variables can only be declared as Variants. The assignment of a value has to be done using the CDec function. Furthermore, VB does not allow the use of integer literals bigger than 4 bytes. As a workaround, you can provide a string that contains the value. For example:

Visual Basic .NET has the build-in type decimal and does not restrict the integer literals.

When Automation objects are called from UNO, then the com.sun.star.bridge.oleautomation.Decimal type can be used to provide arguments with the Automation arguments of type Decimal. Returned Decimal values are converted to com.sun.star.bridge.oleautomation.Decimal.

Mapping of String
A string is a data structure that is common in programming languages. Although the idea of a string is the same, the implementations and their creation can be quite different. For example, a C++ programmer has a range of possibilities to choose from (for example,,  ,  ,  ,  ,  ,  ), whereas a JScript programmer can only use one kind of string. To use Automation across languages, it is necessary to use a string type that is common to all those languages, and that has the same binary representation. This particular string is declared as  in COM. The name can be different, depending on the language. For example, in C++ there is a  type, in VB it is called , and in JScript every string defined is a. Refer to the documentation covering the s equivalent if using an Automation capable language not covered by this document.

Mapping of Interfaces and Structures
UNO interfaces or structures are represented as dispatch objects in the Automation environment. That is, the converted value is an object that implements IDispatch. If an UNO interface was mapped, then you also can access all other UNO interfaces of the object through IDispatch. In other words, the dispatch object represents the UNO object with all its interfaces and not only the one interface which was converted.

If a dispatch object, which actually is a UNO object or a structure, is now passed back to UNO, then the bridge will extract the original UNO interface or structure and pass it on. Since the UNO dispatch object represents the whole UNO object, that is, all its supported interfaces, you can use the dispatch object as argument for all those interface types. For example:

If Automation objects are called from UNO, then the called methods may return other Automation objects, either as  or. These can then be used as arguments in later calls to Automation objects or you can perform calls on them. In case of, this is only possible if the object also supports. To make calls from UNO, the com.sun.star.uno.XInterface must first be queried for com.sun.star.script.XInvocation. When a method returns, then on UNO side a com.sun.star.script.XInvocation is received and can be called immediately.

When these interfaces are passed back as arguments to a call to an Automation object, then the bridge passes the original  or   pointer. This is dependent upon what the parameter type is. Remember, calls can only be performed on Automation objects. Therefore  and   are the only possible COM interfaces. If the expected parameter is a, then it will contain an   if the Automation object was passed as   into the UNO environment. It will contain an  if the object was passed as. For example:

For the purpose of receiving events (listener) it is possible to implement UNO interfaces as dispatch objects Automation Objects with UNO Interfaces. That type of object is used as an argument in UNO functions where particular interface types are required. The bridge will make sure that the proper interface is provided to the UNO function. If the UNO interface is then passed back into the Automation environment, the original Automation object will be passed.

If the Automation object is passed as argument for an any, then the any will contain an com.sun.star.uno.XInterface if the object was passed as  or the any contains an com.sun.star.script.XInvocation if the object was passed as. If, for example, the UNO interface  is implemented as a dispatch object, an instance to UNO as Any parameter is passed, and the Any contains XFoo rather then com.sun.star.script.XInvocation, then the dispatch object must be placed in a Value Object (Value Objects). For example:

Null pointers are converted to null pointers of the required type. That is, if an  pointer with the value null is passed as an argument to a UNO method then the resulting argument is a null pointer of the expected type. This also applies to UNO interface pointers, which are passed in calls to Automation objects. When a UNO method takes a struct as an argument and it is called from the Automation environment where a null pointer (, or ) was supplied, then the UNO method receives a struct that was default constructed.

Mapping of Sequence
Kinds of arrays

Arrays in Automation have a particular type. The. A  array is used when a UNO function takes a sequence as an argument. To create a  in C++, use Windows API functions. The C++ name is also, but in other languages it might be named differently. In VB for example, the type does not even exist, because it is mapped to an ordinary VB array:

JScript is different. It does not have a method to create a. Instead, JScript features an  object that can be used as a common array in terms of indexing and accessing its values. It is represented by a dispatch object internally. JScript offers a  object that converts a   into an   object, which can then be processed further.

The Automation bridge accepts both,  and   object, for arguments whose UNO type is a sequence.

Multidimensional arrays

UNO does not recognize multi-dimensional sequences. Instead, a sequences can have elements that are also sequences. Those "inner" sequences can have different lengths, whereas the elements of a dimension of a multi-dimensional array are all the same length.

To provide an argument for a sequence of sequences, a  containing  s of  s has to be created. For example:

The array seq corresponds to the "outer" sequence and contains two s, which in turn contain  s of different lengths.

It is also possible to use a multi-dimensional  if the elements of the sequence are all the same length:

Be aware that Visual Basic uses a column-oriented ordering in contrast to C. That is, the C equivalent to the VB array is

The highest dimension in VB is represented by the right-most number.

This language binding specifies that the "outer" sequence corresponds to the highest dimension. Therefore, the VB array seq(9,1) would map to a sequence of sequences where the outer sequence has two elements and the inner sequences each have ten elements.

Conversion of returned sequences

Sequences can be returned as return values of uno functions or properties and as in/out or out arguments of uno functions. They are converted into s containing  s. If a sequence of sequences is returned, then the  s contain again  s. For example, if an uno function returns a sequence of strings then the bridge will convert the sequence into a   containing  s of strings. This is necessary because some languages, for example VBScript can only access members of arrays if they are s.

To process a returned  in JScript, use the   object to convert the   into a JScript.

That a returned sequence maps to a  of  s is not ideal because it is ambiguous when the array is passed back to UNO. However, the bridge solves this problem by using UNO type information. For example, a returned sequence of longs will result in a  of  s containing long values. When the  is passed in a method as an argument for a parameter of type   then it is converted accordingly. However, if the parameter is an, then the bridge does not have the necessary type information and converts the   to. If the method now expects the any to contain a  then it may fail. This is confusing if there are pairs of methods like  and , which take any arguments. Then you may get a  as a return value, which cannot be used in the respective   call. For example:

To solve this problem, wrap the argument in a Value Object (Value Objects):

A similar problem may occur when one calls functions of an automation object which takes s as arguments and the function expects particular types within those  s. For example, an automation object expects a   containing a   of strings. The bridge only knows from the object's type information that the function expects a, but not the contained type. The bridge will therefore do a default conversion of the sequence, which produces a  of  s. The function may not be able to understand this argument. Then one can use a value object in order to give the bridge a hint of the expected type.

If the parameter is a multi–dimensional, then a sequence containing sequences has to be provided. The number of nested sequences corresponds to the number of dimensions. Since the elements of a dimension have the same length, the sequences that represent that dimension should also have the same length. For example, assume the expected  can be expressed in C as

Then the outer sequence must have two elements and each of those sequences has 10 elements.

Mapping of Type
Since there is no counterpart to the UNO type among the Automation types, it is mapped to an object. The object implements  and a private tagging interface that is known to the bridge. Therefore, whenever an object is passed in a call to a UNO object the bridge can determine whether it represents a type. To obtain a type one calls  on the service manager object and provides the name of the type. For example:

In case the provided argument does not represent a valid type, the call produces an error.

If a UNO method returns a type, either as return value or out - parameter, then it is automatically converted to an object.

Conversion Mappings
As shown in the previous section, Automation types have a UNO counterpart according to the mapping tables. If a UNO function expects a particular type as an argument, then supply the corresponding Automation type. This is not always necessary as the bridge also accepts similar types. For example:

The following table shows the various Automation types, and how they are converted to UNO IDL types if the expected UNO IDL type has not been passed.

When you use a string for a numeric value, it must contain an appropriate string representation of that value.

Floating point values are rounded if they are used for integer values.

Be careful using types that have a greater value space than the UNO type. Do not provide an argument that exceeds the value space which would result in an error. For example:

The conversion mappings only work with in parameters, that is, during calls from an Automation environment to a UNO function, as far as the UNO function takes in parameters.

Client-Side Conversions
The UNO IDL description and the defined mappings indicate what to expect as a return value when a particular UNO function is called. However, the language used might apply yet another conversion after a value came over the bridge.

When the function returns, VB converts the  value into a   and assigns it to. Such a conversion comes in useful when functions return a character, and a string is preferred instead of a VB Integer value.

Be aware of the different value spaces if taking advantage of these conversions. That is, if the value space of a variable that receives a return value is smaller than the UNO type, a runtime error might occur if the value does not fit into the provided variable. Refer to the documentation of your language for client-side conversions.

Client-side conversions only work with return values and not with out or inout parameters. The current bridge implementation is unable to transport an out or inout parameter back to Automation if it does not have the expected type according to the default mapping.

Another kind of conversion is done implicitly. The user has no influence on the kind of conversion. For example, the scripting engine used with the Windows Scripting Host or Internet Explorer uses double values for all floating point values. Therefore, when a UNO function returns a float value, then it is converted into a double which may cause a slightly different value. For example:

The Automation Value Object
The object can be obtained from any uno object by calling the Bridge_GetValueObject on it. It holds a value and a type description, hence it resembles a UNO any or a VARIANT. A Value Object can stand in for all kinds of arguments in a call to a UNO method from a automation language. A Value Object is used when the bridge needs additional information for the parameter conversion. This is the case when a UNO method takes an any as argument. In many cases, however, one can do without a Value Object if one provides an argument which maps exactly to the expected UNO type according to the default mapping. For example, a UNO method takes an any as argument which is expected to contain a short. Then it would be sufficient to provide a Long in Visual Basic. But in JScript there are no types and implicitly a four byte integer would be passed to the call. Then the any would not contain a short and the call may fail. In that case the Value Object would guarantee the proper conversion.

A Value Object also enables in/out and out parameter in languages which only know in-parameters in functions. JScript is a particular case because one can use Array objects as well as Value Objects for those parameters.

A Value Object exposes four functions that can be accessed through. These are:

Assigns a type and a value.

Returns the value contained in the object. Get is used when the Value Object was used as inout or out parameter.

Tells the object that it is used as out parameter.

Tells the object that it is used as inout parameter and passes the value for the in parameter, as well as the type.

When the Value Object is used as in or inout parameter then specify the type of the value. The names of types correspond to the names used in UNO IDL, except for the "object" name. The following table shows what types can be specified.

To show that the value is a sequence, put brackets before the names, for example:

The  are provided by the bridge and can be obtained from the service manager object. The service manager is a registered COM component with the ProgId "com.sun.star.ServiceManager" (The Service Manager Component). For example:

To use a  as in parameter, specify the type and pass the value to the object:

In the previous example, the  was defined to be a sequence of short values. The array could also contain  again:

If a function takes an out parameter, tell the  like this:

When the  is an   parameter, it needs to know the type and value as well:

UNO Value Object (as of OOo 3.4)
The UNO Value Object is basically the same as the Automation Value Object. It can be provided as argument in calls on automation objects. The value object is an uno service and implements com.sun.star.bridge.oleautomation.XValueObject. The type description is provided by flags which resemble the  as used by. All possible type flags are provided as properties by the XValueObject interface.

If a Value Object is provided as out or in/out parameter then the type will be changed after the function has returned. Therefore the argument type must be of Variant. For example:

Exceptions and Errorcodes
UNO interface functions may throw exceptions to communicate an error. Automation objects provide a different error mechanism. First, the  interface describes a number of error codes ( s) that are returned under certain conditions. Second, the  function takes an argument that can be used by the object to provide descriptive error information. The argument is a structure of type  and is used by the bridge to convey exceptions being thrown by the called UNO interface function. In case the UNO method throws an exception the bridge fills  with these values:

EXCEPINFO::wCode = 1001

EXCEPINFO::bstrSource = "[automation bridge]"

EXCEPINFO::bstrDescription = type name of the exceptions + the message of the exception (com::sun::star::uno::Exception::message )

Also the returned error code will be.

Since the automation bridge processes the Invoke call and calls the respective UNO method in the end, there can be other errors which are not caused by the UNO method itself. The following table shows what these errors are and how they are caused.

Return values of

The functions  and   return.

When a call from UNO to an Automation object is performed, then the following  values are converted to exceptions. Keep in mind that it is determined what exceptions the functions of  are allowed to throw.

Exceptions thrown by  and their   counterparts:

throws the same as  except for:

throws the same as invoke except for:

Automation Objects with UNO Interfaces
It is common that UNO functions take interfaces as arguments. As discussed in section Usage of Types, those objects are usually obtained as return values of UNO functions. With the Automation bridge, it is possible to implement those objects even as Automation objects and use them as arguments, just like UNO objects.

Although Automation objects can act as UNO objects, they are still not fully functional UNO components. That is, they cannot be created by means of the service manager. Also, there is no mapping of UNO exceptions defined. That is, an UNO object implemented as automation object cannot make use of exceptions nor can it convey them in any other way.

One use case for such objects are listeners. For example, if a client wants to know when a writer document is being closed, it can register the listener object with the document, so that it will be notified when the document is closing.

Requirements
Automation objects implement the  interface, and all function calls and property operations go through this interface. We imply that all interface functions are accessed through the dispatch interface when there is mention of an Automation object implementing UNO interfaces. That is, the Automation object still implements  only.

Basically, all UNO interfaces can be implemented as long as the data types used with the functions can be mapped to Automation types. The bridge needs to know what UNO interfaces are supported by an Automation object, so that it can create a UNO object that implements all those interfaces. This is done by requiring the Automation objects to support the property, which is an array of strings. Each of the strings is a fully qualified name of an implemented interface. If an Automation object only implements one UNO interface, then it does not need to support that property.

Examples
The following example shows how a UNO interface is implemented in VB. It is about a listener that gets notified when a writer document is being closed.

To rebuild the project use the wizard for an ActiveX dll and put this code in the class module. The component implements the com.sun.star.lang.XEventListener interface.

You can use these components in VB like this:

The next example shows a JScript implementation of a UNO interface and its usage from JScript. To use JScript with UNO, a method had to be determined to realize arrays and out parameters. Presently, if a UNO object makes a call to a JScript object, the bridge must be aware that it has to convert arguments according to the JScript requirements. Therefore, the bridge must know that one calls a JScript component, but the bridge is not capable of finding out what language was used. The programmer has to provide hints, by implementing a property with the name " " that has the value " ".

Assume there is a UNO object that implements the following interface function:

Now, call this function in JScript and provide a JScript implementation of :

To build a component with C++, write the component from scratch or use a kind of framework, such as the Active Template Library (ATL). When a dual interface is used with ATL, the implementation of  is completely hidden and the functions must be implemented as if they were an ordinary custom interface, that is, use specific types as arguments instead of  s. If a UNO function has a return value, then it has to be specified as the first argument which is flagged as "retval".

DCOM
The Automation bridge maps all UNO objects to automation objects. That is, all those objects implement the  interface. To access a remote interface, the client and server must be able to marshal that interface. The marshaling for  is already provided by Windows, therefore all objects which originate from the bridge can be used remotely.

To make DCOM work, apply proper security settings for client and server. This can be done by setting the appropriate registry entries or programmatically by calling functions of the security API within the programs. The office does not deal with the security, hence the security settings can only be determined by the registry settings which are not completely set by the office's setup. The  key under which the security settings are recorded is not set. This poses no problem because the dcomcnfg.exe configuration tools sets it automatically. [Update] As of OOo 3.2, an AppID entry is written. Using dcomcnfg it will be displayed as "OpenOffice.org Service Manager" or "StarOffice Service Manager".

To access the service manager remotely, the client must have launch and access permission. Those permissions appear as sub-keys of the  and have binary values. The values can be edited with dcomcnfg. Also the identity of the service manager must be set to "Interactive User". When the office is started as a result of a remote activation of the service manager, it runs under the account of the currently logged-on user (the interactive user).

In case of callbacks (office calls into the client), the client must adjust its security settings so that incoming calls from the office are accepted. This happens when listener objects that are implemented as Automation objects (not UNO components) are passed as parameters to UNO objects, which in turn calls on those objects. Callbacks can also originate from the automation bridge, for example, when JScript  objects are used. Then, the bridge modifies the  object by its   interface. To get the interface, the bridge has to call  with a call back to the client.

To avoid these callbacks,  objects and   could be used.

To set security properties on a client, use the security API within a client program or make use of dcomcnfg again. The API can be difficult to use. Modifying the registry is the easiest method, simplified by dcomcnfg. This also adds more flexibility, because administrators can easily change the settings without editing source code and rebuilding the client. However, dcomcnfg only works with COM servers and not with ordinary executables. To use dcomcnfg, put the client code into a server that can be registered on the client machine. This not only works with exe servers, but also with in-process servers, namely dlls. Those can have an  entry when they are remote, that is, they have the   subkey set. To activate them an additional executable which instantiates the in-process server is required. At the first call on an interface of the server DCOM initializes security by using the values from the registry, but it only works if the executable has not called  beforehand.

To run JScript or VBScript programs, an additional program, a script controller that runs the script is required, for example, the Windows Scripting Host (WSH). The problem with these controllers is that they might impose their own security settings by calling  on their own behalf. In that case, the security settings that were previously set for the controller in the registry are not being used. Also, the controller does not have to be configurable by dcomcnfg, because it might not be a COM server. This is the case with WSH (not WSH remote).

To overcome these restrictions write a script controller that applies the security settings before a scripting engine has been created. This is time consuming and requires some knowledge about the engine, along with good programming skills. The Windows Script Components (WSC) is easier to use. A WSC is made of a file that contains XML, and existing JScript and VBS scripts can be put into the respective XML Element. A wizard generates it for you. The WSC must be registered, which can be done with regsvr32.exe or directly through the context menu in the file explorer. To have an AppID entry, declare the component as remotely accessible. This is done by inserting the  attribute into the registration element in the wsc file:

When the WSC is registered, there will be an appropriate  key in the registry. Use dcomcnfg to apply the desired security settings on this component. To run the script. An executable is required. For example:

In this example, the script code is contained in the run function. This is how the wsc file appears:

This WSC contains the WriterDemo example written in JScript.

Service: com.sun.star.bridge.oleautomation.BridgeSupplier
The component implements the com.sun.star.bridge.XBridgeSupplier2 interface and converts Automation values to UNO values. The mapping of types occurs according to the mappings defined in Type Mappings.

A programmer uses the  component to access the office. The COM class factory for  uses   internally to convert the UNO service manager into an Automation object. Another use case for the  might be to use the SDK without an office installation. For example, if there is a UNO component from COM, write code which converts the UNO component without the need of an office. That code could be placed into an ActiveX object that offers a function, such as.

The interface is declared as follows:

The value that is to be converted and the converted value itself are contained in s. The any is similar to the   type in that it can contain all possible types of its type system, but that type system only comprises UNO types and not Automation types. However, it is necessary that the function is able to receive as well as to return Automation values. In C++, void pointers could have been used, but pointers are not used with UNO IDL. Therefore, the any can contain a pointer to a  and that the type should be an unsigned long.

To provide the, write this C++ code:

Whether the argument  or the return value carries a   depends on the mode in which the function is used. The mode is determined by supplying constant values as the  and   arguments. Those constant are defined as follows:

The table shows the two possible modes:

When the function returns a, that is, a UNO value is converted to an Automation value, then the caller has to free the memory of the  :

The function also takes a process ID as an argument. The implementation compares the ID with the ID of the process the component is running in. Only if the IDs are identical a conversion is performed. Consider the following scenario:


 * There are two processes. One process, the server process, runs the  service. The second, the client process, has obtained the   interface by means of the UNO remote bridge. In the client process an Automation object is to be converted and the function   is called. The interface is actually a UNO interface proxy and the remote bridge will ensure that the arguments are marshaled, sent to the server process and that the original interface is being called. The argument   contains an   and must be marshaled as COM interface, but the remote bridge only sees an any that contains an unsigned long and marshals it accordingly. When it arrives in the server process, the   has become invalid and calls on it might crash the application.

Service: com.sun.star.bridge.OleBridgeSupplierVar1
This service has been deprecated as of OpenOffice.org 2.x.

Service: com.sun.star.bridge.oleautomation.ApplicationRegistration
This service registers a COM class factory when the service is being instantiated and deregisters it when the service is being destroyed. The class factory creates a service manager as an Automation object. All UNO objects created by the service manager are then automatically converted into Automation objects.

Service: com.sun.star.bridge.oleautomation.Factory
This service creates ActiveX components and makes them available as UNO objects which implement. For the purpose of component instantiation, the OleClient implements the com.sun.star.lang.XMultiServiceFactory interface. The COM component is specified by its programmatic identifier (ProgId).

Although any ActiveX component with a ProgId can be created, a component can only be used if it supports  and provides type information through.

Unsupported COM Features
The Automation objects provided by the bridge do not provide type information. That is,  and   return. Also, there are no COM type libraries available and the objects do not implement the  interface.

processes only one name at a time. If an array of names is passed, then a  is returned for the first name.

does not support named arguments and the pExcepInfo and puArgErr parameter.

CLI Language Binding
The CLI (Common Language Infrastructure) language binding allows CLI programs to connect to an office and perform operations on it, such as creating and converting documents. A CLI-program consists of IL (Intermediate Language) code and can be produced by tools, such as C# or VB .NET compilers. The binding provides for type-safe programming. All UNO types are available as CLI types.

CLI - components are not fully supported. That is, although one can implement UNO interfaces in a CLI language there is no support for creating instances by means of the office's service manager. More accurately, one cannot register the components with unopkg and load them later from within the running program.

Currently the language binding is only available for the Windows operating system.

Terms
The following CLI-related abbreviations are used within this document:


 * IL = Intermediate Language
 * CLI = Common Language Infrastructure
 * CLR = Common Language Runtime
 * CTS = Common Type System

Requirements
The language binding is part of LibreOffice and is only available for Windows platforms. Refer to the documentation of the Microsoft .NET Framework to find out which operating systems are supported and which prerequisites have to be fulfilled. A Microsoft .NET Framework Version 1.1 must be installed.

As of OpenOffice.org 3.0 the .NET Framework 3.5 is required. Only one office may be installed. That is, no different versions or different brands of LibreOffice may be installed at the same time.

Supported Languages
The language binding should generally enable all CLI languages to be used with UNO. However, not every language may be suitable, because of missing features. For example, since UNO uses out parameters, the CLI language must support it as well, which is not given in JScript .NET.

The language binding was successfully tested with C# and VB code. We found that the C++ compiler provides false IL code in conjunction with arrays of enumeration values. This can cause exceptions, as the following example shows:

When calling, then a   is thrown. Looking at the IL reveals two significant differences to code produced by a C# compiler. First, the array  is constructed as array of   and not as. Therefore  would return a type for   instead of. Second,  is compiled to a " " instruction instead of " ". The example caused the same exception even when compiled with a compiler from the framework SDK version 1.1.

As a workaround you can provide arrays of  for pure in parameter. There is no workaround for in/out and out parameter. Return values are not affected by this bug.

Another problem is that C++ does not support jagged arrays. Although it is possible to create an array of  it is no substitute for a jagged array, since they have different types. Therefore, the compiler will produce an error if you try to pass an  instance rather then a jagged array.

Running on 64 Bit Platforms
OOo 3.0, built by Sun, is built for a 32 bit Windows but also runs on 64 bit. To run cli applications on 64 bit one needs to have the 32bit .Net Framework installed (version 3.5 as of OOo 3.0). The application must be built for the x86 platform (see platform switch of csc.exe), otherwise it will not run. If it uses anycpu or x64 then the application will be loaded in a 64 bit process. In order to connect to LibreOffice and creating the bridge, the process must load a couple of dlls from OOo, which are 32 bit dlls. This does not work and a System.BadImageFormatException is thrown.

To check if the application is set to run as 32 bit application one uses the corflags.exe program which is part of the .NET Framework SDK. For example: corflags myapp.exe could produce this output (not complete):

Version  : v2.0.50727 CLR Header: 2.5 PE       : PE32 CorFlags : 3 ILONLY   : 1 32BIT    : 0 Signed   : 0

If the PE flag has the value PE32 then this binary can also run in a 64 bit process. The 32BIT flag controls the type of process which is created for this application. On a 64bit system a value of 32BIT=0 will cause a 64 bit process. 32BIT=1 will force the use of a 32 bit process.

If the application was build with "anycpu" then it is possible to later change the 32BIT flag with

corflags /32BIT+ This will set 32BIT=1 and therefore the application will always be loaded into a 32 bit process even if run on 64 bit system.

Changes in OpenOffice.org 3.0
cli_types.dll is replaced by cli_oootypes.dll and cli_uretypes.dll and both are installed in the GAC. The cli_uretypes.dll contains all types available to the URE (defined in project udkapi) and cli_oootype.dll contains all office types (defined in project offapi).

The consequence of this is that all client programs which linked with cli_types.dll do not work anymore. They need to be rebuild and reference cli_uretypes.dll and cli_oootypes.dll instead.

The 3.0 release contains a bug which prevents the bridge from working (see issue 95255 for details). This is fixed in 3.0.1.

For debugging purposes it may be convenient to install OOo with the /a switch, which prevents writing registry entries and installing the assemblies in the GAC. To make the client program work, one has to:
 * copy all assemblies which are otherwise in the GAC next to the client executable. They can be found in the OpenOffice.org/URE/bin and OpenOffice.org/Basis 3/program folders.


 * Set UNO_PATH to the program folder of the brand layer, for example, C:\staroffice\Sun\staroffice 9\program
 * run the client program in same console

The Language Binding DLLs
The language binding comprises five libraries prior v 3.0 and six libraries as of OOo version 3.0. Some of these do not need to be dealt with by the programmer, but others must be used during the development or deployment process. All libraries compiled for the CLI are prefixed by "cli_" to separate them from ordinary native libraries:

These libraries were first shipped with OpenOffice.org 2.x. Except for cli_uno.dll, they are installed in the Global Assembly Cache (GAC).
 * cli_uno.dll: This is the CLI-UNO bridge that realizes the interaction between managed code (CLI) and UNO. It does not provide public types.
 * cli_cppuhelper.dll: Provides bootstrapping code to bootstrap native UNO, that is, to use various UNO services implemented in different languages. Types from this assembly are always used in client programs.
 * cli_ure.dll: Contains helper classes which are useful for implementing UNO interfaces. Types from this assembly are not necessarily used.
 * cli_types.dll: (removed in OOo 3.0) Provides classes and interfaces for components and client programs. It is a collection of all UNO interfaces currently used in the office. Types from this assembly are always used in client programs.
 * cli_uretypes.dll: (as of OOo 3.0) Provides the URE types. These types were contained in cli_types.dll before OOo 3.0.
 * cli_oootypes.dll: (as of OOo 3.0) Provides the office types. These types were contained in cli_types.dll before OOo 3.0.
 * cli_basetypes.dll: As the name implies, it provides some base types, which are already needed for the generated UNO types in cli_basetypes.dll. Since it contains the Any type, probably all programs need this library. Also the cli_uretypes.dll and cli_oootypes.dll depend on it.

Modules
As of OpenOffice.org 3.0 the following modules contain the CLI-UNO libraries:

cli_ure: cli_uno.dll, cli_ure.dll, cli_basetypes.dll, cli_uretypes.dll, cli_cppuhelper.dll

unoil: cli_oootypes.dll

Type Mapping
The CLI language binding is intended to run programs that connect to an office and that are written in a CLI compliant language. Therefore, all UNO Types have to be mapped to a CLI type. However, it is not necessary to have mappings for all CLI types unless you intend to interact with arbitrary CLI programs (not UNO components) from UNO (binary UNO). Since we focus on interaction with UNO components, we will restrict the mapping to UNO types. Other mappings might be introduced at a later stage (for example,, indexers, and so on.).

This document only covers the complete mapping of UNO types to CLI.

UNO types will be mapped to types from the Common Type System (CTS). Although some types are not CLS compliant (for example, unsigned types are used), they should be usable from various CLI programming languages.This document will represent CTS types by the respective class from the framework class library, where possible. .NET languages may provide particular build-in types, which can be used instead of those classes. For example, in C# you can use int rather than.

Since this type mapping specification targets the CLI as a whole, mappings can be given as IL assembler code. However, for easier understanding, mappings are mostly described by C# examples.

Metadata is provided in IL assembler syntax.

This document refers to the subject of how UNO types are defined in a certain language. This subject is to be regarded as hypothetical, since current implementations of the UNO runtime do not allow for new types to be introduced by language bindings. For example, a component written in C# or Java may contain new types which should be used across the UNO system. Currently, new types have to be provided as binary output of the unoidl-write compiler, which have to be made known to UNO, for example by adding to the URE_MORE_TYPES deployment variable. In a remote scenario, those type binaries must be present in all participating processes.

Type Name Decoration
IDL type names can potentially conflict with type names of a particular language, or a name from one language could also be used in another language. In these cases, interactions between those language environments are prone to errors, because types are misinterpreted and incorrectly handled. To counter the problem, the bridge decorates all imported and exported type names. For example, the type  is transferred from one environment into a .NET environment. Then the bridge prefixes the name with a string, so that the name is  When that type is sent back into the environment where it came from, then the bridge removes the " " prefix. Likewise, if a type that was defined in the CLI environment is transferred out of that environment, the name is prefixed with " " On return, the prefix will be removed again. For more information, see the concept paper Names in UNO. It can be found at: https://www.openoffice.org/udk/common/man/typenames.html.

When CLI types are declared, their names must not start with " " And types declared in UNOIDL must not start with " "

Simple Types
Simple types are mapped according to the following table.

1. In type declarations  is only used as a return type.

2. Similar to UNOs  there is a   enumeration which, however, does not contain a value for.

any
The  type will be mapped to a value type with the name. For example:

Although a  can represent all types, it was decided to not use it, for the following reasons:

First, in UNO only, an interface can have no value, which amounts to a null reference in C# or a null pointer in C++. The any can represent all uno types and additionally knows a void state. If the  is mapped to   then a CLI null reference would represent both an interface with a null value and a void. This distinction is important.

Second, the  can contain a particular interface. The consumer of the any knows exactly what type the  contains because of the provided type information, and is spared to determine the type by using casts.

The function  determines if the type class is of , in other words, if the any carries a value. The Any class also overrides the methods,,   and   from. There is also an  implementation which takes an   as argument. Hence the argument does not require unboxing as the overridden  method does. The any offers a bunch of constructors. For complete initialization it needs a  and a  :

public Any(System.Type type, System.Object)

Because the type of an object can be identified by, it is in some cases unnecessary to specify the type. Therefore there are also a couple of constructors, which only take the object as argument. For example:

public Any(char value) public Any(bool value)

However, when an UNO interface or struct is to be put in an  then the type must be explicitly provided, because structs can be derived and interface implementations can derive from multiple interfaces. Then  may then not return the intended type.

At this point the polymorphic structs needs to be mentioned in particular, because they currently require to provide a  in the Any constructor:

The Any contains a static member VOID which can be used whenever a void Any is needed:

The type and value contained in the  can be accessed by read-only properties named   and. One can also subsequently assign new values by calling. This can be useful, when handling arrays. For example:

One could also construct new  instances and assign them:

and the read access to the  property may change the state of the instance. Therefore one has to make sure that concurrent access is synchronized. When an  is default constructed, for example when creating an array of  s, then the member representing the  's type is null. Only when the  property is accessed and   has not been called yet, then the type is set to. This setting of the member may interfere with, hence the need for synchronization. However, in most cases synchronization is not necessary.

The  is contained in the   and the C# source file can be found in the cli_ure project.

interface
General

UNOIDL interface types map to CTS interface types with public accessibility. If a UNO interface inherits an interface, then the target interface will do as well.

Methods
General

All methods have public accessibility. The method names and argument names of the target type are the same as the respective names in the UNOIDL declaration. The return type and argument types correspond to the mapping of the respective UNOIDL types. The order of the arguments is the same as in the UNOIDL declaration.

Types declared in a CLI language, do not need to provide argument names in methods. Only their types are required. If names are provided, then this is done for all arguments.

Exceptions, which are expressed by the raised keyword in UNOIDL, have no bearing on the target type. The IL assembler method head does not reflect the exception. However, metadata, which holds information about possible UNO exceptions, is available.

Parameter Types (in,out,in/out)

The CLI supports three kinds of parameter types: by-ref parameters, by-value parameters and typed-reference parameters. Typed-reference parameters are very special types and are of no relevance to this specification (for more information, see class ). Within the CLR, objects are always passed as references. However, only objects that have a by-ref type, which is indicated by the trailing '&' in the type name, can be assigned a new value. Therefore, by-ref parameters can be used as in/out or just out parameters.

Parameters can have an in-attribute, out-attribute (CLI: InAttribute, OutAttribute) or both. They are generated in different ways:

Parameter types are mapped as follows:
 * By using language-specific key words, such as out in C#, which produces an OutAttribute
 * By using attribute classes, such as  and
 * By explicitly defining parameters during dynamic code creation with the  framework (see method  )

In metadata a "by-value" type is represented by a CLI build-in type or class name. A "by-ref" type additionally has an '&' appended. The InAttribute is represented by "[in]" and the OutAttribute by " [out]". If both attributes are applied, then a combination of both markers appears in the metadata. For example:

.method public hidebysig newslot virtual abstract instance int16 func1([in] int16 'value') cil managed { }

.method public hidebysig newslot virtual abstract instance int16 func2([out] int16& 'value') cil managed { }

.method public hidebysig newslot virtual abstract instance int16 func3([out][in] int16& 'value') cil managed { }

It depends on the language, what ways of parameter passings are supported. The language may also require a special syntax with dedicated keywords to mark a parameter to use a particular parameter passing convention. Therefore a general example cannot be provided. However, here are examples in C# and C++:

When one uses UNO types in a language that does not support the different parameter passings, then that language might not be suitable for programming UNO code. For example, JScript .NET does not support out parameters. Therefore it is inappropriate for most UNO applications.

A word about in-parameters. An UNOIDL in-parameter may not be changed from within the method. This could be expressed in C++ with a const modifier. For example:

The const modifier, however, is not supported by the CLI and has only a meaning in code written with the same language. For example, the C++ compiler creates an attribute, that will be evaluated by the same compiler but it is not guaranteed that other compilers make use of this attribute. For example:

// IL asm .method public hidebysig newslot virtual abstract instance void func(class Foo modopt([Microsoft.VisualC]Microsoft.VisualC.IsConstModifier) a) cil managed

Since the C# compiler does not evaluate the IsConstModifier attribute, the argument could be modified in a C# implementation of that function.

A compiler could evaluate the InAttribute and prevent that the argument is changed. Since that is not required, in-parameters could be modified dependent on the language being used. Therefore, every developer must follow the rule:

Exceptions

CLI methods are not particularly marked if they throw exceptions. In ordner to not loose the information what exceptions can be thrown by a UNO interface method a custom attribute may be applied to that method. All exceptions which are indicated by the keyword raises in a UNOIDL interface description are mapped to a custom attribute, named. One only need to use this attribute when one declares a new type in a CLI language. Otherwise it is only for informational purposes. The climaker tool from the cli language binding provides assemblies in which methods which throw exceptions (other than ) are tagged with this Attribute. If the attribute is not present a method can still throw a  or any other exception which is derived from it.

One-Way Methods

The UNOIDL oneway attribute has no counterpart in the CLI. To retain this information, the custom attribute  is applied.

Attributes
The UNOIDL attribute type is mapped to a CTS property. The type of the property is the mapping of the type used in the attribute declaration in UNOIDL.

A UNOIDL readonly attribute is mapped to a read-only property. That is, the property only has a get method.

UNOIDL method attributes can throw exceptions. These are expressed by the custom attribute  which shall be applied to the get and/or set method. It shall only be applied if an exception is specified in UNOIDL.

XInterface
The CLI language binding does not support com.sun.star.uno.XInterface. Wherever a com.sun.star.uno.XInterface occurs in a UNOIDL method signature, the method in the mapping contains a.

com.sun.star.uno.XInterface is used to control the lifetime of UNO objects. Since the CLR uses a garbage collection mechanism, similar to Java and Smalltalk, there is no need for an explicit control of an object's lifetime.

com.sun.star.uno.XInterface also provides a means to obtain other implemented interfaces by calling com.sun.star.uno.XInterface:queryInterface. In CLI, code this is done by casting an object to the desired interface. If the object does not implement this interface, then a  is thrown.

For the previously stated reasons, the com.sun.star.uno.XInterface adds no functionality to an implementation. Therefore, no mapping for this interface exists.

struct
A UNO IDL struct is mapped to CTS class type, which supports inheritance (that is, no sealed attribute in the class head). A struct, such as defined by the C# struct keyword, is a value type and therefore has no inheritance support. For example:

IL class header:

.class public sequential ansi sealed beforefieldinit Foo extends [mscorlib]System.ValueType { }

Also, the class inherits  if the UNO struct has no base struct. Otherwise the target class inherits the class that is the mapping of the respective UNO base struct. Members of a UNOIDL struct are mapped to their respective target types. All members of the target type have public accessibility.

For ease of use, the target has two constructors: one default constructor without arguments and one that completely initializes the struct. The order of the arguments to the second constructor corresponds to the position of the members in the respective UNOIDL description. That is, the first argument initializes the member that is the mapping of the first member of the UNOIDL description. The names of the arguments are the same as the members that they initialize. Both constructors initialize their base class appropriately by calling a constructor of the base class. In some languages, instance constructor initializers are implicitly provided. For example, in C# base does not need to be called in the initializer.

If a struct inherits another struct, the order of the arguments in a constructor is as follows: the arguments for the struct at the root come first, followed by the arguments for the deriving struct, and so on. The order of the arguments that initialize members of the same struct depends again on the position of the respective members within the UNOIDL declaration. The argument for the first member appears first, followed by the argument for the second member, and so on. The constructor calls the constructor of the inherited class and passes the respective arguments.

Polymorphic structs
As of OpenOffice.org 2.x, there is a new UNO IDL feature, the polymorphic struct. This struct is similar to C++ templates, in that the struct is parameterized and members can use the parameters as types. For example:

As one can see, the type that is provided by the parameter is a System.Object. When instantiating a polymorphic struct, one need not initialize the members that are Objects. They can be null.

const
If a UNOIDL const value is contained in a module rather then a constants group, then a class is generated with the name of the const value. The only member is the constant. For example:

In contrast to the Java mapping, interfaces are not used, because interfaces with fields are not CLS compliant.

constants
A constants type is mapped to a class with the same name as the constants group. The namespace of the class reflects the UNOIDL module containing the constants type. For example:

enum
UNOIDL enumeration types map to a CTS enumeration. The target type must inherit  and have the attribute sealed. For example:

sequence
A UNOIDL sequence maps to a CTS array. The target type may only contain CLS types, which is always the case since this mapping specification only uses CLS types. The target array has exactly one dimension. Therefore a sequence that contains a sequence is mapped to an array that contains arrays. Those arrays are also called "jagged arrays". For example:

exception
The com.sun.star.uno.Exception is mapped to an exception that uses the same namespace and name. All members have public accessibility. The target  inherits   and has one member only, which represents the Context member of the UNOIDL com.sun.star.uno.Exception. The target type does not have a member that represents the Message member of the UNOIDL type. Instead, it uses the Message property of.

For ease of use the target has two constructors: one default constructor without arguments and one that completely initializes the exception. The order of the arguments to the second constructor corresponds to the position of the members in the respective UNOIDL description. That is, the first argument initializes the member, which is the mapping of the first member of the UNOIDL description. The names of the arguments are the same as the members, which they initialize. Both constructors initialize their base class appropriately by calling a constructor of the base class. For example:

All UNO exceptions inherit com.sun.star.uno.Exception. Likewise their mappings also inherit from the. The order of the constructor's arguments then depends on the inheritance chain. The arguments for the initialization of  come first followed by the arguments for the derived exception and so on. The order of the arguments, which initialize the members of the same exception, depends again from the position of the respective members within the UNOIDL declaration. The argument for the first member appears first, followed by the argument for the second member, and so on. The constructor calls the constructor of the inherited class and passes the respective arguments. For example, let us assume we have a exception  which has two members:

services
For every single-interface-based service a CLI class is provided which enables typesafe instantiation of the service. For example, if there were a service  then it could be created in these two way

If a service constructor method is specified to throw exceptions, then the respective CLI method hat the custom attribute  applied to it.

See chapter Services/Service Constructors under Data Types for further details.

singletons
Similar to the services there are CLI classes for new-style singletons. For example, if there were a singleton com.sun.star.TestSingleton then it could be created in these two ways:

Additional Structures
Whether a complete type mapping can be achieved depends on the capabilities of a target environment. UNOIDL attributes which have no counterpart in the CLI are mapped to custom attributes. Hence no information becomes lost in the mapping. The attributes can be evaluated by:


 * The CLI - UNO bridge
 * Tools that generated source code files or documentation
 * Tools that use CLI assemblies to dynamically provide type information to UNO.

ExceptionAttribute Attribute
The uno.ExceptionAttribute can be applied to interface methods, property methods (get or set) or service constructor methods. It contains the information about what exceptions can be thrown by the method. The source code can be found at cli_ure/source/basetypes/uno/ExceptionAttribute.cs.

OnewayAttribute
The uno.OnewayAttribute is applied to those interface methods that UNOIDL declarations have tapplied he oneway attribute to. The source code can be found at cli_ure/source/basetypes/uno/OnewayAttribute.cs.

BoundPropertyAttribute
The uno.BoundPropertyAttribute is applied to properties whose respective UNOIDL declarations have the bount attibute applied to it. The source code can be found at cli_ure/source/basetypes/uno/BoundPropertyAttribute.cs.

TypeParametersAttribute
The uno.TypeParametersAttribute is applied to polymorphic structs. It keeps the information of the names in the type list of the struct. For example, a struct may be named com.sun.star.Foo<T, C>. Then the attribute containes the information, that the name of the first type in the type list is "T" and the second is "C".

This attribute will become obsolete when the CLI supports templates and the CLI-UNO language binding has adopted them. The source code can be found at cli_ure/source/basetypes/uno/TypeParametersAttribute.cs.

ParameterizedTypeAttribute
The uno.ParameterizedTypeAttribute is applied to fields of polymorphic structs whose type is specified in the type list. For example, the struct may be declared as com.sun.star.Foo<T,C> and member is of type "T". The member of the CLI struct would then be of type System.Object and the applied ParameterizeTypeAttribute would declare that the actual type is "T".

This attribute will become obsolete when the CLI supports templates and the CLI-UNO language binding has adopted them. The source code can be found at cli_ure/source/basetypes/uno/ParameterizedTypeAttribute.cs.

TypeArgumentsAttribute
The uno.TypeArgumentsAttribute is applied to instantiations of the polymorphic struct. That is, it appears when a polymorphic struct is used as return value, parameter or field. It contains the information about the actual types in the type list. For example, a function has a parameter of type com.sun.star.StructFoo<char, long>. Then the CLI parameter has the attribute which contains the list of types, in this case System.Char and System.Int32.

This attribute will become obsolete when the CLI supports templates and the CLI-UNO language binding has adopted them. The source code can be found at cli_ure/source/basetypes/uno/TypeArgumentsAttribute.cs.

PolymorphicType
The uno.PolymorphicType is derived from System.Type. It is used whenever a type from a polymorphic struct is needed. For example:

If the caller intends to pass the type of polymorphic struct in func1, then they cannot use typeof(structname). Instead, a uno.PolymorphicType must be created. The same goes for func2, when the any contains a polymorphic struct. If a UNO method returns the type of polymorphic struct, then the bridge ensures that a PolymorphicType is returned rather than System.Type.

The PolymorphicType is constructed by a static function:

public static PolymorphicType GetType(Type type, string name)

The function ensures that there exist only one instance for the given combination of type and name.

This attribute will become obsolete when the CLI supports templates and the CLI-UNO language binding has adopted them. The source code can be found at cli_ure/source/basetypes/uno/PolymorphicType.cs.

Lifetime Management and Obtaining Interfaces
The CLR is similar to the Java runtime in that it keeps track of the object's lifetime rather then leaving the task to the developer. Once an object is no longer referenced (unreachable), the CLR deletes that object. Therefore, reference counting, as used in C++, is not necessary. Hence com.sun.star.uno.XInterface:acquire and com.sun.star.uno.XInterface:release are not needed.

com.sun.star.uno.XInterface has a third method, com.sun.star.uno.XInterface:queryInterface, which is used to query an object for a particular interface. This language binding does not use com.sun.star.uno.XInterface:queryInterface. Instead objects can be cast to the desired interface. For example:

Writing Client Programs
To build a client program it must reference at least  and. Also cli_ure can be referenced when one of its classes is used. These libraries are installed in the GAC and the program folder of the office installation. The referencing is done by certain compiler switches, for example /AI for C++ (with managed extensions) or /reference for the C# compiler. C++ also requires dlls to be specified by using the #using:

In c# with Visual Studio mscorlib is included when you create your project. If you want to see it in your references, edit your .csproj file and add:

<ItemGroup> <Reference Include="mscorlib" /> <Reference Include="System" />

For cli_basetypes, cli_cppuhelper, cli_oootypes, cli_ure, and cli_uretypes .dll files, I add them in the Visual Studio project References. I found cli_cppuhelper here C:\WINDOWS\assembly\GAC_32\cli_cppuhelper\1.0.22.0__ce2cb7e279207b9e\cli_cppuhelper.dll and the others in GAC_MSIL near here C:\WINDOWS\assembly\GAC_MSIL\cli_basetypes\1.0.19.0__ce2cb7e279207b9e\cli_basetypes.dll. Then add the following in my source when one of their classes is used:

The following example discusses how to use services provided by a running office process:

The starting point of every remote client program is a component context. It is created by a static function, which is provided by the class. The context provides the service manager by which UNO components can be created. However, these components would still be local to the client process, that is, they are not from a running office and therefore cannot affect the running office. What is actually needed is a service manager of a running office. To achieve that, the component com.sun.star.bridge.UnoUrlResolver is used, which is provided by the local service manager. The com.sun.star.bridge.UnoUrlResolver connects to the remote office and creates a proxy of the office's service manager in the client process. The example code (OOo 2.x) is as follows:

For OOo 3.x the code is this:

Alternatively one could use pipe connection, in which case, no socket needs to be created beforehand.

Usually one would provide a path to the uno.ini (URE/bin folder) in the office installation. In that case and if one does not want to provide particular bootstrap variables (the second parameter of defaultBootstrap_InitialComponentContext) then one can use the version of defaultBootstrap_InitialComponentContext which does not take arguments:

With the factory of the running office at hand, all components of the remote office are accessible.

For a client to connect to a running office, the office must have been started with the proper parameters. In this case, the command line looks like this:

or using a pipe connection

Other useful command line options for LibreOffice are: -minimized -invisible -nologo -nolockcheck -nodefault

See also UNO Interprocess Connections.

As of OOo 3.0 it is necessary to provide an ini file which contains the path to the fundamental.ini when using the defaultBootstrap_InitialComponentContext functions. The ini file must have the same name as the client program (without extension). For example, the program is named client.exe then there must be also a client.ini in the same folder. The path to the fundamental.ini must be a file URL. That is special characters need to be encoded. For example, a space is represented as %20. An example:

Another, simpler way of starting and connection to LibreOffice is to use the function. The function finds LibreOffice by using the registry ( or  ) or the environment variable. The function uses the key in  first, and if it does not exists it uses the key in. In case the office does not start, check these keys. Also make sure that the PATH environment variable does not contain the program path to a different office.

This method of getting the context no even require an ini file. The limitation is, that it always uses a pipe connection. In other word, it is suitable for a local LibreOffice but not for one on a different machine.

It is possible to write UNO applications that do not depend on a running office. Then, you would typically provide an own database of registered services. For more information, see Manual Component Installation.

The CLI-UNO language binding does not support UNO components that are written in a CLI language. Instead, it acts as a liaison between a CLI client program and an office. The client program usually obtains UNO objects from the office and performs operations on them. Therefore, it is rarely necessary to implement UNO interfaces.

To receive notifications from UNO objects, it is necessary to implement the proper interfaces. Also, interfaces can be implemented in order to use the objects as arguments to UNO methods.

Interfaces are implemented by declaring a class that derives from one or more interfaces, and which provides implementations for the interface methods. How this is done is covered by the respective documentation of the various CLI languages.

The Override Problem
The term "override problem" describes a problem that occurs when a virtual function of a base object becomes unreachable because an interface method overrides the implementation of the base class. For example, all CLI objects derive from. If an interface has a method that has the same signature as one of 's methods, then the respective method of System.Object is unreachable if the interface method is virtual.

For example, consider the following declaration of the interface  and its implementing class :

If the method  of an instance is called, then the implementation of the interface method is invoked. For example:

This may not be intended, because the interface method likely has a different semantic than its namesake of.

A solution is to prevent the interface method from overriding the method of  without making the interface method non-virtual. The CLI provides a remedy by way of the " " flag, which is attached to the method header in the IL code. CLI languages may have different means for denoting a method with " ".

The following examples show ways of implementing  in different languages, so that   can still be called.

In C# there are different ways provide an implementation:

The keyword new inserts the  attribute in the CLI method header. This implementation cannot be overridden in an inheriting class.

This method can be overridden in a derived class.

This implementation cannot be overridden in a derived class. An instance of the implementing class must be cast to  before the method can be called.

This implementation cannot be overridden in a derived class.

This method can be overridden.

Important Interfaces and Implementations (Helper Classes)
UNO objects implement a set of UNO interfaces, some of which are always dependent on requirements. The interfaces below belong to the assembly called  within your office's program directory:

com.sun.star.lang.XTypeProvider (recommended for all UNO objects)

com.sun.star.uno.XWeak (recommended for all UNO objects)

com.sun.star.lang.XComponent (optional)

com.sun.star.beans.XPropertySet (optional, required for service implementation concerning defined service properties)

Making object development a little easier, the language binding provides helper implementations for most of the above interfaces. The helper classes belong to the  namespace, and are contained in the assembly called. Notice that there is a helper missing that implements a listener container similar to the one in C++ or Java. The main reason for its existence is to ensure the automatic notification of event listeners (see com.sun.star.lang.XComponent, com.sun.star.lang.XEventListener ). The CLI languages provide a simple mechanism for events (delegates) which makes a helper class superfluous in this particular case, because event notification is easily implemented using language features.

uno.util.WeakBase
This class implements the com.sun.star.lang.XTypeProvider and com.sun.star.uno.XWeak interfaces. com.sun.star.uno.XWeak is used to implement a UNO weak reference mechanism, and it may seem strange that  is not used. You have to remember that your UNO object is held from within other language environments that do not support weak references. This way, weak references are implemented as a UNO concept. Of course, the helper implementation uses, as can every component or application, as long as it is not passed into calls to UNO interfaces. Also, the compiler will not be able to compile the implementation properly.

uno.util.WeakComponentBase
This class derives from  and implements the com.sun.star.lang.XComponent interface. Use this class as base class if the component needs to perform a special cleanup. The class has two protected member functions that are called upon disposal of the object:


 * - called before all registered event listeners are notified
 * - called after all registered event listeners are notified. Resource cleanup should be performed in this method.

Inherit from  and override the appropriate methods.