We use the term “component” here in a very limited, well defined sense. Unfortunately, within the broader field, and even within UNO itself, the term is also used with other meanings, typically to mean some form of collection of what is here called components.
A UNO component is the smallest unit in the UNO component model. A UNO component is a software artifact that has the following properties:
- A component has a component implementation name, by which it is known to its deployment environment. Component implementation names are always relative to a given deployment environment.
- To describe the interface that clients of a component can use, the component links to a component client interface via a component client interface name.
- One of the more obvious requirements a component has on its deployment
environment is that the component itself will be a client of other
components, which it uses internally in its implementation. To describe
this requirement, a component has component dependencies, a map
from component instantiation names to component client
The component dependencies only cover static dependencies. A component may also have dynamic dependencies; for example, at runtime an instance of that component may take an input N, compute a service instantiation name N′ from it, and expect to obtain a component instance with a certain component client interface when passing N′ to the component manager.
A component client interface is a set of UNO interface types (referenced by their—globally unique—names), together with a marker for each interface type, denoting it as either mandatory or optional, and semantic constraints on the functionality of those interface types and the runtime presence of any optional interface types. There is one constraint on the set of interface types: no optional interface type from the set may be an (indirect) base type of any mandatory interface type from the set.
Each component client interfaces is associated with a globally unique component client interface name. This association must be globally unique; otherwise, clients of a component (who describe their expectations of the component by means of a component client interface name) could not be sure that, at runtime, they receive a component instance that meets their expectations. (This requirement of globally unique names for component client interfaces is the same as for named UNO types.)
At runtime, instances of UNO components can be obtained from a component manager. The component instances are UNO objects that behave according to their respective component client interfaces. A component manager works based on component instantiation names. Each code that uses a component manager must document what component instances (adhering to which component client interfaces) it expects to obtain from the component manager, with which component instantiation names. Throughout the lifetime of a component instance, that instance has access to a certain component manager; what other component instances the instance itself expects to obtain from that component manager is documented by the component's component dependencies (but note that this only covers the component's static dependencies).
How UNO Implements the Conceptual Model
Components are often also called services in UNO. The conceptual component client interfaces are implemented as UNOIDL service descriptions, whose names serve as the conceptual component client interface names. The conceptual properties of components are represented in UNO as follows:
- The conceptual component implementation name breaks up into two parts.
First, each component has an implementation name, which must be unique
within the deployment environment (see
com.sun.star.lang.XServiceInfo.getImplemenationName). Second, the
services.rdbregistry associates each implementation name with an activator (e.g.,
com.sun.star.loader.SharedLibrary) and an activator-dependent location (e.g., a platform-dependent shared library pathname, in case of the
- The association of a component with a component client interface is
again done in the
services.rdbregistry, by associating each implementation name with one or more UNOIDL service description names.
- The conceptual component dependencies are not actually recorded for a
UNO component. Rather, they can implicitly be derived from the component's
code. However, with the XML module description approach, they would be
recorded as (optional)
service-dependencyelement contains the name of a UNOIDL service description, serving as both the component instantiation name and the component client interface name.
A UNOIDL service description appears to be richer than a corresponding conceptual component client interface (which, after all, is little more than a set of UNO interface types with associated semantic constraints). But all of this additional richness can be reduced to syntactic sugar:
- A UNOIDL service description implicitly adds
com.sun.star.lang.XServiceInfoto the set of interface types, with respective constraints on their functionality (e.g.,
com.sun.star.lang.XTypeProvider.getTypesmust return all the mandatory interface types covered by the service description).
- A UNOIDL service description can contain property declarations. These
map to functional constraints on an explicitly or implicitly exported
interface type like
com.sun.star.beans.XPropertySet. For example, if a UNOIDL service description contains the property declaration
[property] long P, and exports the mandatory interface type
com.sun.star.beans.XPropertySet, then there is the functional constraint that a call to
ANYvalue of type
- A UNOIDL service description can contain other service descriptions,
marked as either mandatory or optional. This can be considered a textual
inclusion mechanism (the contents of the contained service description is
copied into the containing service description, marking all copied entities
as optional in case the contained service description was marked as
optional), together with possible functional constraints on the resulting
component client interface (e.g., if an optional included service
description exported two mandatory interface types, then
com.sun.star.lang.XTypeProvider.getTypesat runtime must return either both of them or neither of them).
In UNO, the conceptual component managers are instances of
com.sun.star.lang.ServiceManager. UNO does not distinguish between
the conceptional component client interface names and component instantiation
names—the names of UNOIDL service descriptions are used for both
When a component instance is created at runtime, it is passed a
com.sun.star.uno.XComponentContext, through which it has access to
com.sun.star.lang.ServiceManager. The guarantee that this
ServiceManager fulfils the component's component dependencies is
indirect and weak: since component instantiation names are (globally unique)
names of UNOIDL service descriptions, which in turn are the same as component
client interface names, it is guaranteed that if a
returns any component instance at all for a given component instantiation name
from the component dependencies, then that instance will adhere to the
corresponding component client interface from the component dependencies.
However, there is no guarantee that the
ServiceManager does not
return null instead. Also, there is no way to guarantee that a component's
dynamic dependencies are satisfied.