KF XML Metatype: XML for OSGi metatypes and CM values

1. Knopflerfish recommendations May 2004

Public version
http://www.knopflerfish.org/XMLMetatype/
Latest version
https://www.knopflerfish.org/svn/knopflerfish.org/trunk/osgi/bundles/metatype/kf_metatype/src/org/knopflerfish/util/metatype/package.html
Revision
$LastChangedRevision: 591 $
Editors
Erik Wistrand

2. Abstract

KF XML Metatype: XML for OSGi metatypes and values is the Knopflerfish specification defining OSGi Metatypes and Configuration Manager values in XML format. This format can be used by bundles to define Metatypes, and for an OSGi Configuration Manager to store and receive actual configuration values.

3. Status of this document

Draft.

4. Table of contents

1. Knopflerfish recommendations May 2004
2. Abstract
3. Status of this document
4. Table of contents
5. Introduction
5.1 Configuration Manager
5.2 OSGi Metatype API
5.3 XML Schema
5.4 Purpose
5.5 Requirements
5.6 Terminology
6. Metatype specification
6.1 Services and factories
6.2 Metatype XML declaration
6.3 Service and factory definitions - instances of XML Schema
6.4 Supported data types
6.4.1 Optional attributes
7. Configuration value specification
8. Storing Metatype and values in bundle jar files
Appendix
Draft implementation
Localization in the Metatype API

5. Introduction

5.1 Configuration Manager

The OSGi specification defines a Configuration Manager, CM, capable of storing configuration data for installed bundles. Such configuration data is sent to the bundle using instances of java.lang.Dictionary, containing name/value pairs. The CM specification itself does not mandate any specific means of initializing, storing or specifying such data. This is left to the implementation.

5.2 OSGi Metatype API

OSGi also specifies a set of Metatype interfaces, which allows an OSGi bundle to provide metatype to configurations used by CM. Such metatype contains

The types supported by the Metatype API is limited to primitive types as string, int, long, short, float, double, char and boolean, plus vectors and arrays of primitive types. Vectors and arrays only differ in their run-time format, java.lang.Vector respective java arrays of primitive types.

5.3 XML Schema

XML Schemas (http://www.w3.org/XML/Schema) are commonly used for specifying metatype information in XML format, examples are the Web Services (SOAP) specification, the UPnP specification and commercial systems for data exchange.

XML Schema is a rich specification, which is able to define a much larger set of types than OSGi Metatype supports. Thus, only a subset of the XML Schema datatypes need to be supported in KF XML Metatype.

5.4 Purpose

The purpose of the Metatype XML format is to specify an XML format for A typical usage would be:
  1. The bundle developer specifies, in XML format, the metatypes for CM data used by the bundle.
  2. The bundle developer specifies default values, in XML format, for any created CM configurations.
  3. The above XML data is stored statically in the bundle's jar file
  4. The bundle is installed.
  5. A CM user interface reads the bundle's XML data and automatically provides an UI.

The last step in the above list could be replaced by a CM utility automatically creating configurations from default data, if not otherwise present.

5.5 Requirements

  1. The Metatype XML specification should re-use existing XML W3C specifications whenever possible. More specifically, XML Schemas (http://www.w3.org/XML/Schema should be used for datatype specification.
  2. XML Namespaces should be used for defining Metatype specific tags
  3. Supports for all aspects of the OSGi Metatype API must be available in offline format.

5.6 Terminology

["xsd:" is used as XMLSchema namespace]
If not otherwise specified, all names prefixed by "xsd:" are assumed to be specified as by
xmlns:xsd = "http://www.w3.org/2001/XMLSchema"
["metatype:" is used as Metatype namespace]
If not otherwise specified, all names prefixed by "metatype:" are assumed to be specified as by
xmlns:metatype = "http://www.knopflerfish.org/XMLMetatype"
[CM - OSGi Configuration Manager]
CM is used as shorthand for Configuration Manager
[PID - Perstistant Identifier]
A PID is used by the Configuration Manager to uniquely define a configuration service or factory.

6. Metatype specification

6.1 Services and factories

A CM service is a configuration intended to be received by a CM ManagedService. At most one CM configuration for a given persistant ID (PID) exists at a given time.

A CM factory is a configuration intended to be received by a CM ManagedServiceFactory. Several CM configurations can exists for a given PID.

6.2 Metatype XML declaration

Metatype declaration in an XML document must use the <metatype> element as top level element. This element can only contain the <xsd:schema>, and <metatype:values> elements. Each of these is optional.

Services and factories are specified as complexType elements inside the schema element. The only difference between a service and a factory definition is the maxOccurs value. A factory may occur more than once in a value document, a service just once.

Each service or factory defines a possible PID, represented by an object definition containing a set of attribute definitions.

Metatype declaration
<metatype:metatype
        xmlns:metatype = "http://www.knopflerfish.org/XMLMetatype"
        xmlns:xsd      = "http://www.w3.org/2001/XMLSchema">
 
  <xsd:schema>

   <xsd:complexType name      = "ServiceID"
                    maxOccurs = "1">
     ...
   </xsd:complexType>
   ...

   <xsd:complexType name      = "FactoryID"
                    maxOccurs = "unbounded">
     ...
   </xsd:complexType>
   ...

  </xsd:schema>

  <!-- optional default values -->
  <metatype:values>
    ...
  </metatype:values>

</metatype:metatype>

6.3 Service and factory definitions - instances of XML complexType

All service and factory definitions are instances of a complexType specification.
This complexType fully defines the array of AttributeDefinitions in the resulting metatype definition.

A service definition is a complexType with the maxOccurs attribute set to one. A factory definition is a complexType with the maxOccurs attribute larger than one. Default is a service definition.

The name of the service/factory complexType defines the object identifier. During run-time, the name also defines the persistant ID of configurations.

Example - a simple service Metatype specification
   <xsd:complexType name="service1">
    <xsd:element   name="string1" type="xsd:string"/>
   </xsd:complexType> 
Example - a simple factory Metatype specification
   <xsd:complexType name="factory1" maxOccurs="unbounded">
    <xsd:element   name="int1" type="xsd:int"/>
   </xsd:complexType> 

6.3.1 Vectors and arrays

Vector and arrays are specified using the <xsd:sequence> element. The default format is vector.

Discussion: Is it better to use arrays as default format?

The nice thing with arrays is that they have a well-defined item class even if empty. Arrays are also easier to use for a ManagedService since the can avoid verbose to<Type>() calls.

Example - a service using a vector specification

   <xsd:complexType name="service2">
    <xsd:complexType name = "intvector1">
     <xsd:sequence>
      <xsd:element name = "item" type="xsd:int"/>
     </xsd:sequence>
    </xsd:complexType>
   </xsd:complexType> 

Note: <xsd:sequence> must have exacly one element be named "item".

6.3.2 Service/factory descriptions

A service's (and factory's) description is set using schema annotations on the top level complexType. If no description is set, the empty string will be used.

Example - service description
   <xsd:complexType name="service1">
    <xsd:annotation>
     <xsd:documentation>
       This is a service annotation
     </xsd:documentation>
    </xsd:annotation>
    ...
   </xsd:complexType> 

6.3.2.1 Service/factory icon

A service/factory icon URL can be set by adding an option iconURL attribute to the service's defining element.

URLs starting with "/" should be considered relative to the defining bundle's jar file, i.e, bundle resource names.

Example - service icon
 <xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" >
   <xsd:complexType name    = "service1"
                    iconURL = "/image.gif">
   ...

6.3.3 Attribute descriptions

An attribute description is set using schema annotations on the attribues defining element. If no description is set, the empty string will be used.

Example - attribute description
   <xsd:complexType name="service1">
    <xsd:element   name="string1" type="xsd:string">
     <xsd:annotation>
      <xsd:documentation>
       This is an attribute annotation
      </xsd:documentation>
     </xsd:annotation>
    </xsd:element>
   </xsd:complexType> 

6.3.3.1 Localized descriptions

Locale specific description strings can be set on annotations, using the standard xml:lang attribute:

Discussion: The Metatype API has some oddities which makes actual runtime implementation hard. Thus, the draft implementation of the KF XML does not yet read localized data. See appendix for more info.

Example - inline, localized description in two languages
<xsd:element   name="string1" type="xsd:string">
 <xsd:annotation>
  <xsd:documentation xml:lang="en">
      This is the English description.
  </xsd:documentation>
  <xsd:documentation xml:lang="se">
      Detta är beskrivningen på svenska.
  </xsd:documentation>
 </xsd:annotation>
</xsd:element>

Optionally, the <xsd:appInfo> element can be used to specify a an URL or resource file to localization property file. The appInfo should then be set on the object class definition element. Standard file name expansion for locales may be done on the URL.

URLs starting with "/" should be considered relative to the defining bundle's jar file, i.e, bundle resource names.

The key for lookup in the external localization file will be the attribute's ID, plus either ".desc" for attribute description and, optionally, ".name" for attribute names.

If the the key is not found, the xsd:documentation will be searched for default values.

Example - external, localized description
   <xsd:complexType name="service1">
    <xsd:annotation>
     <xsd:appInfo>/settings.props<xsd:/appInfo>
    </xsd:annotation>

    <xsd:element   name="string1" type="xsd:string"/>

   ...

The file /settings.props in the bundle jar should contain lines as:

string1.desc=This is the description for string1
string1.name=First string

A Swedish translation /settings_se.props in the bundle jar could contain lines as:

string1.desc=Humdihumdididum
string1.name=Chef #1

6.4 Supported data types

The name of each service/factory data element represent the ID of an attribute definition. If nothing else is specified in the element annotation, the name of the attribute equals its ID.

The type of each service/factory data element represent the type of the attribute definition.

<xsd:annotation> elements can optionally be used to set an attribute or enumeration description.

Data types
Datatype XML specification Java representation Comment
Primitive types
string <xsd:element name="NAME" type="xsd:string"/> java.lang.String NAME is the ID and default name of the Metatype AttibuteDefinition.

NAME must be possible to use as a valid XML tag name.

integer <xsd:element name="NAME" type="xsd:int"/> java.lang.Integer
long <xsd:element name="NAME" type="xsd:long"/> java.lang.Long
short <xsd:element name="NAME" type="xsd:short"/> java.lang.Short
char <xsd:element name="NAME" type="xsd:char"/> java.lang.Character
float <xsd:element name="NAME" type="xsd:float"/> java.lang.Float
double <xsd:element name="NAME" type="xsd:double"/> java.lang.Double
boolean <xsd:element name="NAME" type="xsd:boolean"/> java.lang.Boolean
BigInteger <xsd:element name="NAME" type="xsd:integer"/> java.math.BigInteger If running on a JVM without the BigInteger class, long is used instead.
BigDecimal <xsd:element name="NAME" type="xsd:decimal"/> java.math.BigDecimal If running on a JVM without the BigDecimal class, double is used instead.
Primitive types with restrictions
Enumerated types
<xsd:simpleType name = "NAME">
 <xsd:restriction base="TYPE">
  <xsd:enumeration value="VALUE1"/>
  <xsd:enumeration value="VALUE2"/>
  ...
 </xsd:restriction>
</xsd:simpleType>
As defined by TYPE. See primitive types above. Enumeration values will be stored as attribute definition option values.
Enumerated types with labels
<xsd:simpleType name = "NAME">
 <xsd:restriction base="TYPE">
  <xsd:enumeration value="VALUE1"/>
   <xsd:annotation>
    <xsd:documentation>
     Label for VALUE1
    </xsd:documentation>
   </xsd:annotation>  
  ...
 </xsd:restriction>
</xsd:simpleType>
As defined by TYPE. See primitive types above. If <xsd:annotation> elements are added to an enumeration, the annotation documentation will be used as the attribute definition's option label. If no annotation documentations are found, the values are used as labels.
Vectors and arrays
Vector
<xsd:complexType 
     name="NAME">
 <xsd:sequence
     [array="false"]
     [maxOccurs="MAX"]>
  PRIMITIVE_TYPE
 </xsd:sequence>
</xsd:complexType>
java.util.Vector, where each item is of the type specified by PRIMITIVE_TYPE

Note: The specifed PRIMITIVE_TYPE must have a name of "item"

The default value for the array property is "false".
The default value for the maxOccurs property is java.lang.Integer.MAX_VALUE.
Array
<xsd:complexType
     name="NAME"
     [maxOccurs="MAX"]>
 <xsd:sequence array="true">
  PRIMITIVE_TYPE
 </xsd:sequence>
</xsd:complexType>
Java array, where each item is of the unboxed type specified by PRIMITIVE_TYPE.

Note: The specifed PRIMITIVE_TYPE must have a name of "item"

Resulting arrays will be represented as:
Primitive type Array type
Integer int[]
Boolean boolean[]
Double double[]
Float float[]
Long long[]
Short short[]
Character char[]
String String[]
BigInteger BigInteger[]
BigDecimal BigDecimal[]

6.4.1 Optional attributes

Attributes can be specified to be optional by setting the minOccurs attribute to zero on the attribute element. By default, attributes are required -- which also can be specified by setting minOccurs to one.

Setting minOccurs > 1 is not allowed.

Example - specifying an optional attribute
<xsd:element   name      = "string1" 
               type      = "xsd:string"
               minOccurs = "0"/>

7. Configuration value specification

Configuration values are specified using the <metatype:values> element. This contains a set of XML elements as defined by the Metatype schema.

A <metatype:values> element can be embedded in <metatype:metatype>. The values should then be considered default values for the specified metatypes.

Configuration value declaration
<?xml version="1.0"?>

  <metatype:values
        xmlns:metatype = "http://www.knopflerfish.org/XMLMetatype">

    [VALUE_DECLARATIONS]

  </metatype:values>

[VALUE_DECLARATIONS] is thus a sequence of top level elements, named as the PIDs used when defining the metatypes. Each such PID element contains elements matching the attribute definitions.

Example - a value declaration for the simple service
  <service1>
   <string1>this the string value</string1>
  </service1>   

Example - a value declaration defining a vector/array
  <service2>
   <intvector1>
    <item>1</item>
    <item>2</item>
    <item>3</item>
   </intvector1>
 </service2>

7.2 Typed value specifications

As value specifications are instances of a schema, the system is assumed to have access to the schema specification when parsing a value document. This can be accomplished by at least three different methods:

8. Storing Metatype and values in bundle jar files

A bundle can store URLs to metatype and value document in its Manifest attributes. The run-time system is then responsible for reading these attributes when the bundle is started (or deployed) and converting them to suitable run-time format (Metatype API and/or CM dictionaries).

URLs starting with "/" should be considered relative to the defining bundle's jar file, i.e, bundle resource names.

Manifest attributes
Manifest attribute Description Default value
Bundle-MetatypeURL URL to XML document describing metatype
/metatype.xml
Bundle-CMDefaultsURL URL to XML document with CM default values
/cmdefaults.xml

Appendix

Draft implementation

A draft implementation is available at
https://www.knopflerfish.org/svn/knopflerfish.org/trunk/osgi/bundles/metatype

See http://www.knopflerfish.org for details on how to access the code repository.

Localization in the Metatype API

  1. The Metatype API specifies that a MetaTypeProvider can return ObjectClassDefinitions based on a PID and a Locale.
  2. This implies that each ObjectClassDefinition, per Locale, should have it's own ID, since every ObjectClassDefinition is specified to have a unique ID.
  3. 2) leads to a very cumbersome mapping of ObjectClassDefinitions to CM PIDs since they never can implemented as equal, even if this would be possible in a given situation (as it very often is)
  4. 1) also leads to a conceptually odd model, where a given Locale actually could specify a ObjectClassDefinition with a *different* set of attributes than another OCD with with the same PID. At, least, the API does not specify that the attributes must be same.
  5. 1) also leads to an expensive implementation situation where the number of instances of OCDs created by a MTP multiplies by the number of supported locales, even if the actual language data is held in single instances if AttributeDefinition

Conclusion: The Locale-specific methods

 OCD.getName, OCD.getDescription,  OCD.getIcon
 AD.getName, AD.getDescription and AD.getOptionLabels
should be themselves take a Locale argument, not the MetatypeProvider.

(...and while I'm at it, the getIcon argument "size" could just as easily be dumped since there is no chance of relying on the results. Also, returning a stream from getIcon effectively removes any possibility of remoting OCD instances. an URL string would be much better)