[ Previous document | Content Table | Next document ]

# 15 Configuration Management

## 15.1 Overview

### 15.1.1 Capabilities

The OpenOffice.org configuration management component provides a uniform interface to get and set OpenOffice.org configuration data in an organized manner, independent of the physical data store used for the data.

The configuration API can be used to get and set existing configuration options. Additionally you can extend the configuration with new settings for your own purposes. For details, see 15.5 Configuration Management - Customizing Configuration Data.

### 15.1.2 Architecture

OpenOffice.org configuration data describes the state or environment of a UNO component or the OpenOffice.org application. There are different kinds of configuration data:

- Static configuration: This is data that describes the configuration of the software and hardware environment. This data is set by a setup tool and does not change at runtime. An example of static configuration data is information about installed filters.

- Explicit settings: This is preference data that can be controlled by the user explicitly. There is a dedicated UI to change these settings. An example explicit settings are the settings controlled through the Tools – Options dialogs in OpenOffice.org.

- Implicit settings: This is status information that is also controlled by the user, but the user does not change explicitly. The application tracks this state in the background, making it persistent across application sessions. An example implicit settings are window positions and states, or a list of the recently used documents.

This list is not comprehensive, but indicates the range of data characteristically stored by configuration management.

The configuration management component organizes the configuration data in a hierarchical structure. The hierarchical structure and the names and data types of entries in this database are described by a schema. Only data that conforms to one of the installed schemas is stored in the database.

The hierarchical database stores any hierarchical information that can be described as a configuration schema, but it is optimized to work with the data needed for application configuration and preferences. Small data items having a well-defined data type are supported efficiently, whereas large, unspecific binary objects should not be stored in the configuration database. These objects should be stored in separate files so that the configuration keeps the URLs of these files only.

Configuration schemas are provided by the authors of applications and components that use the data. When a component is installed, the corresponding configuration schemas are installed into the configuration management system.

Configuration data is stored in a backend data store. In OpenOffice.org, the standard backend consists of XML files stored in a directory hierarchy. You can add another backend component to be used instead. Support for combining data from multiple backends is planned for a future release.

Illustration 1.1: Configuration layers

For a given schema, multiple layers of data may exist that are merged together at runtime. One or more of these layers define default settings, possibly shared by several users. Additionally, there is a layer specific to a single user that contains personal preferences overriding the shared settings. In normal operations all changes to data affect only this user-specific layer.

Access to the merged configuration data for a user is managed by a com.sun.star.configuration.ConfigurationProvider object to connect to a data source, fetch and store data, and merge layers.

This provider provides views on the configuration data. A view is a subset of the entire configuration that can be navigated as an object hierarchy. The objects in this hierarchy represent nodes of the configuration hierarchy to navigate to other nodes and access values of data items.

All configuration items have a fixed type and a name.

The type is prescribed by the schema. The following kinds of items are available:

- 'Properties' are data items that contain a single data value or an array of values from a limited set of basic types.

- 'Groups' are structural nodes that contain a collection of child items of various types. The number and names of children, as well as their types, are fixed by the schema. Structural and data items can be mixed within one group.

- 'Sets' are structural nodes that serve as dynamic containers for a variable number of elements. These elements must be all data or all structural items, and they must all be uniform. In the first case, all values have the same basic type, and in the latter case, all the sub-trees have the same structure. The schema contains templates for container elements, which are prototypes of the element structure.

Properties hold the actual data. Group nodes form the structural skeleton defined in the schema. Set nodes are used to dynamically add and remove configuration data within the confines of the schema. Taken together, they can be used to build hierarchical structures of arbitrary complexity.

Each configuration item has a name that uniquely identifies the item within its parent, that is, the node in the hierarchical tree that immediately contains the item under consideration. Paths spanning multiple levels of the hierarchy are built similarly to UNIX file system paths. The separator for individual name components in paths is a forward slash ('/'). Paths that begin with a slash are considered 'absolute paths' and must completely specify the location of an item within the hierarchy. Paths that start directly with a name are relative paths and describe the location of an item within one of its ancestors in the hierarchy.

The top-level subdivisions of the configuration hierarchy are called configuration modules. Each configuration module has a schema that describes the data items available within that module. Modules are the unit of schema installation. The name of a configuration module must be globally unique. The names of configuration modules have an internal hierarchical structure using a dot ('.') as a separator, similar to Java package names. The predefined configuration modules of OpenOffice.org use package names from the super-package "org.openoffice.*".

The names of container elements are specified when data items are added to a container. Data item names in the schema are limited to ASCII letters, digits and a few punctuation marks, but there are no restrictions applied to the names of container elements. This requires special handling when referring to a container element in a path. A path component addressing a container element takes the form <template-pattern>['<escaped-name>']. Here <template-pattern> can be the name of the template describing the element or an asterisk "*" to match any template. The <escaped-name> is a representation of the name of the element where a few forbidden characters are represented in an escaped form borrowed from XML. The quotes delimiting the <escaped-name> may alternatively be double quote characters "". The following character escapes are used:

Character | Escape
--- | ---
& | &amp;
" | &quot;
' | &apos;

In the table below, are some escaped forms for invented entries in the Set node /org.openoffice.Office.TypeDetection/Filters for (fictitious) filters:

Filter Name | Path Component
--- | ---
Plain Text | Filter['Plain Text']
Q & A Book | *["Q &amp; A Book"]
Bob's Filter | *['Bob&apos;s Filter']

The UIName value of the last example filter would have an absolute path of /org.openoffice.Office.TypeDetection/Filters/Filter['Bob&apos;s Filter']/UIName.

In several places in the configuration management, API arguments are passed to a newly created object instance as Sequence, for example, in the argument to com.sun.star.lang.XMultiServiceFactory:createInstanceWithArguments. Such arguments are type com.sun.star.beans.NamedValue .

| For compatibility with older versions, arguments of type com.sun.star.beans.PropertyValue are accepted as well. Only the Name and Value fields need to be filled.
--- | ---

## 15.2 Object Model

The centralized entry point for configuration access is a com.sun.star.configuration.ConfigurationProvider object. This object represents a connection to a single configuration data source providing access to configuration data for a single user.

The com.sun.star.configuration.AdministrationProvider service is an extended version of this service that enables administrative access to shared configuration data.

The com.sun.star.configuration.ConfigurationProvider serves as a factory for configuration views. A configuration view provides access to the structure and data of a subset of the configuration database. This subset is accessible as a hierarchical object tree. When creating a configuration view, parameters are provided that describe the subset of the data to retrieve. In the simplest case, the only argument is an absolute configuration path that identifies a structural configuration item. This parameter is given as an argument named "nodepath". The configuration view then encompasses the sub-tree which is rooted in the indicated item.

A configuration view is not represented by a single object, but as an object hierarchy formed by all the items that are part of the selected sub-tree. The object that comes closest to representing the view as a whole is the root element of that tree. This object is the one returned by the factory method of the com.sun.star.configuration.ConfigurationProvider. In addition to the simple node-oriented interfaces, it also supports interfaces that apply to the view as a whole.

Illustration 1.2: Configuration object model overview

Within a configuration view, UNO objects with access interfaces are used to represent all structural items. Value items are not represented as objects, but retrieved as types, usually wrapped inside an any.

The following types are supported for data items:

string | Plain Text (Sequence of [printable] Unicode characters)
boolean | Boolean value (true/false)
short | 16-bit integer number
int | 32-bit integer number
long | 64-bit integer number
double | Floating point number
binary | Sequence of uninterpreted octets

Value items contain a single value, or a sequence or array of one of the basic types. The arrays must be homogeneous, that is, mixed arrays are not supported. The configuration API treats array types as atomic items, there is no built-in support for accessing or modifying individual array elements.

| Binary values should be used only for small chunks of data that cannot easily be stored elsewhere. For large BLOBs it is recommended to store links, for example, as URLs, in the configuration. For example, bitmaps for small icons might be stored in the configuration, whereas large images are stored externally.
--- | ---

All of the structural objects implement the service com.sun.star.configuration.ConfigurationAccess that specifies interfaces to navigate the hierarchy and access values within the view. Different instances of this service support different sets of interfaces. The interfaces that an object supports depends on its structural type, that is, is it a group or a set, and context, that is, is it a group member, an element of a set or the root of the view.

A configuration view can be read-only or updatable. This is determined by the access requested when creating the view, but updatability may also be restricted by access rights specified in the schema or data. The basic com.sun.star.configuration.ConfigurationAccess service specifies read-only operations. If an object is part of an updatable view and is not marked read-only in the schema or the data, it implements the extended service com.sun.star.configuration.ConfigurationUpdateAccess. This service adds interfaces to change values and modify set nodes.

These service names are also used to create the configuration views. To create a view for read access, call com.sun.star.lang.XMultiServiceFactory:createInstanceWithArguments at the com.sun.star.configuration.ConfigurationProvider to request a com.sun.star.configuration.ConfigurationAccess. To obtain an updatable view, the service com.sun.star.configuration.ConfigurationUpdateAccess must be requested.

The com.sun.star.configuration.AdministrationProvider supports the same service specifiers, but creates views on shared layers of configuration data.

The object initially returned when creating a configuration view represents the root node of the view. The choice of services and interfaces it supports depends on the type of configuration item it represents. The root object has additional interfaces pertaining to the view as a whole. For example, updates of configuration data within a view are combined into batches of related changes, which exhibit transaction-like behavior. This functionality is controlled by the root object of the view.

## 15.3 Configuration Data Sources

Creating a view to configuration data is a two-step process.

1. Connect to a data source by creating an instance of a com.sun.star.configuration.ConfigurationProvider for user preferences or a com.sun.star.configuration.AdministrationProvider for shared preferences.

2. Ask the provider to create an access object for a specific nodepath in the configuration database using com.sun.star.lang.XMultiServiceFactory:createInstanceWithArguments(). The access object can be a com.sun.star.configuration.ConfigurationAccess or a com.sun.star.configuration.ConfigurationUpdateAccess.

### 15.3.1 Connecting to a Data Source

The first step to access the configuration database is to connect to a configuration data source.

To obtain a provider instance ask the global com.sun.star.lang.ServiceManager for a com.sun.star.configuration.ConfigurationProvider. Typically the first lines of code to get access to configuration data look similar to the following: (Config/ConfigExamples.java)

// get my global service manager

XMultiServiceFactory xServiceManager = (XMultiServiceFactory)UnoRuntime.queryInterface(

XMultiServiceFactory.class, this.getRemoteServiceManager(

"uno:socket,host=localhost,port=2083;urp;StarOffice.ServiceManager"));

final String sProviderService = "com.sun.star.configuration.ConfigurationProvider";

// create the provider and remember it as a XMultiServiceFactory

XMultiServiceFactory xProvider = (XMultiServiceFactory)

UnoRuntime.queryInterface(XMultiServiceFactory.class,

xServiceManager.createInstance(sProviderService));

This code creates a default com.sun.star.configuration.ConfigurationProvider. The most important interface a com.sun.star.configuration.ConfigurationProvider implements is com.sun.star.lang.XMultiServiceFactory that is used to create further configuration objects.

The com.sun.star.configuration.ConfigurationProvider always operates in the user mode, accessing data on behalf of the current user and directing updates to the user's personal layer.

For administrative access to manipulate the default layers the com.sun.star.configuration.AdministrationProvider is used. When creating this service, additional parameters can be used that select the layer for updates or that contain credentials used to authorize administrative access. The backend that is used determines which default layers exist, how they are addressed and how administrative access is authorized.

The standard file-based backend has several shared layers. One of these layers is used to store shared default data. The files for this layer are located in the share directory of the OpenOffice.org installation. To gain administrative access to this layer, no additional parameters are needed. An com.sun.star.configuration.AdministrationProvider for this backend automatically tries to read and write this shared layer. Additionally there are special layers that are used by the pkgchk tool for deploying configuration data associated with uno packages. For details, see 4.9.1 Writing UNO Components - Deployment Options for Components - UNO Package Installation.

Authorization for the file-based backend is done by the operating system based upon file access privileges. The current user requires write privileges in the shared configuration directory if an AdministrationProvider is suppose to update configuration data.

A com.sun.star.configuration.AdministrationProvider is created in the same way as a com.sun.star.configuration.ConfigurationProvider.

// get my global service manager

XMultiServiceFactory xServiceManager = getServiceManager();

// get the arguments to use

com.sun.star.beans.PropertyValue aReinitialize = new com.sun.star.beans.PropertyValue()

aReinitialize.Name = "reinitialize"

aReinitialize.Value = new Boolean(true);

Object[] aProviderArguments = new Object[1];

aProviderArguments[0] = aReinitialize;

final String sAdminService = "com.sun.star.configuration.AdministrationProvider";

// create the provider and remember it as a XMultiServiceFactory

XMultiServiceFactory xAdminProvider = (XMultiServiceFactory)

UnoRuntime.queryInterface(XMultiServiceFactory.class,

xServiceManager.createInstanceWithArguments(sAdminService,aProviderArguments));

As you see in the example above, the default com.sun.star.configuration.AdministrationProvider supports a special parameter for reinitialization:

Parameter Name | Type | Default | Comments
--- | --- | --- | ---
reinitialize | boolean | false | Discard any cached information from previous runs and regenerate from scratch.

Some backend implementations use cached data to speed up access. If the reinitialize parameter is true, this cache will be recreated from the XML data when the AdministrationProvider is created. With the current implementation, the parameter has no effect.

When establishing the connection, specify the parameters that select the backend to use and additional backend-specific parameters to select the data source. When there are no parameters given, the standard configuration backend and data source of the OpenOffice.org installation is used.

The standard values for these parameters may be found in the configuration file configmgr(.ini|rc) (.ini on Windows, rc on Unix) in the program directory of the OpenOffice.org installation. The INI entries have a prefix “CFG_” before the parameter name.

| The list of available backends and the parameters they support may change in a future release. Using these parameters is normally not necessary and therefore is not recommended.
--- | ---

The following parameters are supported to select the backend component to use:

Parameter Name | Type | Default | Comments
--- | --- | --- | ---
BackendService | string | "com.sun.star.configuration.backend.LocalSingleBackend" | This must be a UNO service or implementation name that can be used to create a service instance. The instance created must support either service com.sun.star.configuration.backend.Backend or service com.sun.star.configuration.backend.SingleBackend
BackendWrapper | string | "com.sun.star.configuration.backend.SingleBackendAdapter" | This parameter is used only, if the service specified by parameter “BackendService” only implements service Backend. It must be a UNO service or implementation name that can be used to create a service instance. The instance created must support service com.sun.star.configuration.backend.BackendAdapter.

The following parameter was formerly supported to select the type of backend to use:

Parameter Name | Type | Default | Comments
--- | --- | --- | ---
servertype | string | "uno" | Other values are not supported any more in OpenOffice.org. This setting formerly was used to select between several internal backend implementations.

For the " com.sun.star.configuration.backend.LocalSingleBackend " backend, the following parameters are used to select the location of data:

Parameter Name | Type | Default | Comments
--- | --- | --- | ---
SchemaDataUrl | string or string[] | $(installurl)/share/registry/schema + locations used for uno packages | This must be a file URL pointing to a directory, a whitespace-separated list of such URLs or a sequence of such URLs. The locations are searched in the given order until a schema is found.
DefaultLayerUrls | string or string[] | $(installurl)/share/registry + locations used for uno packages | This must be a file URL pointing to a directory, a whitespace-separated list of such URLs or a sequence of such URLs. The layers are merged in the given order. The data is located in subdirectory data of each location. Additionally locale-specific data can be placed in subdirectory res.
UserLayerUrl | string | $(userurl)/user/registry | This must be a file URL pointing to a directory. If this is one of the entries of parameter “DefaultLayerUrls”, then only the entries before it will be used as default layers. The data is located in the subdirectory data of the given location.

Arguments can be provided that determine the default behavior of views created through this com.sun.star.configuration.ConfigurationProvider. The following parameters may be used for this purpose:

Parameter Name | Type | Default | Comments
--- | --- | --- | ---
Locale | string | The user's locale. | This parameter was called “locale” in a former version. The old name is still supported for compatibility.
EnableAsync | boolean | true | This parameter was called “lazywrite” in a former version. The old name is still supported for compatibility.

| The default configuration provider obtained when no arguments are given will always be the same object. Be careful not to call com.sun.star.lang.XComponent:dispose() on this shared com.sun.star.configuration.ConfigurationProvider. If you provide any arguments, then a new instance is created. You must then call com.sun.star.lang.XComponent:dispose() on this com.sun.star.configuration.ConfigurationProvider.
--- | ---

### 15.3.2 Using a Data Source

After a configuration provider is obtained, call com.sun.star.lang.XMultiServiceFactory:createInstanceWithArguments() to create a view on the configuration data.

The following arguments can be specified when creating a view:

Parameter Name | Type | Default | Comments
--- | --- | --- | ---
nodepath | string | - | This parameter is required. It contains an absolute path to the root node of the view.
Locale | string | The user's locale (or "*") | Using this parameter, specify the locale to be used for selecting locale-dependent values. Use the ISO code for a locale, for example, en-US for U.S. English.
EnableAsync | boolean | true | This parameter was called “lazywrite” in a former version. The old name is still supported for compatibility.
depth | integer | (unlimited) | This parameter causes the view to be truncated to a specified nesting depth.
nocache | boolean | false | This parameter is deprecated.

| If the special value "*" is used for the locale parameter, values for all locales are retrieved. In this case, a locale-dependent property appears as a set item. The items of the set are the values for the different locales. They will have the ISO identifiers of the locales as names. This mode is the default if you are using an com.sun.star.configuration.AdministrationProvider. It can be used if you want to assign values for different locales in a targeted manner. Usually this is logical in an administration or installation context only.
--- | ---

To create a read-only view on the data, the service com.sun.star.configuration.ConfigurationAccess is requested:

// Create a specified read-only configuration view

public Object createConfigurationView(String sPath) throws com.sun.star.uno.Exception {

// get the provider to use

XMultiServiceFactory xProvider = getProvider();

// The service name: Need only read access:

final String sReadOnlyView = "com.sun.star.configuration.ConfigurationAccess";

// creation arguments: nodepath

com.sun.star.beans.PropertyValue aPathArgument = new com.sun.star.beans.PropertyValue();

aPathArgument.Name = "nodepath";

aPathArgument.Value = sPath;

Object[] aArguments = new Object[1];

aArguments[0] = aPathArgument;

// create the view

Object xViewRoot = xProvider.createInstanceWithArguments(sReadOnlyView, aArguments);

return xViewRoot;

}

To obtain updatable access, the service com.sun.star.configuration.ConfigurationUpdateAccess is requested. In this case, there are additional parameters available that control the caching behavior of the configuration management component:

// Create a specified updatable configuration view

Object createUpdatableView(String sPath, boolean bAsync) throws com.sun.star.uno.Exception {

// get the provider to use

XMultiServiceFactory xProvider = getProvider();

// The service name: Need update access:

final String cUpdatableView = "com.sun.star.configuration.ConfigurationUpdateAccess";

// creation arguments: nodepath

com.sun.star.beans.PropertyValue aPathArgument = new com.sun.star.beans.PropertyValue();

aPathArgument.Name = "nodepath";

aPathArgument.Value = sPath;

// creation arguments: commit mode - write-through or write-back

com.sun.star.beans.PropertyValue aModeArgument = new com.sun.star.beans.PropertyValue();

aModeArgument.Name = "EnableAsync";

aModeArgument.Value = new Boolean(bAsync);

Object[] aArguments = new Object[2];

aArguments[0] = aPathArgument;

aArguments[1] = aModeArgument;

// create the view

Object xViewRoot = xProvider.createInstanceWithArguments(cUpdatableView, aArguments);

return xViewRoot;

}

A com.sun.star.configuration.AdministrationProvider supports the same service specifiers, but creates views on shared layers of configuration data. It supports additional parameters to select the exact layer to work on or to specify authorization credentials. Independent of the backend, the following parameter is supportedly the com.sun.star.configuration.AdministrationProvider :

Parameter Name | Type | Default | Comments
--- | --- | --- | ---
Entity | string | - | Identifies an entity that the backend can map to a sequence of layers to merge and a target layer for updates.

If no Entity is provided, the com.sun.star.configuration.AdministrationProvideruses the entity the backend provides through com.sun.star.configuration.backend.XBackendEntities:getAdminEntity(). The supported entities and their meaning depend on the backend. For the default file-based backend an entity is a file URL that points to the base directory of a layer.

For a com.sun.star.configuration.AdministrationProvider, the default value for the locale parameter is "*".

## 15.4 Accessing Configuration Data

### 15.4.1 Reading Configuration Data

Illustration 1.3: ConfigurationAccess services

The com.sun.star.configuration.ConfigurationAccess service is used to navigate through the configuration hierarchy and reading values. It also provides information about a node and its context.

The following example shows how to collect or display information about a part of the hierarchy. For processing elements and values, our example uses its own callback Java interface IConfigurationProcessor:

// Interface to process information when browsing the configuration tree

public interface IConfigurationProcessor {

// process a value item

public abstract void processValueElement(String sPath_, Object aValue_);

// process a structural item

public abstract void processStructuralElement(String sPath_, XInterface xElement_);

};

Then, we define a recursive browser function:

// Internal method to browse a structural element recursively in preorder

public void browseElementRecursively(XInterface xElement, IConfigurationProcessor aProcessor)

throws com.sun.star.uno.Exception {

// First process this as an element (preorder traversal)

XHierarchicalName xElementPath = (XHierarchicalName) UnoRuntime.queryInterface(

XHierarchicalName.class, xElement);

String sPath = xElementPath.getHierarchicalName();

//call configuration processor object

aProcessor.processStructuralElement(sPath, xElement);

// now process this as a container of named elements

XNameAccess xChildAccess =

(XNameAccess) UnoRuntime.queryInterface(XNameAccess.class, xElement);

// get a list of child elements

String[] aElementNames = xChildAccess.getElementNames();

// and process them one by one

for (int i=0; i< aElementNames.length; ++i) {

Object aChild = xChildAccess.getByName(aElementNames[i]);

// is it a structural element (object) ...

if ( aChild instanceof XInterface ) {

// then get an interface

XInterface xChildElement = (XInterface)aChild;

// and continue processing child elements recursively

browseElementRecursively(xChildElement, aProcessor);

}

// ... or is it a simple value

else {

// Build the path to it from the path of

// the element and the name of the child

String sChildPath;

sChildPath = xElementPath.composeHierarchicalName(aElementNames[i]);

// and process the value

aProcessor.processValueElement(sChildPath, aChild);

}

}

}

Now a driver procedure is defined which uses our previously defined routine createConfigurationView() to create a view, and then starts processing:

/** Method to browse the part rooted at sRootPath

of the configuration that the Provider provides.

All nodes will be processed by the IConfigurationProcessor passed.

*/

public void browseConfiguration(String sRootPath, IConfigurationProcessor aProcessor)

throws com.sun.star.uno.Exception {

// create the root element

XInterface xViewRoot = (XInterface)createConfigurationView(sRootPath);

// now do the processing

browseElementRecursively(xViewRoot, aProcessor);

// we are done with the view - dispose it

// This assumes that the processor

// does not keep a reference to the elements in processStructuralElement

((XComponent) UnoRuntime.queryInterface(XComponent.class,xViewRoot)).dispose();

xViewRoot = null;

}

Finally, as an example of how to put the code to use, the following is code to print the currently registered file filters:

/** Method to browse the filter configuration.

Information about installed filters will be printed.

*/

public void printRegisteredFilters() throws com.sun.star.uno.Exception {

final String sProviderService = "com.sun.star.configuration.ConfigurationProvider";

final String sFilterKey = "/org.openoffice.Office.TypeDetection/Filters";

// browse the configuration, dumping filter information

browseConfiguration( sFilterKey,

new IConfigurationProcessor () { // anonymous implementation of our custom interface

// prints Path and Value of properties

public void processValueElement(String sPath_, Object aValue_) {

System.out.println("\tValue: " + sPath_ + " = " + aValue_);

}

// prints the Filter entries

public void processStructuralElement( String sPath_, XInterface xElement_) {

// get template information, to detect instances of the 'Filter' template

XTemplateInstance xInstance =

( XTemplateInstance )UnoRuntime.queryInterface( XTemplateInstance .class,xElement_);

// only select the Filter entries

if (xInstance != null && xInstance.getTemplateName().endsWith("Filter")) {

XNamed xNamed = (XNamed)UnoRuntime.queryInterface(XNamed.class,xElement_);

System.out.println("Filter " + xNamed.getName() + " (" + sPath_ + ")");

}

}

} );

}

For access to sub-nodes, a com.sun.star.configuration.ConfigurationAccess supports container interfaces com.sun.star.container.XNameAccess and com.sun.star.container.XChild. These interfaces access the immediate child nodes in the hierarchy , as well as com.sun.star.container.XHierarchicalNameAccess for direct access to items that are nested deeply.

These interfaces are uniformly supported by all structural configuration items. Therefore, they are utilized by code that browses a sub-tree of the configuration in a generic manner.

Parts of the hierarchy where the structure is known statically can also be viewed as representing a complex object composed of properties, that are composed of sub-properties themselves. This model is supported by the interface com.sun.star.beans.XPropertySet for child access and com.sun.star.beans.XHierarchicalPropertySet for access to deeply nested properties within such parts of the hierarchy. Due to the static nature of property sets, this model does not carry over to set nodes that are dynamic in nature and do not support the associated interfaces.

For effective access to multiple properties, the corresponding com.sun.star.beans.XMultiPropertySet and com.sun.star.beans.XMultiHierarchicalPropertySet interfaces are supported.

| In a read-only view, all properties are marked as com.sun.star.beans.PropertyAttribute:READONLY in com.sun.star.beans.XPropertySetInfo. Attempts to use com.sun.star.beans.XPropertySet:setPropertyValue() to change the value of a property fail accordingly.
--- | ---

Typically, these interfaces are used to access a known set of preferences. The following example reads grid option settings from the OpenOffice.org Calc configuration into this structure:

class GridOptions

{

public boolean visible;

public int resolution_x;

public int resolution_y;

public int subdivision_x;

public int subdivision_y;

};

These data may be read by a procedure such as the following. It demonstrates different approaches to read data:

// This method reads information about grid settings

protected GridOptions readGridConfiguration() throws com.sun.star.uno.Exception {

// The path to the root element

final String cGridOptionsPath = "/org.openoffice.Office.Calc/Grid";

// create the view

Object xViewRoot = createConfigurationView(cGridOptionsPath);

// the result structure

GridOptions options = new GridOptions();

// accessing a single nested value

// the item /org.openoffice.Office.Calc/Grid/Option/VisibleGrid is a boolean data item

XHierarchicalPropertySet xProperties =

(XHierarchicalPropertySet)UnoRuntime.queryInterface(XHierarchicalPropertySet.class, xViewRoot);

Object aVisible = xProperties.getHierarchicalPropertyValue("Option/VisibleGrid");

options.visible = ((Boolean) aVisible).booleanValue();

// accessing a nested object and its subproperties

// the item /org.openoffice.Office.Calc/Grid/Subdivision has sub-properties XAxis and YAxis

Object xSubdivision = xProperties.getHierarchicalPropertyValue("Subdivision");

XMultiPropertySet xSubdivProperties = (XMultiPropertySet)UnoRuntime.queryInterface(

XMultiPropertySet.class, xSubdivision);

// String array containing property names of sub-properties

String[] aElementNames = new String[2];

aElementNames[0] = "XAxis";

aElementNames[1] = "YAxis";

// getPropertyVAlues() returns an array of any objects according to the input array aElementNames

Object[] aElementValues = xSubdivProperties.getPropertyValues(aElementNames);

options.subdivision_x = ((Integer) aElementValues[0]).intValue();

options.subdivision_y = ((Integer) aElementValues[1]).intValue();

// accessing deeply nested subproperties

// the item /org.openoffice.Office.Calc/Grid/Resolution has sub-properties

// XAxis/Metric and YAxis/Metric

Object xResolution = xProperties.getHierarchicalPropertyValue("Resolution");

XMultiHierarchicalPropertySet xResolutionProperties = (XMultiHierarchicalPropertySet)

UnoRuntime.queryInterface(XMultiHierarchicalPropertySet.class, xResolution);

aElementNames[0] = "XAxis/Metric";

aElementNames[1] = "YAxis/Metric";

aElementValues = xResolutionProperties.getHierarchicalPropertyValues(aElementNames);

options.resolution_x = ((Integer) aElementValues[0]).intValue();

options.resolution_y = ((Integer) aElementValues[1]).intValue();

// all options have been retrieved - clean up and return

// we are done with the view - dispose it

((XComponent)UnoRuntime.queryInterface(XComponent.class, xViewRoot)).dispose();

return options;

}

A com.sun.star.configuration.ConfigurationAccess also supports the interfaces com.sun.star.container.XNamed, com.sun.star.container.XHierarchicalName and com.sun.star.beans.XPropertySetInfo to retrieve information about the node, as well as interface com.sun.star.container.XChild to get the parent within the hierarchy. To monitor changes to specific items, register listeners at the interfaces com.sun.star.container.XContainer and com.sun.star.beans.XPropertySet.

The exact set of interfaces supported depends on the role of the node in the hierarchy. For example, a set node does not support com.sun.star.beans.XPropertySet and related interfaces, but it supports com.sun.star.configuration.XTemplateContainer to get information about the template that specifies the schema of elements. The root object of a configuration view does not support com.sun.star.container.XChild, but it supports com.sun.star.util.XChangesNotifier to monitor all changes in the whole view.

### 15.4.2 Updating Configuration Data

A com.sun.star.configuration.ConfigurationUpdateAccess provides operations for updating configuration data, by extendingthe interfaces supported by a com.sun.star.configuration.ConfigurationAccess.

Illustration 1.4: ConfigurationUpdateAccess services

For com.sun.star.beans.XPropertySet and related interfaces, the semantics are extended to set property values. Support for container interfaces is extended to set properties in group nodes, and insert or remove elements in set nodes. Thus, a com.sun.star.configuration.GroupUpdate supports interface com.sun.star.container.XNameReplace and a com.sun.star.configuration.SetUpdate supports com.sun.star.container.XNameContainer. Only complete trees having the appropriate structure are inserted for sets whose elements are complete structures as described by a template,. To support this, the set object is used as a factory that can create structures of the appropriate type. For this purpose, the set supports com.sun.star.lang.XSingleServiceFactory.

Updates done through a configuration view are only visible within that view, providing transactional isolation. When a set of updates is ready, it must be committed explicitly to become visible beyond this view. All pending updates are then sent to the configuration provider in one batch. This batch update behavior is controlled through interfacecom.sun.star.util.XChangesBatch that is implemented by the root element of an updatable configuration view.

| When a set of changes is committed to the provider it becomes visible to other views obtained from the same provider as an atomic and consistent set of changes. Thus, in the local scope of a single com.sun.star.configuration.ConfigurationProvider a high degree of transactional behavior is achieved. The configuration management component does not guarantee true transactional behavior. Committing the changes to the com.sun.star.configuration.ConfigurationProvider does not ensure persistence or durability of the changes. When the provider writes back the changes to the persistent data store, they become durable. Generally, the com.sun.star.configuration.ConfigurationProvider may cache and combine requests, so that updates are propagated to the data store at a later time. If several sets of changes are combined before being saved, isolation and consistency may be weakened in case of failure. As long as the backend does not fully support transactions, only parts of an update request might be stored successfully, thus violating atomicity and consistency. If failures occur while writing configuration data into the backend data store, the com.sun.star.configuration.ConfigurationProvider resynchronizes with the data stored in the backend. The listeners are notified of any differences as if they had been stored through another view. If an application has more stringent error handling needs, the caching behavior can be adjusted by providing arguments when creating the view. In summary, , there are few overall guarantees regarding transactional integrity for the configuration database, but locally, the configuration behaves as if the support is in place. Depending on the backend capabilities, the com.sun.star.configuration.ConfigurationProvider tries to provide the best approximation to transactional integrity that can be achieved considering the capabilities of the backend without compromising performance.
--- | ---

The following example demonstrates how the configuration interfaces are used to feed a user-interface for preference changes. This shows the framework needed to update configuration values, and demonstrates how listeners are used with configuration views. This example concentrates on properties in group nodes with a fixed structure. It uses the same OpenOffice.org Calc grid settings as the previous example. It assumes that there is a class GridOptionsEditor that drives a dialog to display and edit the configuration data:

// This method simulates editing configuration data using a GridEditor dialog class

public void editGridOptions() throws com.sun.star.uno.Exception {

// The path to the root element

final String cGridOptionsPath = "/org.openoffice.Office.Calc/Grid";

// create a synchronous view for better error handling (lazywrite = false)

Object xViewRoot = createUpdatableView(cGridOptionsPath, false);

// the 'editor'

GridOptionsEditor dialog = new GridOptionsEditor();

// set up the initial values and register listeners

// get a data access interface, to supply the view with a model

XMultiHierarchicalPropertySet xProperties = (XMultiHierarchicalPropertySet)

UnoRuntime.queryInterface(XMultiHierarchicalPropertySet.class, xViewRoot);

dialog.setModel(xProperties);

// get a listener object (probably an adapter) that notifies

// the dialog of external changes to its model

XChangesListener xListener = dialog.createChangesListener( );

XChangesNotifier xNotifier =

(XChangesNotifier)UnoRuntime.queryInterface(XChangesNotifier.class, xViewRoot);

xNotifier.addChangesListener(xListener);

if (dialog.execute() == GridOptionsEditor.SAVE_SETTINGS) {

// changes have been applied to the view here

XChangesBatch xUpdateControl =

(XChangesBatch) UnoRuntime.queryInterface(XChangesBatch.class,xViewRoot);

try {

xUpdateControl.commitChanges();

}

catch (Exception e) {

dialog.informUserOfError( e );

}

}

// all changes have been handled - clean up and return

// listener is done now

xNotifier.removeChangesListener(xListener);

// we are done with the view - dispose it

((XComponent)UnoRuntime.queryInterface(XComponent.class, xViewRoot)).dispose();

}

In this example, the dialog controller uses the com.sun.star.beans.XMultiHierarchicalPropertySet interface to read and change configuration values. If the grid options are changed and committed in another view, com.sun.star.util.XChangesListener:changesOccurred() is sent to the listener supplied by the dialog which can then update its display accordingly.

Note that a synchronous com.sun.star.configuration.ConfigurationUpdateAccess was created for this example (argument lazywrite==false). As the action here is driven by user interaction, synchronous committing is used to detect errors immediately.

Besides the values for the current user, there are also default values that are determined by merging the schema with any default layers. It is possible to retrieve the default values for individual properties, and to reset a property or a set node to their default states, thus backing out any changes done for the current user. For this purpose, group nodes support the interfaces com.sun.star.beans.XPropertyState and com.sun.star.beans.XMultiPropertyStates, offering operations to query if a property assumes its default state or the default value, and to reset an updatable property to its default state. The com.sun.star.beans.PropertyAttribute structs available through com.sun.star.beans.XPropertySetInfo:getProperty() are used to determine if a particular item or node supports this operation.

Individual set elements can not be reset because set nodes do not support com.sun.star.beans.XPropertyState. Instead a com.sun.star.configuration.SetAccess supports com.sun.star.beans.XPropertyWithStatethat resets the set as a whole.

The following is an example code using this feature to reset the OpenOffice.org Calc grid settings used in the preceding examples to their default state:

/// This method resets the grid settings to their default values

protected void resetGridConfiguration() throws com.sun.star.uno.Exception {

// The path to the root element

final String cGridOptionsPath = "/org.openoffice.Office.Calc/Grid";

// create the view

Object xViewRoot = createUpdatableView(cGridOptionsPath);

// ### resetting a single nested value ###

XHierarchicalNameAccess xHierarchicalAccess =

(XHierarchicalNameAccess)UnoRuntime.queryInterface(XHierarchicalNameAccess.class, xViewRoot);

// get using absolute name

Object xOptions = xHierarchicalAccess.getByHierarchicalName(cGridOptionsPath + "/Option");

XPropertyState xOptionState =

(XPropertyState)UnoRuntime.queryInterface(XPropertyState.class, xOptions);

xOptionState.setPropertyToDefault("VisibleGrid");

// ### resetting more deeply nested values ###

Object xResolutionX = xHierarchicalAccess.getByHierarchicalName("Resolution/XAxis");

Object xResolutionY = xHierarchicalAccess.getByHierarchicalName("Resolution/YAxis");

XPropertyState xResolutionStateX =

(XPropertyState)UnoRuntime.queryInterface(XPropertyState.class, xResolutionX);

XPropertyState xResolutionStateY =

(XPropertyState)UnoRuntime.queryInterface(XPropertyState.class, xResolutionY);

xResolutionStateX.setPropertyToDefault("Metric");

xResolutionStateY.setPropertyToDefault("Metric");

// ### resetting multiple sibling values ###

Object xSubdivision = xHierarchicalAccess.getByHierarchicalName("Subdivision");

XMultiPropertyStates xSubdivisionStates =

(XMultiPropertyStates)UnoRuntime.queryInterface(XMultiPropertyStates.class, xSubdivision);

xSubdivisionStates.setAllPropertiesToDefault();

// commit the changes

XChangesBatch xUpdateControl =

(XChangesBatch) UnoRuntime.queryInterface(XChangesBatch.class, xViewRoot);

xUpdateControl.commitChanges();

// we are done with the view - dispose it

((XComponent)UnoRuntime.queryInterface(XComponent.class, xViewRoot)).dispose();

}

| Currently, group nodes do not support the attribute com.sun.star.beans.PropertyAttribute:MAYBEDEFAULT set in the com.sun.star.beans.Property structure available from com.sun.star.beans.XPropertySetInfo. Attempts to use com.sun.star.beans.XPropertyState:setPropertyToDefault to reset an entire group node fail. Also, because the group nodes can not be reset, the com.sun.star.beans.XPropertyState:setPropertyToDefault or com.sun.star.beans.XMultiPropertyStates:setAllPropertiesToDefault cannot be used to reset all descendents of a node. It is intended to lift this restriction in a future release. To avoid unexpected changes in behavior when this change is introduced, you should apply com.sun.star.beans.XPropertyState:setPropertyToDefault only to actual properties, such as value items, or set nodes. In particular, you should avoid com.sun.star.beans.XMultiPropertyStates:setAllPropertiesToDefault() on group nodes.
--- | ---

A more comprehensive example is provided that shows how set elements are created and added, and how it employs advanced techniques for reducing the amount of data that needs to be loaded.

This example uses the OpenOffice.org configuration module org.openoffice.Office.DataAccess. This component has a set item DataSources that contains group items described by the template DataSourceDescription. A data source description holds information about the settings required to connect to a data source.

The template org.openoffice.Office.DataAccess/DataSourceDescription has the following properties that describe the data source connection:

Name | Type | Comment
--- | --- | ---
URL | String | Data source URL.
IsPasswordRequired | Boolean | Is a password needed to connect.
TableFilter | String [] | Filters tables for display.
TableTypeFilter | String [] | Filters tables for display.
User | String | User name to be used for connecting.
LoginTimeout | int | Default time-out for connection attempt.
SuppressVersionColumns | Boolean | Controls display of certain data.
DataSourceSettings | set node | Contains DataSourceSetting entriesthat contain driver-specific settings.
Bookmarks | set node | Contains Bookmark entries that link to related documents, for example, Forms.

It also contains the binary properties NumberFormatSettings and LayoutInformation that store information for layout and display of the data source contents. It also contains the set items Tables and Queries containing the layout information for the data access views.

The example shows a procedure that creates and saves basic settings for connecting to a new data source. It uses an asynchronous com.sun.star.configuration.ConfigurationUpdateAccess. Thus, when com.sun.star.util.XChangesBatch:commitChanges is called, the data becomes visible at the com.sun.star.configuration.ConfigurationProvider, but is only stored in the provider's cache. It is written to the data store at later when the cache is automatically flushed by the com.sun.star.configuration.ConfigurationProvider. As this is done in the background there is no exception when the write-back fails.

| The recommended method to configure a new data source is to use the com.sun.star.sdb.DatabaseContext service as described in 12.2.1 Database Access - Data Sources in OpenOffice.org API - DatabaseContext. This is a high-level service that ensures that all the settings required to establish a connection are properly set.
--- | ---

Among the parameters of the routine is the name of the data source that must be chosen to uniquely identify the data source from other parameters directly related to the above properties. There also is a parameter to pass a list of entries for the DataSourceSettings set.

The resulting routine is: (Config/ConfigExamples.java)

// This method stores a data source for given connection data

void storeDataSource(

String sDataSourceName,

String sDataSourceURL,

String sUser,

boolean bNeedsPassword,

int nTimeout,

com.sun.star.beans.NamedValue [] aDriverSettings,

String [] aTableFilter ) throws com.sun.star.uno.Exception {

// create the view and get the data source element in a

// helper method createDataSourceDescription() (see below)

Object xDataSource = createDataSourceDescription(getProvider(), sDataSourceName);

// set the values

XPropertySet xDataSourceProperties = (XPropertySet)UnoRuntime.queryInterface(

XPropertySet.class, xDataSource);

xDataSourceProperties.setPropertyValue("URL", sDataSourceURL);

xDataSourceProperties.setPropertyValue("User", sUser);

xDataSourceProperties.setPropertyValue("IsPasswordRequired", new Boolean(bNeedsPassword));

xDataSourceProperties.setPropertyValue("LoginTimeout", new Integer(nTimeout));

if (aTableFilter != null)

xDataSourceProperties.setPropertyValue("TableFilter", aTableFilter);

// ### store the driver-specific settings ###

if (aDriverSettings != null) {

Object xSettingsSet = xDataSourceProperties.getPropertyValue("DataSourceSettings");

// helper for storing (see below)

storeSettings( xSettingsSet, aDriverSettings);

}

// ### save the data and dispose the view ###

// recover the view root (helper method)

Object xViewRoot = getViewRoot(xDataSource);

// commit the changes

XChangesBatch xUpdateControl = (XChangesBatch) UnoRuntime.queryInterface(

XChangesBatch.class, xViewRoot);

xUpdateControl.commitChanges();

// now clean up

((XComponent) UnoRuntime.queryInterface(XComponent.class, xViewRoot)).dispose();

}

Notice the function createDataSourceDescription in our example. It is called to get a DataSourceDescription instance to access a pre-existing item, or create and insert a new item using the passed name.

The function is optimized to reduce the view to as little data as necessary. To this end it employs the depth parameter when creating the view.

| The "depth" parameter for optimization purposes is used here for demonstration purposes only. Use of the "depth" flag does not have a noticeable effect on performance with the current implementation of the OpenOffice.org configuration management components. Actually, there are few cases where the use of this parameter has any value.
--- | ---

This results in a view where descendents of the root are only included in the view up to the given nesting depth. In this case, where depth = 1, only the immediate children are loaded. If the requested item is found, the function gets a deeper view for only that item, otherwise it creates a new instance. In the latter case, the item returned is not the root of the view. (Config/ConfigExamples.java)

/** This method gets the DataSourceDescription for a data source.

It either gets the existing entry or creates a new instance.

The method attempts to keep the view used as small as possible. In particular there

is no view created, that contains data for all data source that are registered.

*/

Object createDataSourceDescription(XMultiServiceFactory xProvider, String sDataSourceName)

throws com.sun.star.uno.Exception {

// The service name: Need an update access:

final String cUpdatableView = "com.sun.star.configuration.ConfigurationUpdateAccess";

// The path to the DataSources set node

final String cDataSourcesPath = "/org.openoffice.Office.DataAccess/DataSources";

// creation arguments: nodepath

com.sun.star.beans.PropertyValue aPathArgument = new com.sun.star.beans.PropertyValue();

aPathArgument.Name = "nodepath";

aPathArgument.Value = cDataSourcesPath ;

// creation arguments: commit mode

com.sun.star.beans.PropertyValue aModeArgument = new com.sun.star.beans.PropertyValue();

aModeArgument.Name = "lazywrite";

aModeArgument.Value = new Boolean(true);

// creation arguments: depth

com.sun.star.beans.PropertyValue aDepthArgument = new com.sun.star.beans.PropertyValue();

aDepthArgument.Name = "depth";

aDepthArgument.Value = new Integer(1);

Object[] aArguments = new Object[3];

aArguments[0] = aPathArgument;

aArguments[1] = aModeArgument;

aArguments[2] = aDepthArgument;

// create the view: asynchronously updatable, with depth 1

Object xViewRoot =

xProvider.createInstanceWithArguments(cUpdatableView, aArguments);

XNameAccess xSetOfDataSources = (XNameAccess) UnoRuntime.queryInterface(

XNameAccess.class,xViewRoot);

Object xDataSourceDescriptor = null; // the result

if (xSetOfDataSources .hasByName(sDataSourceName)) {

// the element is there, but it is loaded only with depth zero !

try {

// the view should point to the element directly, so we need to extend the path

XHierarchicalName xComposePath = (XHierarchicalName) UnoRuntime.queryInterface(

XHierarchicalName.class, xSetOfDataSources );

String sElementPath = xComposePath.composeHierarchicalName( sDataSourceName );

// use the name of the element now

aPathArgument.Value = sElementPath;

// create another view now (without depth limit)

Object[] aDeepArguments = new Object[2];

aDeepArguments[0] = aPathArgument;

aDeepArguments[1] = aModeArgument;

// create the view: asynchronously updatable, with unlimited depth

xDataSourceDescriptor =

xProvider.createInstanceWithArguments(cUpdatableView, aDeepArguments);

if ( xDataSourceDescriptor != null) // all went fine

{

// dispose the other view

((XComponent)UnoRuntime.queryInterface(XComponent.class, xViewRoot)).dispose();

xViewRoot = null;

}

}

catch (Exception e) {

// something went wrong, we retry with a new element

System.out.println("WARNING: An exception occurred while creating a view" +

" for an existing data source: " + e);

xDataSourceDescriptor = null;

}

}

// do we have a result element yet ?

if (xDataSourceDescriptor == null) {

// get the container

XNameContainer xSetUpdate = (XNameContainer)UnoRuntime.queryInterface(

XNameContainer.class, xViewRoot);

// create a new detached set element (instance of DataSourceDescription)

XSingleServiceFactory xElementFactory = (XSingleServiceFactory)UnoRuntime.queryInterface(

XSingleServiceFactory.class, xSetUpdate);

// the new element is the result !

xDataSourceDescriptor = xElementFactory.createInstance();

// insert it - this also names the element

xSetUpdate.insertByName( sDataSourceName , xDataSourceDescriptor );

}

return xDataSourceDescriptor ;

}

A method is required to recover the view root from an element object, because it is unknown if the item is the root of the view or a descendant : (Config/ConfigExamples.java)

// This method get the view root node given an interface to any node in the view

public static Object getViewRoot(Object xElement) {

Object xResult = xElement;

// set the result to its parent until that would be null

Object xParent;

do {

XChild xParentAccess =

(XChild) UnoRuntime.queryInterface(XChild.class,xResult);

if (xParentAccess != null)

xParent = xParentAccess.getParent();

else

xParent = null;

if (xParent != null)

xResult = xParent;

}

while (xParent != null);

return xResult;

}

Another function used is storeDataSource is storeSettings to store an array of com.sun.star.beans.NamedValues in a set of DataSourceSetting items. A DataSourceSetting contains a single property named Value that is set to any of the basic types supported for configuration values. This example demonstrates the two steps required to add a new item to a set node: (Config/ConfigExamples.java)

/// this method stores a number of settings in a set node containing DataSourceSetting objects

void storeSettings(Object xSettingsSet, com.sun.star.beans.NamedValue [] aSettings)

throws com.sun.star.uno.Exception {

if (aSettings == null)

return;

// get the settings set as a container

XNameContainer xSettingsContainer =

(XNameContainer) UnoRuntime.queryInterface( XNameContainer.class, xSettingsSet);

// and get a factory interface for creating the entries

XSingleServiceFactory xSettingsFactory =

(XSingleServiceFactory) UnoRuntime.queryInterface(XSingleServiceFactory.class, xSettingsSet);

// now insert the individual settings

for (int i = 0; i < aSettings.length; ++i) {

// create a DataSourceSetting object

XPropertySet xSetting = (XPropertySet)

UnoRuntime.queryInterface(XPropertySet.class, xSettingsFactory.createInstance());

// can set the value before inserting

xSetting.setPropertyValue("Value", aSettings[i].Value);

// and now insert or replace as appropriate

if (xSettingsContainer.hasByName(aSettings[i].Name))

xSettingsContainer.replaceByName(aSettings[i].Name, xSetting);

else

xSettingsContainer.insertByName(aSettings[i].Name, xSetting);

}

}

Besides adding a freshly created instance of a template, a set item can be removed from a set and added to any other set supporting the same template for its elements, provided both sets are part of the same view. You cannot move a set item between views, as this contradicts the transactional isolation of views. The set item you removed in one view will still be in its old place in the other. If a set item is moved between sets in one view and the changes are committed, the change appears in another overlapping view as removal of the original item and insertion of a new element in the target location, not as relocation of an identical element.

| The methods com.sun.star.container.XNamed:setName() and com.sun.star.container.XChild:setParent() are supported by a com.sun.star.configuration.ConfigurationUpdateAccess only if it is a com.sun.star.configuration.SetElement. They offer another way to move an item within a set or from one set to another set. In the current release of OpenOffice.org, these methods are not supported correctly. You can achieve the same effect by using a sequence of remove item - insert item. In some cases you need to commit the changes in the current view between these two steps. To rename an item: (Config/ConfigExamples.java) /// Does the same as xNamedItem.setName(sNewName) should do void renameSetItem(XNamed xNamedItem, String sNewName) throws com.sun.star.uno.Exception { XChild xChildItem = (XChild) UnoRuntime.queryInterface(XChild.class, xNamedItem); XNameContainer xParentSet = (XNameContainer) UnoRuntime.queryInterface(XNameContainer.class, xChildItem.getParent()); String sOldName = xNamedItem.getName(); // now rename the item xParentSet.removeByName(sOldName); // commit needed to work around known bug getViewRoot(xParentSet).commitChanges(); xParentSet.insertByName(sNewName,xNamedItem); } To move an item to a different parent: (Config/ConfigExamples.java) /// Does the same as xChildItem.setParent( xNewParent ) should do void moveSetItem(XChild xChildItem, XNameContainer xNewParent) throws com.sun.star.uno.Exception { XNamed xNamedItem = (XNamed) UnoRuntime.queryInterface(XNamed.class, xChildItem); XNameContainer xOldParent = (XNameContainer) UnoRuntime.queryInterface(XNameContainer.class, xChildItem.getParent()); String sItemName = xNamedItem.getName(); // now rename the item xOldParent.removeByName(sItemName); // commit needed to work around known bug getViewRoot(xOldParent).commitChanges(); xNewParent.insertByName(sItemName,xChildItem); }
--- | ---

## 15.5 Customizing Configuration Data

The configuration management API is a data manipulation API. There is no support for data definition functionality. You cannot programmatically inspect, modify or create a configuration schema.

You can add configuration data for your own components by creating a new configuration schema file and installing it into the configuration backend. You can also create a configuration data file for either your own schema or an existing schema and import it into the configuration database. The file format used for both kinds of configuration documents is documented at http://util.openoffice.org/common/configuration/oor-document-format.html.

The standard file-based backend uses these file formats internally as well. Some information about the internal organization of this backend is available at http://util.openoffice.org/common/configuration/oor-registry.html.

### 15.5.1 Creating a Custom Configuration Schema

A configuration schema file is an XML file that conforms to the OOR Registry Component Schema Format defined in http://util.openoffice.org/common/configuration/oor-document-format.html . Normally, configuration schema files carry the extension .xcs.

| Not all schemas that can be described using the OOR Registry Component Schema Format are accepted by the current version of OpenOffice.org. In particular support for extensible nodes is limited: Only group nodes that otherwise contain no child elements may be marked as extensible. Such nodes are represented as set nodes having property elements in the API.
--- | ---

As an example, consider the schema of the rg.openoffice.Office.Addons component. For details about configuration for Addon components, see 4.7.3 Writing UNO Components - Integrating Components into OpenOffice.org - User Interface Add-Ons - Configuration .

<?xml version='1.0' encoding='UTF-8'?>

<oor:component-schema oor:name="Addons" oor:package="org.openoffice.Office" xml:lang="en-US" xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<templates>

<group oor:name="MenuItem">

<prop oor:name="URL" oor:type="xs:string"/>

<prop oor:name="Title" oor:type="xs:string" oor:localized="true"/>

<prop oor:name="ImageIdentifier" oor:type="xs:string"/>

<prop oor:name="Target" oor:type="xs:string"/>

<prop oor:name="Context" oor:type="xs:string"/>

<set oor:name="Submenu" oor:node-type="MenuItem"/>

</group>

<group oor:name="PopupMenu">

<prop oor:name="Title" oor:type="xs:string" oor:localized="true"/>

<prop oor:name="Context" oor:type="xs:string"/>

<set oor:name="Submenu" oor:node-type="MenuItem"/>

</group>

<group oor:name="ToolBarItem">

<prop oor:name="URL" oor:type="xs:string"/>

<prop oor:name="Title" oor:type="xs:string" oor:localized="true"/>

<prop oor:name="ImageIdentifier" oor:type="xs:string"/>

<prop oor:name="Target" oor:type="xs:string"/>

<prop oor:name="Context" oor:type="xs:string"/>

</group>

<group oor:name="UserDefinedImages">

<prop oor:name="ImageSmall" oor:type="xs:hexBinary"/>

<prop oor:name="ImageBig" oor:type="xs:hexBinary"/>

<prop oor:name="ImageSmallHC" oor:type="xs:hexBinary"/>

<prop oor:name="ImageBigHC" oor:type="xs:hexBinary"/>

<prop oor:name=”ImageSmallURL” oor:type=”xs:string”/>

<prop oor:name=”ImageBigURL” oor:type=”xs:string”/>

<prop oor:name=”ImageSmallHCURL” oor:type=”xs:string”/>

<prop oor:name=”ImageBigHCURL” oor:type=”xs:string”/>

</group>

<group oor:name="Images">

<prop oor:name="URL" oor:type="xs:string"/>

<node-ref oor:name="UserDefinedImages" oor:node-type="UserDefinedImages"/>

</group>

<set oor:name="ToolBarItems" oor:node-type="ToolBarItem"/>

</templates>

<component>

<group oor:name="AddonUI">

<set oor:name="AddonMenu" oor:node-type="MenuItem"/>

<set oor:name="Images" oor:node-type="Images"/>

<set oor:name="OfficeMenuBar" oor:node-type="PopupMenu"/>

<set oor:name="OfficeToolBar" oor:node-type="ToolBarItems"/>

<set oor:name="OfficeHelp" oor:node-type="MenuItem"/>

</group>

</component>

</oor:component-schema>

The schema has an XML root node that contains two parts, a list of template definitions and a definition of the component tree. The root node also declares XML namespaces that are used within the schema. Template definitions describe configuration tree fragments, which can be reused within the schema by reference or as element type of set nodes. In the case of set elements they serve as blueprints from which new instances of set items are built by the configuration management API components. Templates can either be group nodes or set nodes. The component part describes the actual data tree of the component. The component node is a special group node that represents the root of the component tree. Both parts are optional in the schema definition. A schema may provide only templates for reuse by other components or it may describe only a component tree without defining any templates of its own.

The tree structure is built from group nodes, set nodes. Properties are represented as prop nodes. The XML elements contain the information necessary to identify the node and its type as attributes. They may further contain extra child elements that contain human-readable descriptions of the node or that specify constraints on the permissible or meaningful values of properties. Property elements may also contain a default value.

| Currently the OpenOffice.org configuration management components do not handle XML namespaces correctly. Namespace prefixes must be named and used exactly as in the example. Nevertheless, all namespaces used should be declared correctly, to enable processing configuration files by namespace-aware tools.
--- | ---

A schema must be installed into the backend to be usable. Once a schema is installed the component it describes can be accessed through the configuration management API. An installed schema is assumed to not change any more.

### 15.5.2 Preparing Custom Configuration Data

A configuration data file is an XML file that conforms to the OOR Registry Update Format defined in http://util.openoffice.org/common/configuration/oor-document-format.html . Normally, configuration data files carry the extension .xcu.

A configuration data file contains changes to a configuration tree. When configuration data is read, an initial configuration tree is constructed from the component data described in the component schema. Then the configuration data files from all applicable layers are successively applied to this configuration tree. A layer is applied by applying the changes to the tree described by the data file while respecting any access control attributes and ensuring that the changes conform to the schema. Simple schema violations, like trying to update a node that does not exist in the configuration tree, are simply ignored. Outright schema violations, like updates that specify a data type that disagrees with the type specified in the schema, are considered errors and result in complete failure to read the component.

As an example, consider data for a sample Addon component. For details about configuration for Addon components, see 4.7.3 Writing UNO Components - Integrating Components into OpenOffice.org - User Interface Add-Ons - Configuration .

<?xml version='1.0' encoding='UTF-8'?>

<oor:component-data xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" oor:name="Addons" oor:package="org.openoffice.Office">

<node oor:name="AddonUI">

<node oor:name="OfficeMenuBar">

<node oor:name="org.openoffice.example.addon" oor:op="replace">

<prop oor:name="Title" oor:type="xs:string">

<value xml:lang="en-US">Add-On example</value>

<value xml:lang=”de”>Add-On Beispiel</value>

</prop>

<prop oor:name="Context" oor:type="xs:string">

<value>com.sun.star.text.TextDocument</value>

</prop>

<node oor:name="Submenu">

<node oor:name="m1" oor:op="replace">

<prop oor:name="URL">

<value>org.openoffice.Office.addon.example:Function1</value>

</prop>

<prop oor:name="Title">

<value xml:lang=”en-US”>Add-On Function 1</value>

<value xml:lang="de">Add-On Funktion 1</value>

</prop>

<prop oor:name="Target">

<value>_self</value>

</prop>

</node>

</node>

</node>

</node>

</node>

</oor:component-data>

The component-data root element of the configuration data XML corresponds to the component element of the associated schema. The elements of the update format do not reflect the distinction between set nodes and group nodes. All changes to structural nodes are expressed in the same way as simple node elements. Changes to property nodes use their own element tag. If a property has been declared as localized in the schema, the data file may contain different values for different locales. Changes may contain an operation attribute, which describes how the data is to be combined with preexisting data from the configuration tree, in order to obtain the result configuration data tree.

Changes also may contain access control attributes that restrict how the data can be overwritten by data in subsequent data layers. These access control attributes are not currently available directly through the configuration management API. But if a node in a default layer is protected from being overwritten by the user layer, the protection is reflected in the API by marking the corresponding node as read-only or non-removable.

| Currently the OpenOffice.org configuration management components do not handle XML namespaces correctly. Namespace prefixes must be named and used exactly as in the example. Nevertheless, all namespaces used should be declared correctly, to enable processing configuration files by namespace-aware tools.
--- | ---

Configuration data must be imported or installed into the backend to be effective.

### 15.5.3 Installing Custom Configuration Data

The easiest way to install configuration schema or data files is by using the pkgchk tool to deploy configuration data as part of an uno package. For details, see 4.9.1 Writing UNO Components - Deployment Options for Components - UNO Package Installation.

To manually install configuration data for an existing schema, use the API to import the data into the backend. You can use service com.sun.star.configuration.backend.LocalDataImporter to import configuration data from a file. If you need more control or want to import data that is not stored in a local file, then you can directly use the services com.sun.star.configuration.backend.MergeImporter and com.sun.star.configuration.backend.CopyImporter, which the LocalDataImporter itself uses internally.

Using these services, the configuration data is imported directly into the backend, bypassing any existing com.sun.star.configuration.ConfigurationProvider instances.

| After importing configuration data, a running OpenOffice.org instance should be terminated and restarted to make sure that the new data becomes visible despite internal caching.
--- | ---

If you can not use uno packages, you can manually install schemas and associated data files into the standard, local file-based backend. The internal organization of that backend is described at http://util.openoffice.org/common/configuration/oor-registry.html.

To manually install a schema into the local file-based based backend, copy it to the schema subdirectory corresponding to the package the schema belongs to and make sure it has the proper name. For example, a schema for component org.myorg.MySettings, has the name “MySettings” and package “org.myorg”. To install it, you have to create directory <OfficeInstallation>/share/registry/schema/org/myorg and copy the schema file there as MySettings.xcs.

To manually install the associated default configuration data, create the the corresponding configuration data directory <OfficeInstallation>/share/registry/data/org/myorg and place the file there as MySettings.xcu.

## 15.6 Adding a Backend Data Store

The configuration management components select and access a data store according to parameters passed at runtime or specified in file configmgr(.ini|rc) .

The parameter BackendService (ini-file entry: CFG_BackendService) specifies an UNO service or implementation name. This name is used to create a service instance that is used as backend. It must implement either service com.sun.star.configuration.backend.Backend or service com.sun.star.configuration.backend.SingleBackend. If service SingleBackend is discovered, a com.sun.star.configuration.backend.BackendAdapter is created, which implements service Backend on top of a SingleBackend. By default, a com.sun.star.configuration.backend.SingleBackendAdapter is used; a different implementation can be specified by the BackendWrapper (ini-file entry: CFG_BackendWrapper) parameter.

You can provide your own implementation of services com.sun.star.configuration.backend.Backend, com.sun.star.configuration.backend.SingleBackend orcom.sun.star.configuration.backend.BackendAdapter to access a different data store.

You can use your own backend as the default backend within OpenOffice.org by changing configmg(.ini|rc) to name your implementations instead of the default backends. You can use your own backend for selected data only by creating a custom com.sun.star.configuration.ConfigurationProvider with arguments that override the default parameters.

We are working on providing an implementation of com.sun.star.configuration.backend.Backend that allows combining layers from different different data stores in a flexible manner. This feature will become available in a future version of OpenOffice.org. For more information, visit http://util.openoffice.org.

[ Previous document | Content Table | Next document ]