Copyright(c) Jonathan Borden October 10, 1998
Contact Information:sodl-info or jborden@mediaone.net
Abstract: The Simple Object Definition Language (SODL) is an XML IDL DTD which allows objects to be described in a fashion compatible with Interface Definition Language (IDL) used in COM and CORBA object systems. SODL is a simplfied XML IDL designed to be compatible with currently available and widely used non-XML IDLs. SODL allows objects to be described as well as serialized for transport across networks. These serialization/marshalling techniques can be readily integrated into Object RPC over XML transports. SODL is the DTD employed for the XML Metadata Object Persistence (XMOP) service of the XPository(tm) system. The initial implementation of XMOP (XML Metadata Object Persistance) uses the SODL 1.0 DTD and is compatible with Microsoft IDL and COM Automation objects.
This document discusses three issues
This specification deals primarily with ways to represent distributed objects using XML, and ways to transport objects over network protocols such as HTTP.
The common thread among distributed object systems such as DCOM, CORBA and java/RMI is the concept of the interface. We communicate with objects using interfaces and objects may have one or more individual interfaces. In COM, interfaces are exposed using QueryInterface, in CORBA using multiple inheritance.
Both DCOM/DCE-RPC and CORBA employ Interface Definition Languages which serve as meta-data languages for objects. A DTD for the Simple Object Description Language (SODL) is presented below.
The following types are defined by SODL:
C++/IDL Type | SODL Type | COM Automation type |
long | i4 | VT_I4 |
short | i2 | VT_I2 |
int64 | i8 | VT_I8 |
char | char | VT_I1 |
unsigned char | ui1 | VT_UI1 |
unsigned short | ui2 | VT_UI2 |
unsigned long | ui4 | VT_UI4 |
unsigned int64 | ui8 | VT_UI8 |
int | int | VT_INT |
unsigned int | uint | VT_UINT |
float | r4 | VT_R4 |
double | r8 | VT_R8 |
DATE | date | VT_DATE |
BSTR | string | VT_BSTR |
enum | udt/enum | VT_USERDEFINED |
struct | udt/struct | VT_USERDEFINED |
interface | interfaceDef/object | VT_UNKNOWN |
dispinterface | interfaceDef/disp | VT_DISPATCH |
coclass | objectDef | VT_UNKNOWN |
SAFEARRAY | array | VT_SAFEARRAY/VT_ARRAY |
IStream* | stream | VT_STREAM |
IStorage* | storage | VT_STORAGE |
BLOB | blob | VT_BLOB |
This table is necessarily simplified because there is not always a one-one correspondance between types.
Properties which are themselves objects are represented in one of several ways:
An object which is instanciated on a remote machine is represented as a link to a URI which represents the object e.g. http://www.jabrtech.com/objects/object34
Many objects may be marshalled by value using SODL. The uid associated with the objectDef may be used to associate the object with code used to instanciate the object, though it is possible to create objects and associate properties with names and values from the definition alone.
e.g.
<objectDef uuid=" " name="JABR.DataObject">
<interfaceDef uuid=" " name="IJABRDataInterface">
<property name="X" type="string"><string>This is the value of the string property</string></property>
<property name="Y" type="i4"><i4>12345</i4></property>
<property id="1" type="string"><string>An unnamed property</string></property>
<property name="Example" type="string"><i4>4567</i4></property>
<!-- this property will be coerced to type = "string" though it must have a valid i4 value-->
</interfaceDef>
</objectDef>
The encoding for Word.Document.8
Objects which are associated with large amounts of binary data are not efficiently marshalled using SODL alone. Binary data streams are represented with URIs. URIs often point to external data streams. In order to represent binary data streams in the same message as the descriptive SODL/XML data, the multipart/related MIME type is used to represent the marshalled object. The Content-ID field of individual multipart/related parts is used as an internal link to the binary stream.
Multipart/related MIME messages represent compound documents in a straightforward and efficient manner. Individual parts represent individual streams in the compound document. Individual parts may themselves have the multipart/related MIME type and hence represent sub-storages of the compound document. Boundary strings are used to delimit individual parts. The cid:XXXX is used as a URI to an internal Content-ID:XXXX named part.
Marshalling an object using a multipart/related message is analagous to marshalling an object using file transfer.
e.g.
Content-Type: multipart/related; boundary=xxxxxxxxxx;
--xxxxxxxxxx
Content-Type: text/xml
Content-ID: Contents
<?xml version="1.0" ?>
<objectDef uid=" ">
<property name="Width" type="i4">
<i4>1024</i4>
</property>
<property name="Height" type="i4">
<i4>1024</i4>>
</property>
<property name="BitCount" type="i2">
<i4>16</i4>
</property>
<property name="Pixels" type="stream"
<stream href=cid:Pixels />
</property>
--xxxxxxxxxx
Content-Type: application/binary
Content-Transfer-Encoding: Little-Endian
Content-ID: Pixels
Content-Length: 524288
....binary data here...
--xxxxxxxxxx
In order to run a defined script on object transfer (using marshal by value), a script is placed into a text stream within the multipart/related message. The object is loaded from the compound document and bound to the script variable "this". E.g.
Content-Type: multipart/related; boundary=xxxxxxxxxx;
--xxxxxxxxxx
Content-Type: text/xml
Content-ID: Contents
<?xml version="1.0" ?>
<objectDef uid=" ">
<property><name>Width</name>
<value><i4>1024</i4></value>
</property>
<property><name>Height</name>
<value><i4>1024</i4></value>
</property>
<property><name>BitCount</name>
<value><i4>16</i4></value>
</property>
<property><name>BitCount</name>
<value><i4>16</i4></value>
</property>
<property><name>Pixels</name>
<value><stream href=cid:Pixels /></value>
</property>
--xxxxxxxxxx
Content-Type: application/binary
Content-Transfer-Encoding: Little-Endian
Content-ID: Pixels
Content-Length: 524288
....binary data here...
--xxxxxxxxxx
Content-Type: text/script
Content-ID: ActivationScript
<script language="JavaScript">
var width = this.Width;
var height = this.Height;
var doc = document.open;
doc.body.insertAdjacentHTML("BeforeEnd", "<object classid=" + this.uid +"" + "<param width = " + width + " height = " + height ">
<param image = this.Pixels>>");
</script>
--xxxxxxxxxxx
A well known mechanism can be used to return an object definition in response to a query. This will allow clients to query servers about objects they support. The response is delivered in SODL.
COM Typelibaries can be readily converted to and from SODL allowing common scripting languages to use SODL marshalled objects. Contact JABR Technology Corporation for implementation.